@opengsd/gsd-pi 1.4.0 → 1.5.0-dev.4fb2d460

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