@opengsd/gsd-pi 1.8.1 → 1.9.0-dev.97ef11e3

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 (613) 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 +27 -3
  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/loop.js +24 -4
  18. package/dist/resources/extensions/gsd/auto/run-unit.js +19 -1
  19. package/dist/resources/extensions/gsd/auto/unit-phase.js +37 -5
  20. package/dist/resources/extensions/gsd/auto-artifact-paths.js +16 -10
  21. package/dist/resources/extensions/gsd/auto-dispatch.js +76 -19
  22. package/dist/resources/extensions/gsd/auto-post-unit.js +4 -0
  23. package/dist/resources/extensions/gsd/auto-prompts.js +137 -22
  24. package/dist/resources/extensions/gsd/auto-recovery.js +10 -5
  25. package/dist/resources/extensions/gsd/auto-runtime-state.js +5 -5
  26. package/dist/resources/extensions/gsd/auto-start.js +29 -9
  27. package/dist/resources/extensions/gsd/auto-tool-tracking.js +40 -0
  28. package/dist/resources/extensions/gsd/auto-worktree-cleanup.js +4 -0
  29. package/dist/resources/extensions/gsd/auto-worktree-sync.js +7 -3
  30. package/dist/resources/extensions/gsd/auto-worktree-teardown.js +1 -1
  31. package/dist/resources/extensions/gsd/auto.js +20 -6
  32. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +80 -4
  33. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +33 -7
  34. package/dist/resources/extensions/gsd/bootstrap/system-context.js +10 -3
  35. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +88 -50
  36. package/dist/resources/extensions/gsd/command-feedback.js +16 -12
  37. package/dist/resources/extensions/gsd/commands-verdict.js +10 -9
  38. package/dist/resources/extensions/gsd/compat/compat-marker.js +98 -6
  39. package/dist/resources/extensions/gsd/constants.js +12 -13
  40. package/dist/resources/extensions/gsd/context-masker.js +97 -21
  41. package/dist/resources/extensions/gsd/db/command-queue.js +7 -2
  42. package/dist/resources/extensions/gsd/db/engine.js +56 -18
  43. package/dist/resources/extensions/gsd/db/writers/cascades.js +5 -1
  44. package/dist/resources/extensions/gsd/db/writers/status.js +13 -3
  45. package/dist/resources/extensions/gsd/db-base-schema.js +28 -0
  46. package/dist/resources/extensions/gsd/db-migration-steps.js +30 -0
  47. package/dist/resources/extensions/gsd/db-schema-metadata.js +4 -1
  48. package/dist/resources/extensions/gsd/docs/preferences-reference.md +26 -4
  49. package/dist/resources/extensions/gsd/doctor-engine-checks.js +24 -8
  50. package/dist/resources/extensions/gsd/error-classifier.js +12 -2
  51. package/dist/resources/extensions/gsd/exec-sandbox.js +1 -0
  52. package/dist/resources/extensions/gsd/flat-phase-migration.js +168 -21
  53. package/dist/resources/extensions/gsd/git-service.js +19 -7
  54. package/dist/resources/extensions/gsd/gsd-db.js +262 -76
  55. package/dist/resources/extensions/gsd/guided-flow.js +40 -15
  56. package/dist/resources/extensions/gsd/markdown-renderer.js +20 -22
  57. package/dist/resources/extensions/gsd/md-importer.js +107 -20
  58. package/dist/resources/extensions/gsd/migrate/command.js +19 -162
  59. package/dist/resources/extensions/gsd/migrate/execution.js +98 -0
  60. package/dist/resources/extensions/gsd/migrate/plan.js +49 -0
  61. package/dist/resources/extensions/gsd/migrate/planning-writer.js +12 -17
  62. package/dist/resources/extensions/gsd/migrate/presentation.js +64 -0
  63. package/dist/resources/extensions/gsd/model-cost-table.js +2 -0
  64. package/dist/resources/extensions/gsd/model-router.js +11 -0
  65. package/dist/resources/extensions/gsd/parallel-eligibility.js +5 -4
  66. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +28 -43
  67. package/dist/resources/extensions/gsd/paths.js +70 -16
  68. package/dist/resources/extensions/gsd/phase-anchor.js +7 -2
  69. package/dist/resources/extensions/gsd/planning-subagent-policy.js +37 -0
  70. package/dist/resources/extensions/gsd/planning-subagent-registry.js +25 -0
  71. package/dist/resources/extensions/gsd/post-execution-checks.js +4 -4
  72. package/dist/resources/extensions/gsd/preferences-types.js +5 -0
  73. package/dist/resources/extensions/gsd/preferences-validation.js +48 -1
  74. package/dist/resources/extensions/gsd/preferences.js +17 -0
  75. package/dist/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  76. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +5 -5
  77. package/dist/resources/extensions/gsd/provider-payload-policy.js +16 -5
  78. package/dist/resources/extensions/gsd/safety/destructive-guard.js +1 -1
  79. package/dist/resources/extensions/gsd/safety/evidence-collector.js +26 -1
  80. package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +30 -5
  81. package/dist/resources/extensions/gsd/skill-activation.js +17 -3
  82. package/dist/resources/extensions/gsd/state-reconciliation/drift/external-markdown-edit.js +125 -15
  83. package/dist/resources/extensions/gsd/state-reconciliation/drift/external-planning-edit.js +17 -4
  84. package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +5 -2
  85. package/dist/resources/extensions/gsd/stop-notice.js +24 -1
  86. package/dist/resources/extensions/gsd/sync-lock.js +13 -7
  87. package/dist/resources/extensions/gsd/templates/PREFERENCES.md +5 -0
  88. package/dist/resources/extensions/gsd/tools/complete-task.js +94 -6
  89. package/dist/resources/extensions/gsd/tools/plan-task.js +13 -15
  90. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +18 -15
  91. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +14 -5
  92. package/dist/resources/extensions/gsd/tools/reopen-slice.js +15 -5
  93. package/dist/resources/extensions/gsd/tools/reopen-task.js +16 -10
  94. package/dist/resources/extensions/gsd/tools/replan-task.js +128 -0
  95. package/dist/resources/extensions/gsd/tools/rework-brief.js +74 -0
  96. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +81 -0
  97. package/dist/resources/extensions/gsd/unit-context-composer.js +28 -5
  98. package/dist/resources/extensions/gsd/unit-registry.js +4 -0
  99. package/dist/resources/extensions/gsd/uok/plan-v2.js +19 -3
  100. package/dist/resources/extensions/gsd/workflow-projections.js +2 -3
  101. package/dist/resources/extensions/gsd/workspace.js +2 -1
  102. package/dist/resources/extensions/gsd/worktree-state-projection.js +26 -18
  103. package/dist/resources/extensions/mac-tools/index.js +31 -9
  104. package/dist/resources/extensions/shared/interview-ui.js +43 -6
  105. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  106. package/dist/web/standalone/.next/BUILD_ID +1 -1
  107. package/dist/web/standalone/.next/app-path-routes-manifest.json +7 -7
  108. package/dist/web/standalone/.next/build-manifest.json +3 -3
  109. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  110. package/dist/web/standalone/.next/required-server-files.json +3 -3
  111. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  112. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  113. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  114. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  122. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  124. package/dist/web/standalone/.next/server/app/_not-found.rsc +4 -4
  125. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -4
  126. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -4
  128. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  130. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  131. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  138. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  150. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/mcp-connections/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  172. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  182. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  188. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  195. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  196. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  197. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  199. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  200. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  201. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  202. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  203. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  204. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  205. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  206. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  207. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  208. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  209. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  210. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  211. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  212. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  213. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  214. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  215. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  216. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  217. package/dist/web/standalone/.next/server/app/index.html +1 -1
  218. package/dist/web/standalone/.next/server/app/index.rsc +5 -5
  219. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  220. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +5 -5
  221. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  222. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -4
  223. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  224. package/dist/web/standalone/.next/server/app/page.js +2 -2
  225. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  226. package/dist/web/standalone/.next/server/app-paths-manifest.json +7 -7
  227. package/dist/web/standalone/.next/server/chunks/1991.js +2 -2
  228. package/dist/web/standalone/.next/server/chunks/2842.js +4 -4
  229. package/dist/web/standalone/.next/server/chunks/5124.js +1 -1
  230. package/dist/web/standalone/.next/server/chunks/8357.js +3 -3
  231. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  232. package/dist/web/standalone/.next/server/middleware.js +3 -3
  233. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  234. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  235. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  236. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-a6fb1847f67f167c.js +1 -0
  237. package/dist/web/standalone/.next/static/chunks/app/{layout-b35cbfff38aaf4cf.js → layout-4ae2d68984392bbf.js} +1 -1
  238. package/dist/web/standalone/.next/static/chunks/app/page-72a856634ad14c10.js +1 -0
  239. package/dist/web/standalone/.next/static/chunks/{main-app-590a74400e35f685.js → main-app-90d1d8d5e5d2dc6b.js} +1 -1
  240. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-1115d46ac61b9823.js +1 -0
  241. package/dist/web/standalone/.next/static/css/3b1ceb7abfb9a230.css +1 -0
  242. package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
  243. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  244. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  245. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  246. package/dist/web/standalone/package.json +0 -1
  247. package/dist/web/standalone/server.js +1 -1
  248. package/dist/web-mode.js +31 -3
  249. package/integrations/hermes/open_gsd_hermes/gsd_client.py +1 -1
  250. package/integrations/hermes/pyproject.toml +1 -1
  251. package/package.json +13 -10
  252. package/packages/cloud-mcp-gateway/package.json +2 -2
  253. package/packages/contracts/dist/workflow.d.ts +14 -0
  254. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  255. package/packages/contracts/dist/workflow.js +16 -0
  256. package/packages/contracts/dist/workflow.js.map +1 -1
  257. package/packages/contracts/package.json +1 -1
  258. package/packages/daemon/dist/cloud-config.d.ts +1 -1
  259. package/packages/daemon/dist/cloud-config.d.ts.map +1 -1
  260. package/packages/daemon/dist/cloud-config.js +5 -1
  261. package/packages/daemon/dist/cloud-config.js.map +1 -1
  262. package/packages/daemon/dist/cloud-config.test.js +51 -1
  263. package/packages/daemon/dist/cloud-config.test.js.map +1 -1
  264. package/packages/daemon/dist/local-tool-executor.d.ts.map +1 -1
  265. package/packages/daemon/dist/local-tool-executor.js +2 -0
  266. package/packages/daemon/dist/local-tool-executor.js.map +1 -1
  267. package/packages/daemon/package.json +6 -6
  268. package/packages/gsd-agent-core/dist/compaction/compaction.d.ts.map +1 -1
  269. package/packages/gsd-agent-core/dist/compaction/compaction.js +36 -4
  270. package/packages/gsd-agent-core/dist/compaction/compaction.js.map +1 -1
  271. package/packages/gsd-agent-core/dist/sdk.d.ts.map +1 -1
  272. package/packages/gsd-agent-core/dist/sdk.js +1 -0
  273. package/packages/gsd-agent-core/dist/sdk.js.map +1 -1
  274. package/packages/gsd-agent-core/package.json +5 -5
  275. package/packages/gsd-agent-modes/package.json +7 -7
  276. package/packages/gsd-cloud/README.md +9 -3
  277. package/packages/gsd-cloud/dist/background-cli.test.d.ts +2 -0
  278. package/packages/gsd-cloud/dist/background-cli.test.d.ts.map +1 -0
  279. package/packages/gsd-cloud/dist/background-cli.test.js +248 -0
  280. package/packages/gsd-cloud/dist/background-cli.test.js.map +1 -0
  281. package/packages/gsd-cloud/dist/cli.d.ts +5 -0
  282. package/packages/gsd-cloud/dist/cli.d.ts.map +1 -0
  283. package/packages/gsd-cloud/dist/cli.js +266 -0
  284. package/packages/gsd-cloud/dist/cli.js.map +1 -0
  285. package/packages/gsd-cloud/dist/cloud-config.d.ts +19 -0
  286. package/packages/gsd-cloud/dist/cloud-config.d.ts.map +1 -0
  287. package/packages/gsd-cloud/dist/cloud-config.js +237 -0
  288. package/packages/gsd-cloud/dist/cloud-config.js.map +1 -0
  289. package/packages/gsd-cloud/dist/cloud-config.test.d.ts +2 -0
  290. package/packages/gsd-cloud/dist/cloud-config.test.d.ts.map +1 -0
  291. package/packages/gsd-cloud/dist/cloud-config.test.js +118 -0
  292. package/packages/gsd-cloud/dist/cloud-config.test.js.map +1 -0
  293. package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.d.ts +2 -0
  294. package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.d.ts.map +1 -0
  295. package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.js +37 -0
  296. package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.js.map +1 -0
  297. package/packages/gsd-cloud/dist/cloud-runtime.d.ts +33 -0
  298. package/packages/gsd-cloud/dist/cloud-runtime.d.ts.map +1 -0
  299. package/packages/gsd-cloud/dist/cloud-runtime.js +260 -0
  300. package/packages/gsd-cloud/dist/cloud-runtime.js.map +1 -0
  301. package/packages/gsd-cloud/dist/cloud-runtime.test.d.ts +2 -0
  302. package/packages/gsd-cloud/dist/cloud-runtime.test.d.ts.map +1 -0
  303. package/packages/gsd-cloud/dist/cloud-runtime.test.js +88 -0
  304. package/packages/gsd-cloud/dist/cloud-runtime.test.js.map +1 -0
  305. package/packages/gsd-cloud/dist/cloud-token.d.ts +3 -0
  306. package/packages/gsd-cloud/dist/cloud-token.d.ts.map +1 -0
  307. package/packages/gsd-cloud/dist/cloud-token.js +37 -0
  308. package/packages/gsd-cloud/dist/cloud-token.js.map +1 -0
  309. package/packages/gsd-cloud/dist/config.d.ts +17 -0
  310. package/packages/gsd-cloud/dist/config.d.ts.map +1 -0
  311. package/packages/gsd-cloud/dist/config.js +146 -0
  312. package/packages/gsd-cloud/dist/config.js.map +1 -0
  313. package/packages/gsd-cloud/dist/device-flow.d.ts +24 -0
  314. package/packages/gsd-cloud/dist/device-flow.d.ts.map +1 -0
  315. package/packages/gsd-cloud/dist/device-flow.js +128 -0
  316. package/packages/gsd-cloud/dist/device-flow.js.map +1 -0
  317. package/packages/gsd-cloud/dist/device-flow.test.d.ts +2 -0
  318. package/packages/gsd-cloud/dist/device-flow.test.d.ts.map +1 -0
  319. package/packages/gsd-cloud/dist/device-flow.test.js +155 -0
  320. package/packages/gsd-cloud/dist/device-flow.test.js.map +1 -0
  321. package/packages/gsd-cloud/dist/executors/claude-executor.d.ts +6 -0
  322. package/packages/gsd-cloud/dist/executors/claude-executor.d.ts.map +1 -0
  323. package/packages/gsd-cloud/dist/executors/claude-executor.js +15 -0
  324. package/packages/gsd-cloud/dist/executors/claude-executor.js.map +1 -0
  325. package/packages/gsd-cloud/dist/executors/codex-executor.d.ts +6 -0
  326. package/packages/gsd-cloud/dist/executors/codex-executor.d.ts.map +1 -0
  327. package/packages/gsd-cloud/dist/executors/codex-executor.js +15 -0
  328. package/packages/gsd-cloud/dist/executors/codex-executor.js.map +1 -0
  329. package/packages/gsd-cloud/dist/executors/executor.d.ts +28 -0
  330. package/packages/gsd-cloud/dist/executors/executor.d.ts.map +1 -0
  331. package/packages/gsd-cloud/dist/executors/executor.js +11 -0
  332. package/packages/gsd-cloud/dist/executors/executor.js.map +1 -0
  333. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.d.ts +34 -0
  334. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.d.ts.map +1 -0
  335. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.js +179 -0
  336. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.js.map +1 -0
  337. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.d.ts +2 -0
  338. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.d.ts.map +1 -0
  339. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.js +44 -0
  340. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.js.map +1 -0
  341. package/packages/gsd-cloud/dist/executors/index.d.ts +17 -0
  342. package/packages/gsd-cloud/dist/executors/index.d.ts.map +1 -0
  343. package/packages/gsd-cloud/dist/executors/index.js +29 -0
  344. package/packages/gsd-cloud/dist/executors/index.js.map +1 -0
  345. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.d.ts +36 -0
  346. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.d.ts.map +1 -0
  347. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.js +176 -0
  348. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.js.map +1 -0
  349. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.d.ts +2 -0
  350. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.d.ts.map +1 -0
  351. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.js +34 -0
  352. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.js.map +1 -0
  353. package/packages/gsd-cloud/dist/index.d.ts +7 -0
  354. package/packages/gsd-cloud/dist/index.d.ts.map +1 -0
  355. package/packages/gsd-cloud/dist/index.js +8 -0
  356. package/packages/gsd-cloud/dist/index.js.map +1 -0
  357. package/packages/gsd-cloud/dist/inject-gateway.d.ts +16 -0
  358. package/packages/gsd-cloud/dist/inject-gateway.d.ts.map +1 -0
  359. package/packages/gsd-cloud/dist/inject-gateway.js +29 -0
  360. package/packages/gsd-cloud/dist/inject-gateway.js.map +1 -0
  361. package/packages/gsd-cloud/dist/inject-gateway.test.d.ts +2 -0
  362. package/packages/gsd-cloud/dist/inject-gateway.test.d.ts.map +1 -0
  363. package/packages/gsd-cloud/dist/inject-gateway.test.js +41 -0
  364. package/packages/gsd-cloud/dist/inject-gateway.test.js.map +1 -0
  365. package/packages/gsd-cloud/dist/logger.d.ts +25 -0
  366. package/packages/gsd-cloud/dist/logger.d.ts.map +1 -0
  367. package/packages/gsd-cloud/dist/logger.js +72 -0
  368. package/packages/gsd-cloud/dist/logger.js.map +1 -0
  369. package/packages/gsd-cloud/dist/runtime-process.d.ts +27 -0
  370. package/packages/gsd-cloud/dist/runtime-process.d.ts.map +1 -0
  371. package/packages/gsd-cloud/dist/runtime-process.js +272 -0
  372. package/packages/gsd-cloud/dist/runtime-process.js.map +1 -0
  373. package/packages/gsd-cloud/dist/runtime-process.test.d.ts +2 -0
  374. package/packages/gsd-cloud/dist/runtime-process.test.d.ts.map +1 -0
  375. package/packages/gsd-cloud/dist/runtime-process.test.js +97 -0
  376. package/packages/gsd-cloud/dist/runtime-process.test.js.map +1 -0
  377. package/packages/gsd-cloud/dist/types.d.ts +51 -0
  378. package/packages/gsd-cloud/dist/types.d.ts.map +1 -0
  379. package/packages/gsd-cloud/dist/types.js +9 -0
  380. package/packages/gsd-cloud/dist/types.js.map +1 -0
  381. package/packages/gsd-cloud/package.json +3 -3
  382. package/packages/mcp-server/README.md +15 -2
  383. package/packages/mcp-server/dist/cli-runner.d.ts +3 -0
  384. package/packages/mcp-server/dist/cli-runner.d.ts.map +1 -1
  385. package/packages/mcp-server/dist/cli-runner.js +119 -33
  386. package/packages/mcp-server/dist/cli-runner.js.map +1 -1
  387. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  388. package/packages/mcp-server/dist/server.js +5 -5
  389. package/packages/mcp-server/dist/server.js.map +1 -1
  390. package/packages/mcp-server/dist/workflow-tools.d.ts +4 -3
  391. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  392. package/packages/mcp-server/dist/workflow-tools.js +64 -2
  393. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  394. package/packages/mcp-server/package.json +4 -4
  395. package/packages/native/package.json +1 -1
  396. package/packages/pi-agent-core/dist/agent.d.ts +5 -1
  397. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  398. package/packages/pi-agent-core/dist/agent.js +2 -0
  399. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  400. package/packages/pi-agent-core/package.json +1 -1
  401. package/packages/pi-ai/dist/models.generated.d.ts +136 -0
  402. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  403. package/packages/pi-ai/dist/models.generated.js +124 -0
  404. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  405. package/packages/pi-ai/dist/providers/amazon-bedrock.js +1 -0
  406. package/packages/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
  407. package/packages/pi-ai/dist/providers/anthropic.js +25 -1
  408. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  409. package/packages/pi-ai/dist/providers/openai-codex-responses.js +1 -1
  410. package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
  411. package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  412. package/packages/pi-ai/dist/providers/openai-completions.js +103 -0
  413. package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
  414. package/packages/pi-ai/dist/providers/openai-responses.js +1 -1
  415. package/packages/pi-ai/dist/providers/openai-responses.js.map +1 -1
  416. package/packages/pi-ai/package.json +1 -1
  417. package/packages/pi-coding-agent/dist/core/capability-patches.js +1 -1
  418. package/packages/pi-coding-agent/dist/core/capability-patches.js.map +1 -1
  419. package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -1
  420. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  421. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +11 -1
  422. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  423. package/packages/pi-coding-agent/dist/core/settings-manager.js +8 -0
  424. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  425. package/packages/pi-coding-agent/package.json +7 -7
  426. package/packages/pi-tui/package.json +2 -2
  427. package/packages/rpc-client/package.json +2 -2
  428. package/pkg/package.json +1 -1
  429. package/src/resources/GSD-WORKFLOW.md +18 -49
  430. package/src/resources/extensions/browser-tools/capture.ts +2 -86
  431. package/src/resources/extensions/browser-tools/screenshot-constraints.ts +94 -0
  432. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +18 -1
  433. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +108 -0
  434. package/src/resources/extensions/claude-code-cli/turn-assembler.ts +30 -2
  435. package/src/resources/extensions/gsd/artifact-verification.ts +3 -8
  436. package/src/resources/extensions/gsd/auto/loop.ts +48 -4
  437. package/src/resources/extensions/gsd/auto/run-unit.ts +20 -1
  438. package/src/resources/extensions/gsd/auto/unit-phase.ts +41 -5
  439. package/src/resources/extensions/gsd/auto-artifact-paths.ts +16 -9
  440. package/src/resources/extensions/gsd/auto-dispatch.ts +87 -19
  441. package/src/resources/extensions/gsd/auto-post-unit.ts +4 -0
  442. package/src/resources/extensions/gsd/auto-prompts.ts +156 -20
  443. package/src/resources/extensions/gsd/auto-recovery.ts +10 -8
  444. package/src/resources/extensions/gsd/auto-runtime-state.ts +12 -7
  445. package/src/resources/extensions/gsd/auto-start.ts +31 -8
  446. package/src/resources/extensions/gsd/auto-tool-tracking.ts +56 -0
  447. package/src/resources/extensions/gsd/auto-worktree-cleanup.ts +4 -0
  448. package/src/resources/extensions/gsd/auto-worktree-sync.ts +10 -3
  449. package/src/resources/extensions/gsd/auto-worktree-teardown.ts +1 -1
  450. package/src/resources/extensions/gsd/auto.ts +25 -8
  451. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +92 -4
  452. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +41 -12
  453. package/src/resources/extensions/gsd/bootstrap/system-context.ts +11 -3
  454. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +87 -53
  455. package/src/resources/extensions/gsd/command-feedback.ts +19 -12
  456. package/src/resources/extensions/gsd/commands-verdict.ts +16 -9
  457. package/src/resources/extensions/gsd/compat/compat-marker.ts +119 -8
  458. package/src/resources/extensions/gsd/constants.ts +14 -13
  459. package/src/resources/extensions/gsd/context-masker.ts +98 -2
  460. package/src/resources/extensions/gsd/db/command-queue.ts +7 -1
  461. package/src/resources/extensions/gsd/db/engine.ts +58 -19
  462. package/src/resources/extensions/gsd/db/writers/cascades.ts +5 -1
  463. package/src/resources/extensions/gsd/db/writers/status.ts +25 -8
  464. package/src/resources/extensions/gsd/db-base-schema.ts +30 -0
  465. package/src/resources/extensions/gsd/db-migration-steps.ts +32 -0
  466. package/src/resources/extensions/gsd/db-schema-metadata.ts +4 -1
  467. package/src/resources/extensions/gsd/docs/preferences-reference.md +26 -4
  468. package/src/resources/extensions/gsd/doctor-engine-checks.ts +30 -7
  469. package/src/resources/extensions/gsd/error-classifier.ts +13 -2
  470. package/src/resources/extensions/gsd/exec-sandbox.ts +1 -0
  471. package/src/resources/extensions/gsd/flat-phase-migration.ts +174 -19
  472. package/src/resources/extensions/gsd/git-service.ts +19 -6
  473. package/src/resources/extensions/gsd/gsd-db.ts +340 -85
  474. package/src/resources/extensions/gsd/guided-flow.ts +50 -14
  475. package/src/resources/extensions/gsd/markdown-renderer.ts +28 -30
  476. package/src/resources/extensions/gsd/md-importer.ts +114 -16
  477. package/src/resources/extensions/gsd/migrate/command.ts +21 -227
  478. package/src/resources/extensions/gsd/migrate/execution.ts +136 -0
  479. package/src/resources/extensions/gsd/migrate/plan.ts +101 -0
  480. package/src/resources/extensions/gsd/migrate/planning-writer.ts +12 -20
  481. package/src/resources/extensions/gsd/migrate/presentation.ts +83 -0
  482. package/src/resources/extensions/gsd/model-cost-table.ts +2 -0
  483. package/src/resources/extensions/gsd/model-router.ts +12 -0
  484. package/src/resources/extensions/gsd/parallel-eligibility.ts +5 -4
  485. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +37 -40
  486. package/src/resources/extensions/gsd/paths.ts +77 -16
  487. package/src/resources/extensions/gsd/phase-anchor.ts +8 -2
  488. package/src/resources/extensions/gsd/planning-subagent-policy.ts +58 -0
  489. package/src/resources/extensions/gsd/planning-subagent-registry.ts +31 -0
  490. package/src/resources/extensions/gsd/post-execution-checks.ts +4 -4
  491. package/src/resources/extensions/gsd/preferences-types.ts +16 -0
  492. package/src/resources/extensions/gsd/preferences-validation.ts +62 -0
  493. package/src/resources/extensions/gsd/preferences.ts +25 -0
  494. package/src/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  495. package/src/resources/extensions/gsd/prompts/validate-milestone.md +5 -5
  496. package/src/resources/extensions/gsd/provider-payload-policy.ts +18 -4
  497. package/src/resources/extensions/gsd/safety/destructive-guard.ts +1 -1
  498. package/src/resources/extensions/gsd/safety/evidence-collector.ts +28 -1
  499. package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +31 -5
  500. package/src/resources/extensions/gsd/skill-activation.ts +17 -3
  501. package/src/resources/extensions/gsd/state-reconciliation/drift/external-markdown-edit.ts +162 -15
  502. package/src/resources/extensions/gsd/state-reconciliation/drift/external-planning-edit.ts +20 -4
  503. package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +4 -2
  504. package/src/resources/extensions/gsd/state-reconciliation/types.ts +2 -2
  505. package/src/resources/extensions/gsd/stop-notice.ts +29 -1
  506. package/src/resources/extensions/gsd/sync-lock.ts +14 -6
  507. package/src/resources/extensions/gsd/templates/PREFERENCES.md +5 -0
  508. package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +7 -7
  509. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +264 -0
  510. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +39 -0
  511. package/src/resources/extensions/gsd/tests/auto-start-index-lock.test.ts +21 -1
  512. package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +74 -1
  513. package/src/resources/extensions/gsd/tests/before-provider-context-management.test.ts +55 -0
  514. package/src/resources/extensions/gsd/tests/closeout-git-deferral.test.ts +96 -1
  515. package/src/resources/extensions/gsd/tests/command-feedback.test.ts +12 -0
  516. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +10 -0
  517. package/src/resources/extensions/gsd/tests/compat-marker.test.ts +129 -0
  518. package/src/resources/extensions/gsd/tests/complete-task.test.ts +362 -1
  519. package/src/resources/extensions/gsd/tests/context-masker.test.ts +204 -8
  520. package/src/resources/extensions/gsd/tests/db-engine-cjs-compat.test.ts +12 -0
  521. package/src/resources/extensions/gsd/tests/db-engine-migrate-guards.test.ts +186 -0
  522. package/src/resources/extensions/gsd/tests/db-tools-alias-suppression.test.ts +62 -0
  523. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +29 -0
  524. package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +33 -0
  525. package/src/resources/extensions/gsd/tests/destructive-guard.test.ts +14 -0
  526. package/src/resources/extensions/gsd/tests/discuss-routing-fixes.test.ts +123 -0
  527. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +50 -0
  528. package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +49 -0
  529. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +83 -0
  530. package/src/resources/extensions/gsd/tests/evidence-cross-ref.test.ts +81 -0
  531. package/src/resources/extensions/gsd/tests/evidence-xref-gsd-exec.test.ts +22 -0
  532. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +33 -1
  533. package/src/resources/extensions/gsd/tests/external-edit-scoped-import.test.ts +262 -0
  534. package/src/resources/extensions/gsd/tests/external-markdown-edit.test.ts +38 -1
  535. package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +201 -0
  536. package/src/resources/extensions/gsd/tests/flat-phase-validation-path.test.ts +20 -1
  537. package/src/resources/extensions/gsd/tests/gate-storage.test.ts +29 -0
  538. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +57 -0
  539. package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +22 -0
  540. package/src/resources/extensions/gsd/tests/import-slice-milestone-completion-preserve.test.ts +116 -0
  541. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +13 -0
  542. package/src/resources/extensions/gsd/tests/integration/paths.test.ts +22 -4
  543. package/src/resources/extensions/gsd/tests/integration-branch-meta-location.test.ts +62 -0
  544. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +5 -5
  545. package/src/resources/extensions/gsd/tests/migrate-plan.test.ts +68 -0
  546. package/src/resources/extensions/gsd/tests/migrate-presentation.test.ts +98 -0
  547. package/src/resources/extensions/gsd/tests/migrate-safety-audit.test.ts +1 -1
  548. package/src/resources/extensions/gsd/tests/milestone-leases.test.ts +55 -0
  549. package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +9 -1
  550. package/src/resources/extensions/gsd/tests/model-router.test.ts +1 -1
  551. package/src/resources/extensions/gsd/tests/parallel-eligibility-file-overlap.test.ts +146 -0
  552. package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +59 -0
  553. package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +7 -5
  554. package/src/resources/extensions/gsd/tests/phase-anchor.test.ts +32 -4
  555. package/src/resources/extensions/gsd/tests/plan-task.test.ts +26 -23
  556. package/src/resources/extensions/gsd/tests/planning-writer.test.ts +29 -0
  557. package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +22 -0
  558. package/src/resources/extensions/gsd/tests/preferences.test.ts +84 -0
  559. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +4 -0
  560. package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +87 -0
  561. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +121 -1
  562. package/src/resources/extensions/gsd/tests/reactive-executor.test.ts +39 -0
  563. package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +50 -0
  564. package/src/resources/extensions/gsd/tests/register-hooks-loop-guard-auto.test.ts +105 -0
  565. package/src/resources/extensions/gsd/tests/replan-task-handler.test.ts +103 -0
  566. package/src/resources/extensions/gsd/tests/rework-brief.test.ts +197 -0
  567. package/src/resources/extensions/gsd/tests/service-tier.test.ts +4 -0
  568. package/src/resources/extensions/gsd/tests/single-writer-v3-tool-surface.test.ts +33 -7
  569. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +20 -16
  570. package/src/resources/extensions/gsd/tests/skip-slice-cascades-tasks.test.ts +21 -0
  571. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +52 -0
  572. package/src/resources/extensions/gsd/tests/stop-notice.test.ts +38 -1
  573. package/src/resources/extensions/gsd/tests/sync-lock.test.ts +19 -0
  574. package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +13 -7
  575. package/src/resources/extensions/gsd/tests/terminated-transient.test.ts +14 -0
  576. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +19 -0
  577. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +8 -0
  578. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +73 -0
  579. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +93 -1
  580. package/src/resources/extensions/gsd/tests/validate-milestone-prompt-verification-classes.test.ts +7 -0
  581. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -0
  582. package/src/resources/extensions/gsd/tests/workflow-migration-gates.test.ts +139 -0
  583. package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +4 -4
  584. package/src/resources/extensions/gsd/tests/worktree-state-projection.test.ts +36 -0
  585. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +60 -0
  586. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +34 -0
  587. package/src/resources/extensions/gsd/tests/write-gate-seam.test.ts +52 -0
  588. package/src/resources/extensions/gsd/tools/complete-task.ts +140 -5
  589. package/src/resources/extensions/gsd/tools/plan-task.ts +14 -16
  590. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +18 -17
  591. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +24 -5
  592. package/src/resources/extensions/gsd/tools/reopen-slice.ts +25 -5
  593. package/src/resources/extensions/gsd/tools/reopen-task.ts +23 -9
  594. package/src/resources/extensions/gsd/tools/replan-task.ts +160 -0
  595. package/src/resources/extensions/gsd/tools/rework-brief.ts +91 -0
  596. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +92 -0
  597. package/src/resources/extensions/gsd/types.ts +11 -0
  598. package/src/resources/extensions/gsd/unit-context-composer.ts +34 -8
  599. package/src/resources/extensions/gsd/unit-registry.ts +4 -0
  600. package/src/resources/extensions/gsd/uok/plan-v2.ts +20 -3
  601. package/src/resources/extensions/gsd/workflow-projections.ts +2 -3
  602. package/src/resources/extensions/gsd/workspace.ts +2 -1
  603. package/src/resources/extensions/gsd/worktree-state-projection.ts +33 -24
  604. package/src/resources/extensions/mac-tools/index.ts +52 -9
  605. package/src/resources/extensions/mac-tools/tests/mac-screenshot-payload.test.cjs +70 -0
  606. package/src/resources/extensions/shared/interview-ui.ts +47 -8
  607. package/src/resources/extensions/shared/tests/interview-ui-border.test.ts +29 -0
  608. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-49f565245e1e4afe.js +0 -1
  609. package/dist/web/standalone/.next/static/chunks/app/page-bc4c723c6a19c6f0.js +0 -1
  610. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ec3eaffc9785ba48.js +0 -1
  611. package/dist/web/standalone/.next/static/css/18c2fdf261bfc1b7.css +0 -1
  612. /package/dist/web/standalone/.next/static/{UaXRrOYxBpG9QBINKhZkg → DXD9fZPnqtjZSlT5xdC3v}/_buildManifest.js +0 -0
  613. /package/dist/web/standalone/.next/static/{UaXRrOYxBpG9QBINKhZkg → DXD9fZPnqtjZSlT5xdC3v}/_ssgManifest.js +0 -0
@@ -635,6 +635,7 @@ function mergePreferences(base, override) {
635
635
  : undefined,
636
636
  post_unit_hooks: mergePostUnitHooks(base.post_unit_hooks, override.post_unit_hooks),
637
637
  pre_dispatch_hooks: mergePreDispatchHooks(base.pre_dispatch_hooks, override.pre_dispatch_hooks),
638
+ planning_subagents: mergePlanningSubagents(base.planning_subagents, override.planning_subagents),
638
639
  dynamic_routing: (base.dynamic_routing || override.dynamic_routing)
639
640
  ? { ...(base.dynamic_routing ?? {}), ...(override.dynamic_routing ?? {}) }
640
641
  : undefined,
@@ -752,6 +753,22 @@ function mergePreDispatchHooks(base, override) {
752
753
  }
753
754
  return merged.length > 0 ? merged : undefined;
754
755
  }
756
+ function mergePlanningSubagents(base, override) {
757
+ if (!base && !override)
758
+ return undefined;
759
+ const merged = {};
760
+ const unitTypes = new Set([
761
+ ...Object.keys(base ?? {}),
762
+ ...Object.keys(override ?? {}),
763
+ ]);
764
+ for (const unitType of unitTypes) {
765
+ const allowed = mergeStringLists(base?.[unitType]?.allowed, override?.[unitType]?.allowed);
766
+ if (allowed?.length) {
767
+ merged[unitType] = { allowed };
768
+ }
769
+ }
770
+ return Object.keys(merged).length > 0 ? merged : undefined;
771
+ }
755
772
  // ─── System Prompt Rendering ──────────────────────────────────────────────────
756
773
  export function renderPreferencesForSystemPrompt(preferences, resolutions, options) {
757
774
  const validated = validatePreferences(preferences);
@@ -66,12 +66,12 @@ Then:
66
66
  **Web apps:** when inlined Web App UAT guidance is present, follow it for Playwright scaffolding and browser-capable verification commands.
67
67
  4. For non-trivial slices, plan observability / proof level / integration closure, threat surface, and requirement impact. Omit entirely for simple slices.
68
68
  5. Decompose the slice into tasks that fit one context window each. Every task passed to `gsd_plan_slice` must use the exact keys `taskId`, `title`, `description`, `estimate`, `files`, `verify`, `inputs`, `expectedOutput`, and optional `observabilityImpact`. Put Why / Do / Done-when detail in `description`. `files`, `inputs`, and `expectedOutput` must be JSON arrays of strings, even for one path (for example, `"expectedOutput": ["src/index.ts"]`, never `"expectedOutput": "src/index.ts"`). `expectedOutput` is path-only: list only files the task creates or overwrites, and use `[]` for pure verification tasks. Never list GSD planning artifacts — anything under `.gsd/`, `.planning/`, or `.audits/`, or artifact names like `M001-CONTEXT.md` / `S01-PLAN.md` — in `inputs`, `files`, or `expectedOutput`: their content is preloaded as context, and they are written by workflow tools, not by tasks.
69
- 6. **Persist planning state through `gsd_plan_slice`.** Call it with the full payload. The tool writes to the DB and renders `{{outputPath}}` and `{{slicePath}}/tasks/T##-PLAN.md` automatically. Do NOT rely on direct `PLAN.md` writes.
69
+ 6. **Persist planning state through `gsd_plan_slice`.** Call it with the full payload. The tool writes to the DB and renders `{{outputPath}}` with embedded task planning automatically. Do NOT rely on direct `PLAN.md` writes.
70
70
  7. **Self-audit the plan.** If every task were completed exactly as written, the slice goal/demo should be true. Every must-have maps to a task. Inputs and Expected Output are backtick-wrapped file paths.
71
71
  8. If refinement produced structural decisions that diverge from the sketch, call `gsd_decision_save` for each; the tool persists the decision and regenerates `.gsd/DECISIONS.md`.
72
72
  9. {{commitInstruction}}
73
73
 
74
- The slice directory and tasks/ subdirectory already exist. Do NOT mkdir.
74
+ The slice plan path already exists. Do NOT mkdir.
75
75
 
76
76
  **Autonomous execution:** Do not call `ask_user_questions` or `secure_env_collect`. Document assumptions in the plan.
77
77
 
@@ -24,18 +24,18 @@ Roadmap, slice summaries, assessments, requirements, decisions, and project cont
24
24
 
25
25
  ### Step 1 - Dispatch Parallel Reviewers
26
26
 
27
- The Inlined Context above already preloads the evidence reviewers need — the roadmap, per-slice SUMMARY/ASSESSMENT excerpts, requirements, and verification classes. **Embed the relevant preloaded evidence directly into each reviewer's task prompt** so reviewers work from it instead of re-reading the same artifacts from disk. Each reviewer should read a full file only when its excerpt is missing, truncated, or internally inconsistent — never as a routine first step. This avoids three reviewers independently re-surveying artifacts the orchestrator already holds.
27
+ The Inlined Context above already preloads the evidence reviewers need — the roadmap, per-slice SUMMARY/ASSESSMENT excerpts, requirements, and verification classes. **Embed the relevant preloaded evidence directly into each reviewer's task prompt** so reviewers work from it instead of re-reading the same artifacts from disk. Each reviewer should read a full file only when its excerpt is missing, truncated, or internally inconsistent — never as a routine first step. When a reviewer needs a full artifact, use only explicit file paths from the On-demand Validation Artifacts / On-demand Milestone Context blocks or discover files with `find .gsd -type f`; never pass a phase, slice, `tasks/`, or `slices/` directory to `read` or `readFileSync`. This avoids three reviewers independently re-surveying artifacts the orchestrator already holds.
28
28
 
29
29
  Call `subagent` with `tasks: [...]` containing ALL THREE reviewers simultaneously:
30
30
 
31
31
  **Reviewer A - Requirements Coverage**
32
- Prompt: "Review milestone {{milestoneId}} requirements coverage. Working directory: {{workingDirectory}}. Use the preloaded requirements and slice SUMMARY evidence embedded in this task — do not re-read them from disk. For each requirement, mark COVERED, PARTIAL, or MISSING against that evidence. Read a full SUMMARY under `.gsd/milestones/{{milestoneId}}/slices/` only if its preloaded excerpt is missing, truncated, or inconsistent. Output table: Requirement | Status | Evidence. End with one-line verdict: PASS if all covered, NEEDS-ATTENTION if partials exist, FAIL if any missing."
32
+ Prompt: "Review milestone {{milestoneId}} requirements coverage. Working directory: {{workingDirectory}}. Use the preloaded requirements and slice SUMMARY evidence embedded in this task — do not re-read them from disk. For each requirement, mark COVERED, PARTIAL, or MISSING against that evidence. Read a full SUMMARY only from an explicit file path in the On-demand Validation Artifacts list, or discover candidates with `find .gsd -type f -name '*-SUMMARY.md'`; never read a directory path. Output table: Requirement | Status | Evidence. End with one-line verdict: PASS if all covered, NEEDS-ATTENTION if partials exist, FAIL if any missing."
33
33
 
34
34
  **Reviewer B - Cross-Slice Integration**
35
- Prompt: "Review milestone {{milestoneId}} cross-slice integration. Working directory: {{workingDirectory}}. Use the preloaded roadmap and slice SUMMARY evidence embedded in this task — do not re-read them from disk. Find the boundary map (produces/consumes contracts) in the roadmap. For each boundary, confirm producer SUMMARY produced the artifact and consumer SUMMARY consumed it. Read `{{roadmapPath}}` or a full SUMMARY only if the preloaded evidence is missing, truncated, or inconsistent. Output table: Boundary | Producer Summary | Consumer Summary | Status. End with one-line verdict: PASS if all boundaries honored, NEEDS-ATTENTION if any gaps."
35
+ Prompt: "Review milestone {{milestoneId}} cross-slice integration. Working directory: {{workingDirectory}}. Use the preloaded roadmap and slice SUMMARY evidence embedded in this task — do not re-read them from disk. Find the boundary map (produces/consumes contracts) in the roadmap. For each boundary, confirm producer SUMMARY produced the artifact and consumer SUMMARY consumed it. Read `{{roadmapPath}}` or a full SUMMARY from the On-demand Validation Artifacts list only if the preloaded evidence is missing, truncated, or inconsistent; never read a directory path. Output table: Boundary | Producer Summary | Consumer Summary | Status. End with one-line verdict: PASS if all boundaries honored, NEEDS-ATTENTION if any gaps."
36
36
 
37
37
  **Reviewer C - Assessment & Acceptance Criteria**
38
- Prompt: "Review milestone {{milestoneId}} assessment evidence and acceptance criteria. Working directory: {{workingDirectory}}. Use the preloaded milestone context, slice SUMMARY, and ASSESSMENT evidence embedded in this task — do not re-read them from disk. Read `.gsd/milestones/{{milestoneId}}/{{milestoneId}}-CONTEXT.md`, a full SUMMARY, or a full ASSESSMENT only if the preloaded excerpt is missing, truncated, or inconsistent. UAT files are specs, not evidence. Verify each criterion maps to passing evidence. Then review the inlined `Verification Classes (from planning)` table. For every planned row in that table, output a `Verification Classes` table with columns `Class | Planned Check | Evidence | Verdict`. Preserve every planned non-empty class row; do not summarize, rename, combine, or omit planned classes. The first cell of each row must be exactly `Contract`, `Integration`, `Operational`, or `UAT` when that class is present in planning. If a planned class lacks evidence, still include its canonical row and mark the verdict NEEDS-ATTENTION or FAIL. If a planned browser/UAT class has no ASSESSMENT with browser/runtime actions and assertions, return NEEDS-ATTENTION. If no verification classes were planned, say that explicitly. Output sections `Acceptance Criteria` with checklist `[ ] Criterion | Evidence`, and `Verification Classes` with the table. End with one-line verdict: PASS if all criteria and classes are covered by evidence, NEEDS-ATTENTION if gaps exist."
38
+ Prompt: "Review milestone {{milestoneId}} assessment evidence and acceptance criteria. Working directory: {{workingDirectory}}. Use the preloaded milestone context, slice SUMMARY, and ASSESSMENT evidence embedded in this task — do not re-read them from disk. Read the milestone context from the On-demand Milestone Context file path, and read full SUMMARY or ASSESSMENT files only from explicit paths in the On-demand Validation Artifacts list, if the preloaded excerpt is missing, truncated, or inconsistent. UAT files are specs, not evidence. Verify each criterion maps to passing evidence. Then review the inlined `Verification Classes (from planning)` table. For every planned row in that table, output a `Verification Classes` table with columns `Class | Planned Check | Evidence | Verdict`. Preserve every planned non-empty class row; do not summarize, rename, combine, or omit planned classes. The first cell of each row must be exactly `Contract`, `Integration`, `Operational`, or `UAT` when that class is present in planning. If a planned class lacks evidence, still include its canonical row and mark the verdict NEEDS-ATTENTION or FAIL. If a planned browser/UAT class has no ASSESSMENT with browser/runtime actions and assertions, return NEEDS-ATTENTION. If no verification classes were planned, say that explicitly. Output sections `Acceptance Criteria` with checklist `[ ] Criterion | Evidence`, and `Verification Classes` with the table. End with one-line verdict: PASS if all criteria and classes are covered by evidence, NEEDS-ATTENTION if gaps exist."
39
39
 
40
40
  ### Step 2 - Synthesize Findings
41
41
 
@@ -85,6 +85,6 @@ If verdict is `needs-remediation`:
85
85
 
86
86
  **You MUST call `gsd_validate_milestone` before finishing. Do not manually write `{{validationPath}}`.**
87
87
 
88
- **File system safety:** When scanning milestone directories, use `ls` or `find` first. Never pass a directory path such as `tasks/` or `slices/` directly to `read`; it only accepts files.
88
+ **File system safety:** When scanning milestone directories, use `find .gsd -type f` first and read only files. In flat-phase projects, `.gsd/phases/<NN>-<slug>/` is a directory, not an artifact. Never pass a directory path such as a phase directory, `tasks/`, or `slices/` directly to `read`, `readFile`, or `readFileSync`.
89
89
 
90
90
  When done, say: "Milestone {{milestoneId}} validation complete — verdict: <verdict>." Say this exactly once — if you already said it in a prior message, do not repeat it.
@@ -2,12 +2,14 @@
2
2
  * Provider Payload Policy - ordered shaping of provider request payloads.
3
3
  *
4
4
  * The order is intentional:
5
- * 1. observation budgeting masks old tool results in auto-mode,
6
- * 2. display truncation caps tool-result text for every mode,
7
- * 3. the protected Source Context Block is appended after truncation,
8
- * 4. supported models receive the configured service tier.
5
+ * 1. superseded GSD context injections (memory/guided/forensics) are removed,
6
+ * keeping only the latest, for every mode,
7
+ * 2. observation budgeting masks old tool results in auto-mode,
8
+ * 3. display truncation caps tool-result text for every mode,
9
+ * 4. the protected Source Context Block is appended after truncation,
10
+ * 5. supported models receive the configured service tier.
9
11
  */
10
- import { createObservationMask, createResponsesInputObservationMask, truncateContextResultMessages, truncateResponsesInputResultItems, } from "./context-masker.js";
12
+ import { createObservationMask, createResponsesInputObservationMask, filterSupersededContextInjections, filterSupersededResponsesContextInjections, truncateContextResultMessages, truncateResponsesInputResultItems, } from "./context-masker.js";
11
13
  import { getSourceObservationStore, isAutoActive } from "./auto-runtime-state.js";
12
14
  import { loadEffectiveGSDPreferences } from "./preferences.js";
13
15
  import { getEffectiveServiceTier, supportsServiceTier } from "./service-tier.js";
@@ -42,9 +44,18 @@ export function applyProviderPayloadPolicy({ payload, modelId, deps: overrides,
42
44
  }
43
45
  function applyContextManagement(payload, deps) {
44
46
  const config = deps.loadContextManagementConfig();
47
+ applyContextInjectionFilter(payload);
45
48
  applyObservationBudget(payload, config, deps.isAutoActive());
46
49
  applyDisplayTruncation(payload, config);
47
50
  }
51
+ function applyContextInjectionFilter(payload) {
52
+ if (Array.isArray(payload.messages)) {
53
+ payload.messages = filterSupersededContextInjections(payload.messages);
54
+ }
55
+ if (Array.isArray(payload.input)) {
56
+ payload.input = filterSupersededResponsesContextInjections(payload.input);
57
+ }
58
+ }
48
59
  function applyObservationBudget(payload, config, autoActive) {
49
60
  if (!autoActive || config?.observation_masking === false)
50
61
  return;
@@ -6,7 +6,7 @@
6
6
  * Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
7
7
  */
8
8
  const DESTRUCTIVE_PATTERNS = [
9
- { pattern: /\brm\s+(-[^\s]*[rfRF][^\s]*\s+|.*\s+-[^\s]*[rfRF])/, label: "recursive delete" },
9
+ { pattern: /\brm\s+((?:-(?!-)[^\s]*[rR][^\s]*|--recursive)\s+|.*\s+(?:-(?!-)[^\s]*[rR][^\s]*|--recursive)(?:\s|$))/, label: "recursive delete" },
10
10
  { pattern: /\bgit\s+push\s+.*--force/, label: "force push" },
11
11
  { pattern: /\bgit\s+push\s+-f\b/, label: "force push" },
12
12
  { pattern: /\bgit\s+reset\s+--hard/, label: "hard reset" },
@@ -173,7 +173,7 @@ export function recordToolCall(toolCallId, toolName, input) {
173
173
  toolCallId,
174
174
  // gsd_exec / gsd_uat_exec carry the script body in `script` (or `code`);
175
175
  // bash-style tools use `command`/`cmd`; gsd_exec_search uses `query`.
176
- command: String(input.command ?? input.script ?? input.cmd ?? input.code ?? input.query ?? ""),
176
+ command: formatExecutionEvidenceCommand(toolName, input),
177
177
  exitCode: -1,
178
178
  outputSnippet: "",
179
179
  timestamp: Date.now(),
@@ -196,6 +196,31 @@ export function recordToolCall(toolCallId, toolName, input) {
196
196
  });
197
197
  }
198
198
  }
199
+ function pickString(input, ...keys) {
200
+ for (const key of keys) {
201
+ const value = input[key];
202
+ if (typeof value === "string" && value.trim().length > 0)
203
+ return value.trim();
204
+ }
205
+ return "";
206
+ }
207
+ function canonicalExecutionToolLabel(toolName) {
208
+ const normalized = toolName.trim().toLowerCase();
209
+ const mcpMatch = normalized.match(/^mcp__.+__(gsd_(?:uat_)?exec(?:_search)?)$/);
210
+ return mcpMatch?.[1] ?? normalized;
211
+ }
212
+ function formatExecutionEvidenceCommand(toolName, input) {
213
+ const body = pickString(input, "command", "script", "cmd", "code", "query");
214
+ const tool = canonicalExecutionToolLabel(toolName);
215
+ const purpose = pickString(input, "purpose");
216
+ const runtime = pickString(input, "runtime").toLowerCase();
217
+ const label = purpose && (tool === "gsd_exec" || tool === "gsd_uat_exec")
218
+ ? `${tool}${runtime ? ` ${runtime}` : ""}: ${purpose}`
219
+ : "";
220
+ if (label && body)
221
+ return `${label}\n${body}`;
222
+ return body || label;
223
+ }
199
224
  /**
200
225
  * Record a tool execution result. Matches the entry by toolCallId (assigned
201
226
  * at dispatch time) and fills in exit code + output. Prior versions matched
@@ -118,16 +118,25 @@ function latestClaimBatch(claimedEvidence) {
118
118
  */
119
119
  function findMatches(claimedCommand, bashCalls) {
120
120
  const normalized = claimedCommand.trim();
121
- // Exact matches first
122
- const exact = bashCalls.filter(b => b.command.trim() === normalized);
121
+ const exact = bashCalls.filter((b) => b.command.trim() === normalized);
122
+ // When an exact run exists, also consider wrapper-equivalent reruns (e.g.
123
+ // `cd ... && <command>`) so a newer pass is not shadowed by a stale exact
124
+ // failure. Do not merge arbitrary containing scripts: their exit code may
125
+ // belong to later work, not to the claimed verification command.
126
+ const scriptWrapped = bashCalls.filter((b) => {
127
+ const command = b.command.trim();
128
+ if (command.length === 0 || command === normalized)
129
+ return false;
130
+ return isWrapperEquivalentCommand(command, normalized);
131
+ });
123
132
  if (exact.length > 0)
124
- return exact;
133
+ return [...exact, ...scriptWrapped];
125
134
  // Substring match: claimed is contained in actual or actual in claimed.
126
135
  // A claimed verification command typically appears verbatim inside a
127
136
  // larger gsd_exec script body (cd prefix, multi-line scripts), so
128
137
  // script-containing-claim is the common direction. Blank-command entries
129
138
  // must be excluded — `"x".includes("")` is true, so they'd match anything.
130
- const substring = bashCalls.filter(b => b.command.trim().length > 0 &&
139
+ const substring = bashCalls.filter((b) => b.command.trim().length > 0 &&
131
140
  (b.command.includes(normalized) || normalized.includes(b.command)));
132
141
  if (substring.length > 0)
133
142
  return substring;
@@ -150,5 +159,21 @@ function findMatches(claimedCommand, bashCalls) {
150
159
  .map((match) => match.call);
151
160
  }
152
161
  function latestMatch(matches) {
153
- return matches.reduce((latest, match) => (match.timestamp > latest.timestamp ? match : latest));
162
+ return matches.reduce((latest, match) => (match.timestamp >= latest.timestamp ? match : latest));
163
+ }
164
+ /** True when `actual` is the same command with only shell wrapper noise. */
165
+ function isWrapperEquivalentCommand(actual, claimed) {
166
+ const claimIndex = actual.lastIndexOf(claimed);
167
+ if (claimIndex < 0)
168
+ return false;
169
+ const prefix = actual.slice(0, claimIndex).trim();
170
+ if (prefix.length > 0 && !/^cd\s+.+\s+&&$/.test(prefix))
171
+ return false;
172
+ const suffix = actual.slice(claimIndex + claimed.length).trim();
173
+ return suffix.length === 0 || isBenignWrapperSuffix(suffix);
174
+ }
175
+ function isBenignWrapperSuffix(suffix) {
176
+ if (/^;\s*echo\s+["']?[A-Z_]*EXIT=\$\?["']?$/.test(suffix))
177
+ return true;
178
+ return /^(?:(?:\d?>>?|&>)\s*\S+|\d?>&\d)(?:\s+(?:(?:\d?>>?|&>)\s*\S+|\d?>&\d))*$/.test(suffix);
154
179
  }
@@ -104,11 +104,24 @@ function resolvePreferredSkillNames(prefs, visibleSkills, contextTokens, base) {
104
104
  /** Skill names must be lowercase alphanumeric with hyphens — reject anything else
105
105
  * to prevent prompt injection via crafted directory names. */
106
106
  const SAFE_SKILL_NAME = /^[a-z0-9][a-z0-9-]*$/;
107
- function formatSkillActivationBlock(skillNames) {
107
+ function escapeXml(str) {
108
+ return str
109
+ .replace(/&/g, "&amp;")
110
+ .replace(/</g, "&lt;")
111
+ .replace(/>/g, "&gt;")
112
+ .replace(/"/g, "&quot;")
113
+ .replace(/'/g, "&apos;");
114
+ }
115
+ function formatSkillActivationBlock(skillNames, skillPaths) {
108
116
  const safe = skillNames.filter(name => SAFE_SKILL_NAME.test(name));
109
117
  if (safe.length === 0)
110
118
  return "";
111
- const reads = safe.map(name => `Read the installed '${name}' skill file from <available_skills>`).join(". ");
119
+ const reads = safe.map(name => {
120
+ const path = skillPaths.get(name);
121
+ if (path)
122
+ return `Read the skill file at \`${escapeXml(path)}\``;
123
+ return `Find '${name}' in <available_skills>, copy its <location> value, and pass that exact path to read`;
124
+ }).join(". ");
112
125
  return `<skill_activation>${reads}.</skill_activation>`;
113
126
  }
114
127
  /**
@@ -149,6 +162,7 @@ export function buildSkillActivationBlock(params) {
149
162
  const visibleSkills = loaded;
150
163
  const manifestScopedSkills = filterSkillsByManifest(visibleSkills, params.unitType);
151
164
  const installedNames = new Set(visibleSkills.map(skill => normalizeSkillReference(skill.name)));
165
+ const installedSkillPaths = new Map(visibleSkills.map(skill => [normalizeSkillReference(skill.name), skill.filePath]));
152
166
  warnIfManifestHasMissingSkills(params.unitType, installedNames);
153
167
  const avoided = new Set(resolvePreferenceSkillNames(prefs?.avoid_skills ?? [], params.base));
154
168
  const matched = new Set();
@@ -196,7 +210,7 @@ export function buildSkillActivationBlock(params) {
196
210
  const ordered = [...matched]
197
211
  .filter(name => installedNames.has(name) && !avoided.has(name))
198
212
  .sort();
199
- const activationBlock = formatSkillActivationBlock(ordered);
213
+ const activationBlock = formatSkillActivationBlock(ordered, installedSkillPaths);
200
214
  // Omit recommendations when the system catalog is manifest-scoped for this
201
215
  // unit — skill names are already listed in <available_skills>.
202
216
  let recommendationsBlock = "";
@@ -3,13 +3,86 @@
3
3
  //
4
4
  // gsd-pi's DB is canonical, but .gsd/*.md is the inter-tool contract. When
5
5
  // gsd-core edits a projection file, this handler detects the sha drift vs the
6
- // recorded baseline in .gsd/.compat.json and re-imports the affected entities
7
- // into the DB. The next renderAllFromDb pass re-projects; the write-time
8
- // invalidation hook then refreshes the marker entry, closing the loop.
6
+ // recorded baseline in .gsd/.compat.json and re-imports from markdown with
7
+ // status authority scoped to the affected milestone ids. The next
8
+ // renderAllFromDb pass re-projects; the write-time invalidation hook then
9
+ // refreshes the marker entry, closing the loop.
9
10
  import { existsSync, readFileSync } from "node:fs";
10
- import { join } from "node:path";
11
+ import { basename, join } from "node:path";
11
12
  import { computeProjectionSha, readCompatMarker, writeCompatMarker, } from "../../compat/compat-marker.js";
13
+ import { _getAdapter } from "../../gsd-db.js";
12
14
  import { logWarning } from "../../workflow-logger.js";
15
+ function deepestProjectionScope(entities) {
16
+ let best = null;
17
+ for (const entity of entities) {
18
+ const parts = entity.split("/").filter(Boolean);
19
+ if (parts.length === 0)
20
+ continue;
21
+ if (!best || parts.length > best.length)
22
+ best = parts;
23
+ }
24
+ if (!best)
25
+ return null;
26
+ return {
27
+ milestoneId: best[0],
28
+ sliceId: best[1] ?? null,
29
+ taskId: best[2] ?? null,
30
+ };
31
+ }
32
+ function artifactTypeFromProjectionPath(projectionPath) {
33
+ const name = basename(projectionPath);
34
+ const match = name.match(/^(?:[A-Za-z]\d+|\d+(?:-\d+)?)-(.+)\.md$/);
35
+ return match?.[1]?.toUpperCase() ?? null;
36
+ }
37
+ function dbProjectionMatches(projectionPath, entry, actualSha) {
38
+ const adapter = _getAdapter();
39
+ if (!adapter)
40
+ return false;
41
+ try {
42
+ const rows = adapter
43
+ .prepare("SELECT full_content FROM artifacts WHERE path = :path")
44
+ .all({ ":path": projectionPath });
45
+ const scope = deepestProjectionScope(entry.entities);
46
+ const artifactType = artifactTypeFromProjectionPath(projectionPath);
47
+ if (scope?.taskId) {
48
+ rows.push(...adapter
49
+ .prepare(`SELECT full_content
50
+ FROM artifacts
51
+ WHERE milestone_id = :mid AND slice_id = :sid AND task_id = :tid
52
+ AND (:type IS NULL OR artifact_type = :type)`)
53
+ .all({
54
+ ":mid": scope.milestoneId,
55
+ ":sid": scope.sliceId,
56
+ ":tid": scope.taskId,
57
+ ":type": artifactType,
58
+ }));
59
+ }
60
+ else if (scope?.sliceId) {
61
+ rows.push(...adapter
62
+ .prepare(`SELECT full_content
63
+ FROM artifacts
64
+ WHERE milestone_id = :mid AND slice_id = :sid AND task_id IS NULL
65
+ AND (:type IS NULL OR artifact_type = :type)`)
66
+ .all({
67
+ ":mid": scope.milestoneId,
68
+ ":sid": scope.sliceId,
69
+ ":type": artifactType,
70
+ }));
71
+ }
72
+ else if (scope) {
73
+ rows.push(...adapter
74
+ .prepare(`SELECT full_content
75
+ FROM artifacts
76
+ WHERE milestone_id = :mid AND slice_id IS NULL AND task_id IS NULL
77
+ AND (:type IS NULL OR artifact_type = :type)`)
78
+ .all({ ":mid": scope.milestoneId, ":type": artifactType }));
79
+ }
80
+ return rows.some((row) => computeProjectionSha(row.full_content) === actualSha);
81
+ }
82
+ catch {
83
+ return false;
84
+ }
85
+ }
13
86
  /**
14
87
  * Detect sha drift between the marker baseline and current file contents.
15
88
  *
@@ -20,11 +93,15 @@ import { logWarning } from "../../workflow-logger.js";
20
93
  * - Sha mismatch → one record per drifted file, scoped to its recorded entities.
21
94
  */
22
95
  function detectExternalMarkdownEdit(_state, ctx) {
23
- const marker = readCompatMarker(ctx.basePath);
96
+ const marker = readCompatMarker(ctx.basePath, {
97
+ healInvalidKeys: !ctx.dryRun,
98
+ quarantineInvalid: !ctx.dryRun,
99
+ });
24
100
  const entries = Object.entries(marker.projections);
25
101
  if (entries.length === 0)
26
102
  return [];
27
103
  const records = [];
104
+ let markerChanged = false;
28
105
  for (const [projectionPath, entry] of entries) {
29
106
  const abs = join(ctx.basePath, ".gsd", projectionPath);
30
107
  if (!existsSync(abs))
@@ -32,6 +109,21 @@ function detectExternalMarkdownEdit(_state, ctx) {
32
109
  const actual = computeProjectionSha(readFileSync(abs, "utf-8"));
33
110
  if (actual === entry.sha)
34
111
  continue;
112
+ if (dbProjectionMatches(projectionPath, entry, actual)) {
113
+ if (!ctx.dryRun) {
114
+ marker.projections[projectionPath] = {
115
+ sha: actual,
116
+ entities: entry.entities,
117
+ };
118
+ markerChanged = true;
119
+ logWarning("reconcile", `external-markdown-edit: refreshed stale compat marker for ${projectionPath} (expectedSha=${entry.sha}, actualSha=${actual})`);
120
+ }
121
+ else {
122
+ logWarning("reconcile", `external-markdown-edit: stale compat marker for ${projectionPath} (expectedSha=${entry.sha}, actualSha=${actual})`);
123
+ }
124
+ continue;
125
+ }
126
+ logWarning("reconcile", `external-markdown-edit drift for ${projectionPath} (expectedSha=${entry.sha}, actualSha=${actual})`);
35
127
  records.push({
36
128
  kind: "external-markdown-edit",
37
129
  projectionPath,
@@ -40,26 +132,44 @@ function detectExternalMarkdownEdit(_state, ctx) {
40
132
  entities: entry.entities,
41
133
  });
42
134
  }
135
+ if (markerChanged) {
136
+ marker.lastWriter = "gsd-pi";
137
+ marker.lastProjectedAt = new Date().toISOString();
138
+ writeCompatMarker(ctx.basePath, marker);
139
+ }
43
140
  return records;
44
141
  }
45
142
  /**
46
- * Idempotent repair: re-import hierarchy for the affected entities from
47
- * markdown into the DB, then update the marker entry so the next detect pass
48
- * sees the file as expected. migrateHierarchyToDb is itself idempotent
49
- * (upsert), so re-running this repair after a successful one is a no-op.
143
+ * Idempotent repair: re-import the hierarchy from markdown while allowing
144
+ * markdown status authority only for milestones named by the drifted file's
145
+ * marker entities, then update the marker entry so the next detect pass sees
146
+ * the file as expected. migrateHierarchyToDb is itself idempotent (upsert), so
147
+ * re-running this repair after a successful one is a no-op.
50
148
  */
51
149
  async function repairExternalMarkdownEdit(record, ctx) {
52
150
  try {
53
151
  // Dynamic imports break a module-init cycle: this handler ← registry ←
54
152
  // state.ts ← guided-flow.ts ← md-importer.ts ← (this handler's old static
55
153
  // import). Deferring to repair time keeps module load cycle-free.
56
- const { migrateHierarchyToDb } = await import("../../md-importer.js");
154
+ const { migrateHierarchyToDb, milestoneIdsFromEntities } = await import("../../md-importer.js");
57
155
  const { invalidateStateCache } = await import("../../state.js");
58
- // Scoped re-import. migrateHierarchyToDb walks the whole tree but is a
59
- // cheap upsert; per-entity scoping would require decomposing it, which is
60
- // out of scope for v1. The cost is bounded by tree size and runs at most
61
- // once per reconcile pass (MAX_PASSES=2).
62
- migrateHierarchyToDb(ctx.basePath);
156
+ // #027: migrateHierarchyToDb walks the whole tree (a cheap upsert), so
157
+ // without scoping every projection rides along with markdown *status*
158
+ // authority. That lets an unrelated file that is stale from gsd-pi's own
159
+ // miss silently revert a reopened slice/milestone. Scope status authority to
160
+ // exactly the milestone(s) this drifted file projects.
161
+ //
162
+ // Step 1: the marker's `entities` are DB ids (`M001`, `M001/S01`,
163
+ // `M001/S01/T01`), so the milestone id is always the first `/`-segment —
164
+ // layout-independent (legacy `milestones/<MID>/…` and flat `phases/NN-slug/…`
165
+ // both resolve the same way), no projectionPath parsing needed. An empty set
166
+ // (no resolvable entities) preserves DB status everywhere: fail toward
167
+ // protecting the DB, not toward markdown authority.
168
+ const statusAuthoritativeMilestones = milestoneIdsFromEntities(record.entities);
169
+ if (statusAuthoritativeMilestones.size === 0) {
170
+ logWarning("reconcile", `external-markdown-edit: no milestone scope resolved for ${record.projectionPath}; preserving DB status for all milestones`);
171
+ }
172
+ migrateHierarchyToDb(ctx.basePath, { statusAuthoritativeMilestones });
63
173
  invalidateStateCache();
64
174
  }
65
175
  catch (err) {
@@ -3,7 +3,8 @@
3
3
  // Parallel to external-markdown-edit.ts. Detects sha drift between the compat
4
4
  // marker's planning.projections/passthrough and current .planning/ files.
5
5
  //
6
- // Modeled files (projections): re-imported via parsePlanningDirectory → DB.
6
+ // Modeled files (projections): re-imported via parsePlanningDirectory → DB,
7
+ // with markdown status authority scoped to their marker entity milestone ids.
7
8
  // Passthrough files (un-modeled docs): sha refreshed, content untouched.
8
9
  import { existsSync, readFileSync } from "node:fs";
9
10
  import { join } from "node:path";
@@ -54,7 +55,10 @@ function detectUnseededPlanningFiles(ctx, projections, passthrough) {
54
55
  return records;
55
56
  }
56
57
  async function detectExternalPlanningEdit(_state, ctx) {
57
- const marker = readCompatMarker(ctx.basePath);
58
+ const marker = readCompatMarker(ctx.basePath, {
59
+ healInvalidKeys: !ctx.dryRun,
60
+ quarantineInvalid: !ctx.dryRun,
61
+ });
58
62
  if (!marker.planning?.active) {
59
63
  // Not yet activated. Activation (layout parse + DB import) is owned by
60
64
  // capturePlanningCompatIfNeeded, called from reconcileBeforeDispatch when
@@ -115,12 +119,21 @@ async function repairExternalPlanningEdit(record, ctx) {
115
119
  const { parsePlanningDirectory } = await import("../../migrate/parser.js");
116
120
  const { transformToGSD } = await import("../../migrate/transformer.js");
117
121
  const { writeGSDDirectory } = await import("../../migrate/writer.js");
118
- const { migrateHierarchyToDb } = await import("../../md-importer.js");
122
+ const { migrateHierarchyToDb, milestoneIdsFromEntities } = await import("../../md-importer.js");
119
123
  const { invalidateStateCache } = await import("../../state.js");
120
124
  const parsed = await parsePlanningDirectory(join(ctx.basePath, ".planning"));
121
125
  const gsdProject = transformToGSD(parsed);
122
126
  await writeGSDDirectory(gsdProject, ctx.basePath);
123
- migrateHierarchyToDb(ctx.basePath);
127
+ // #027: scope status authority to the milestone(s) this drifted .planning/
128
+ // file projects (first `/`-segment of its DB entity ids), so a stale
129
+ // checkbox in an unrelated projection can't revert a reopened slice/milestone
130
+ // in the DB. Unseeded files carry no entities → empty set → preserve DB
131
+ // status everywhere (fail toward the DB, log the breadcrumb).
132
+ const statusAuthoritativeMilestones = milestoneIdsFromEntities(record.entities);
133
+ if (statusAuthoritativeMilestones.size === 0) {
134
+ logWarning("reconcile", `external-planning-edit: no milestone scope resolved for ${record.projectionPath}; preserving DB status for all milestones`);
135
+ }
136
+ migrateHierarchyToDb(ctx.basePath, { statusAuthoritativeMilestones });
124
137
  invalidateStateCache();
125
138
  }
126
139
  catch (err) {
@@ -9,7 +9,7 @@ import { renderRoadmapFromDb } from "../../markdown-renderer.js";
9
9
  import { findMilestoneIds } from "../../milestone-ids.js";
10
10
  import { parseRoadmap } from "../../parsers-legacy.js";
11
11
  import { resolveMilestoneFile } from "../../paths.js";
12
- import { isClosedStatus } from "../../status-guards.js";
12
+ import { isClosedStatus, isSkippedForDispatch } from "../../status-guards.js";
13
13
  function arraysEqual(a, b) {
14
14
  if (a.length !== b.length)
15
15
  return false;
@@ -76,7 +76,10 @@ export function detectRoadmapDivergenceDrift(_state, ctx) {
76
76
  for (const milestoneId of findMilestoneIds(ctx.basePath)) {
77
77
  // Skip milestones that don't yet have a DB row — that's the
78
78
  // unregistered-milestone drift handler's responsibility.
79
- if (!getMilestone(milestoneId))
79
+ const milestone = getMilestone(milestoneId);
80
+ if (!milestone)
81
+ continue;
82
+ if (isSkippedForDispatch(milestone.status))
80
83
  continue;
81
84
  if (milestoneHasDivergence(ctx.basePath, milestoneId)) {
82
85
  drifts.push({ kind: "roadmap-divergence", milestoneId });
@@ -22,6 +22,12 @@ export function formatStopNoticePrefix(reason) {
22
22
  const prefix = stopNoticeKind(reason) === "blocked" ? "Auto-mode blocked" : "Auto-mode stopped";
23
23
  return displayReason ? `${prefix} — ${displayReason}` : prefix;
24
24
  }
25
+ export function formatVerdictRecordedNotice(message) {
26
+ return `Verdict recorded: ${message}`;
27
+ }
28
+ export function formatVerdictRejectedNotice(message) {
29
+ return `Verdict rejected: ${message}`;
30
+ }
25
31
  // ─── Classification (headless host side) ────────────────────────────────
26
32
  // The canonical lowercase prefixes the headless event loop recognizes in
27
33
  // notify messages. Emitters above and ad-hoc emitters elsewhere must start
@@ -33,6 +39,8 @@ export const TERMINAL_NOTICE_PREFIXES = [
33
39
  "auto-mode complete",
34
40
  "no active milestone",
35
41
  "auto-mode idle",
42
+ "verdict recorded",
43
+ "verdict rejected",
36
44
  ];
37
45
  /** Manual-resolution notices emitted before auto-mode can formally pause/stop. */
38
46
  export function isManualResolutionNotice(message) {
@@ -50,8 +58,23 @@ export function isTerminalNotice(message) {
50
58
  export function isNonBlockingPauseNotice(message) {
51
59
  return message.includes("idempotent advance: unit already active");
52
60
  }
61
+ /**
62
+ * A picker / next-action menu that could not render in a non-interactive
63
+ * (headless / RPC) session. Both wordings originate from the menu-unavailable
64
+ * helpers (`notifyCommandMenuUnavailable` and `notifyPickerCommandNeedsInteractiveMenu`
65
+ * in next-action-ui.ts / command-feedback.ts). Headless `auto`/`next` cannot
66
+ * answer such a menu, so the run has dead-ended and needs operator intervention.
67
+ * Classify it as blocked so the headless host exits 10 instead of idling
68
+ * forever waiting for a completion signal that never comes. (#1294)
69
+ */
70
+ export function isInteractiveMenuUnavailableNotice(message) {
71
+ return (message.includes("menu could not be shown in this session") ||
72
+ message.includes("did not start:"));
73
+ }
53
74
  export function isBlockedNoticeMessage(message) {
54
75
  return (message.includes("blocked:") ||
76
+ message.startsWith("verdict rejected") ||
55
77
  (isPauseNotice(message) && !isNonBlockingPauseNotice(message)) ||
56
- isManualResolutionNotice(message));
78
+ isManualResolutionNotice(message) ||
79
+ isInteractiveMenuUnavailableNotice(message));
57
80
  }
@@ -6,8 +6,9 @@ import { closeSync, existsSync, mkdirSync, openSync, readFileSync, statSync, unl
6
6
  import { dirname, join } from "node:path";
7
7
  const STALE_THRESHOLD_MS = 60_000; // 60 seconds
8
8
  const DEFAULT_TIMEOUT_MS = 0; // fail fast; sync waits block the JS event loop
9
- function lockFilePath(basePath) {
10
- return join(basePath, ".gsd", "sync.lock");
9
+ const DEFAULT_LOCK_NAME = "sync.lock";
10
+ function lockFilePath(basePath, lockName = DEFAULT_LOCK_NAME) {
11
+ return join(basePath, ".gsd", lockName);
11
12
  }
12
13
  /** True if the given PID is alive in the current process namespace. */
13
14
  function isPidAlive(pid) {
@@ -71,8 +72,8 @@ function tryCreateLockFile(lp, payload) {
71
72
  * I/O, and UI work on Node's single JS thread. The timeout argument remains
72
73
  * accepted for compatibility but is intentionally not used for sync waiting.
73
74
  */
74
- export function acquireSyncLock(basePath, _timeoutMs = DEFAULT_TIMEOUT_MS) {
75
- const lp = lockFilePath(basePath);
75
+ export function acquireSyncLock(basePath, _timeoutMs = DEFAULT_TIMEOUT_MS, lockName = DEFAULT_LOCK_NAME) {
76
+ const lp = lockFilePath(basePath, lockName);
76
77
  const lockData = JSON.stringify({ pid: process.pid, acquired_at: new Date().toISOString() }, null, 2);
77
78
  while (true) {
78
79
  // First try the fast path: atomic create. No check-then-write race.
@@ -82,7 +83,12 @@ export function acquireSyncLock(basePath, _timeoutMs = DEFAULT_TIMEOUT_MS) {
82
83
  }
83
84
  }
84
85
  catch {
85
- /* unexpected fall through to retry */
86
+ // tryCreateLockFile only throws for non-EEXIST errors — a persistently
87
+ // uncreatable lock path (dangling-symlink parent, ENOTDIR, read-only FS).
88
+ // Retrying would spin the loop forever with no progress condition,
89
+ // blocking the JS event loop. Fail open like a contended lock so callers
90
+ // proceed (racy but functional) instead of hanging.
91
+ return { acquired: false };
86
92
  }
87
93
  // File exists. Decide whether to steal (stale + owner dead) or skip.
88
94
  let canSteal = false;
@@ -125,8 +131,8 @@ export function acquireSyncLock(basePath, _timeoutMs = DEFAULT_TIMEOUT_MS) {
125
131
  /**
126
132
  * Release the advisory sync lock. No-op if lock file does not exist.
127
133
  */
128
- export function releaseSyncLock(basePath) {
129
- const lp = lockFilePath(basePath);
134
+ export function releaseSyncLock(basePath, lockName = DEFAULT_LOCK_NAME) {
135
+ const lp = lockFilePath(basePath, lockName);
130
136
  try {
131
137
  if (existsSync(lp)) {
132
138
  unlinkSync(lp);