@opengsd/gsd-pi 1.4.0 → 1.5.0-dev.553dc518

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 (606) 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 +137 -42
  14. package/dist/resources/extensions/gsd/auto/finalize.js +9 -0
  15. package/dist/resources/extensions/gsd/auto/orchestrator.js +4 -3
  16. package/dist/resources/extensions/gsd/auto/pre-dispatch.js +6 -3
  17. package/dist/resources/extensions/gsd/auto/run-unit.js +5 -2
  18. package/dist/resources/extensions/gsd/auto/schedule-wakeup.js +3 -0
  19. package/dist/resources/extensions/gsd/auto/unit-phase.js +5 -9
  20. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +4 -5
  21. package/dist/resources/extensions/gsd/auto-dispatch.js +15 -5
  22. package/dist/resources/extensions/gsd/auto-model-selection.js +36 -18
  23. package/dist/resources/extensions/gsd/auto-prompts.js +76 -2
  24. package/dist/resources/extensions/gsd/auto-start.js +7 -5
  25. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +4 -0
  26. package/dist/resources/extensions/gsd/auto-worktree-branch-lifecycle.js +189 -0
  27. package/dist/resources/extensions/gsd/auto-worktree-cleanup.js +133 -0
  28. package/dist/resources/extensions/gsd/auto-worktree-conflict-auto-resolve.js +35 -0
  29. package/dist/resources/extensions/gsd/auto-worktree-creation.js +130 -0
  30. package/dist/resources/extensions/gsd/auto-worktree-entry.js +118 -0
  31. package/dist/resources/extensions/gsd/auto-worktree-merge-already-merged.js +98 -0
  32. package/dist/resources/extensions/gsd/auto-worktree-merge-branch-head.js +52 -0
  33. package/dist/resources/extensions/gsd/auto-worktree-merge-cleanup.js +87 -0
  34. package/dist/resources/extensions/gsd/auto-worktree-merge-code-changes.js +46 -0
  35. package/dist/resources/extensions/gsd/auto-worktree-merge-db-ready.js +68 -0
  36. package/dist/resources/extensions/gsd/auto-worktree-merge-integration-branch.js +51 -0
  37. package/dist/resources/extensions/gsd/auto-worktree-merge-message.js +106 -0
  38. package/dist/resources/extensions/gsd/auto-worktree-merge-pre-teardown.js +64 -0
  39. package/dist/resources/extensions/gsd/auto-worktree-merge-stash.js +168 -0
  40. package/dist/resources/extensions/gsd/auto-worktree-merge.js +302 -0
  41. package/dist/resources/extensions/gsd/auto-worktree-milestone-shelter.js +119 -0
  42. package/dist/resources/extensions/gsd/auto-worktree-path-resolution.js +5 -0
  43. package/dist/resources/extensions/gsd/auto-worktree-path-utils.js +5 -0
  44. package/dist/resources/extensions/gsd/auto-worktree-resource-version.js +41 -0
  45. package/dist/resources/extensions/gsd/auto-worktree-runtime-cleanup.js +99 -0
  46. package/dist/resources/extensions/gsd/auto-worktree-session-registry.js +57 -0
  47. package/dist/resources/extensions/gsd/auto-worktree-sync.js +249 -0
  48. package/dist/resources/extensions/gsd/auto-worktree-teardown.js +120 -0
  49. package/dist/resources/extensions/gsd/auto-worktree.js +20 -2046
  50. package/dist/resources/extensions/gsd/auto.js +31 -5
  51. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +3 -0
  52. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +1 -1
  53. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +133 -6
  54. package/dist/resources/extensions/gsd/bootstrap/schedule-wakeup-tool.js +58 -9
  55. package/dist/resources/extensions/gsd/bootstrap/system-context.js +1 -1
  56. package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +127 -22
  57. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +14 -1
  58. package/dist/resources/extensions/gsd/codebase-generator.js +157 -19
  59. package/dist/resources/extensions/gsd/commands/handlers/core.js +40 -4
  60. package/dist/resources/extensions/gsd/commands-handlers.js +1 -1
  61. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +153 -1
  62. package/dist/resources/extensions/gsd/commands-workflow-templates.js +3 -3
  63. package/dist/resources/extensions/gsd/commands-worktree.js +11 -2
  64. package/dist/resources/extensions/gsd/db/queries.js +48 -9
  65. package/dist/resources/extensions/gsd/discussion-handoff.js +8 -3
  66. package/dist/resources/extensions/gsd/docs/preferences-reference.md +8 -2
  67. package/dist/resources/extensions/gsd/doctor-engine-checks.js +292 -18
  68. package/dist/resources/extensions/gsd/doctor-providers.js +38 -10
  69. package/dist/resources/extensions/gsd/doctor.js +93 -3
  70. package/dist/resources/extensions/gsd/exec-sandbox.js +6 -2
  71. package/dist/resources/extensions/gsd/flat-phase-migration.js +88 -26
  72. package/dist/resources/extensions/gsd/forensics.js +1 -1
  73. package/dist/resources/extensions/gsd/git-conflict-resolve.js +2 -2
  74. package/dist/resources/extensions/gsd/git-service.js +59 -18
  75. package/dist/resources/extensions/gsd/gsd-db.js +63 -0
  76. package/dist/resources/extensions/gsd/guidance.js +1 -0
  77. package/dist/resources/extensions/gsd/guided-flow.js +46 -12
  78. package/dist/resources/extensions/gsd/key-manager.js +1 -0
  79. package/dist/resources/extensions/gsd/markdown-renderer.js +40 -11
  80. package/dist/resources/extensions/gsd/migrate-external.js +24 -7
  81. package/dist/resources/extensions/gsd/milestone-merge-transaction.js +14 -3
  82. package/dist/resources/extensions/gsd/milestone-settlement.js +1 -1
  83. package/dist/resources/extensions/gsd/parallel-merge.js +1 -1
  84. package/dist/resources/extensions/gsd/parallel-orchestrator.js +3 -1
  85. package/dist/resources/extensions/gsd/preferences-diagnostics.js +24 -1
  86. package/dist/resources/extensions/gsd/preferences-models.js +6 -4
  87. package/dist/resources/extensions/gsd/preferences-types.js +1 -0
  88. package/dist/resources/extensions/gsd/preferences-validation.js +107 -2
  89. package/dist/resources/extensions/gsd/preferences.js +29 -2
  90. package/dist/resources/extensions/gsd/prompts/plan-slice.md +4 -2
  91. package/dist/resources/extensions/gsd/prompts/system.md +6 -6
  92. package/dist/resources/extensions/gsd/quick.js +12 -3
  93. package/dist/resources/extensions/gsd/redact-secrets.js +37 -0
  94. package/dist/resources/extensions/gsd/repo-identity.js +16 -0
  95. package/dist/resources/extensions/gsd/repository-registry.js +6 -1
  96. package/dist/resources/extensions/gsd/root-write-leak-guard.js +4 -2
  97. package/dist/resources/extensions/gsd/safe-fs.js +23 -2
  98. package/dist/resources/extensions/gsd/skills/gsd-headless/SKILL.md +7 -9
  99. package/dist/resources/extensions/gsd/skills/gsd-headless/references/commands.md +1 -0
  100. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +2 -1
  101. package/dist/resources/extensions/gsd/state/derive/from-db.js +88 -153
  102. package/dist/resources/extensions/gsd/tool-contract.js +14 -0
  103. package/dist/resources/extensions/gsd/tools/plan-task.js +76 -8
  104. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +40 -0
  105. package/dist/resources/extensions/gsd/unit-context-manifest.js +5 -4
  106. package/dist/resources/extensions/gsd/unit-registry.js +37 -2
  107. package/dist/resources/extensions/gsd/unit-runtime.js +21 -0
  108. package/dist/resources/extensions/gsd/unmerged-milestone-guard.js +1 -1
  109. package/dist/resources/extensions/gsd/validation-block-guard.js +2 -1
  110. package/dist/resources/extensions/gsd/workspace-git-preflight.js +2 -2
  111. package/dist/resources/extensions/gsd/workspace.js +26 -8
  112. package/dist/resources/extensions/gsd/worktree-command.js +1 -1
  113. package/dist/resources/extensions/gsd/worktree-lifecycle.js +81 -14
  114. package/dist/resources/extensions/gsd/worktree-manager.js +97 -4
  115. package/dist/resources/extensions/gsd/worktree-reentry.js +2 -1
  116. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  117. package/dist/web/standalone/.next/BUILD_ID +1 -1
  118. package/dist/web/standalone/.next/app-path-routes-manifest.json +10 -10
  119. package/dist/web/standalone/.next/build-manifest.json +3 -3
  120. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  121. package/dist/web/standalone/.next/required-server-files.json +3 -3
  122. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  123. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  124. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  125. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  128. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  130. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  131. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  132. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  133. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  134. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  135. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  136. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  137. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  138. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  139. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  140. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  141. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  142. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  149. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  161. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/mcp-connections/route_client-reference-manifest.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  183. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  193. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  195. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  196. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  197. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  199. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  200. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  201. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  202. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  203. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  204. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  205. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  206. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  207. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  208. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  209. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  210. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  211. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  212. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  213. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  214. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  215. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  216. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  217. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  218. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  219. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  220. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  221. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  222. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  223. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  224. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  225. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  226. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  227. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  228. package/dist/web/standalone/.next/server/app/index.html +1 -1
  229. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  230. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  231. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  232. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  233. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  234. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  235. package/dist/web/standalone/.next/server/app/page.js +2 -2
  236. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  237. package/dist/web/standalone/.next/server/app-paths-manifest.json +10 -10
  238. package/dist/web/standalone/.next/server/chunks/2842.js +4 -4
  239. package/dist/web/standalone/.next/server/chunks/8357.js +2 -2
  240. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  241. package/dist/web/standalone/.next/server/middleware.js +3 -3
  242. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  243. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  244. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  245. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-a6fb1847f67f167c.js +1 -0
  246. package/dist/web/standalone/.next/static/chunks/app/{layout-b35cbfff38aaf4cf.js → layout-4ae2d68984392bbf.js} +1 -1
  247. package/dist/web/standalone/.next/static/chunks/app/page-72a856634ad14c10.js +1 -0
  248. package/dist/web/standalone/.next/static/chunks/{main-app-590a74400e35f685.js → main-app-90d1d8d5e5d2dc6b.js} +1 -1
  249. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-1115d46ac61b9823.js +1 -0
  250. package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
  251. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  252. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  253. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  254. package/dist/web/standalone/server.js +1 -1
  255. package/dist/wizard.d.ts +8 -0
  256. package/dist/wizard.js +8 -1
  257. package/integrations/hermes/CONTEXT.md +47 -0
  258. package/integrations/hermes/README.md +21 -0
  259. package/integrations/hermes/__init__.py +31 -0
  260. package/integrations/hermes/docs/issue-1162-grilling.md +197 -0
  261. package/integrations/hermes/docs/setup.md +4 -0
  262. package/integrations/hermes/open_gsd_hermes/commands.py +141 -0
  263. package/integrations/hermes/open_gsd_hermes/config.py +2 -0
  264. package/integrations/hermes/open_gsd_hermes/gsd_client.py +591 -39
  265. package/integrations/hermes/open_gsd_hermes/notifications.py +10 -1
  266. package/integrations/hermes/plugin.yaml +4 -0
  267. package/integrations/hermes/tests/test_config.py +6 -0
  268. package/integrations/hermes/tests/test_directory_loader.py +37 -0
  269. package/integrations/hermes/tests/test_gsd_client_cache.py +3 -0
  270. package/integrations/hermes/tests/test_gsd_client_execute.py +35 -0
  271. package/integrations/hermes/tests/test_gsd_client_process_cwd.py +22 -0
  272. package/integrations/hermes/tests/test_gsd_client_timeout.py +98 -0
  273. package/integrations/hermes/tests/test_milestone_client.py +447 -0
  274. package/integrations/hermes/tests/test_new_milestone_command.py +313 -0
  275. package/integrations/hermes/tests/test_supervisor_fsm.py +40 -0
  276. package/package.json +8 -8
  277. package/packages/cloud-mcp-gateway/dist/auth-store.d.ts +1 -0
  278. package/packages/cloud-mcp-gateway/dist/auth-store.d.ts.map +1 -1
  279. package/packages/cloud-mcp-gateway/dist/auth-store.js +21 -1
  280. package/packages/cloud-mcp-gateway/dist/auth-store.js.map +1 -1
  281. package/packages/cloud-mcp-gateway/dist/auth-store.test.js +34 -0
  282. package/packages/cloud-mcp-gateway/dist/auth-store.test.js.map +1 -1
  283. package/packages/cloud-mcp-gateway/package.json +2 -2
  284. package/packages/contracts/package.json +1 -1
  285. package/packages/daemon/dist/cloud-runtime.d.ts +2 -0
  286. package/packages/daemon/dist/cloud-runtime.d.ts.map +1 -1
  287. package/packages/daemon/dist/cloud-runtime.js +25 -1
  288. package/packages/daemon/dist/cloud-runtime.js.map +1 -1
  289. package/packages/daemon/dist/cloud-runtime.test.js +51 -0
  290. package/packages/daemon/dist/cloud-runtime.test.js.map +1 -1
  291. package/packages/daemon/dist/message-batcher.d.ts +7 -0
  292. package/packages/daemon/dist/message-batcher.d.ts.map +1 -1
  293. package/packages/daemon/dist/message-batcher.js +13 -0
  294. package/packages/daemon/dist/message-batcher.js.map +1 -1
  295. package/packages/daemon/dist/message-batcher.test.js +48 -0
  296. package/packages/daemon/dist/message-batcher.test.js.map +1 -1
  297. package/packages/daemon/dist/session-manager.js +1 -1
  298. package/packages/daemon/dist/session-manager.js.map +1 -1
  299. package/packages/daemon/package.json +5 -5
  300. package/packages/gsd-agent-core/dist/compaction/compaction.d.ts +13 -1
  301. package/packages/gsd-agent-core/dist/compaction/compaction.d.ts.map +1 -1
  302. package/packages/gsd-agent-core/dist/compaction/compaction.js +15 -1
  303. package/packages/gsd-agent-core/dist/compaction/compaction.js.map +1 -1
  304. package/packages/gsd-agent-core/dist/export-html/template.js +53 -4
  305. package/packages/gsd-agent-core/dist/session/agent-session-navigation.d.ts.map +1 -1
  306. package/packages/gsd-agent-core/dist/session/agent-session-navigation.js +4 -1
  307. package/packages/gsd-agent-core/dist/session/agent-session-navigation.js.map +1 -1
  308. package/packages/gsd-agent-core/package.json +5 -5
  309. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  310. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +3 -2
  311. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  312. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts.map +1 -1
  313. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js +1 -0
  314. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js.map +1 -1
  315. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.js +1 -1
  316. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.js.map +1 -1
  317. package/packages/gsd-agent-modes/package.json +7 -7
  318. package/packages/mcp-server/dist/server.d.ts +18 -5
  319. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  320. package/packages/mcp-server/dist/server.js +46 -5
  321. package/packages/mcp-server/dist/server.js.map +1 -1
  322. package/packages/mcp-server/dist/session-manager.js +1 -1
  323. package/packages/mcp-server/dist/session-manager.js.map +1 -1
  324. package/packages/mcp-server/package.json +4 -4
  325. package/packages/native/package.json +1 -1
  326. package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  327. package/packages/pi-agent-core/dist/agent-loop.js +14 -9
  328. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  329. package/packages/pi-agent-core/package.json +1 -1
  330. package/packages/pi-ai/dist/env-api-keys.d.ts.map +1 -1
  331. package/packages/pi-ai/dist/env-api-keys.js +3 -0
  332. package/packages/pi-ai/dist/env-api-keys.js.map +1 -1
  333. package/packages/pi-ai/dist/index.d.ts +1 -0
  334. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  335. package/packages/pi-ai/dist/index.js +1 -0
  336. package/packages/pi-ai/dist/index.js.map +1 -1
  337. package/packages/pi-ai/dist/providers/transform-messages.d.ts.map +1 -1
  338. package/packages/pi-ai/dist/providers/transform-messages.js +7 -3
  339. package/packages/pi-ai/dist/providers/transform-messages.js.map +1 -1
  340. package/packages/pi-ai/dist/tool-result-content.d.ts +3 -0
  341. package/packages/pi-ai/dist/tool-result-content.d.ts.map +1 -0
  342. package/packages/pi-ai/dist/tool-result-content.js +62 -0
  343. package/packages/pi-ai/dist/tool-result-content.js.map +1 -0
  344. package/packages/pi-ai/dist/types.d.ts +10 -22
  345. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  346. package/packages/pi-ai/dist/types.js.map +1 -1
  347. package/packages/pi-ai/package.json +1 -1
  348. package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
  349. package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -0
  350. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  351. package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts +1 -0
  352. package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts.map +1 -1
  353. package/packages/pi-coding-agent/dist/core/session-manager-types.js.map +1 -1
  354. package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
  355. package/packages/pi-coding-agent/dist/core/session-manager.js +3 -0
  356. package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
  357. package/packages/pi-coding-agent/package.json +7 -7
  358. package/packages/pi-tui/package.json +2 -2
  359. package/packages/rpc-client/dist/rpc-client.js +1 -1
  360. package/packages/rpc-client/dist/rpc-client.js.map +1 -1
  361. package/packages/rpc-client/package.json +2 -2
  362. package/pkg/dist/core/export-html/template.js +53 -4
  363. package/pkg/package.json +1 -1
  364. package/scripts/link-workspace-packages.cjs +14 -4
  365. package/src/resources/GSD-WORKFLOW.md +20 -25
  366. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +130 -51
  367. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +371 -39
  368. package/src/resources/extensions/cursor-cli/index.ts +18 -0
  369. package/src/resources/extensions/cursor-cli/models.ts +65 -0
  370. package/src/resources/extensions/cursor-cli/package.json +11 -0
  371. package/src/resources/extensions/cursor-cli/readiness.ts +143 -0
  372. package/src/resources/extensions/cursor-cli/stream-adapter.ts +440 -0
  373. package/src/resources/extensions/cursor-cli/tests/index.test.ts +54 -0
  374. package/src/resources/extensions/cursor-cli/tests/readiness.test.ts +29 -0
  375. package/src/resources/extensions/cursor-cli/tests/stream-adapter.test.ts +166 -0
  376. package/src/resources/extensions/gsd/activity-log.ts +4 -1
  377. package/src/resources/extensions/gsd/artifact-verification.ts +25 -9
  378. package/src/resources/extensions/gsd/auto/closeout.ts +163 -58
  379. package/src/resources/extensions/gsd/auto/finalize.ts +8 -0
  380. package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
  381. package/src/resources/extensions/gsd/auto/orchestrator.ts +4 -3
  382. package/src/resources/extensions/gsd/auto/pre-dispatch.ts +6 -3
  383. package/src/resources/extensions/gsd/auto/run-unit.ts +5 -2
  384. package/src/resources/extensions/gsd/auto/schedule-wakeup.ts +8 -0
  385. package/src/resources/extensions/gsd/auto/unit-phase.ts +5 -9
  386. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +4 -5
  387. package/src/resources/extensions/gsd/auto-dispatch.ts +17 -5
  388. package/src/resources/extensions/gsd/auto-model-selection.ts +49 -18
  389. package/src/resources/extensions/gsd/auto-prompts.ts +73 -2
  390. package/src/resources/extensions/gsd/auto-start.ts +8 -5
  391. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +4 -0
  392. package/src/resources/extensions/gsd/auto-worktree-branch-lifecycle.ts +237 -0
  393. package/src/resources/extensions/gsd/auto-worktree-cleanup.ts +166 -0
  394. package/src/resources/extensions/gsd/auto-worktree-conflict-auto-resolve.ts +37 -0
  395. package/src/resources/extensions/gsd/auto-worktree-creation.ts +171 -0
  396. package/src/resources/extensions/gsd/auto-worktree-entry.ts +154 -0
  397. package/src/resources/extensions/gsd/auto-worktree-merge-already-merged.ts +161 -0
  398. package/src/resources/extensions/gsd/auto-worktree-merge-branch-head.ts +83 -0
  399. package/src/resources/extensions/gsd/auto-worktree-merge-cleanup.ts +132 -0
  400. package/src/resources/extensions/gsd/auto-worktree-merge-code-changes.ts +71 -0
  401. package/src/resources/extensions/gsd/auto-worktree-merge-db-ready.ts +112 -0
  402. package/src/resources/extensions/gsd/auto-worktree-merge-integration-branch.ts +99 -0
  403. package/src/resources/extensions/gsd/auto-worktree-merge-message.ts +166 -0
  404. package/src/resources/extensions/gsd/auto-worktree-merge-pre-teardown.ts +93 -0
  405. package/src/resources/extensions/gsd/auto-worktree-merge-stash.ts +213 -0
  406. package/src/resources/extensions/gsd/auto-worktree-merge.ts +391 -0
  407. package/src/resources/extensions/gsd/auto-worktree-milestone-shelter.ts +159 -0
  408. package/src/resources/extensions/gsd/auto-worktree-path-resolution.ts +6 -0
  409. package/src/resources/extensions/gsd/auto-worktree-path-utils.ts +10 -0
  410. package/src/resources/extensions/gsd/auto-worktree-resource-version.ts +44 -0
  411. package/src/resources/extensions/gsd/auto-worktree-runtime-cleanup.ts +119 -0
  412. package/src/resources/extensions/gsd/auto-worktree-session-registry.ts +71 -0
  413. package/src/resources/extensions/gsd/auto-worktree-sync.ts +370 -0
  414. package/src/resources/extensions/gsd/auto-worktree-teardown.ts +161 -0
  415. package/src/resources/extensions/gsd/auto-worktree.ts +69 -2390
  416. package/src/resources/extensions/gsd/auto.ts +32 -19
  417. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +3 -0
  418. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +1 -1
  419. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +147 -6
  420. package/src/resources/extensions/gsd/bootstrap/schedule-wakeup-tool.ts +80 -12
  421. package/src/resources/extensions/gsd/bootstrap/system-context.ts +1 -1
  422. package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +163 -22
  423. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +23 -1
  424. package/src/resources/extensions/gsd/codebase-generator.ts +179 -18
  425. package/src/resources/extensions/gsd/commands/handlers/core.ts +39 -3
  426. package/src/resources/extensions/gsd/commands-handlers.ts +1 -1
  427. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +135 -1
  428. package/src/resources/extensions/gsd/commands-workflow-templates.ts +3 -3
  429. package/src/resources/extensions/gsd/commands-worktree.ts +13 -2
  430. package/src/resources/extensions/gsd/db/queries.ts +49 -9
  431. package/src/resources/extensions/gsd/discussion-handoff.ts +10 -2
  432. package/src/resources/extensions/gsd/docs/preferences-reference.md +8 -2
  433. package/src/resources/extensions/gsd/doctor-engine-checks.ts +372 -22
  434. package/src/resources/extensions/gsd/doctor-providers.ts +39 -10
  435. package/src/resources/extensions/gsd/doctor-types.ts +5 -1
  436. package/src/resources/extensions/gsd/doctor.ts +95 -3
  437. package/src/resources/extensions/gsd/exec-sandbox.ts +6 -2
  438. package/src/resources/extensions/gsd/flat-phase-migration.ts +112 -25
  439. package/src/resources/extensions/gsd/forensics.ts +1 -1
  440. package/src/resources/extensions/gsd/git-conflict-resolve.ts +2 -2
  441. package/src/resources/extensions/gsd/git-service.ts +67 -17
  442. package/src/resources/extensions/gsd/gsd-db.ts +85 -0
  443. package/src/resources/extensions/gsd/guidance.ts +2 -0
  444. package/src/resources/extensions/gsd/guided-flow.ts +52 -13
  445. package/src/resources/extensions/gsd/key-manager.ts +1 -0
  446. package/src/resources/extensions/gsd/markdown-renderer.ts +40 -10
  447. package/src/resources/extensions/gsd/migrate-external.ts +23 -6
  448. package/src/resources/extensions/gsd/milestone-merge-transaction.ts +19 -4
  449. package/src/resources/extensions/gsd/milestone-settlement.ts +1 -1
  450. package/src/resources/extensions/gsd/model-router.ts +4 -5
  451. package/src/resources/extensions/gsd/parallel-merge.ts +1 -1
  452. package/src/resources/extensions/gsd/parallel-orchestrator.ts +3 -1
  453. package/src/resources/extensions/gsd/preferences-diagnostics.ts +24 -0
  454. package/src/resources/extensions/gsd/preferences-models.ts +6 -3
  455. package/src/resources/extensions/gsd/preferences-types.ts +30 -0
  456. package/src/resources/extensions/gsd/preferences-validation.ts +97 -2
  457. package/src/resources/extensions/gsd/preferences.ts +38 -4
  458. package/src/resources/extensions/gsd/prompts/plan-slice.md +4 -2
  459. package/src/resources/extensions/gsd/prompts/system.md +6 -6
  460. package/src/resources/extensions/gsd/quick.ts +11 -3
  461. package/src/resources/extensions/gsd/redact-secrets.ts +40 -0
  462. package/src/resources/extensions/gsd/repo-identity.ts +17 -0
  463. package/src/resources/extensions/gsd/repository-registry.ts +7 -1
  464. package/src/resources/extensions/gsd/root-write-leak-guard.ts +3 -2
  465. package/src/resources/extensions/gsd/safe-fs.ts +22 -2
  466. package/src/resources/extensions/gsd/skills/gsd-headless/SKILL.md +7 -9
  467. package/src/resources/extensions/gsd/skills/gsd-headless/references/commands.md +1 -0
  468. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +3 -1
  469. package/src/resources/extensions/gsd/state/derive/from-db.ts +201 -157
  470. package/src/resources/extensions/gsd/tests/auto-loop-no-copy-artifacts.test.ts +2 -1
  471. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +131 -5
  472. package/src/resources/extensions/gsd/tests/auto-migrating-recovery.test.ts +18 -0
  473. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +178 -0
  474. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +43 -1
  475. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +54 -0
  476. package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +41 -0
  477. package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +41 -0
  478. package/src/resources/extensions/gsd/tests/auto-session-scope.test.ts +4 -4
  479. package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +3 -0
  480. package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +1 -1
  481. package/src/resources/extensions/gsd/tests/auto-timeout-recovery-harness-abort.test.ts +55 -0
  482. package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +10 -1
  483. package/src/resources/extensions/gsd/tests/auto-worktree-auto-resolve.test.ts +1 -1
  484. package/src/resources/extensions/gsd/tests/auto-worktree-merge-already-merged.test.ts +177 -0
  485. package/src/resources/extensions/gsd/tests/auto-worktree-merge-branch-head.test.ts +118 -0
  486. package/src/resources/extensions/gsd/tests/auto-worktree-merge-cleanup.test.ts +115 -0
  487. package/src/resources/extensions/gsd/tests/auto-worktree-merge-code-changes.test.ts +76 -0
  488. package/src/resources/extensions/gsd/tests/auto-worktree-merge-db-ready.test.ts +140 -0
  489. package/src/resources/extensions/gsd/tests/auto-worktree-merge-integration-branch.test.ts +123 -0
  490. package/src/resources/extensions/gsd/tests/auto-worktree-merge-message.test.ts +114 -0
  491. package/src/resources/extensions/gsd/tests/auto-worktree-merge-pre-teardown.test.ts +84 -0
  492. package/src/resources/extensions/gsd/tests/auto-worktree-merge-stash.test.ts +70 -0
  493. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-shelter.test.ts +52 -0
  494. package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +6 -6
  495. package/src/resources/extensions/gsd/tests/auto-worktree-resource-version.test.ts +59 -0
  496. package/src/resources/extensions/gsd/tests/auto-worktree-untracked-content.test.ts +3 -1
  497. package/src/resources/extensions/gsd/tests/batch-task-query.test.ts +85 -0
  498. package/src/resources/extensions/gsd/tests/check-auto-start-ready-guard.test.ts +29 -0
  499. package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +365 -0
  500. package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +62 -1
  501. package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +1 -1
  502. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +4 -0
  503. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +138 -1
  504. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +571 -5
  505. package/src/resources/extensions/gsd/tests/doctor-workspace.test.ts +207 -0
  506. package/src/resources/extensions/gsd/tests/fast-forward-reused-milestone-branch.test.ts +1 -1
  507. package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +82 -2
  508. package/src/resources/extensions/gsd/tests/flat-phase-renderer.test.ts +25 -1
  509. package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +87 -19
  510. package/src/resources/extensions/gsd/tests/gate-1b-orphan-discrimination.test.ts +89 -0
  511. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +40 -0
  512. package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +9 -0
  513. package/src/resources/extensions/gsd/tests/integration/all-milestones-complete-merge.test.ts +4 -6
  514. package/src/resources/extensions/gsd/tests/integration/auto-stash-merge.test.ts +2 -1
  515. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +3 -3
  516. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +7 -8
  517. package/src/resources/extensions/gsd/tests/integration/feature-branch-lifecycle-integration.test.ts +2 -5
  518. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +76 -0
  519. package/src/resources/extensions/gsd/tests/integration/merge-cwd-restore.test.ts +1 -1
  520. package/src/resources/extensions/gsd/tests/integration/merge-preserve-worktree-on-preteardown-error.test.ts +1 -1
  521. package/src/resources/extensions/gsd/tests/integration/merge-strategy-regular.test.ts +2 -1
  522. package/src/resources/extensions/gsd/tests/integration/milestone-transition-worktree.test.ts +5 -7
  523. package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +4 -2
  524. package/src/resources/extensions/gsd/tests/integration/workspace-collapse-integration.test.ts +2 -4
  525. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +122 -0
  526. package/src/resources/extensions/gsd/tests/merge-closeout-consistency-gate.test.ts +1 -1
  527. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +4 -4
  528. package/src/resources/extensions/gsd/tests/merge-db-cycle.test.ts +1 -1
  529. package/src/resources/extensions/gsd/tests/merge-self-branch-guard.test.ts +1 -1
  530. package/src/resources/extensions/gsd/tests/migrate-external-worktree.test.ts +116 -0
  531. package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +592 -23
  532. package/src/resources/extensions/gsd/tests/milestone-merge-transaction.test.ts +25 -1
  533. package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +1 -1
  534. package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +3 -3
  535. package/src/resources/extensions/gsd/tests/parallel-worker-lock-contention.test.ts +1 -1
  536. package/src/resources/extensions/gsd/tests/pending-autostart-scope.test.ts +2 -2
  537. package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +50 -6
  538. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +17 -0
  539. package/src/resources/extensions/gsd/tests/plan-task.test.ts +264 -1
  540. package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +1 -4
  541. package/src/resources/extensions/gsd/tests/preferences.test.ts +150 -0
  542. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +147 -0
  543. package/src/resources/extensions/gsd/tests/recovery-verify-logs.test.ts +4 -4
  544. package/src/resources/extensions/gsd/tests/redact-secrets.test.ts +56 -0
  545. package/src/resources/extensions/gsd/tests/register-hooks-flat-phase-migration.test.ts +73 -0
  546. package/src/resources/extensions/gsd/tests/register-hooks-loop-guard-auto.test.ts +275 -0
  547. package/src/resources/extensions/gsd/tests/repository-registry.test.ts +41 -2
  548. package/src/resources/extensions/gsd/tests/require-slice-discussion-dispatch.test.ts +55 -0
  549. package/src/resources/extensions/gsd/tests/root-write-leak-guard.test.ts +31 -9
  550. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +20 -0
  551. package/src/resources/extensions/gsd/tests/schedule-wakeup-tool.test.ts +167 -0
  552. package/src/resources/extensions/gsd/tests/stale-worktree-cwd.test.ts +3 -5
  553. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +49 -0
  554. package/src/resources/extensions/gsd/tests/stash-pop-gsd-conflict.test.ts +2 -1
  555. package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +2 -1
  556. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +1 -1
  557. package/src/resources/extensions/gsd/tests/status-per-repo.test.ts +94 -0
  558. package/src/resources/extensions/gsd/tests/steer-worktree-path.test.ts +1 -1
  559. package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +1 -1
  560. package/src/resources/extensions/gsd/tests/system-flat-phase-layout.test.ts +33 -0
  561. package/src/resources/extensions/gsd/tests/teardown-chdir-failure-clears-registry.test.ts +4 -4
  562. package/src/resources/extensions/gsd/tests/teardown-cleanup-parity.test.ts +2 -1
  563. package/src/resources/extensions/gsd/tests/teardown-failure-clears-registry.test.ts +4 -4
  564. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +35 -0
  565. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +166 -0
  566. package/src/resources/extensions/gsd/tests/uat-stuck-loop-orphaned-worktree.test.ts +1 -1
  567. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +66 -18
  568. package/src/resources/extensions/gsd/tests/unit-registry.test.ts +81 -0
  569. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +30 -0
  570. package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +52 -0
  571. package/src/resources/extensions/gsd/tests/validator-scope-parity.test.ts +53 -1
  572. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +208 -1
  573. package/src/resources/extensions/gsd/tests/workspace.test.ts +18 -4
  574. package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +1 -1
  575. package/src/resources/extensions/gsd/tests/worktree-db-respawn-truncation.test.ts +1 -1
  576. package/src/resources/extensions/gsd/tests/worktree-db-same-file.test.ts +1 -3
  577. package/src/resources/extensions/gsd/tests/worktree-expected-warnings.test.ts +1 -1
  578. package/src/resources/extensions/gsd/tests/worktree-git-pathspec.test.ts +1 -1
  579. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +4 -4
  580. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +2 -2
  581. package/src/resources/extensions/gsd/tests/worktree-main-branch.test.ts +1 -1
  582. package/src/resources/extensions/gsd/tests/worktree-preferences-sync.test.ts +1 -1
  583. package/src/resources/extensions/gsd/tests/worktree-reentry.test.ts +2 -1
  584. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +36 -3
  585. package/src/resources/extensions/gsd/tests/worktree-sync-overwrite-loop.test.ts +1 -1
  586. package/src/resources/extensions/gsd/tests/worktree-sync-tasks.test.ts +1 -1
  587. package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +32 -0
  588. package/src/resources/extensions/gsd/tool-contract.ts +29 -0
  589. package/src/resources/extensions/gsd/tools/plan-task.ts +107 -9
  590. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +58 -0
  591. package/src/resources/extensions/gsd/unit-context-manifest.ts +11 -5
  592. package/src/resources/extensions/gsd/unit-registry.ts +48 -2
  593. package/src/resources/extensions/gsd/unit-runtime.ts +42 -0
  594. package/src/resources/extensions/gsd/unmerged-milestone-guard.ts +1 -1
  595. package/src/resources/extensions/gsd/validation-block-guard.ts +2 -1
  596. package/src/resources/extensions/gsd/workspace-git-preflight.ts +2 -2
  597. package/src/resources/extensions/gsd/workspace.ts +42 -8
  598. package/src/resources/extensions/gsd/worktree-command.ts +1 -1
  599. package/src/resources/extensions/gsd/worktree-lifecycle.ts +154 -26
  600. package/src/resources/extensions/gsd/worktree-manager.ts +143 -5
  601. package/src/resources/extensions/gsd/worktree-reentry.ts +2 -1
  602. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-49f565245e1e4afe.js +0 -1
  603. package/dist/web/standalone/.next/static/chunks/app/page-bc4c723c6a19c6f0.js +0 -1
  604. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ec3eaffc9785ba48.js +0 -1
  605. /package/dist/web/standalone/.next/static/{zQLcXm0Za8lexoXtgDpMG → ZpFDazP-38PXBPiI_LdZf}/_buildManifest.js +0 -0
  606. /package/dist/web/standalone/.next/static/{zQLcXm0Za8lexoXtgDpMG → ZpFDazP-38PXBPiI_LdZf}/_ssgManifest.js +0 -0
@@ -722,3 +722,368 @@ test("ensureCodebaseMapFresh: uses TTL cache before enumerating files", () => {
722
722
  cleanup(base);
723
723
  }
724
724
  });
725
+
726
+ // ─── Workspace-aware (parent mode) ───────────────────────────────────────
727
+
728
+ /**
729
+ * Build a parent workspace: a parent git repo whose .gsd/PREFERENCES.md declares
730
+ * child repositories, each child being its own separate git repo nested inside.
731
+ */
732
+ function makeTmpParentWorkspace(children: string[]): string {
733
+ const base = join(tmpdir(), `gsd-codebase-parent-${randomUUID()}`);
734
+ mkdirSync(join(base, ".gsd"), { recursive: true });
735
+ execSync("git init", { cwd: base, stdio: "ignore" });
736
+
737
+ const repoLines = children.map((id) => ` ${id}:\n path: ${id}`).join("\n");
738
+ writeFileSync(
739
+ join(base, ".gsd", "PREFERENCES.md"),
740
+ `---\nversion: 1\nworkspace:\n mode: parent\n repositories:\n${repoLines}\n---\n`,
741
+ "utf-8",
742
+ );
743
+
744
+ for (const child of children) {
745
+ const childPath = join(base, child);
746
+ mkdirSync(childPath, { recursive: true });
747
+ execSync("git init", { cwd: childPath, stdio: "ignore" });
748
+ }
749
+ return base;
750
+ }
751
+
752
+ function addChildFile(base: string, child: string, path: string, content = ""): void {
753
+ const childRoot = join(base, child);
754
+ const fullPath = join(childRoot, path);
755
+ mkdirSync(join(fullPath, ".."), { recursive: true });
756
+ writeFileSync(fullPath, content || `// ${child}/${path}\n`, "utf-8");
757
+ execSync(`git add "${path}"`, { cwd: childRoot, stdio: "ignore" });
758
+ }
759
+
760
+ test("workspace-aware: parent mode enumerates each declared child repo under a repo heading", () => {
761
+ const base = makeTmpParentWorkspace(["frontend", "backend"]);
762
+ try {
763
+ addChildFile(base, "frontend", "src/App.tsx");
764
+ addChildFile(base, "backend", "src/server.ts");
765
+
766
+ const result = generateCodebaseMap(base);
767
+
768
+ // Both repos appear as labelled sections.
769
+ assert.match(result.content, /## \[frontend\]/);
770
+ assert.match(result.content, /## \[backend\]/);
771
+ // Child files are rewritten to workspace-relative paths.
772
+ assert.match(result.content, /`frontend\/src\/App\.tsx`/);
773
+ assert.match(result.content, /`backend\/src\/server\.ts`/);
774
+ assert.equal(result.fileCount, 2);
775
+ } finally {
776
+ cleanup(base);
777
+ }
778
+ });
779
+
780
+ test("workspace-aware: metadata records the repositories whose files appear in the map", () => {
781
+ const base = makeTmpParentWorkspace(["frontend", "backend"]);
782
+ try {
783
+ addChildFile(base, "frontend", "src/App.tsx");
784
+ addChildFile(base, "backend", "src/server.ts");
785
+
786
+ const result = generateCodebaseMap(base);
787
+ const metadata = parseCodebaseMapMetadata(result.content);
788
+
789
+ assert.ok(metadata, "metadata should be present");
790
+ assert.deepEqual(metadata?.repositories?.sort(), ["backend", "frontend"]);
791
+ } finally {
792
+ cleanup(base);
793
+ }
794
+ });
795
+
796
+ test("workspace-aware: parseCodebaseMap recovers descriptions across repo sections", () => {
797
+ const base = makeTmpParentWorkspace(["frontend", "backend"]);
798
+ try {
799
+ addChildFile(base, "frontend", "src/App.tsx");
800
+ addChildFile(base, "backend", "src/server.ts");
801
+
802
+ // Seed descriptions keyed by the workspace-relative paths.
803
+ const descriptions = new Map<string, string>([
804
+ ["frontend/src/App.tsx", "React entry"],
805
+ ["backend/src/server.ts", "Express API"],
806
+ ]);
807
+ const result = generateCodebaseMap(base, undefined, descriptions);
808
+ writeCodebaseMap(base, result.content);
809
+
810
+ const parsed = parseCodebaseMap(readCodebaseMap(base)!);
811
+ assert.equal(parsed.get("frontend/src/App.tsx"), "React entry");
812
+ assert.equal(parsed.get("backend/src/server.ts"), "Express API");
813
+ } finally {
814
+ cleanup(base);
815
+ }
816
+ });
817
+
818
+ test("workspace-aware: project mode (no declared children) stays single-section", () => {
819
+ // A plain single repo with no workspace config must render exactly as before.
820
+ const base = makeTmpRepo();
821
+ try {
822
+ addFile(base, "src/main.ts");
823
+
824
+ const result = generateCodebaseMap(base);
825
+
826
+ assert.doesNotMatch(result.content, /## \[/);
827
+ assert.match(result.content, /`src\/main\.ts`/);
828
+ const metadata = parseCodebaseMapMetadata(result.content);
829
+ assert.equal(metadata?.repositories, undefined);
830
+ } finally {
831
+ cleanup(base);
832
+ }
833
+ });
834
+
835
+ test("workspace-aware: updateCodebaseMap tracks child-repo file additions", () => {
836
+ const base = makeTmpParentWorkspace(["frontend"]);
837
+ try {
838
+ addChildFile(base, "frontend", "src/App.tsx");
839
+ const first = updateCodebaseMap(base);
840
+ writeCodebaseMap(base, first.content);
841
+ assert.equal(first.added, 1);
842
+
843
+ addChildFile(base, "frontend", "src/index.tsx");
844
+ const second = updateCodebaseMap(base);
845
+ assert.equal(second.added, 1);
846
+ assert.equal(second.removed, 0);
847
+ assert.equal(second.fileCount, 2);
848
+ } finally {
849
+ cleanup(base);
850
+ }
851
+ });
852
+
853
+ test("workspace-aware: workspace-relative exclude patterns filter child-repo files", () => {
854
+ // Regression guard: exclude patterns like `frontend/` are workspace-relative,
855
+ // so they must be matched against the rewritten path, not the child-relative one.
856
+ const base = makeTmpParentWorkspace(["frontend", "backend"]);
857
+ try {
858
+ addChildFile(base, "frontend", "src/App.tsx");
859
+ addChildFile(base, "backend", "src/server.ts");
860
+
861
+ const result = generateCodebaseMap(base, { excludePatterns: ["frontend/"] });
862
+
863
+ assert.doesNotMatch(result.content, /frontend\/src\/App\.tsx/);
864
+ assert.match(result.content, /backend\/src\/server\.ts/);
865
+ assert.equal(result.fileCount, 1);
866
+ } finally {
867
+ cleanup(base);
868
+ }
869
+ });
870
+
871
+ test("workspace-aware: maxFiles cap does not starve child repos for the project repo", () => {
872
+ // The implicit project repo is enumerated alongside children; the cap must be
873
+ // applied fairly (round-robin) so a large project repo cannot crowd out children.
874
+ const base = makeTmpParentWorkspace(["frontend", "backend"]);
875
+ try {
876
+ addChildFile(base, "frontend", "a.ts");
877
+ addChildFile(base, "frontend", "b.ts");
878
+ addChildFile(base, "backend", "c.ts");
879
+
880
+ // Cap at 2 files — with fair distribution both repos should appear.
881
+ const result = generateCodebaseMap(base, { maxFiles: 2 });
882
+ const repoSections = (result.content.match(/^## \[.+\]/gm) ?? []).length;
883
+
884
+ assert.equal(result.fileCount, 2);
885
+ assert.ok(repoSections >= 2, "both child repos should be represented under a tight cap");
886
+ } finally {
887
+ cleanup(base);
888
+ }
889
+ });
890
+
891
+ test("workspace-aware: overlapping paths dedupe without falsely reporting truncation", () => {
892
+ // Regression guard: a path tracked by both the implicit project repo and a child
893
+ // repo collapses to one workspace-relative entry. Deduplicated duplicates must not
894
+ // count toward the maxFiles cap, so the map must not be flagged as truncated.
895
+ const base = join(tmpdir(), `gsd-codebase-parent-${randomUUID()}`);
896
+ mkdirSync(join(base, ".gsd"), { recursive: true });
897
+ execSync("git init", { cwd: base, stdio: "ignore" });
898
+ writeFileSync(
899
+ join(base, ".gsd", "PREFERENCES.md"),
900
+ `---\nversion: 1\nworkspace:\n mode: parent\n repositories:\n lib:\n path: lib\n---\n`,
901
+ "utf-8",
902
+ );
903
+ try {
904
+ // The project repo tracks lib/util.ts before lib becomes its own repo; the child
905
+ // repo then tracks util.ts, so both resolve to the same workspace path lib/util.ts.
906
+ addFile(base, "lib/util.ts");
907
+ execSync("git init", { cwd: join(base, "lib"), stdio: "ignore" });
908
+ execSync("git add util.ts", { cwd: join(base, "lib"), stdio: "ignore" });
909
+
910
+ const result = generateCodebaseMap(base);
911
+
912
+ assert.equal(result.fileCount, 1);
913
+ assert.equal(result.truncated, false);
914
+ assert.equal((result.content.match(/`lib\/util\.ts`/g) ?? []).length, 1);
915
+ } finally {
916
+ cleanup(base);
917
+ }
918
+ });
919
+
920
+ test("workspace-aware: project directories interleaving child prefixes stay under one heading", () => {
921
+ // Regression guard: the implicit project repo has an empty prefix, so its
922
+ // root-level dirs (aaa/, zzz/) sort lexically around a child prefix (mmm/).
923
+ // Groups must be ordered per repo so `## [project]` is emitted exactly once.
924
+ const base = makeTmpParentWorkspace(["mmm"]);
925
+ try {
926
+ addFile(base, "aaa/x.ts"); // project repo, sorts before "mmm"
927
+ addFile(base, "zzz/y.ts"); // project repo, sorts after "mmm"
928
+ addChildFile(base, "mmm", "src/thing.ts");
929
+
930
+ const result = generateCodebaseMap(base);
931
+
932
+ const projectHeadings = (result.content.match(/^## \[project\]$/gm) ?? []).length;
933
+ const mmmHeadings = (result.content.match(/^## \[mmm\]$/gm) ?? []).length;
934
+ const allHeadings = (result.content.match(/^## \[.+\]$/gm) ?? []).length;
935
+
936
+ assert.equal(projectHeadings, 1, "project section must not be split across headings");
937
+ assert.equal(mmmHeadings, 1);
938
+ assert.equal(allHeadings, 2);
939
+ } finally {
940
+ cleanup(base);
941
+ }
942
+ });
943
+
944
+ test("workspace-aware: renaming a declared repo id invalidates map freshness", () => {
945
+ // Regression guard: repo identity is rendered into the map, so renaming a repo id
946
+ // (path unchanged → identical file paths) must be caught by the freshness
947
+ // fingerprint rather than leaving a stale `## [old-id]` heading in place.
948
+ const base = makeTmpParentWorkspace(["frontend"]);
949
+ try {
950
+ addChildFile(base, "frontend", "src/App.tsx");
951
+
952
+ ensureCodebaseMapFresh(base, undefined, { ttlMs: 0, force: true });
953
+ assert.match(readCodebaseMap(base)!, /^## \[frontend\]$/m);
954
+
955
+ // Rename the repo id to `web`; the path (and therefore the file paths) is unchanged.
956
+ writeFileSync(
957
+ join(base, ".gsd", "PREFERENCES.md"),
958
+ `---\nversion: 1\nworkspace:\n mode: parent\n repositories:\n web:\n path: frontend\n---\n`,
959
+ "utf-8",
960
+ );
961
+
962
+ const refreshed = ensureCodebaseMapFresh(base, undefined, { ttlMs: 0, force: true });
963
+ const written = readCodebaseMap(base)!;
964
+
965
+ assert.equal(refreshed.status, "updated");
966
+ assert.match(written, /^## \[web\]$/m);
967
+ assert.doesNotMatch(written, /^## \[frontend\]$/m);
968
+ assert.deepEqual(parseCodebaseMapMetadata(written)?.repositories, ["web"]);
969
+ } finally {
970
+ cleanup(base);
971
+ }
972
+ });
973
+
974
+ test("single-repo: directory order stays byte-identical code-unit sort (not locale-aware)", () => {
975
+ // Byte-identical single-repo invariant: pre-workspace output ordered
976
+ // directories with a bare `.sort()` (UTF-16 code-unit order), so uppercase
977
+ // sorts before lowercase ("Zoo" < "apple"). A locale-aware comparator inverts
978
+ // these and silently changes project-mode CODEBASE.md, so guard the ordering.
979
+ const base = makeTmpRepo();
980
+ try {
981
+ addFile(base, "Zoo/keeper.ts"); // 'Z' (0x5A) < 'a' (0x61) → sorts first
982
+ addFile(base, "apple/tree.ts");
983
+
984
+ const content = generateCodebaseMap(base).content;
985
+ const zooIdx = content.indexOf("### Zoo/");
986
+ const appleIdx = content.indexOf("### apple/");
987
+
988
+ assert.notEqual(zooIdx, -1);
989
+ assert.notEqual(appleIdx, -1);
990
+ assert.ok(zooIdx < appleIdx, "code-unit order must place Zoo/ before apple/");
991
+ // Project mode emits no repo partition heading.
992
+ assert.doesNotMatch(content, /^## \[.+\]$/m);
993
+ } finally {
994
+ cleanup(base);
995
+ }
996
+ });
997
+
998
+ test("workspace-aware: an invalid workspace registry surfaces an error instead of silently falling back", () => {
999
+ // Regression guard: a broken parent-mode config (here a child path escaping the
1000
+ // project root) must propagate as an error. Swallowing it and falling back to a
1001
+ // single-root map would silently drop every child repo from planning context.
1002
+ const base = makeTmpRepo();
1003
+ try {
1004
+ addFile(base, "src/main.ts");
1005
+ writeFileSync(
1006
+ join(base, ".gsd", "PREFERENCES.md"),
1007
+ `---\nversion: 1\nworkspace:\n mode: parent\n repositories:\n frontend:\n path: ../escapes-root\n---\n`,
1008
+ "utf-8",
1009
+ );
1010
+
1011
+ assert.throws(() => generateCodebaseMap(base), /resolves outside project root/);
1012
+ } finally {
1013
+ cleanup(base);
1014
+ }
1015
+ });
1016
+
1017
+ test("workspace-aware: files sharing a directory across repos keep their own repo heading", () => {
1018
+ // Regression guard: the implicit project repo and a child repo can own different
1019
+ // files under the same workspace-relative directory (lib/). Groups are keyed by
1020
+ // (repo, dir), so each file must render under its own `## [repo-id]` heading
1021
+ // instead of collapsing into one section labelled with a single (wrong) repo.
1022
+ const base = join(tmpdir(), `gsd-codebase-parent-${randomUUID()}`);
1023
+ mkdirSync(join(base, ".gsd"), { recursive: true });
1024
+ execSync("git init", { cwd: base, stdio: "ignore" });
1025
+ writeFileSync(
1026
+ join(base, ".gsd", "PREFERENCES.md"),
1027
+ `---\nversion: 1\nworkspace:\n mode: parent\n repositories:\n lib:\n path: lib\n---\n`,
1028
+ "utf-8",
1029
+ );
1030
+ try {
1031
+ // Project repo tracks lib/app.ts before lib becomes its own repo; the child
1032
+ // repo then tracks helper.ts → workspace path lib/helper.ts. Different files,
1033
+ // same directory, different repos.
1034
+ addFile(base, "lib/app.ts");
1035
+ execSync("git init", { cwd: join(base, "lib"), stdio: "ignore" });
1036
+ writeFileSync(join(base, "lib", "helper.ts"), "// helper\n", "utf-8");
1037
+ execSync("git add helper.ts", { cwd: join(base, "lib"), stdio: "ignore" });
1038
+
1039
+ const content = generateCodebaseMap(base).content;
1040
+
1041
+ // Both files present, each under its own repo section (not merged under one).
1042
+ assert.match(content, /## \[project\]/);
1043
+ assert.match(content, /## \[lib\]/);
1044
+ const projectIdx = content.indexOf("## [project]");
1045
+ const appIdx = content.indexOf("`lib/app.ts`");
1046
+ const libIdx = content.indexOf("## [lib]");
1047
+ const helperIdx = content.indexOf("`lib/helper.ts`");
1048
+ assert.ok(
1049
+ projectIdx < appIdx && appIdx < libIdx && libIdx < helperIdx,
1050
+ "lib/app.ts must sit under [project] and lib/helper.ts under [lib]",
1051
+ );
1052
+ } finally {
1053
+ cleanup(base);
1054
+ }
1055
+ });
1056
+
1057
+ test("ensureCodebaseMapFresh: editing declared repos within the TTL window bypasses the cache", () => {
1058
+ // Regression guard: the freshness TTL cache key folds in the workspace signature
1059
+ // (mode + declared repos). Adding a child repo must miss the cache and re-enumerate
1060
+ // rather than serve a stale map that omits the new repo until the TTL expires.
1061
+ const base = makeTmpParentWorkspace(["frontend"]);
1062
+ try {
1063
+ addChildFile(base, "frontend", "src/App.tsx");
1064
+
1065
+ const initial = ensureCodebaseMapFresh(base, undefined, { ttlMs: 60_000 });
1066
+ assert.equal(initial.status, "generated");
1067
+ assert.doesNotMatch(readCodebaseMap(base)!, /## \[backend\]/);
1068
+
1069
+ // Declare a second child repo and back it with a real nested repo + file.
1070
+ mkdirSync(join(base, "backend"), { recursive: true });
1071
+ execSync("git init", { cwd: join(base, "backend"), stdio: "ignore" });
1072
+ addChildFile(base, "backend", "src/server.ts");
1073
+ writeFileSync(
1074
+ join(base, ".gsd", "PREFERENCES.md"),
1075
+ `---\nversion: 1\nworkspace:\n mode: parent\n repositories:\n frontend:\n path: frontend\n backend:\n path: backend\n---\n`,
1076
+ "utf-8",
1077
+ );
1078
+
1079
+ // Same TTL window, no force: the changed workspace signature must miss the cache.
1080
+ const refreshed = ensureCodebaseMapFresh(base, undefined, { ttlMs: 60_000 });
1081
+ const written = readCodebaseMap(base)!;
1082
+
1083
+ assert.equal(refreshed.status, "updated");
1084
+ assert.match(written, /## \[backend\]/);
1085
+ assert.match(written, /`backend\/src\/server\.ts`/);
1086
+ } finally {
1087
+ cleanup(base);
1088
+ }
1089
+ });
@@ -12,7 +12,14 @@ import { tmpdir } from "node:os";
12
12
 
13
13
  import { buildSliceSummaryExcerpt, buildCompleteMilestonePrompt, buildValidateMilestonePrompt } from "../auto-prompts.ts";
14
14
  import { invalidateAllCaches } from "../cache.ts";
15
- import { closeDatabase, insertMilestone, openDatabase } from "../gsd-db.ts";
15
+ import {
16
+ closeDatabase,
17
+ insertGateRow,
18
+ insertMilestone,
19
+ insertSlice,
20
+ openDatabase,
21
+ saveGateResult,
22
+ } from "../gsd-db.ts";
16
23
 
17
24
  // ─── Fixture helpers ──────────────────────────────────────────────────────
18
25
 
@@ -366,6 +373,60 @@ test("validate-milestone prompt uses slice excerpts and on-demand paths instead
366
373
  );
367
374
  });
368
375
 
376
+ test("validate-milestone prompt inlines persisted slice-level Q3/Q4 gate flags", async (t) => {
377
+ const base = createBase();
378
+ t.after(() => {
379
+ try { closeDatabase(); } catch { /* ignore */ }
380
+ cleanup(base);
381
+ });
382
+ invalidateAllCaches();
383
+
384
+ openDatabase(join(base, ".gsd", "gsd.db"));
385
+ insertMilestone({ id: "M001", title: "Test Milestone", status: "active" });
386
+ insertSlice({ id: "S01", milestoneId: "M001", title: "Risky Slice", status: "complete" });
387
+ insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q3", scope: "slice" });
388
+ insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q4", scope: "slice" });
389
+ insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q8", scope: "slice" });
390
+ saveGateResult({
391
+ milestoneId: "M001",
392
+ sliceId: "S01",
393
+ gateId: "Q3",
394
+ verdict: "flag",
395
+ rationale: "New callback boundary.",
396
+ findings: "Re-check token exposure in the web callback.",
397
+ });
398
+ saveGateResult({
399
+ milestoneId: "M001",
400
+ sliceId: "S01",
401
+ gateId: "Q4",
402
+ verdict: "flag",
403
+ rationale: "Requirement touched but not re-tested.",
404
+ findings: "R012 must be re-tested; revisit decision D-3.",
405
+ });
406
+ saveGateResult({
407
+ milestoneId: "M001",
408
+ sliceId: "S01",
409
+ gateId: "Q8",
410
+ verdict: "flag",
411
+ rationale: "Operational readiness gap.",
412
+ findings: "Operational finding should not be milestone validation input.",
413
+ });
414
+ writeRoadmap(base, makeRoadmap());
415
+ writeSummary(base, "S01", makeFatSummary("S01"));
416
+
417
+ const prompt = await buildValidateMilestonePrompt("M001", "Test Milestone", base);
418
+
419
+ assert.match(prompt, /### Persisted Slice-Level Gate Flags \(from quality_gates\)/);
420
+ assert.match(prompt, /S01 \/ Q3 \(Threat Surface\) \/ flag/);
421
+ assert.match(prompt, /Re-check token exposure in the web callback\./);
422
+ assert.match(prompt, /S01 \/ Q4 \(Requirement Impact\) \/ flag/);
423
+ assert.match(prompt, /R012 must be re-tested; revisit decision D-3\./);
424
+ assert.ok(
425
+ !prompt.includes("Operational finding should not be milestone validation input."),
426
+ "validate-milestone should not inline unrelated Q8 gate findings",
427
+ );
428
+ });
429
+
369
430
  test("validate-milestone prompt inlines planned verification classes as canonical rows", async (t) => {
370
431
  const base = createBase();
371
432
  t.after(() => {
@@ -7,7 +7,7 @@ import assert from "node:assert/strict";
7
7
  import { readFileSync, mkdtempSync, mkdirSync, writeFileSync, existsSync, cpSync, rmSync } from "node:fs";
8
8
  import { join } from "node:path";
9
9
  import { tmpdir } from "node:os";
10
- import { syncStateToProjectRoot } from "../auto-worktree.ts";
10
+ import { syncStateToProjectRoot } from "../auto-worktree-sync.ts";
11
11
 
12
12
  test("#2313: syncStateToProjectRoot copies metrics and completed-units to the project root", () => {
13
13
  const root = mkdtempSync(join(tmpdir(), "gsd-sync-metrics-"));
@@ -1034,6 +1034,10 @@ describe('derive-state-db', async () => {
1034
1034
 
1035
1035
  assert.deepStrictEqual(dbState.phase, 'replanning-slice', 'replan-db: phase is replanning-slice');
1036
1036
  assert.deepStrictEqual(dbState.phase, fileState.phase, 'replan-db: phase matches filesystem');
1037
+ assert.ok(
1038
+ Object.hasOwn(dbState, 'activeWorkspace'),
1039
+ 'replan-db: state preserves explicit activeWorkspace field for auto-loop consumers',
1040
+ );
1037
1041
 
1038
1042
  closeDatabase();
1039
1043
  } finally {
@@ -1014,6 +1014,143 @@ test("runProviderChecks detects claude.exe in PATH on Windows (#4548)", { skip:
1014
1014
  });
1015
1015
  });
1016
1016
 
1017
+
1018
+ test("runProviderChecks reports error for required cursor-agent when binary is missing", () => {
1019
+ const repo = realpathSync(mkdtempSync(join(tmpdir(), "gsd-providers-cursor-repo-")));
1020
+ mkdirSync(join(repo, ".gsd"), { recursive: true });
1021
+ writeFileSync(
1022
+ join(repo, ".gsd", "PREFERENCES.md"),
1023
+ [
1024
+ "---",
1025
+ "models:",
1026
+ " execution:",
1027
+ " model: composer-2.5",
1028
+ " provider: cursor-agent",
1029
+ "---",
1030
+ "",
1031
+ ].join("\n"),
1032
+ );
1033
+
1034
+ const tmpHome = realpathSync(mkdtempSync(join(tmpdir(), "gsd-providers-cursor-home-")));
1035
+
1036
+ withEnv({
1037
+ HOME: tmpHome,
1038
+ PATH: tmpHome,
1039
+ CURSOR_API_KEY: undefined,
1040
+ }, () => {
1041
+ withCwd(repo, () => {
1042
+ const results = runProviderChecks();
1043
+ const cursor = results.find(r => r.name === "cursor-agent");
1044
+ assert.ok(cursor, "cursor-agent result should exist");
1045
+ assert.equal(cursor!.status, "error", "cursor-agent should error when the CLI binary is missing");
1046
+ assert.ok(cursor!.detail?.includes("Cursor Agent"), "should explain Cursor Agent must be installed");
1047
+ });
1048
+ });
1049
+
1050
+ rmSync(repo, { recursive: true, force: true });
1051
+ rmSync(tmpHome, { recursive: true, force: true });
1052
+ });
1053
+
1054
+ test("runProviderChecks does not route OpenAI via unauthenticated cursor-agent binary in PATH", () => {
1055
+ const repo = realpathSync(mkdtempSync(join(tmpdir(), "gsd-providers-cursor-route-repo-")));
1056
+ mkdirSync(join(repo, ".gsd"), { recursive: true });
1057
+ writeFileSync(
1058
+ join(repo, ".gsd", "PREFERENCES.md"),
1059
+ [
1060
+ "---",
1061
+ "models:",
1062
+ " execution: gpt-5.5",
1063
+ "---",
1064
+ "",
1065
+ ].join("\n"),
1066
+ );
1067
+
1068
+ const tmpHome = realpathSync(mkdtempSync(join(tmpdir(), "gsd-providers-cursor-route-home-")));
1069
+ const binDir = join(tmpHome, "bin");
1070
+ mkdirSync(binDir, { recursive: true });
1071
+ const fakeCursor = join(binDir, "cursor-agent");
1072
+ writeFileSync(fakeCursor, [
1073
+ "#!/bin/sh",
1074
+ "if [ \"$1\" = \"status\" ]; then echo \"Not logged in\"; exit 0; fi",
1075
+ "echo mock",
1076
+ "",
1077
+ ].join("\n"));
1078
+ chmodSync(fakeCursor, 0o755);
1079
+
1080
+ withEnv({
1081
+ HOME: tmpHome,
1082
+ OPENAI_API_KEY: undefined,
1083
+ COPILOT_GITHUB_TOKEN: undefined,
1084
+ GH_TOKEN: undefined,
1085
+ GITHUB_TOKEN: undefined,
1086
+ PATH: `${binDir}${delimiter}${process.env.PATH ?? ""}`,
1087
+ }, () => {
1088
+ try {
1089
+ withCwd(repo, () => {
1090
+ const results = runProviderChecks();
1091
+ const openai = results.find(r => r.name === "openai");
1092
+ assert.ok(openai, "openai result should exist");
1093
+ assert.equal(openai!.status, "error", "binary-only cursor-agent must not satisfy OpenAI routing");
1094
+ assert.ok(openai!.detail?.includes("OPENAI_API_KEY"), "should still tell the user how to configure OpenAI");
1095
+ });
1096
+ } finally {
1097
+ rmSync(repo, { recursive: true, force: true });
1098
+ rmSync(tmpHome, { recursive: true, force: true });
1099
+ }
1100
+ });
1101
+ });
1102
+
1103
+ test("runProviderChecks routes OpenAI via authenticated cursor-agent CLI", () => {
1104
+ const repo = realpathSync(mkdtempSync(join(tmpdir(), "gsd-providers-cursor-auth-route-repo-")));
1105
+ mkdirSync(join(repo, ".gsd"), { recursive: true });
1106
+ writeFileSync(
1107
+ join(repo, ".gsd", "PREFERENCES.md"),
1108
+ [
1109
+ "---",
1110
+ "models:",
1111
+ " execution: gpt-5.5",
1112
+ "---",
1113
+ "",
1114
+ ].join("\n"),
1115
+ );
1116
+
1117
+ const tmpHome = realpathSync(mkdtempSync(join(tmpdir(), "gsd-providers-cursor-auth-route-home-")));
1118
+ const binDir = join(tmpHome, "bin");
1119
+ mkdirSync(binDir, { recursive: true });
1120
+ const fakeCursor = join(binDir, "cursor-agent");
1121
+ writeFileSync(fakeCursor, [
1122
+ "#!/bin/sh",
1123
+ "if [ \"$1\" = \"--version\" ]; then echo cursor-agent 1.0; exit 0; fi",
1124
+ "if [ \"$1\" = \"status\" ]; then echo \"Authenticated as user@example.com\"; exit 0; fi",
1125
+ "echo mock",
1126
+ "",
1127
+ ].join("\n"));
1128
+ chmodSync(fakeCursor, 0o755);
1129
+
1130
+ withEnv({
1131
+ HOME: tmpHome,
1132
+ OPENAI_API_KEY: undefined,
1133
+ COPILOT_GITHUB_TOKEN: undefined,
1134
+ GH_TOKEN: undefined,
1135
+ GITHUB_TOKEN: undefined,
1136
+ CURSOR_API_KEY: undefined,
1137
+ PATH: `${binDir}${delimiter}${process.env.PATH ?? ""}`,
1138
+ }, () => {
1139
+ try {
1140
+ withCwd(repo, () => {
1141
+ const results = runProviderChecks();
1142
+ const openai = results.find(r => r.name === "openai");
1143
+ assert.ok(openai, "openai result should exist");
1144
+ assert.equal(openai!.status, "ok", "authenticated cursor-agent should satisfy OpenAI routing");
1145
+ assert.ok(openai!.message.toLowerCase().includes("cursor"), "should mention cursor-agent as source");
1146
+ });
1147
+ } finally {
1148
+ rmSync(repo, { recursive: true, force: true });
1149
+ rmSync(tmpHome, { recursive: true, force: true });
1150
+ }
1151
+ });
1152
+ });
1153
+
1017
1154
  test("PROVIDER_ROUTES includes google-antigravity and google-gemini-cli as routes for google (#2922)", async () => {
1018
1155
  const { readFileSync: readFS } = await import("node:fs");
1019
1156
  const { dirname: dirn, join: joinPath } = await import("node:path");
@@ -1022,7 +1159,7 @@ test("PROVIDER_ROUTES includes google-antigravity and google-gemini-cli as route
1022
1159
  const src = readFS(joinPath(__dir, "..", "doctor-providers.ts"), "utf-8");
1023
1160
 
1024
1161
  assert.ok(
1025
- src.includes('google: ["google-antigravity", "google-gemini-cli"]'),
1162
+ src.includes('google: ["google-antigravity", "google-gemini-cli", "cursor-agent"]'),
1026
1163
  'PROVIDER_ROUTES must prefer "google-antigravity" over "google-gemini-cli" for google (#2922)',
1027
1164
  );
1028
1165
  });