@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
@@ -1,3 +1,5 @@
1
+ import { GSD_CONTEXT_MESSAGE_SENTINEL } from "./constants.js";
2
+
1
3
  /**
2
4
  * Observation masking for GSD auto-mode sessions.
3
5
  *
@@ -75,6 +77,26 @@ function findTurnBoundary(messages: MaskableMessage[], keepRecentTurns: number):
75
77
  return 0;
76
78
  }
77
79
 
80
+ function countRealUserTurns(messages: MaskableMessage[]): number {
81
+ let count = 0;
82
+ for (const m of messages) {
83
+ if (m.role === "user" && !isBashResultUserMessage(m)) count++;
84
+ }
85
+ return count;
86
+ }
87
+
88
+ /**
89
+ * Quantizes how many recent turns stay unmasked so the boundary only moves
90
+ * forward once per full block of `keepRecentTurns` new turns, instead of
91
+ * every turn. Keeps the masked prefix byte-stable within a block, which is
92
+ * what lets the LLM provider's prompt cache survive across turns.
93
+ */
94
+ function quantizedKeepTurns(totalTurns: number, keepRecentTurns: number): number {
95
+ if (keepRecentTurns <= 0 || totalTurns < 2 * keepRecentTurns) return totalTurns;
96
+ const maskedTurns = Math.floor((totalTurns - keepRecentTurns) / keepRecentTurns) * keepRecentTurns;
97
+ return totalTurns - maskedTurns;
98
+ }
99
+
78
100
  /**
79
101
  * Detect user messages that originated from bashExecution.
80
102
  * After convertToLlm, these are {role: "user", content: [{type:"text", text:"Ran `cmd`\n..."}]}.
@@ -95,7 +117,8 @@ function isMaskableMessage(m: MaskableMessage): boolean {
95
117
 
96
118
  export function createObservationMask(keepRecentTurns: number = 8) {
97
119
  return (messages: MaskableMessage[]): MaskableMessage[] => {
98
- const boundary = findTurnBoundary(messages, keepRecentTurns);
120
+ const totalTurns = countRealUserTurns(messages);
121
+ const boundary = findTurnBoundary(messages, quantizedKeepTurns(totalTurns, keepRecentTurns));
99
122
  if (boundary === 0) return messages;
100
123
 
101
124
  return messages.map((m, i) => {
@@ -126,6 +149,14 @@ function findResponsesTurnBoundary(items: ResponsesInputItem[], keepRecentTurns:
126
149
  return 0;
127
150
  }
128
151
 
152
+ function countResponsesRealUserTurns(items: ResponsesInputItem[]): number {
153
+ let count = 0;
154
+ for (const item of items) {
155
+ if (item.role === "user" && !isResponsesBashResultUserItem(item)) count++;
156
+ }
157
+ return count;
158
+ }
159
+
129
160
  /**
130
161
  * Observation masking for OpenAI/Codex Responses API payloads.
131
162
  *
@@ -135,7 +166,8 @@ function findResponsesTurnBoundary(items: ResponsesInputItem[], keepRecentTurns:
135
166
  */
136
167
  export function createResponsesInputObservationMask(keepRecentTurns: number = 8) {
137
168
  return (items: ResponsesInputItem[]): ResponsesInputItem[] => {
138
- const boundary = findResponsesTurnBoundary(items, keepRecentTurns);
169
+ const totalTurns = countResponsesRealUserTurns(items);
170
+ const boundary = findResponsesTurnBoundary(items, quantizedKeepTurns(totalTurns, keepRecentTurns));
139
171
  if (boundary === 0) return items;
140
172
 
141
173
  return items.map((item, i) => {
@@ -219,3 +251,67 @@ export function truncateResponsesInputResultItems(items: ResponsesInputItem[], m
219
251
  return item;
220
252
  });
221
253
  }
254
+
255
+ // GSD injects at most one context message per turn (memory/guided/forensics —
256
+ // see buildContextMessage in bootstrap/system-context.ts), marked with
257
+ // GSD_CONTEXT_MESSAGE_SENTINEL. convertToLlm strips the distinguishing
258
+ // customType before the payload reaches this hook, so detection is by content
259
+ // prefix instead. Pre-sentinel session history lacks the sentinel, so we also
260
+ // match the stable *bracketed* GSD block labels those injections begin with,
261
+ // letting resumed sessions dedupe older memory/guided blocks.
262
+ //
263
+ // Only GSD-specific bracketed markers belong here — never generic prose. A
264
+ // message is dropped from the payload when it matches, so a natural-language
265
+ // prefix (e.g. the forensics prompt "Debug GSD itself.") could silently delete
266
+ // a real user message that happens to start the same way. Legacy forensics
267
+ // injections without memory are therefore left un-deduped by design; those
268
+ // with memory still match via the "[GSD Context Metadata]" wrapper.
269
+ const LEGACY_GSD_CONTEXT_INJECTION_PREFIXES = [
270
+ "[GSD Context Metadata]",
271
+ "[MEMORY — Critical and prompt-relevant memories from the GSD memory store]",
272
+ "[GSD Guided Execute Context]",
273
+ ] as const;
274
+
275
+ function isGsdContextInjectionText(text: string | undefined): boolean {
276
+ if (typeof text !== "string") return false;
277
+ if (text.startsWith(GSD_CONTEXT_MESSAGE_SENTINEL)) return true;
278
+ return LEGACY_GSD_CONTEXT_INJECTION_PREFIXES.some((prefix) => text.startsWith(prefix));
279
+ }
280
+
281
+ function isGsdContextInjectionMessage(m: MaskableMessage): boolean {
282
+ if (m.role !== "user") return false;
283
+ return isGsdContextInjectionText(firstTextFromContent(m.content));
284
+ }
285
+
286
+ /**
287
+ * Removes every GSD context-injection user message except the latest one.
288
+ * Each turn re-injects a near-identical memory/guided/forensics block; left
289
+ * in place they duplicate verbatim across an N-turn session. Removal (not
290
+ * masking) — an empty placeholder still costs tokens and shifts message
291
+ * positions, breaking cache byte-stability. Pure function: stored history is
292
+ * never mutated, only the outgoing payload array.
293
+ */
294
+ export function filterSupersededContextInjections(messages: MaskableMessage[]): MaskableMessage[] {
295
+ let lastIndex = -1;
296
+ for (let i = 0; i < messages.length; i++) {
297
+ if (isGsdContextInjectionMessage(messages[i])) lastIndex = i;
298
+ }
299
+ if (lastIndex === -1) return messages;
300
+ return messages.filter((m, i) => i === lastIndex || !isGsdContextInjectionMessage(m));
301
+ }
302
+
303
+ function isResponsesGsdContextInjectionItem(item: ResponsesInputItem): boolean {
304
+ if (item.role !== "user") return false;
305
+ return isGsdContextInjectionText(firstTextFromContent(item.content));
306
+ }
307
+
308
+ export function filterSupersededResponsesContextInjections(
309
+ items: ResponsesInputItem[],
310
+ ): ResponsesInputItem[] {
311
+ let lastIndex = -1;
312
+ for (let i = 0; i < items.length; i++) {
313
+ if (isResponsesGsdContextInjectionItem(items[i])) lastIndex = i;
314
+ }
315
+ if (lastIndex === -1) return items;
316
+ return items.filter((item, i) => i === lastIndex || !isResponsesGsdContextInjectionItem(item));
317
+ }
@@ -15,6 +15,7 @@
15
15
 
16
16
  import {
17
17
  _getAdapter,
18
+ immediateTransaction,
18
19
  isDbAvailable,
19
20
  transaction,
20
21
  } from "../gsd-db.js";
@@ -75,7 +76,12 @@ export function claimNextCommand(workerId: string): CommandQueueRow | null {
75
76
  const now = new Date().toISOString();
76
77
  const db = _getAdapter()!;
77
78
 
78
- return transaction((): CommandQueueRow | null => {
79
+ // BEGIN IMMEDIATE: this is a read-then-write claim. Under WAL, a deferred
80
+ // transaction that reads first and then upgrades to a writer can fail with
81
+ // SQLITE_BUSY_SNAPSHOT (not retried by busy_timeout) when two workers race;
82
+ // taking the write lock up front serializes claimants so the loser waits
83
+ // and then sees the row already claimed (changes !== 1 → null).
84
+ return immediateTransaction((): CommandQueueRow | null => {
79
85
  // Find the oldest unclaimed command targeted at this worker OR
80
86
  // broadcast. The partial index covers both via NULL-in-B-tree.
81
87
  const row = db.prepare(
@@ -46,6 +46,7 @@ import {
46
46
  applyMigrationV27ArtifactHash,
47
47
  applyMigrationV28MemoryLastHitAt,
48
48
  applyMigrationV29RepositoryTargets,
49
+ applyMigrationV30ReworkBriefs,
49
50
  } from "../db-migration-steps.js";
50
51
  import {
51
52
  isMemoriesFtsAvailableSchema,
@@ -93,7 +94,7 @@ const providerLoader = createSqliteProviderLoader({
93
94
  nodeVersion: process.versions.node,
94
95
  writeStderr: (message: string) => process.stderr.write(message),
95
96
  });
96
- export const SCHEMA_VERSION = 29;
97
+ export const SCHEMA_VERSION = 30;
97
98
  function initSchema(db: DbAdapter, fileBacked: boolean, dbPath: string | null): void {
98
99
  const conservativeFilePragmas = fileBacked && _isLikelyWslDrvFsPathForTest(dbPath);
99
100
  if (fileBacked) db.exec(conservativeFilePragmas ? "PRAGMA journal_mode=DELETE" : "PRAGMA journal_mode=WAL");
@@ -114,21 +115,39 @@ function initSchema(db: DbAdapter, fileBacked: boolean, dbPath: string | null):
114
115
 
115
116
  const existing = db.prepare("SELECT count(*) as cnt FROM schema_version").get();
116
117
  if (existing && (existing["cnt"] as number) === 0) {
117
- createCoordinationTablesV24(db);
118
- createRuntimeKvTableV25(db);
119
-
120
- // Fresh install all tables are created above with the full current schema,
121
- // so it is safe to create all migration-specific indexes here. For existing
122
- // databases these indexes are created inside the individual migration guards
123
- // in migrateSchema() after the corresponding columns have been added.
124
- db.exec("CREATE INDEX IF NOT EXISTS idx_tasks_escalation_pending ON tasks(milestone_id, slice_id, escalation_pending)");
125
- db.exec("CREATE INDEX IF NOT EXISTS idx_memories_scope ON memories(scope)");
126
- db.exec("CREATE INDEX IF NOT EXISTS idx_memory_sources_kind ON memory_sources(kind)");
127
- db.exec("CREATE INDEX IF NOT EXISTS idx_memory_sources_scope ON memory_sources(scope)");
128
- db.exec("CREATE INDEX IF NOT EXISTS idx_memory_relations_from ON memory_relations(from_id)");
129
- db.exec("CREATE INDEX IF NOT EXISTS idx_memory_relations_to ON memory_relations(to_id)");
130
-
131
- recordSchemaVersion(db, SCHEMA_VERSION);
118
+ // An empty schema_version table usually means a fresh install, but it can
119
+ // also be a legacy/truncated DB that already holds user data. Stamping
120
+ // that DB SCHEMA_VERSION without running migrations would mis-mark it as
121
+ // fully migrated and break at first query. Probe before stamping.
122
+ const hasData = ["milestones", "decisions", "memories"].some((t) => {
123
+ try {
124
+ const r = db.prepare(`SELECT count(*) as cnt FROM ${t}`).get();
125
+ return ((r?.["cnt"] as number) ?? 0) > 0;
126
+ } catch { /* table absent on a truly fresh DB — treat as no data */ return false; }
127
+ });
128
+ if (hasData) {
129
+ // Legacy DB with data but no version row: record the baseline so
130
+ // migrateSchema runs the full chain instead of stamping the current version.
131
+ recordSchemaVersion(db, 1);
132
+ } else {
133
+ createCoordinationTablesV24(db);
134
+ createRuntimeKvTableV25(db);
135
+
136
+ // Fresh install — all tables are created above with the full current schema,
137
+ // so it is safe to create all migration-specific indexes here. For existing
138
+ // databases these indexes are created inside the individual migration guards
139
+ // in migrateSchema() after the corresponding columns have been added.
140
+ db.exec("CREATE INDEX IF NOT EXISTS idx_tasks_escalation_pending ON tasks(milestone_id, slice_id, escalation_pending)");
141
+ db.exec("CREATE INDEX IF NOT EXISTS idx_memories_scope ON memories(scope)");
142
+ db.exec("CREATE INDEX IF NOT EXISTS idx_memory_sources_kind ON memory_sources(kind)");
143
+ db.exec("CREATE INDEX IF NOT EXISTS idx_memory_sources_scope ON memory_sources(scope)");
144
+ db.exec("CREATE INDEX IF NOT EXISTS idx_memory_relations_from ON memory_relations(from_id)");
145
+ db.exec("CREATE INDEX IF NOT EXISTS idx_memory_relations_to ON memory_relations(to_id)");
146
+ db.exec("CREATE INDEX IF NOT EXISTS idx_rework_briefs_task ON rework_briefs(milestone_id, slice_id, task_id)");
147
+ db.exec("CREATE INDEX IF NOT EXISTS idx_rework_findings_status ON rework_brief_findings(brief_id, severity, status)");
148
+
149
+ recordSchemaVersion(db, SCHEMA_VERSION);
150
+ }
132
151
  }
133
152
 
134
153
  db.exec("COMMIT");
@@ -183,9 +202,19 @@ function copyQualityGateRowsToRepairedTable(db: DbAdapter): void {
183
202
  `);
184
203
  }
185
204
 
205
+ let _migrationFaultForTest = false;
206
+ /** Test-only: force migrateSchema to throw after applying its steps but before COMMIT. */
207
+ export function _setMigrationFaultForTest(v: boolean): void { _migrationFaultForTest = v; }
208
+
186
209
  function migrateSchema(db: DbAdapter, dbPath: string | null): void {
187
210
  const currentVersion = getCurrentSchemaVersion(db);
188
- if (currentVersion >= SCHEMA_VERSION) return;
211
+ if (currentVersion > SCHEMA_VERSION) {
212
+ throw new Error(
213
+ `gsd.db schema is v${currentVersion}, newer than the v${SCHEMA_VERSION} this gsd-pi supports. ` +
214
+ `Update gsd-pi (npm i -g @opengsd/gsd-pi) before opening this project.`,
215
+ );
216
+ }
217
+ if (currentVersion === SCHEMA_VERSION) return;
189
218
 
190
219
  backupDatabaseBeforeMigration(db, dbPath, currentVersion, {
191
220
  existsSync,
@@ -351,6 +380,13 @@ function migrateSchema(db: DbAdapter, dbPath: string | null): void {
351
380
  recordSchemaVersion(db, 29);
352
381
  }
353
382
 
383
+ if (currentVersion < 30) {
384
+ applyMigrationV30ReworkBriefs(db);
385
+ recordSchemaVersion(db, 30);
386
+ }
387
+
388
+ if (_migrationFaultForTest) throw new Error("migration fault injected for test");
389
+
354
390
  db.exec("COMMIT");
355
391
  } catch (err) {
356
392
  db.exec("ROLLBACK");
@@ -211,7 +211,11 @@ export function skipSliceCascade(milestoneId: string, sliceId: string): SkipSlic
211
211
  transaction(() => {
212
212
  const slice = getSlice(milestoneId, sliceId);
213
213
  if (!slice) { outcome = { ok: false, reason: "slice-not-found" }; return; }
214
- if (slice.status === "complete" || slice.status === "done") {
214
+ // Reject any closed slice except "skipped" (which falls through to the
215
+ // wasAlreadySkipped no-op). isClosedStatus covers the "closed"/"done"
216
+ // aliases too — hand-picking literals here nulls a completed slice's
217
+ // completed_at on re-skip.
218
+ if (isClosedStatus(slice.status) && slice.status !== "skipped") {
215
219
  outcome = { ok: false, reason: "slice-already-complete" };
216
220
  return;
217
221
  }
@@ -19,11 +19,18 @@ import { getDbOrNull } from "../engine.js";
19
19
  import { GSDError, GSD_STALE_STATE } from "../../errors.js";
20
20
  import { isClosedStatus } from "../../status-guards.js";
21
21
 
22
- /** A single row-level status write, discriminated by entity (the faces' arity). */
22
+ /**
23
+ * A single row-level status write, discriminated by entity (the faces' arity).
24
+ *
25
+ * preserveCompletion (#1291): when true, an existing non-null completed_at on the
26
+ * row is kept rather than overwritten. Mirrors the task upsert's guard so a
27
+ * markdown re-import cannot re-stamp an already-complete slice/milestone with the
28
+ * current import time — the DB row is strictly richer than the plan.
29
+ */
23
30
  export type StatusTransition =
24
- | { entity: "task"; milestoneId: string; sliceId: string; taskId: string; status: string; completedAt?: string | null }
25
- | { entity: "slice"; milestoneId: string; sliceId: string; status: string; completedAt?: string | null }
26
- | { entity: "milestone"; milestoneId: string; status: string; completedAt?: string | null };
31
+ | { entity: "task"; milestoneId: string; sliceId: string; taskId: string; status: string; completedAt?: string | null; preserveCompletion?: boolean }
32
+ | { entity: "slice"; milestoneId: string; sliceId: string; status: string; completedAt?: string | null; preserveCompletion?: boolean }
33
+ | { entity: "milestone"; milestoneId: string; status: string; completedAt?: string | null; preserveCompletion?: boolean };
27
34
 
28
35
  function requireDb() {
29
36
  const db = getDbOrNull();
@@ -44,15 +51,19 @@ function requireDb() {
44
51
  export function applyStatusTransition(t: StatusTransition): void {
45
52
  const db = requireDb();
46
53
  const completedAt = t.completedAt ?? null;
54
+ const preserve = t.preserveCompletion ? 1 : 0;
47
55
 
48
56
  switch (t.entity) {
49
57
  case "task":
50
58
  db.prepare(
51
- `UPDATE tasks SET status = :status, completed_at = :completed_at
59
+ `UPDATE tasks SET status = :status,
60
+ completed_at = CASE WHEN :preserve_completion = 1 AND tasks.completed_at IS NOT NULL
61
+ THEN tasks.completed_at ELSE :completed_at END
52
62
  WHERE milestone_id = :milestone_id AND slice_id = :slice_id AND id = :id`,
53
63
  ).run({
54
64
  ":status": t.status,
55
65
  ":completed_at": completedAt,
66
+ ":preserve_completion": preserve,
56
67
  ":milestone_id": t.milestoneId,
57
68
  ":slice_id": t.sliceId,
58
69
  ":id": t.taskId,
@@ -61,11 +72,14 @@ export function applyStatusTransition(t: StatusTransition): void {
61
72
 
62
73
  case "slice":
63
74
  db.prepare(
64
- `UPDATE slices SET status = :status, completed_at = :completed_at
75
+ `UPDATE slices SET status = :status,
76
+ completed_at = CASE WHEN :preserve_completion = 1 AND slices.completed_at IS NOT NULL
77
+ THEN slices.completed_at ELSE :completed_at END
65
78
  WHERE milestone_id = :milestone_id AND id = :id`,
66
79
  ).run({
67
80
  ":status": t.status,
68
81
  ":completed_at": completedAt,
82
+ ":preserve_completion": preserve,
69
83
  ":milestone_id": t.milestoneId,
70
84
  ":id": t.sliceId,
71
85
  });
@@ -80,8 +94,11 @@ export function applyStatusTransition(t: StatusTransition): void {
80
94
  );
81
95
  }
82
96
  db.prepare(
83
- `UPDATE milestones SET status = :status, completed_at = :completed_at WHERE id = :id`,
84
- ).run({ ":status": t.status, ":completed_at": completedAt, ":id": t.milestoneId });
97
+ `UPDATE milestones SET status = :status,
98
+ completed_at = CASE WHEN :preserve_completion = 1 AND milestones.completed_at IS NOT NULL
99
+ THEN milestones.completed_at ELSE :completed_at END
100
+ WHERE id = :id`,
101
+ ).run({ ":status": t.status, ":completed_at": completedAt, ":preserve_completion": preserve, ":id": t.milestoneId });
85
102
  return;
86
103
  }
87
104
  }
@@ -245,6 +245,34 @@ export function createBaseSchemaObjects(db: DbAdapter, hooks: BaseSchemaHooks):
245
245
  )
246
246
  `);
247
247
 
248
+ db.exec(`
249
+ CREATE TABLE IF NOT EXISTS rework_briefs (
250
+ id TEXT PRIMARY KEY,
251
+ milestone_id TEXT NOT NULL DEFAULT '',
252
+ slice_id TEXT NOT NULL DEFAULT '',
253
+ task_id TEXT NOT NULL DEFAULT '',
254
+ created_at TEXT NOT NULL DEFAULT '',
255
+ updated_at TEXT NOT NULL DEFAULT ''
256
+ )
257
+ `);
258
+
259
+ db.exec(`
260
+ CREATE TABLE IF NOT EXISTS rework_brief_findings (
261
+ brief_id TEXT NOT NULL,
262
+ finding_id TEXT NOT NULL,
263
+ severity TEXT NOT NULL DEFAULT 'blocking',
264
+ description TEXT NOT NULL DEFAULT '',
265
+ required_fix TEXT NOT NULL DEFAULT '',
266
+ verification_commands TEXT NOT NULL DEFAULT '[]',
267
+ status TEXT NOT NULL DEFAULT 'pending',
268
+ evidence TEXT NOT NULL DEFAULT '',
269
+ decision_ref TEXT NOT NULL DEFAULT '',
270
+ updated_at TEXT NOT NULL DEFAULT '',
271
+ PRIMARY KEY (brief_id, finding_id),
272
+ FOREIGN KEY (brief_id) REFERENCES rework_briefs(id)
273
+ )
274
+ `);
275
+
248
276
  db.exec(`
249
277
  CREATE TABLE IF NOT EXISTS assessments (
250
278
  path TEXT PRIMARY KEY,
@@ -367,6 +395,8 @@ export function createBaseSchemaObjects(db: DbAdapter, hooks: BaseSchemaHooks):
367
395
 
368
396
  db.exec("CREATE INDEX IF NOT EXISTS idx_memories_active ON memories(superseded_by)");
369
397
  db.exec("CREATE INDEX IF NOT EXISTS idx_replan_history_milestone ON replan_history(milestone_id, created_at)");
398
+ db.exec("CREATE INDEX IF NOT EXISTS idx_rework_briefs_task ON rework_briefs(milestone_id, slice_id, task_id)");
399
+ db.exec("CREATE INDEX IF NOT EXISTS idx_rework_findings_status ON rework_brief_findings(brief_id, severity, status)");
370
400
  db.exec("CREATE INDEX IF NOT EXISTS idx_tasks_active ON tasks(milestone_id, slice_id, status)");
371
401
  db.exec("CREATE INDEX IF NOT EXISTS idx_slices_active ON slices(milestone_id, status)");
372
402
  db.exec("CREATE INDEX IF NOT EXISTS idx_milestones_status ON milestones(status)");
@@ -462,3 +462,35 @@ export function applyMigrationV22QualityGateRepair(db: DbAdapter, hooks: Migrati
462
462
  ensureColumn(db, "quality_gates", "scope", "ALTER TABLE quality_gates ADD COLUMN scope TEXT NOT NULL DEFAULT 'slice'");
463
463
  ensureColumn(db, "assessments", "scope", "ALTER TABLE assessments ADD COLUMN scope TEXT NOT NULL DEFAULT ''");
464
464
  }
465
+
466
+
467
+ export function applyMigrationV30ReworkBriefs(db: DbAdapter): void {
468
+ db.exec(`
469
+ CREATE TABLE IF NOT EXISTS rework_briefs (
470
+ id TEXT PRIMARY KEY,
471
+ milestone_id TEXT NOT NULL DEFAULT '',
472
+ slice_id TEXT NOT NULL DEFAULT '',
473
+ task_id TEXT NOT NULL DEFAULT '',
474
+ created_at TEXT NOT NULL DEFAULT '',
475
+ updated_at TEXT NOT NULL DEFAULT ''
476
+ )
477
+ `);
478
+ db.exec(`
479
+ CREATE TABLE IF NOT EXISTS rework_brief_findings (
480
+ brief_id TEXT NOT NULL,
481
+ finding_id TEXT NOT NULL,
482
+ severity TEXT NOT NULL DEFAULT 'blocking',
483
+ description TEXT NOT NULL DEFAULT '',
484
+ required_fix TEXT NOT NULL DEFAULT '',
485
+ verification_commands TEXT NOT NULL DEFAULT '[]',
486
+ status TEXT NOT NULL DEFAULT 'pending',
487
+ evidence TEXT NOT NULL DEFAULT '',
488
+ decision_ref TEXT NOT NULL DEFAULT '',
489
+ updated_at TEXT NOT NULL DEFAULT '',
490
+ PRIMARY KEY (brief_id, finding_id),
491
+ FOREIGN KEY (brief_id) REFERENCES rework_briefs(id)
492
+ )
493
+ `);
494
+ db.exec("CREATE INDEX IF NOT EXISTS idx_rework_briefs_task ON rework_briefs(milestone_id, slice_id, task_id)");
495
+ db.exec("CREATE INDEX IF NOT EXISTS idx_rework_findings_status ON rework_brief_findings(brief_id, severity, status)");
496
+ }
@@ -19,8 +19,11 @@ export function ensureColumn(db: DbAdapter, table: string, column: string, ddl:
19
19
  }
20
20
 
21
21
  export function getCurrentSchemaVersion(db: DbAdapter): number {
22
+ // MAX(version) on an empty table returns a row whose value is NULL —
23
+ // treat that (and any non-numeric value) as version 0, not NULL-as-number.
22
24
  const row = db.prepare("SELECT MAX(version) as v FROM schema_version").get();
23
- return row ? (row["v"] as number) : 0;
25
+ const v = row?.["v"];
26
+ return typeof v === "number" ? v : 0;
24
27
  }
25
28
 
26
29
  export function recordSchemaVersion(db: DbAdapter, version: number): void {
@@ -128,7 +128,7 @@ Diagnostics record the file path, scope (global/project), severity (error/warnin
128
128
  - Two equivalent ways to set it: inline as `models.<phase>.thinking`, or as a separate `thinking:` block keyed by phase. For the same phase, the inline value wins over the block; project preferences win over global; a phase that's unset inherits via the same sibling chain as `models` (e.g. `discuss → planning`).
129
129
  - If no thinking is configured for a phase, the session level (set via `/model`) is used, exactly as before — this is fully backward-compatible.
130
130
  - `execute-task` (code-writing) has a measured reasoning floor of `medium`: at lower levels models stop planning edits and thrash on file re-reads. The floor applies to the session/default path. An **explicit** `execution` thinking level bypasses the floor and is honored verbatim (with a one-time advisory) — set `execution: low` deliberately if you want it.
131
- - Levels a model can't support are clamped to the nearest supported level at dispatch and never sent to the provider, so a model/level mismatch never fails a unit mid-run. `xhigh` is only honored by select model families.
131
+ - Levels a model can't support are clamped to the nearest supported level at dispatch and never sent to the provider, so a model/level mismatch never fails a unit mid-run. `xhigh` support is model-dependent; current examples include OpenAI Codex Max models and Claude Sonnet 5 on Amazon Bedrock.
132
132
 
133
133
  - `skill_staleness_days`: number — skills unused for this many days get deprioritized during discovery. Set to `0` to disable staleness tracking. Default: `60`.
134
134
 
@@ -357,6 +357,28 @@ In `"parent"` mode, slice/task `targetRepositories` default to the declared chil
357
357
  - `"replace"` requires `prompt`.
358
358
  - `"skip"` is valid with no additional fields.
359
359
 
360
+ - `planning_subagents`: object — project-local widening for read-only planning subagent dispatch. Supported unit keys are `plan-milestone` and `plan-slice`; each has:
361
+ - `allowed`: string[] — additional planning-safe agents for that unit.
362
+
363
+ Agents must already be classified by GSD as read-only planning specialists: `mnemo`, `scout`, `planner`, `reviewer`, `security`, or `tester`. The write gate still blocks source writes outside `.gsd/**`, unrestricted bash, stale subagent calls without agent identities, agents outside the global read-only registry, and agents not listed for the active unit.
364
+
365
+ Example:
366
+
367
+ ```yaml
368
+ planning_subagents:
369
+ plan-milestone:
370
+ allowed:
371
+ - scout
372
+ - planner
373
+ - security
374
+ plan-slice:
375
+ allowed:
376
+ - scout
377
+ - planner
378
+ - reviewer
379
+ - security
380
+ ```
381
+
360
382
  **Known unit types for `before`/`after`:** `research-milestone`, `plan-milestone`, `research-slice`, `plan-slice`, `execute-task`, `complete-slice`, `replan-slice`, `reassess-roadmap`, `run-uat`.
361
383
 
362
384
  - `experimental`: opt-in experimental features. All features here are **off by default** — you must explicitly set each one to `true` to enable it. Features in this block may change or be removed without a deprecation cycle while in experimental status. Keys:
@@ -482,13 +504,13 @@ Inline form — thinking pinned alongside the model:
482
504
  version: 1
483
505
  models:
484
506
  planning:
485
- model: openai-codex/gpt-5.4
507
+ model: bedrock/global.anthropic.claude-sonnet-5
486
508
  thinking: xhigh
487
509
  execution:
488
- model: openai-codex/gpt-5.4
510
+ model: bedrock/global.anthropic.claude-sonnet-5
489
511
  thinking: low # explicit → bypasses the execute-task medium floor
490
512
  validation:
491
- model: openai-codex/gpt-5.4
513
+ model: bedrock/global.anthropic.claude-sonnet-5
492
514
  thinking: high
493
515
  ---
494
516
  ```
@@ -15,13 +15,13 @@ import {
15
15
  import { MEMORIES_FTS_REBUILT_KEY } from "./db-memory-fts-schema.js";
16
16
  import { isAfter, latestExplicitReopenAt } from "./milestone-reopen-events.js";
17
17
  import {
18
- buildTaskFileName,
19
18
  gsdProjectionRoot,
20
19
  gsdRoot,
21
20
  resolveGsdPathContract,
22
21
  resolveMilestoneFile,
23
22
  resolveMilestonePath,
24
23
  resolveSliceFile,
24
+ resolveTaskFile,
25
25
  } from "./paths.js";
26
26
  import { deriveState } from "./state.js";
27
27
  import { isClosedStatus } from "./status-guards.js";
@@ -208,10 +208,8 @@ function resolveFlatPhaseArtifactDiskPath(basePath: string, row: ArtifactRow): s
208
208
  if (!artifactType) return null;
209
209
 
210
210
  if (row.slice_id && row.task_id) {
211
- const phaseDir = resolveMilestonePath(basePath, row.milestone_id);
212
- if (!phaseDir || !isFlatPhaseDiskPath(basePath, phaseDir)) return null;
213
- const candidate = join(phaseDir, buildTaskFileName(row.task_id, artifactType));
214
- return existsSync(candidate) ? candidate : null;
211
+ const candidate = resolveTaskFile(basePath, row.milestone_id, row.slice_id, row.task_id, artifactType);
212
+ return candidate && isFlatPhaseDiskPath(basePath, candidate) ? candidate : null;
215
213
  }
216
214
 
217
215
  const candidate = row.slice_id