@opengsd/gsd-pi 1.8.1 → 1.9.0-dev.5c1a3ff2

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 (546) hide show
  1. package/README.md +10 -8
  2. package/dist/cli.js +5 -1
  3. package/dist/headless-events.d.ts +2 -1
  4. package/dist/headless-events.js +11 -3
  5. package/dist/headless-milestone-readiness.d.ts +29 -0
  6. package/dist/headless-milestone-readiness.js +161 -0
  7. package/dist/headless.js +25 -2
  8. package/dist/print-mode-exit.d.ts +12 -0
  9. package/dist/print-mode-exit.js +14 -0
  10. package/dist/resources/.managed-resources-content-hash +1 -1
  11. package/dist/resources/GSD-WORKFLOW.md +18 -49
  12. package/dist/resources/extensions/browser-tools/capture.js +2 -77
  13. package/dist/resources/extensions/browser-tools/screenshot-constraints.js +83 -0
  14. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +17 -2
  15. package/dist/resources/extensions/claude-code-cli/turn-assembler.js +30 -2
  16. package/dist/resources/extensions/gsd/artifact-verification.js +3 -4
  17. package/dist/resources/extensions/gsd/auto-artifact-paths.js +16 -10
  18. package/dist/resources/extensions/gsd/auto-dispatch.js +74 -19
  19. package/dist/resources/extensions/gsd/auto-post-unit.js +4 -0
  20. package/dist/resources/extensions/gsd/auto-prompts.js +125 -18
  21. package/dist/resources/extensions/gsd/auto-recovery.js +10 -5
  22. package/dist/resources/extensions/gsd/auto-worktree-cleanup.js +4 -0
  23. package/dist/resources/extensions/gsd/auto-worktree-teardown.js +1 -1
  24. package/dist/resources/extensions/gsd/auto.js +5 -1
  25. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +80 -4
  26. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +31 -5
  27. package/dist/resources/extensions/gsd/bootstrap/system-context.js +10 -3
  28. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +88 -50
  29. package/dist/resources/extensions/gsd/command-feedback.js +16 -12
  30. package/dist/resources/extensions/gsd/compat/compat-marker.js +19 -2
  31. package/dist/resources/extensions/gsd/constants.js +12 -13
  32. package/dist/resources/extensions/gsd/context-masker.js +97 -21
  33. package/dist/resources/extensions/gsd/db/command-queue.js +7 -2
  34. package/dist/resources/extensions/gsd/db/engine.js +51 -16
  35. package/dist/resources/extensions/gsd/db/writers/cascades.js +5 -1
  36. package/dist/resources/extensions/gsd/db/writers/status.js +13 -3
  37. package/dist/resources/extensions/gsd/db-base-schema.js +28 -0
  38. package/dist/resources/extensions/gsd/db-migration-steps.js +30 -0
  39. package/dist/resources/extensions/gsd/db-schema-metadata.js +4 -1
  40. package/dist/resources/extensions/gsd/docs/preferences-reference.md +26 -4
  41. package/dist/resources/extensions/gsd/doctor-engine-checks.js +3 -6
  42. package/dist/resources/extensions/gsd/flat-phase-migration.js +156 -21
  43. package/dist/resources/extensions/gsd/git-service.js +19 -7
  44. package/dist/resources/extensions/gsd/gsd-db.js +187 -45
  45. package/dist/resources/extensions/gsd/guided-flow.js +38 -13
  46. package/dist/resources/extensions/gsd/markdown-renderer.js +17 -13
  47. package/dist/resources/extensions/gsd/md-importer.js +107 -20
  48. package/dist/resources/extensions/gsd/migrate/command.js +19 -162
  49. package/dist/resources/extensions/gsd/migrate/execution.js +98 -0
  50. package/dist/resources/extensions/gsd/migrate/plan.js +49 -0
  51. package/dist/resources/extensions/gsd/migrate/planning-writer.js +12 -17
  52. package/dist/resources/extensions/gsd/migrate/presentation.js +64 -0
  53. package/dist/resources/extensions/gsd/model-cost-table.js +2 -0
  54. package/dist/resources/extensions/gsd/model-router.js +11 -0
  55. package/dist/resources/extensions/gsd/parallel-eligibility.js +5 -4
  56. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +28 -43
  57. package/dist/resources/extensions/gsd/paths.js +55 -11
  58. package/dist/resources/extensions/gsd/phase-anchor.js +7 -2
  59. package/dist/resources/extensions/gsd/planning-subagent-policy.js +37 -0
  60. package/dist/resources/extensions/gsd/planning-subagent-registry.js +25 -0
  61. package/dist/resources/extensions/gsd/post-execution-checks.js +4 -4
  62. package/dist/resources/extensions/gsd/preferences-types.js +5 -0
  63. package/dist/resources/extensions/gsd/preferences-validation.js +48 -1
  64. package/dist/resources/extensions/gsd/preferences.js +17 -0
  65. package/dist/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  66. package/dist/resources/extensions/gsd/provider-payload-policy.js +16 -5
  67. package/dist/resources/extensions/gsd/safety/destructive-guard.js +1 -1
  68. package/dist/resources/extensions/gsd/safety/evidence-collector.js +26 -1
  69. package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +30 -5
  70. package/dist/resources/extensions/gsd/skill-activation.js +17 -3
  71. package/dist/resources/extensions/gsd/state-reconciliation/drift/external-markdown-edit.js +27 -13
  72. package/dist/resources/extensions/gsd/state-reconciliation/drift/external-planning-edit.js +13 -3
  73. package/dist/resources/extensions/gsd/stop-notice.js +15 -1
  74. package/dist/resources/extensions/gsd/sync-lock.js +13 -7
  75. package/dist/resources/extensions/gsd/templates/PREFERENCES.md +5 -0
  76. package/dist/resources/extensions/gsd/tools/complete-task.js +94 -6
  77. package/dist/resources/extensions/gsd/tools/plan-task.js +13 -15
  78. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +18 -15
  79. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +14 -5
  80. package/dist/resources/extensions/gsd/tools/reopen-slice.js +15 -5
  81. package/dist/resources/extensions/gsd/tools/reopen-task.js +16 -10
  82. package/dist/resources/extensions/gsd/tools/replan-task.js +128 -0
  83. package/dist/resources/extensions/gsd/tools/rework-brief.js +74 -0
  84. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +81 -0
  85. package/dist/resources/extensions/gsd/unit-context-composer.js +28 -5
  86. package/dist/resources/extensions/gsd/unit-registry.js +4 -0
  87. package/dist/resources/extensions/gsd/uok/plan-v2.js +19 -3
  88. package/dist/resources/extensions/gsd/workflow-projections.js +2 -3
  89. package/dist/resources/extensions/gsd/workspace.js +2 -1
  90. package/dist/resources/extensions/gsd/worktree-state-projection.js +6 -0
  91. package/dist/resources/extensions/mac-tools/index.js +31 -9
  92. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  93. package/dist/web/standalone/.next/BUILD_ID +1 -1
  94. package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
  95. package/dist/web/standalone/.next/build-manifest.json +3 -3
  96. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  97. package/dist/web/standalone/.next/required-server-files.json +3 -3
  98. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  99. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  100. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  101. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  102. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  103. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  104. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  109. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  110. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  111. package/dist/web/standalone/.next/server/app/_not-found.rsc +4 -4
  112. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -4
  113. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -4
  115. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  118. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  125. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  137. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/mcp-connections/route_client-reference-manifest.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  159. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  169. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  175. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  191. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  195. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  196. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  197. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  199. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  200. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  201. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  202. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  203. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  204. package/dist/web/standalone/.next/server/app/index.html +1 -1
  205. package/dist/web/standalone/.next/server/app/index.rsc +5 -5
  206. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  207. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +5 -5
  208. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  209. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -4
  210. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  211. package/dist/web/standalone/.next/server/app/page.js +2 -2
  212. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  213. package/dist/web/standalone/.next/server/app-paths-manifest.json +8 -8
  214. package/dist/web/standalone/.next/server/chunks/2842.js +4 -4
  215. package/dist/web/standalone/.next/server/chunks/8357.js +3 -3
  216. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  217. package/dist/web/standalone/.next/server/middleware.js +3 -3
  218. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  219. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  220. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  221. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-a6fb1847f67f167c.js +1 -0
  222. package/dist/web/standalone/.next/static/chunks/app/{layout-b35cbfff38aaf4cf.js → layout-4ae2d68984392bbf.js} +1 -1
  223. package/dist/web/standalone/.next/static/chunks/app/page-72a856634ad14c10.js +1 -0
  224. package/dist/web/standalone/.next/static/chunks/{main-app-590a74400e35f685.js → main-app-90d1d8d5e5d2dc6b.js} +1 -1
  225. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-1115d46ac61b9823.js +1 -0
  226. package/dist/web/standalone/.next/static/css/3b1ceb7abfb9a230.css +1 -0
  227. package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
  228. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  229. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  230. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  231. package/dist/web/standalone/package.json +0 -1
  232. package/dist/web/standalone/server.js +1 -1
  233. package/dist/web-mode.js +31 -3
  234. package/integrations/hermes/open_gsd_hermes/gsd_client.py +1 -1
  235. package/integrations/hermes/pyproject.toml +1 -1
  236. package/package.json +12 -10
  237. package/packages/cloud-mcp-gateway/package.json +2 -2
  238. package/packages/contracts/dist/workflow.d.ts +14 -0
  239. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  240. package/packages/contracts/dist/workflow.js +16 -0
  241. package/packages/contracts/dist/workflow.js.map +1 -1
  242. package/packages/contracts/package.json +1 -1
  243. package/packages/daemon/dist/cloud-config.d.ts +1 -1
  244. package/packages/daemon/dist/cloud-config.d.ts.map +1 -1
  245. package/packages/daemon/dist/cloud-config.js +5 -1
  246. package/packages/daemon/dist/cloud-config.js.map +1 -1
  247. package/packages/daemon/dist/cloud-config.test.js +51 -1
  248. package/packages/daemon/dist/cloud-config.test.js.map +1 -1
  249. package/packages/daemon/dist/local-tool-executor.d.ts.map +1 -1
  250. package/packages/daemon/dist/local-tool-executor.js +2 -0
  251. package/packages/daemon/dist/local-tool-executor.js.map +1 -1
  252. package/packages/daemon/package.json +6 -6
  253. package/packages/gsd-agent-core/dist/compaction/compaction.d.ts.map +1 -1
  254. package/packages/gsd-agent-core/dist/compaction/compaction.js +36 -4
  255. package/packages/gsd-agent-core/dist/compaction/compaction.js.map +1 -1
  256. package/packages/gsd-agent-core/dist/sdk.d.ts.map +1 -1
  257. package/packages/gsd-agent-core/dist/sdk.js +1 -0
  258. package/packages/gsd-agent-core/dist/sdk.js.map +1 -1
  259. package/packages/gsd-agent-core/package.json +5 -5
  260. package/packages/gsd-agent-modes/package.json +7 -7
  261. package/packages/gsd-cloud/dist/cli.d.ts +5 -0
  262. package/packages/gsd-cloud/dist/cli.d.ts.map +1 -0
  263. package/packages/gsd-cloud/dist/cli.js +160 -0
  264. package/packages/gsd-cloud/dist/cli.js.map +1 -0
  265. package/packages/gsd-cloud/dist/cloud-config.d.ts +19 -0
  266. package/packages/gsd-cloud/dist/cloud-config.d.ts.map +1 -0
  267. package/packages/gsd-cloud/dist/cloud-config.js +231 -0
  268. package/packages/gsd-cloud/dist/cloud-config.js.map +1 -0
  269. package/packages/gsd-cloud/dist/cloud-config.test.d.ts +2 -0
  270. package/packages/gsd-cloud/dist/cloud-config.test.d.ts.map +1 -0
  271. package/packages/gsd-cloud/dist/cloud-config.test.js +118 -0
  272. package/packages/gsd-cloud/dist/cloud-config.test.js.map +1 -0
  273. package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.d.ts +2 -0
  274. package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.d.ts.map +1 -0
  275. package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.js +37 -0
  276. package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.js.map +1 -0
  277. package/packages/gsd-cloud/dist/cloud-runtime.d.ts +35 -0
  278. package/packages/gsd-cloud/dist/cloud-runtime.d.ts.map +1 -0
  279. package/packages/gsd-cloud/dist/cloud-runtime.js +258 -0
  280. package/packages/gsd-cloud/dist/cloud-runtime.js.map +1 -0
  281. package/packages/gsd-cloud/dist/cloud-runtime.test.d.ts +2 -0
  282. package/packages/gsd-cloud/dist/cloud-runtime.test.d.ts.map +1 -0
  283. package/packages/gsd-cloud/dist/cloud-runtime.test.js +88 -0
  284. package/packages/gsd-cloud/dist/cloud-runtime.test.js.map +1 -0
  285. package/packages/gsd-cloud/dist/cloud-token.d.ts +3 -0
  286. package/packages/gsd-cloud/dist/cloud-token.d.ts.map +1 -0
  287. package/packages/gsd-cloud/dist/cloud-token.js +37 -0
  288. package/packages/gsd-cloud/dist/cloud-token.js.map +1 -0
  289. package/packages/gsd-cloud/dist/config.d.ts +17 -0
  290. package/packages/gsd-cloud/dist/config.d.ts.map +1 -0
  291. package/packages/gsd-cloud/dist/config.js +146 -0
  292. package/packages/gsd-cloud/dist/config.js.map +1 -0
  293. package/packages/gsd-cloud/dist/device-flow.d.ts +24 -0
  294. package/packages/gsd-cloud/dist/device-flow.d.ts.map +1 -0
  295. package/packages/gsd-cloud/dist/device-flow.js +128 -0
  296. package/packages/gsd-cloud/dist/device-flow.js.map +1 -0
  297. package/packages/gsd-cloud/dist/device-flow.test.d.ts +2 -0
  298. package/packages/gsd-cloud/dist/device-flow.test.d.ts.map +1 -0
  299. package/packages/gsd-cloud/dist/device-flow.test.js +155 -0
  300. package/packages/gsd-cloud/dist/device-flow.test.js.map +1 -0
  301. package/packages/gsd-cloud/dist/executors/claude-executor.d.ts +6 -0
  302. package/packages/gsd-cloud/dist/executors/claude-executor.d.ts.map +1 -0
  303. package/packages/gsd-cloud/dist/executors/claude-executor.js +15 -0
  304. package/packages/gsd-cloud/dist/executors/claude-executor.js.map +1 -0
  305. package/packages/gsd-cloud/dist/executors/codex-executor.d.ts +6 -0
  306. package/packages/gsd-cloud/dist/executors/codex-executor.d.ts.map +1 -0
  307. package/packages/gsd-cloud/dist/executors/codex-executor.js +15 -0
  308. package/packages/gsd-cloud/dist/executors/codex-executor.js.map +1 -0
  309. package/packages/gsd-cloud/dist/executors/executor.d.ts +28 -0
  310. package/packages/gsd-cloud/dist/executors/executor.d.ts.map +1 -0
  311. package/packages/gsd-cloud/dist/executors/executor.js +11 -0
  312. package/packages/gsd-cloud/dist/executors/executor.js.map +1 -0
  313. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.d.ts +34 -0
  314. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.d.ts.map +1 -0
  315. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.js +179 -0
  316. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.js.map +1 -0
  317. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.d.ts +2 -0
  318. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.d.ts.map +1 -0
  319. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.js +44 -0
  320. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.js.map +1 -0
  321. package/packages/gsd-cloud/dist/executors/index.d.ts +17 -0
  322. package/packages/gsd-cloud/dist/executors/index.d.ts.map +1 -0
  323. package/packages/gsd-cloud/dist/executors/index.js +29 -0
  324. package/packages/gsd-cloud/dist/executors/index.js.map +1 -0
  325. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.d.ts +36 -0
  326. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.d.ts.map +1 -0
  327. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.js +176 -0
  328. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.js.map +1 -0
  329. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.d.ts +2 -0
  330. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.d.ts.map +1 -0
  331. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.js +34 -0
  332. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.js.map +1 -0
  333. package/packages/gsd-cloud/dist/index.d.ts +7 -0
  334. package/packages/gsd-cloud/dist/index.d.ts.map +1 -0
  335. package/packages/gsd-cloud/dist/index.js +8 -0
  336. package/packages/gsd-cloud/dist/index.js.map +1 -0
  337. package/packages/gsd-cloud/dist/inject-gateway.d.ts +16 -0
  338. package/packages/gsd-cloud/dist/inject-gateway.d.ts.map +1 -0
  339. package/packages/gsd-cloud/dist/inject-gateway.js +29 -0
  340. package/packages/gsd-cloud/dist/inject-gateway.js.map +1 -0
  341. package/packages/gsd-cloud/dist/inject-gateway.test.d.ts +2 -0
  342. package/packages/gsd-cloud/dist/inject-gateway.test.d.ts.map +1 -0
  343. package/packages/gsd-cloud/dist/inject-gateway.test.js +41 -0
  344. package/packages/gsd-cloud/dist/inject-gateway.test.js.map +1 -0
  345. package/packages/gsd-cloud/dist/logger.d.ts +25 -0
  346. package/packages/gsd-cloud/dist/logger.d.ts.map +1 -0
  347. package/packages/gsd-cloud/dist/logger.js +72 -0
  348. package/packages/gsd-cloud/dist/logger.js.map +1 -0
  349. package/packages/gsd-cloud/dist/types.d.ts +51 -0
  350. package/packages/gsd-cloud/dist/types.d.ts.map +1 -0
  351. package/packages/gsd-cloud/dist/types.js +9 -0
  352. package/packages/gsd-cloud/dist/types.js.map +1 -0
  353. package/packages/gsd-cloud/package.json +3 -3
  354. package/packages/mcp-server/README.md +15 -2
  355. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  356. package/packages/mcp-server/dist/server.js +5 -5
  357. package/packages/mcp-server/dist/server.js.map +1 -1
  358. package/packages/mcp-server/dist/workflow-tools.d.ts +4 -3
  359. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  360. package/packages/mcp-server/dist/workflow-tools.js +64 -2
  361. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  362. package/packages/mcp-server/package.json +4 -4
  363. package/packages/native/package.json +1 -1
  364. package/packages/pi-agent-core/dist/agent.d.ts +5 -1
  365. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  366. package/packages/pi-agent-core/dist/agent.js +2 -0
  367. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  368. package/packages/pi-agent-core/package.json +1 -1
  369. package/packages/pi-ai/dist/models.generated.d.ts +119 -0
  370. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  371. package/packages/pi-ai/dist/models.generated.js +107 -0
  372. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  373. package/packages/pi-ai/dist/providers/amazon-bedrock.js +1 -0
  374. package/packages/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
  375. package/packages/pi-ai/dist/providers/anthropic.js +25 -1
  376. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  377. package/packages/pi-ai/dist/providers/openai-codex-responses.js +1 -1
  378. package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
  379. package/packages/pi-ai/dist/providers/openai-responses.js +1 -1
  380. package/packages/pi-ai/dist/providers/openai-responses.js.map +1 -1
  381. package/packages/pi-ai/package.json +1 -1
  382. package/packages/pi-coding-agent/dist/core/capability-patches.js +1 -1
  383. package/packages/pi-coding-agent/dist/core/capability-patches.js.map +1 -1
  384. package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -1
  385. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  386. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +11 -1
  387. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  388. package/packages/pi-coding-agent/dist/core/settings-manager.js +8 -0
  389. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  390. package/packages/pi-coding-agent/package.json +7 -7
  391. package/packages/pi-tui/package.json +2 -2
  392. package/packages/rpc-client/package.json +2 -2
  393. package/pkg/package.json +1 -1
  394. package/src/resources/GSD-WORKFLOW.md +18 -49
  395. package/src/resources/extensions/browser-tools/capture.ts +2 -86
  396. package/src/resources/extensions/browser-tools/screenshot-constraints.ts +94 -0
  397. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +18 -1
  398. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +108 -0
  399. package/src/resources/extensions/claude-code-cli/turn-assembler.ts +30 -2
  400. package/src/resources/extensions/gsd/artifact-verification.ts +3 -8
  401. package/src/resources/extensions/gsd/auto-artifact-paths.ts +16 -9
  402. package/src/resources/extensions/gsd/auto-dispatch.ts +86 -19
  403. package/src/resources/extensions/gsd/auto-post-unit.ts +4 -0
  404. package/src/resources/extensions/gsd/auto-prompts.ts +142 -16
  405. package/src/resources/extensions/gsd/auto-recovery.ts +10 -8
  406. package/src/resources/extensions/gsd/auto-worktree-cleanup.ts +4 -0
  407. package/src/resources/extensions/gsd/auto-worktree-teardown.ts +1 -1
  408. package/src/resources/extensions/gsd/auto.ts +5 -1
  409. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +92 -4
  410. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +39 -10
  411. package/src/resources/extensions/gsd/bootstrap/system-context.ts +11 -3
  412. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +87 -53
  413. package/src/resources/extensions/gsd/command-feedback.ts +19 -12
  414. package/src/resources/extensions/gsd/compat/compat-marker.ts +21 -4
  415. package/src/resources/extensions/gsd/constants.ts +14 -13
  416. package/src/resources/extensions/gsd/context-masker.ts +98 -2
  417. package/src/resources/extensions/gsd/db/command-queue.ts +7 -1
  418. package/src/resources/extensions/gsd/db/engine.ts +53 -17
  419. package/src/resources/extensions/gsd/db/writers/cascades.ts +5 -1
  420. package/src/resources/extensions/gsd/db/writers/status.ts +25 -8
  421. package/src/resources/extensions/gsd/db-base-schema.ts +30 -0
  422. package/src/resources/extensions/gsd/db-migration-steps.ts +32 -0
  423. package/src/resources/extensions/gsd/db-schema-metadata.ts +4 -1
  424. package/src/resources/extensions/gsd/docs/preferences-reference.md +26 -4
  425. package/src/resources/extensions/gsd/doctor-engine-checks.ts +3 -5
  426. package/src/resources/extensions/gsd/flat-phase-migration.ts +160 -19
  427. package/src/resources/extensions/gsd/git-service.ts +19 -6
  428. package/src/resources/extensions/gsd/gsd-db.ts +255 -52
  429. package/src/resources/extensions/gsd/guided-flow.ts +48 -12
  430. package/src/resources/extensions/gsd/markdown-renderer.ts +25 -21
  431. package/src/resources/extensions/gsd/md-importer.ts +114 -16
  432. package/src/resources/extensions/gsd/migrate/command.ts +21 -227
  433. package/src/resources/extensions/gsd/migrate/execution.ts +136 -0
  434. package/src/resources/extensions/gsd/migrate/plan.ts +101 -0
  435. package/src/resources/extensions/gsd/migrate/planning-writer.ts +12 -20
  436. package/src/resources/extensions/gsd/migrate/presentation.ts +83 -0
  437. package/src/resources/extensions/gsd/model-cost-table.ts +2 -0
  438. package/src/resources/extensions/gsd/model-router.ts +12 -0
  439. package/src/resources/extensions/gsd/parallel-eligibility.ts +5 -4
  440. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +37 -40
  441. package/src/resources/extensions/gsd/paths.ts +62 -11
  442. package/src/resources/extensions/gsd/phase-anchor.ts +8 -2
  443. package/src/resources/extensions/gsd/planning-subagent-policy.ts +58 -0
  444. package/src/resources/extensions/gsd/planning-subagent-registry.ts +31 -0
  445. package/src/resources/extensions/gsd/post-execution-checks.ts +4 -4
  446. package/src/resources/extensions/gsd/preferences-types.ts +16 -0
  447. package/src/resources/extensions/gsd/preferences-validation.ts +62 -0
  448. package/src/resources/extensions/gsd/preferences.ts +25 -0
  449. package/src/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  450. package/src/resources/extensions/gsd/provider-payload-policy.ts +18 -4
  451. package/src/resources/extensions/gsd/safety/destructive-guard.ts +1 -1
  452. package/src/resources/extensions/gsd/safety/evidence-collector.ts +28 -1
  453. package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +31 -5
  454. package/src/resources/extensions/gsd/skill-activation.ts +17 -3
  455. package/src/resources/extensions/gsd/state-reconciliation/drift/external-markdown-edit.ts +30 -13
  456. package/src/resources/extensions/gsd/state-reconciliation/drift/external-planning-edit.ts +16 -3
  457. package/src/resources/extensions/gsd/state-reconciliation/types.ts +2 -2
  458. package/src/resources/extensions/gsd/stop-notice.ts +18 -1
  459. package/src/resources/extensions/gsd/sync-lock.ts +14 -6
  460. package/src/resources/extensions/gsd/templates/PREFERENCES.md +5 -0
  461. package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +7 -7
  462. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +39 -0
  463. package/src/resources/extensions/gsd/tests/before-provider-context-management.test.ts +55 -0
  464. package/src/resources/extensions/gsd/tests/closeout-git-deferral.test.ts +96 -1
  465. package/src/resources/extensions/gsd/tests/command-feedback.test.ts +12 -0
  466. package/src/resources/extensions/gsd/tests/compat-marker.test.ts +104 -0
  467. package/src/resources/extensions/gsd/tests/complete-task.test.ts +362 -1
  468. package/src/resources/extensions/gsd/tests/context-masker.test.ts +204 -8
  469. package/src/resources/extensions/gsd/tests/db-engine-migrate-guards.test.ts +186 -0
  470. package/src/resources/extensions/gsd/tests/db-tools-alias-suppression.test.ts +62 -0
  471. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +29 -0
  472. package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +33 -0
  473. package/src/resources/extensions/gsd/tests/destructive-guard.test.ts +14 -0
  474. package/src/resources/extensions/gsd/tests/discuss-routing-fixes.test.ts +123 -0
  475. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +50 -0
  476. package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +49 -0
  477. package/src/resources/extensions/gsd/tests/evidence-cross-ref.test.ts +81 -0
  478. package/src/resources/extensions/gsd/tests/evidence-xref-gsd-exec.test.ts +22 -0
  479. package/src/resources/extensions/gsd/tests/external-edit-scoped-import.test.ts +262 -0
  480. package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +202 -0
  481. package/src/resources/extensions/gsd/tests/gate-storage.test.ts +29 -0
  482. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +25 -0
  483. package/src/resources/extensions/gsd/tests/import-slice-milestone-completion-preserve.test.ts +116 -0
  484. package/src/resources/extensions/gsd/tests/integration/paths.test.ts +22 -4
  485. package/src/resources/extensions/gsd/tests/integration-branch-meta-location.test.ts +62 -0
  486. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +5 -5
  487. package/src/resources/extensions/gsd/tests/migrate-plan.test.ts +68 -0
  488. package/src/resources/extensions/gsd/tests/migrate-presentation.test.ts +98 -0
  489. package/src/resources/extensions/gsd/tests/migrate-safety-audit.test.ts +1 -1
  490. package/src/resources/extensions/gsd/tests/milestone-leases.test.ts +55 -0
  491. package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +9 -1
  492. package/src/resources/extensions/gsd/tests/model-router.test.ts +1 -1
  493. package/src/resources/extensions/gsd/tests/parallel-eligibility-file-overlap.test.ts +146 -0
  494. package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +59 -0
  495. package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +7 -5
  496. package/src/resources/extensions/gsd/tests/phase-anchor.test.ts +32 -4
  497. package/src/resources/extensions/gsd/tests/plan-task.test.ts +26 -23
  498. package/src/resources/extensions/gsd/tests/planning-writer.test.ts +29 -0
  499. package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +22 -0
  500. package/src/resources/extensions/gsd/tests/preferences.test.ts +84 -0
  501. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +4 -0
  502. package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +66 -0
  503. package/src/resources/extensions/gsd/tests/reactive-executor.test.ts +39 -0
  504. package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +50 -0
  505. package/src/resources/extensions/gsd/tests/replan-task-handler.test.ts +103 -0
  506. package/src/resources/extensions/gsd/tests/rework-brief.test.ts +197 -0
  507. package/src/resources/extensions/gsd/tests/service-tier.test.ts +4 -0
  508. package/src/resources/extensions/gsd/tests/single-writer-v3-tool-surface.test.ts +33 -7
  509. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +20 -16
  510. package/src/resources/extensions/gsd/tests/skip-slice-cascades-tasks.test.ts +21 -0
  511. package/src/resources/extensions/gsd/tests/stop-notice.test.ts +17 -0
  512. package/src/resources/extensions/gsd/tests/sync-lock.test.ts +19 -0
  513. package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +13 -7
  514. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +8 -0
  515. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +73 -0
  516. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +93 -1
  517. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -0
  518. package/src/resources/extensions/gsd/tests/workflow-migration-gates.test.ts +139 -0
  519. package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +4 -4
  520. package/src/resources/extensions/gsd/tests/worktree-state-projection.test.ts +36 -0
  521. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +34 -0
  522. package/src/resources/extensions/gsd/tests/write-gate-seam.test.ts +52 -0
  523. package/src/resources/extensions/gsd/tools/complete-task.ts +140 -5
  524. package/src/resources/extensions/gsd/tools/plan-task.ts +14 -16
  525. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +18 -17
  526. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +24 -5
  527. package/src/resources/extensions/gsd/tools/reopen-slice.ts +25 -5
  528. package/src/resources/extensions/gsd/tools/reopen-task.ts +23 -9
  529. package/src/resources/extensions/gsd/tools/replan-task.ts +160 -0
  530. package/src/resources/extensions/gsd/tools/rework-brief.ts +91 -0
  531. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +92 -0
  532. package/src/resources/extensions/gsd/types.ts +11 -0
  533. package/src/resources/extensions/gsd/unit-context-composer.ts +34 -8
  534. package/src/resources/extensions/gsd/unit-registry.ts +4 -0
  535. package/src/resources/extensions/gsd/uok/plan-v2.ts +20 -3
  536. package/src/resources/extensions/gsd/workflow-projections.ts +2 -3
  537. package/src/resources/extensions/gsd/workspace.ts +2 -1
  538. package/src/resources/extensions/gsd/worktree-state-projection.ts +12 -0
  539. package/src/resources/extensions/mac-tools/index.ts +52 -9
  540. package/src/resources/extensions/mac-tools/tests/mac-screenshot-payload.test.cjs +70 -0
  541. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-49f565245e1e4afe.js +0 -1
  542. package/dist/web/standalone/.next/static/chunks/app/page-bc4c723c6a19c6f0.js +0 -1
  543. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ec3eaffc9785ba48.js +0 -1
  544. package/dist/web/standalone/.next/static/css/18c2fdf261bfc1b7.css +0 -1
  545. /package/dist/web/standalone/.next/static/{UaXRrOYxBpG9QBINKhZkg → 6YWV7VAPg-jqjfPswrKZb}/_buildManifest.js +0 -0
  546. /package/dist/web/standalone/.next/static/{UaXRrOYxBpG9QBINKhZkg → 6YWV7VAPg-jqjfPswrKZb}/_ssgManifest.js +0 -0
@@ -58,6 +58,7 @@ function registerAlias(pi: ExtensionAPI, toolDef: any, aliasName: string, canoni
58
58
  // eslint-disable-next-line @typescript-eslint/no-explicit-any -- toolDef shape matches ToolDefinition but varies by schema
59
59
  function registerWorkflowTool(pi: ExtensionAPI, toolDef: any): void {
60
60
  pi.registerTool(toolDef);
61
+ if (process.env.GSD_ADVERTISE_TOOL_ALIASES !== "1") return; // canonical-only model surface (see plan 035)
61
62
  for (const alias of aliasesForWorkflowTool(toolDef.name)) {
62
63
  registerAlias(pi, toolDef, alias, toolDef.name);
63
64
  }
@@ -771,12 +772,12 @@ export function registerDbTools(pi: ExtensionAPI): void {
771
772
  name: "gsd_plan_task",
772
773
  label: "Plan Task",
773
774
  description:
774
- "Write task planning state to the GSD database, render tasks/T##-PLAN.md from DB, and clear caches after a successful render.",
775
- promptSnippet: "Plan a task via DB write + task PLAN render + cache invalidation",
775
+ "Write task planning state to the GSD database, render the slice PLAN from DB, and clear caches after a successful render.",
776
+ promptSnippet: "Plan a task via DB write + slice PLAN render + cache invalidation",
776
777
  promptGuidelines: [
777
- "Use gsd_plan_task for task planning instead of writing tasks/T##-PLAN.md directly.",
778
+ "Use gsd_plan_task for task planning instead of writing task PLAN files directly.",
778
779
  "Keep parameters flat and provide the full task planning payload.",
779
- "The tool validates input, requires an existing parent slice, writes task planning data, renders the task PLAN file from DB, and clears both state and parse caches after success.",
780
+ "The tool validates input, requires an existing parent slice, writes task planning data, renders the slice PLAN file from DB, and clears both state and parse caches after success.",
780
781
  "Use the canonical name gsd_plan_task; gsd_task_plan is only an alias.",
781
782
  ],
782
783
  parameters: Type.Object({
@@ -860,6 +861,15 @@ export function registerDbTools(pi: ExtensionAPI): void {
860
861
  }),
861
862
  { description: "Array of verification evidence entries (structured objects only)" },
862
863
  )),
864
+ reworkResolution: Type.Optional(Type.Array(
865
+ Type.Object({
866
+ findingId: Type.String({ description: "Rework finding ID being resolved (e.g. F1)" }),
867
+ status: StringEnum(["resolved", "deferred-with-override"], { description: "Resolution status for this finding" }),
868
+ evidence: Type.String({ description: "Concrete evidence that the required fix was completed" }),
869
+ decisionRef: Type.Optional(Type.String({ description: "Decision reference required for deferred-with-override findings" })),
870
+ }),
871
+ { description: "Resolution evidence for structured rework findings linked to this task" },
872
+ )),
863
873
  // Single-writer v3 audit trail (Stream 2): caller-provided actor identity + causation.
864
874
  actorName: Type.Optional(Type.String({ description: "Caller-provided actor identity for the audit trail (e.g. 'executor-01', 'gsd-orchestrator')" })),
865
875
  triggerReason: Type.Optional(Type.String({ description: "Caller-provided reason this action was triggered (e.g. 'task verified after retry')" })),
@@ -1180,6 +1190,84 @@ export function registerDbTools(pi: ExtensionAPI): void {
1180
1190
 
1181
1191
  registerWorkflowTool(pi, replanSliceTool);
1182
1192
 
1193
+ // ─── gsd_replan_task ───────────────────────────────────────────────────
1194
+
1195
+ const replanTaskExecute = async (_toolCallId: string, params: any, _signal: AbortSignal | undefined, _onUpdate: unknown, _ctx: unknown) => {
1196
+ const { executeReplanTask } = await loadWorkflowExecutors();
1197
+ return executeReplanTask(params, resolveWorkflowToolBasePath(_ctx, params));
1198
+ };
1199
+
1200
+ const replanTaskTool = {
1201
+ name: "gsd_replan_task",
1202
+ label: "Replan Task",
1203
+ description:
1204
+ "Update one pending task's planning contract after rework without touching sibling tasks. " +
1205
+ "Completed tasks are structurally protected. Re-renders the task/slice PLAN projection and records replan history.",
1206
+ promptSnippet: "Replan one pending GSD task after rework",
1207
+ promptGuidelines: [
1208
+ "Use gsd_replan_task when a reopened pending task needs its title, description, files, verify, inputs, or expectedOutput updated for rework.",
1209
+ "The task must already exist and be pending; completed tasks are rejected.",
1210
+ "Set reworkBriefRef when a structured rework brief triggered the task replan.",
1211
+ ],
1212
+ parameters: Type.Object({
1213
+ milestoneId: Type.String({ description: "Milestone ID (e.g. M001)" }),
1214
+ sliceId: Type.String({ description: "Slice ID (e.g. S01)" }),
1215
+ taskId: Type.String({ description: "Task ID (e.g. T01)" }),
1216
+ title: Type.String({ description: "Updated task title" }),
1217
+ description: Type.String({ description: "Updated task description incorporating rework scope" }),
1218
+ estimate: Type.String({ description: "Updated task estimate string" }),
1219
+ files: Type.Array(Type.String(), { description: "Updated files likely touched" }),
1220
+ verify: Type.String({ description: "Updated verification command or block" }),
1221
+ inputs: Type.Array(Type.String(), { description: "Updated input files or references" }),
1222
+ expectedOutput: Type.Array(Type.String(), { description: "Updated files this task creates or overwrites" }),
1223
+ reworkBriefRef: Type.Optional(Type.String({ description: "Rework brief ID/reference that triggered this task replan" })),
1224
+ actorName: Type.Optional(Type.String({ description: "Caller-provided actor identity for the audit trail" })),
1225
+ triggerReason: Type.Optional(Type.String({ description: "Caller-provided reason this action was triggered" })),
1226
+ }),
1227
+ execute: replanTaskExecute,
1228
+ };
1229
+
1230
+ registerWorkflowTool(pi, replanTaskTool);
1231
+
1232
+ // ─── gsd_rework_brief_save ─────────────────────────────────────────────
1233
+
1234
+ const reworkBriefSaveExecute = async (_toolCallId: string, params: any, _signal: AbortSignal | undefined, _onUpdate: unknown, _ctx: unknown) => {
1235
+ const { executeReworkBriefSave } = await loadWorkflowExecutors();
1236
+ return executeReworkBriefSave(params, resolveWorkflowToolBasePath(_ctx, params));
1237
+ };
1238
+
1239
+ const reworkBriefSaveTool = {
1240
+ name: "gsd_rework_brief_save",
1241
+ label: "Save Rework Brief",
1242
+ description:
1243
+ "Persist a structured rework brief for a task. Blocking findings are enforced by gsd_task_complete until resolved with evidence.",
1244
+ promptSnippet: "Persist structured task rework findings",
1245
+ promptGuidelines: [
1246
+ "Use gsd_rework_brief_save when post-unit checks produce task rework findings.",
1247
+ "Use severity 'blocking' for findings that must be resolved before gsd_task_complete succeeds.",
1248
+ "Each finding needs a stable findingId, requiredFix, and verificationCommands.",
1249
+ ],
1250
+ parameters: Type.Object({
1251
+ briefId: Type.Optional(Type.String({ description: "Stable brief ID; omitted defaults to RB-<milestone>-<slice>-<task>" })),
1252
+ milestoneId: Type.String({ description: "Milestone ID (e.g. M001)" }),
1253
+ sliceId: Type.String({ description: "Slice ID (e.g. S01)" }),
1254
+ taskId: Type.String({ description: "Task ID (e.g. T01)" }),
1255
+ findings: Type.Array(Type.Object({
1256
+ findingId: Type.String({ description: "Stable finding ID (e.g. F1)" }),
1257
+ severity: StringEnum(["blocking", "advisory"], { description: "Whether this finding blocks task completion" }),
1258
+ description: Type.String({ description: "What was found" }),
1259
+ requiredFix: Type.String({ description: "What must change" }),
1260
+ verificationCommands: Type.Array(Type.String(), { description: "Commands that must pass after the fix" }),
1261
+ status: Type.Optional(StringEnum(["pending", "resolved", "deferred-with-override"], { description: "Finding status; defaults to pending" })),
1262
+ evidence: Type.Optional(Type.String({ description: "Resolution evidence when already resolved" })),
1263
+ decisionRef: Type.Optional(Type.String({ description: "Decision reference for deferred-with-override" })),
1264
+ }), { description: "Structured rework findings for this task" }),
1265
+ }),
1266
+ execute: reworkBriefSaveExecute,
1267
+ };
1268
+
1269
+ registerWorkflowTool(pi, reworkBriefSaveTool);
1270
+
1183
1271
  // ─── gsd_reassess_roadmap (gsd_roadmap_reassess alias) ─────────────────
1184
1272
 
1185
1273
  const reassessRoadmapExecute = async (_toolCallId: string, params: any, _signal: AbortSignal | undefined, _onUpdate: unknown, _ctx: unknown) => {
@@ -51,7 +51,9 @@ import {
51
51
  confirmDestructiveCommand,
52
52
  consumeDestructiveConfirmation,
53
53
  isDestructiveConfirmGateId,
54
+ peekPendingDestructiveCommand,
54
55
  requestDestructiveConfirmation,
56
+ resetDestructiveConfirmation,
55
57
  } from "../safety/destructive-confirmation.js";
56
58
  import { logWarning as safetyLogWarning, setStderrLoggingEnabled } from "../workflow-logger.js";
57
59
  import { isUnitCloseoutTool, runInteractiveUnitCloseout } from "../unit-closeout.js";
@@ -59,6 +61,7 @@ import { installNotifyInterceptor } from "./notify-interceptor.js";
59
61
  import { initNotificationStore } from "../notification-store.js";
60
62
  import { initNotificationWidget } from "../notification-widget.js";
61
63
  import { notifyPreferenceDiagnostics } from "../preferences-diagnostics.js";
64
+ import { resolveEffectivePlanningToolsPolicy } from "../planning-subagent-policy.js";
62
65
  import { resolveWorktreeProjectRoot } from "../worktree-root.js";
63
66
  import { extractSubagentAgentClasses } from "./subagent-input.js";
64
67
  import {
@@ -187,6 +190,7 @@ function suppressWelcomeHeader(ctx: ExtensionContext): void {
187
190
  * are bounded — cleared on activation, session boundaries, and verification.
188
191
  */
189
192
  const deferredApprovalGates = new Map<string, string>();
193
+ const deferredDestructiveConfirmationPauses = new Set<string>();
190
194
 
191
195
  export const MINIMAL_GSD_TOOL_NAMES = [
192
196
  "gsd_exec",
@@ -618,6 +622,23 @@ function clearDeferredApprovalGate(basePath?: string): void {
618
622
  }
619
623
  }
620
624
 
625
+ function deferDestructiveConfirmationPause(basePath: string): void {
626
+ deferredDestructiveConfirmationPauses.add(basePath);
627
+ }
628
+
629
+ function clearDeferredDestructiveConfirmationPause(basePath?: string): void {
630
+ if (!basePath) {
631
+ deferredDestructiveConfirmationPauses.clear();
632
+ } else {
633
+ deferredDestructiveConfirmationPauses.delete(basePath);
634
+ }
635
+ }
636
+
637
+ function isDestructiveConfirmationBlocking(basePath: string): boolean {
638
+ return deferredDestructiveConfirmationPauses.has(basePath)
639
+ && Boolean(peekPendingDestructiveCommand(basePath));
640
+ }
641
+
621
642
  function deferApprovalGate(gateId: string, basePath: string): void {
622
643
  // Verified-on-disk wins (same adapter policy as activation/re-arm): if the
623
644
  // workflow MCP child already verified this gate, deferring would block
@@ -1015,6 +1036,7 @@ export function registerHooks(
1015
1036
  await applyToolCallLoopGuardConfig(basePath);
1016
1037
  approvalQuestionAbortInFlight = false;
1017
1038
  clearDeferredApprovalGate();
1039
+ clearDeferredDestructiveConfirmationPause();
1018
1040
  await resetAskUserQuestionsTurnCache();
1019
1041
  await syncServiceTierStatus(ctx);
1020
1042
  await applyDisabledModelProviderPolicy(ctx);
@@ -1106,6 +1128,7 @@ export function registerHooks(
1106
1128
  resetToolCallLoopGuard();
1107
1129
  await applyToolCallLoopGuardConfig(basePath);
1108
1130
  clearDeferredApprovalGate();
1131
+ clearDeferredDestructiveConfirmationPause();
1109
1132
  await resetAskUserQuestionsTurnCache();
1110
1133
  clearDiscussionFlowState(basePath);
1111
1134
  // /clear or /new destroys the conversation holding a discuss interview, so
@@ -1157,6 +1180,7 @@ export function registerHooks(
1157
1180
  }
1158
1181
  }
1159
1182
  clearDeferredApprovalGate(beforeAgentBasePath);
1183
+ clearDeferredDestructiveConfirmationPause(beforeAgentBasePath);
1160
1184
 
1161
1185
  // session_start can fire before the active provider has settled. By
1162
1186
  // before_agent_start, Claude Code CLI sessions should get the same
@@ -1244,12 +1268,20 @@ export function registerHooks(
1244
1268
  await handleAgentEnd(pi, event, ctx);
1245
1269
  } finally {
1246
1270
  activateDeferredApprovalGate(agentEndBasePath);
1271
+ const destructiveConfirmationBlocking = isDestructiveConfirmationBlocking(agentEndBasePath);
1272
+ clearDeferredDestructiveConfirmationPause(agentEndBasePath);
1247
1273
  await maybePauseAutoForApprovalGate(
1248
1274
  ctx,
1249
1275
  pi,
1250
1276
  isApprovalGateBlocking(agentEndBasePath),
1251
1277
  "Depth confirmation is waiting for your answer — pausing auto-mode.",
1252
1278
  );
1279
+ await maybePauseAutoForApprovalGate(
1280
+ ctx,
1281
+ pi,
1282
+ destructiveConfirmationBlocking,
1283
+ "Destructive-command confirmation is waiting for your answer — pausing auto-mode.",
1284
+ );
1253
1285
  }
1254
1286
  });
1255
1287
 
@@ -1559,6 +1591,7 @@ export function registerHooks(
1559
1591
  const activeUnitType = dash.currentUnit?.type ?? guidedUnit?.unitType;
1560
1592
  if (activeUnitType) {
1561
1593
  const manifest = resolveManifest(activeUnitType);
1594
+ const planningBasePath = dash.basePath || guidedUnit?.basePath || discussionBasePath;
1562
1595
  let planningInput = "";
1563
1596
  let agentClasses: string[] | undefined;
1564
1597
  if (isToolCallEventType("write", event)) {
@@ -1574,9 +1607,9 @@ export function registerHooks(
1574
1607
  const planningGuard = shouldBlockPlanningUnit(
1575
1608
  event.toolName,
1576
1609
  planningInput,
1577
- dash.basePath || guidedUnit?.basePath || discussionBasePath,
1610
+ planningBasePath,
1578
1611
  activeUnitType,
1579
- manifest?.tools,
1612
+ resolveEffectivePlanningToolsPolicy(activeUnitType, manifest?.tools, planningBasePath),
1580
1613
  agentClasses,
1581
1614
  (event as { input?: unknown }).input,
1582
1615
  dash.currentUnit?.id,
@@ -1685,6 +1718,7 @@ export function registerHooks(
1685
1718
  // Record the command as pending so an affirmative answer to a
1686
1719
  // destructive_confirm gate (handled in tool_result) can confirm it.
1687
1720
  requestDestructiveConfirmation(command, guardBasePath);
1721
+ deferDestructiveConfirmationPause(guardBasePath);
1688
1722
  const reason = [
1689
1723
  "HARD BLOCK: destructive Bash command requires explicit human confirmation.",
1690
1724
  `Detected: ${classification.labels.join(", ")}`,
@@ -1695,14 +1729,6 @@ export function registerHooks(
1695
1729
  safetyLogWarning("safety", `destructive command: ${classification.labels.join(", ")}`, {
1696
1730
  command: String(command).slice(0, 200),
1697
1731
  });
1698
- if (ctx) {
1699
- await maybePauseAutoForApprovalGate(
1700
- ctx,
1701
- pi,
1702
- isAutoActive(),
1703
- "Destructive-command confirmation is waiting for your answer — pausing auto-mode.",
1704
- );
1705
- }
1706
1732
  return { block: true, reason };
1707
1733
  }
1708
1734
  }
@@ -1884,7 +1910,10 @@ export function registerHooks(
1884
1910
  const answer = details.response?.answers?.[question.id];
1885
1911
  if (isDepthConfirmationAnswer(answer?.selected, question.options)) {
1886
1912
  confirmDestructiveCommand(basePath);
1913
+ } else {
1914
+ resetDestructiveConfirmation(basePath);
1887
1915
  }
1916
+ clearDeferredDestructiveConfirmationPause(basePath);
1888
1917
  break;
1889
1918
  }
1890
1919
  }
@@ -21,6 +21,14 @@ import { formatOverridesSection, formatShortcut, loadActiveOverrides, loadFile,
21
21
  import { toPosixPath } from "../../shared/mod.js";
22
22
  import { autoEnableCmuxPreferences } from "../commands-cmux.js";
23
23
  import { gsdHome } from "../gsd-home.js";
24
+ import { GSD_CONTEXT_MESSAGE_SENTINEL } from "../constants.js";
25
+
26
+ // Single source of truth lives in ../constants.js; re-exported here because
27
+ // buildContextMessage() stamps this marker on every context injection and the
28
+ // provider payload policy (filterSupersededContextInjections in
29
+ // context-masker.ts) matches it to dedupe. Adding a new context customType?
30
+ // Ensure buildContextMessage still prepends this sentinel.
31
+ export { GSD_CONTEXT_MESSAGE_SENTINEL };
24
32
 
25
33
  const DEFAULT_CONTEXT_MESSAGE_MAX_CHARS = 4_000;
26
34
  const DEFAULT_KNOWLEDGE_MAX_CHARS = 12_000;
@@ -448,14 +456,14 @@ export function buildContextMessage(opts: {
448
456
  const memoryContent = markMemoryContextSupplied(opts.memoryBlock.trim());
449
457
  if (opts.injection) {
450
458
  const content = limitContextMessageContent(
451
- memoryContent ? `${memoryContent}\n\n${opts.injection}` : opts.injection,
459
+ `${GSD_CONTEXT_MESSAGE_SENTINEL}\n${memoryContent ? `${memoryContent}\n\n${opts.injection}` : opts.injection}`,
452
460
  contextCharLimit,
453
461
  );
454
462
  return { customType: "gsd-guided-context", content, display: false as const };
455
463
  }
456
464
  if (opts.forensicsInjection) {
457
465
  const content = limitContextMessageContent(
458
- memoryContent ? `${memoryContent}\n\n${opts.forensicsInjection}` : opts.forensicsInjection,
466
+ `${GSD_CONTEXT_MESSAGE_SENTINEL}\n${memoryContent ? `${memoryContent}\n\n${opts.forensicsInjection}` : opts.forensicsInjection}`,
459
467
  contextCharLimit,
460
468
  );
461
469
  return { customType: "gsd-forensics", content, display: false as const };
@@ -463,7 +471,7 @@ export function buildContextMessage(opts: {
463
471
  if (memoryContent) {
464
472
  return {
465
473
  customType: "gsd-memory",
466
- content: limitContextMessageContent(memoryContent, contextCharLimit),
474
+ content: limitContextMessageContent(`${GSD_CONTEXT_MESSAGE_SENTINEL}\n${memoryContent}`, contextCharLimit),
467
475
  display: false as const,
468
476
  };
469
477
  }
@@ -9,7 +9,12 @@ import { canonicalToolName } from "../engine-hook-contract.js";
9
9
  import { loadJsonFileOrNull } from "../json-persistence.js";
10
10
  import { getIsolationMode } from "../preferences.js";
11
11
  import { compileSubagentPermissionContract, type ToolsPolicy } from "../unit-context-manifest.js";
12
+ import {
13
+ allowedPlanningDispatchAgentsList,
14
+ isReadOnlyPlanningDispatchAgent,
15
+ } from "../planning-subagent-registry.js";
12
16
  import { logWarning } from "../workflow-logger.js";
17
+ import { acquireSyncLock, releaseSyncLock } from "../sync-lock.js";
13
18
  import { isGsdWorktreePath, resolveWorktreeProjectRoot } from "../worktree-root.js";
14
19
  import { worktreesDirs } from "../worktree-placement.js";
15
20
  import { bashReferencesProjectRootOutsideWorktree } from "../worktree-shell-guard.js";
@@ -364,12 +369,63 @@ export function refreshWriteGateStateFromDisk(basePath: string): WriteGateSnapsh
364
369
  return currentWriteGateSnapshot(basePath);
365
370
  }
366
371
 
372
+ const WRITE_GATE_LOCK_NAME = "write-gate.lock";
373
+
374
+ /**
375
+ * Test-only seam: fires once inside the held cross-process lock (after acquire,
376
+ * before the read-merge-write body) with the resolved lock root. Lets a
377
+ * regression test observe that a concurrent process is genuinely locked out of
378
+ * the critical section. Production leaves it null. Follows the repo's
379
+ * `_setGhAvailableForTest` naming convention.
380
+ */
381
+ let interleaveHookForTest: ((lockRoot: string) => void) | null = null;
382
+ export function _setWriteGateInterleaveHookForTest(fn: ((lockRoot: string) => void) | null): void {
383
+ interleaveHookForTest = fn;
384
+ }
385
+
386
+ /**
387
+ * Serialize the read-merge-write critical section across the two processes
388
+ * that share the snapshot file (extension host + workflow MCP child). Atomic
389
+ * rename prevents torn files but not lost updates: without this lock the host
390
+ * can read the snapshot, the child can arm a gate and persist, then the host's
391
+ * later persist overwrites `pendingGateId`/`activeQueuePhase` (last-writer-wins
392
+ * fields) and silently drops the armed HARD-BLOCK gate.
393
+ *
394
+ * Fail-OPEN by contract: if a live peer holds the lock we proceed WITHOUT it —
395
+ * exactly the racy-but-functional behavior that shipped before this lock — and
396
+ * log once. The lock shrinks the race window to ~zero; it must never block,
397
+ * throw, or refuse a gate mutation. The lock is skipped entirely when snapshot
398
+ * persistence is off (no disk file, no cross-process seam).
399
+ */
400
+ function withWriteGateLock<T>(basePath: string, fn: () => T): T {
401
+ if (!shouldPersistWriteGateSnapshot()) return fn();
402
+ const lockRoot = resolveWriteGateSnapshotRoot(basePath);
403
+ // Materialize `.gsd/` (including a dangling external-state symlink target)
404
+ // before locking. acquireSyncLock's own mkdir does NOT follow a symlink to
405
+ // create its target, so without this the O_EXCL open lands on a missing
406
+ // parent and the lock silently fails open — leaving the seam unserialized
407
+ // for exactly the external-state projects that need it. This is the same
408
+ // directory the persist path ensures anyway.
409
+ try { ensureWriteGateSnapshotDirectory(basePath); } catch { /* best-effort; acquire fails-open below */ }
410
+ const { acquired } = acquireSyncLock(lockRoot, 0, WRITE_GATE_LOCK_NAME);
411
+ if (!acquired) {
412
+ logWarning("intercept", "write-gate: proceeding without cross-process lock (held by live peer)", { lockRoot });
413
+ return fn();
414
+ }
415
+ try {
416
+ interleaveHookForTest?.(lockRoot);
417
+ return fn();
418
+ } finally {
419
+ releaseSyncLock(lockRoot, WRITE_GATE_LOCK_NAME);
420
+ }
421
+ }
422
+
367
423
  /**
368
424
  * Read-modify-write primitive for gate mutations. Reconciles the disk
369
425
  * snapshot into memory (union merge), applies the mutation on top, then
370
- * persists. The whole sequence is synchronous, so the reconcile read
371
- * doubles as the pre-persist merge of concurrent writes there is no
372
- * version field; the read-merge-write is simply unconditional.
426
+ * persists all under the cross-process lock (withWriteGateLock). The whole
427
+ * sequence is synchronous, so the reconcile read doubles as the pre-persist
428
+ * merge of concurrent writes; there is no version field.
373
429
  *
374
430
  * The mutate callback sees the already-reconciled state, so policy checks
375
431
  * (e.g. host setPending's verified-on-disk-wins guard) can live inside it
@@ -385,21 +441,23 @@ function mutateWriteGateState(
385
441
  opts?: { writer?: WriteGateWriter; reconcile?: boolean },
386
442
  ): boolean {
387
443
  const state = getWriteGateState(basePath);
388
- if (shouldPersistWriteGateSnapshot() && (opts?.reconcile ?? true)) {
389
- const disk = readDiskSnapshot(basePath);
390
- if (disk) {
391
- mergeSnapshotIntoState(state, disk);
392
- } else {
393
- // Missing OR unparseable on disk: treat as a full reset. Keeping
394
- // stale in-memory state across a corrupt snapshot would persist it
395
- // back on this very mutation and defeat the documented
396
- // "delete the file to clear the HARD BLOCK gate" escape hatch.
397
- replaceStateFromSnapshot(state, EMPTY_SNAPSHOT);
444
+ return withWriteGateLock(basePath, () => {
445
+ if (shouldPersistWriteGateSnapshot() && (opts?.reconcile ?? true)) {
446
+ const disk = readDiskSnapshot(basePath);
447
+ if (disk) {
448
+ mergeSnapshotIntoState(state, disk);
449
+ } else {
450
+ // Missing OR unparseable on disk: treat as a full reset. Keeping
451
+ // stale in-memory state across a corrupt snapshot would persist it
452
+ // back on this very mutation and defeat the documented
453
+ // "delete the file to clear the HARD BLOCK gate" escape hatch.
454
+ replaceStateFromSnapshot(state, EMPTY_SNAPSHOT);
455
+ }
398
456
  }
399
- }
400
- if (mutate(state) === false) return false;
401
- persistWriteGateSnapshot(basePath, opts?.writer ?? defaultWriteGateWriter());
402
- return true;
457
+ if (mutate(state) === false) return false;
458
+ persistWriteGateSnapshot(basePath, opts?.writer ?? defaultWriteGateWriter());
459
+ return true;
460
+ });
403
461
  }
404
462
 
405
463
  export function isDepthVerified(basePath: string = process.cwd()): boolean {
@@ -643,13 +701,15 @@ export const childWriteGateAdapter: WriteGateStateAdapter = {
643
701
 
644
702
  function childMutate(basePath: string, mutate: (state: InMemoryWriteGateState) => void): void {
645
703
  const state = getWriteGateState(basePath);
646
- if (shouldPersistWriteGateSnapshot()) {
647
- // Always-fresh: disk is the only truth for the child; discard any
648
- // cross-turn in-memory residue before mutating.
649
- replaceStateFromSnapshot(state, readDiskSnapshot(basePath) ?? EMPTY_SNAPSHOT);
650
- }
651
- mutate(state);
652
- persistWriteGateSnapshot(basePath, "child");
704
+ withWriteGateLock(basePath, () => {
705
+ if (shouldPersistWriteGateSnapshot()) {
706
+ // Always-fresh: disk is the only truth for the child; discard any
707
+ // cross-turn in-memory residue before mutating.
708
+ replaceStateFromSnapshot(state, readDiskSnapshot(basePath) ?? EMPTY_SNAPSHOT);
709
+ }
710
+ mutate(state);
711
+ persistWriteGateSnapshot(basePath, "child");
712
+ });
653
713
  }
654
714
 
655
715
  /**
@@ -1135,36 +1195,10 @@ export function shouldBlockQueueExecutionInSnapshot(
1135
1195
  const PLANNING_WRITE_TOOLS = new Set(["write", "edit", "multi_edit", "notebook_edit"]);
1136
1196
  const PLANNING_SUBAGENT_TOOLS = new Set(["subagent", "task"]);
1137
1197
 
1138
- /**
1139
- * Canonical registry for agents that planning-dispatch may consider. Unit
1140
- * manifests still declare per-unit subsets via ToolsPolicy.allowedSubagents.
1141
- */
1142
- const PLANNING_DISPATCH_AGENT_REGISTRY = {
1143
- mnemo: { readOnlySpecialist: true },
1144
- scout: { readOnlySpecialist: true },
1145
- planner: { readOnlySpecialist: true },
1146
- reviewer: { readOnlySpecialist: true },
1147
- security: { readOnlySpecialist: true },
1148
- tester: { readOnlySpecialist: true },
1149
- } as const satisfies Record<string, { readonly readOnlySpecialist: boolean }>;
1150
-
1151
- export const ALLOWED_PLANNING_DISPATCH_AGENTS = new Set<string>(
1152
- Object.entries(PLANNING_DISPATCH_AGENT_REGISTRY)
1153
- .filter(([, metadata]) => metadata.readOnlySpecialist)
1154
- .map(([agentId]) => agentId),
1155
- );
1198
+ export { ALLOWED_PLANNING_DISPATCH_AGENTS } from "../planning-subagent-registry.js";
1156
1199
 
1157
1200
  let warnedMissingControlledDispatchAgentClasses = false;
1158
1201
 
1159
- function isReadOnlySpecialist(agentId: string): boolean {
1160
- const metadata = PLANNING_DISPATCH_AGENT_REGISTRY[agentId as keyof typeof PLANNING_DISPATCH_AGENT_REGISTRY];
1161
- return metadata?.readOnlySpecialist === true;
1162
- }
1163
-
1164
- function allowedPlanningDispatchAgentsList(): string {
1165
- return [...ALLOWED_PLANNING_DISPATCH_AGENTS].join(", ");
1166
- }
1167
-
1168
1202
  function allowsControlledSubagentDispatch(
1169
1203
  policy: ToolsPolicy,
1170
1204
  ): policy is ToolsPolicy & { readonly allowedSubagents: readonly string[] } {
@@ -1337,7 +1371,7 @@ export function shouldBlockPlanningUnit(
1337
1371
  if (requested.length === 0) {
1338
1372
  return { block: false };
1339
1373
  }
1340
- const globallyDisallowed = requested.find(a => !isReadOnlySpecialist(a));
1374
+ const globallyDisallowed = requested.find(a => !isReadOnlyPlanningDispatchAgent(a));
1341
1375
  if (globallyDisallowed) {
1342
1376
  return planningBlock(
1343
1377
  unitType,
@@ -1350,7 +1384,7 @@ export function shouldBlockPlanningUnit(
1350
1384
  return planningBlock(
1351
1385
  unitType,
1352
1386
  policy.mode,
1353
- `subagent dispatch of "${disallowedByPolicy}" not permitted by ToolsPolicy.allowedSubagents; permitted agents for this unit: ${allowedSubagents.join(", ")}`,
1387
+ `subagent dispatch of "${disallowedByPolicy}" not permitted by unit allowlist (ToolsPolicy.allowedSubagents/planning_subagents); permitted agents for this unit: ${allowedSubagents.join(", ")}`,
1354
1388
  );
1355
1389
  }
1356
1390
  return { block: false };
@@ -96,22 +96,29 @@ export function notifyDiscussNeedsInteractiveMenu(
96
96
  });
97
97
  }
98
98
 
99
- /** Hub picker for /gsd queue (reorder vs add) is unavailable. */
99
+ /**
100
+ * Hub picker for /gsd queue (reorder vs add) is unavailable.
101
+ *
102
+ * Unlike the other picker-guidance notices, /gsd queue does NOT dead-end here:
103
+ * the caller falls through to the add-work flow, which runs headlessly. So this
104
+ * notice must avoid the "did not start:" picker-failure phrasing — the headless
105
+ * host classifies that as a blocked dead-end (see stop-notice.ts / #1294) and
106
+ * would exit 10 before the add-work run starts.
107
+ */
100
108
  export function notifyQueueHubNeedsInteractiveMenu(
101
109
  ctx: ExtensionCommandContext,
102
110
  reason: string,
103
111
  ): void {
104
- notifyPickerCommandNeedsInteractiveMenu(ctx, {
105
- command: "/gsd queue",
106
- reason,
107
- alternatives: [
108
- "Add-work flow can run headless — continuing with queue discussion.",
109
- ],
110
- hints: [
111
- "/gsd queue — run from the GSD TUI to reorder pending milestones",
112
- "/gsd status — see milestone order and phase",
113
- ],
114
- });
112
+ ctx.ui.notify(
113
+ [
114
+ `/gsd queue reorder menu needs an interactive session (${reason}).`,
115
+ "Continuing headless with the add-work flow.",
116
+ "",
117
+ " • /gsd queue — run from the GSD TUI to reorder pending milestones",
118
+ " • /gsd status — see milestone order and phase",
119
+ ].join("\n"),
120
+ "warning",
121
+ );
115
122
  }
116
123
 
117
124
  /** /gsd, /gsd new-milestone, /gsd new-project wizard menus. */
@@ -7,7 +7,7 @@
7
7
 
8
8
  import { createHash } from "node:crypto";
9
9
  import { existsSync, readFileSync, renameSync, unlinkSync, writeFileSync, mkdirSync } from "node:fs";
10
- import { dirname, join } from "node:path";
10
+ import { dirname, join, isAbsolute, normalize } from "node:path";
11
11
 
12
12
  /** Current marker schema version. Bump on breaking format changes + migrate. */
13
13
  export const COMPAT_MARKER_SCHEMA = 2;
@@ -34,8 +34,10 @@ export interface PlanningMarker {
34
34
 
35
35
  /**
36
36
  * Per-file projection entry. `sha` is a normalized-content SHA-256; `entities`
37
- * is the list of DB entity ids (milestone/slice/task) that the file projects,
38
- * so repair can scope re-import rather than re-importing the whole tree.
37
+ * is the list of DB entity ids (milestone/slice/task) that the file projects.
38
+ * External-edit repair derives milestone ids from this list so markdown status
39
+ * authority is limited to the drifted projection's milestone scope while the
40
+ * importer still walks the whole tree.
39
41
  */
40
42
  export interface ProjectionEntry {
41
43
  sha: string;
@@ -220,9 +222,24 @@ function isValidProjectionEntry(x: unknown): x is ProjectionEntry {
220
222
  return true;
221
223
  }
222
224
 
225
+ /**
226
+ * Projection-map keys are repo-relative paths under .gsd/ or .planning/.
227
+ * The marker is repo-controlled content, so a key must never escape its
228
+ * root: reject absolute paths, drive letters, backslashes, and any
229
+ * normalized form that starts with "..". Mirrors the write-side guard in
230
+ * db-writer.ts.
231
+ */
232
+ function isSafeProjectionKey(key: string): boolean {
233
+ if (key.length === 0 || key.includes("\\") || key.includes("\0")) return false;
234
+ if (isAbsolute(key) || /^[A-Za-z]:/.test(key)) return false;
235
+ const norm = normalize(key);
236
+ return norm !== ".." && !norm.startsWith("../") && !isAbsolute(norm);
237
+ }
238
+
223
239
  function isValidProjectionMap(x: unknown): boolean {
224
240
  if (typeof x !== "object" || x === null) return false;
225
- for (const v of Object.values(x as Record<string, unknown>)) {
241
+ for (const [k, v] of Object.entries(x as Record<string, unknown>)) {
242
+ if (!isSafeProjectionKey(k)) return false;
226
243
  if (!isValidProjectionEntry(v)) return false;
227
244
  }
228
245
  return true;
@@ -31,36 +31,37 @@ export const CACHE_MAX = 50;
31
31
  * By scoping tools to this allowlist during discuss dispatches, the grammar
32
32
  * sent to the provider stays well under provider limits.
33
33
  *
34
- * Included tools and why:
34
+ * Included tools and why (canonical names only — aliases are no longer
35
+ * advertised to models by default, see plan 035):
35
36
  * - gsd_summary_save: writes CONTEXT.md artifacts (all discuss prompts)
36
- * - gsd_save_summary: alias for above
37
37
  * - gsd_decision_save: records decisions (discuss.md output phase)
38
- * - gsd_save_decision: alias for above
39
38
  * - gsd_plan_milestone: writes roadmap (discuss.md single/multi milestone)
40
- * - gsd_milestone_plan: alias for above
41
39
  * - gsd_milestone_generate_id: generates milestone IDs (discuss.md multi-milestone)
42
- * - gsd_generate_milestone_id: alias for above
43
40
  * - gsd_requirement_save: creates requirements during discuss
44
- * - gsd_save_requirement: alias for above
45
41
  * - gsd_requirement_update: updates requirements during discuss
46
- * - gsd_update_requirement: alias for above
47
42
  */
48
43
  export const DISCUSS_TOOLS_ALLOWLIST: readonly string[] = [
49
44
  // Context / summary writing
50
45
  "gsd_summary_save",
51
- "gsd_save_summary",
52
46
  // Decision recording
53
47
  "gsd_decision_save",
54
- "gsd_save_decision",
55
48
  // Milestone planning (needed for discuss.md output phase)
56
49
  "gsd_plan_milestone",
57
- "gsd_milestone_plan",
58
50
  // Milestone ID generation (multi-milestone flow)
59
51
  "gsd_milestone_generate_id",
60
- "gsd_generate_milestone_id",
61
52
  // Requirement updates
62
53
  "gsd_requirement_save",
63
- "gsd_save_requirement",
64
54
  "gsd_requirement_update",
65
- "gsd_update_requirement",
66
55
  ];
56
+
57
+ // ─── Context Injection ────────────────────────────────────────────────────────
58
+
59
+ /**
60
+ * Leading marker stamped on every buildContextMessage() output
61
+ * (bootstrap/system-context.ts). Single source of truth for the producer and
62
+ * the consumer: the provider payload policy (filterSupersededContextInjections
63
+ * in context-masker.ts) matches this prefix to find and dedupe injected
64
+ * memory/guided/forensics messages after convertToLlm strips their customType.
65
+ * Both sides import it from here — do not inline the literal in either module.
66
+ */
67
+ export const GSD_CONTEXT_MESSAGE_SENTINEL = "[GSD Context Injection]";