@opengsd/gsd-pi 1.9.0 → 1.10.0-dev.a5e42e99

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 (502) hide show
  1. package/README.md +10 -9
  2. package/dist/headless.js +2 -1
  3. package/dist/resources/.managed-resources-content-hash +1 -1
  4. package/dist/resources/GSD-WORKFLOW.md +2 -2
  5. package/dist/resources/extensions/gsd/artifact-verification.js +3 -4
  6. package/dist/resources/extensions/gsd/auto/loop.js +24 -4
  7. package/dist/resources/extensions/gsd/auto/run-unit.js +19 -1
  8. package/dist/resources/extensions/gsd/auto/unit-phase.js +37 -5
  9. package/dist/resources/extensions/gsd/auto-artifact-paths.js +14 -8
  10. package/dist/resources/extensions/gsd/auto-dispatch.js +2 -0
  11. package/dist/resources/extensions/gsd/auto-model-selection.js +1 -0
  12. package/dist/resources/extensions/gsd/auto-prompts.js +102 -21
  13. package/dist/resources/extensions/gsd/auto-recovery.js +10 -5
  14. package/dist/resources/extensions/gsd/auto-runtime-state.js +5 -5
  15. package/dist/resources/extensions/gsd/auto-start.js +30 -10
  16. package/dist/resources/extensions/gsd/auto-tool-tracking.js +40 -0
  17. package/dist/resources/extensions/gsd/auto-verification.js +25 -12
  18. package/dist/resources/extensions/gsd/auto-worktree-cleanup.js +4 -0
  19. package/dist/resources/extensions/gsd/auto-worktree-sync.js +7 -3
  20. package/dist/resources/extensions/gsd/auto-worktree-teardown.js +1 -1
  21. package/dist/resources/extensions/gsd/auto.js +15 -5
  22. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +2 -0
  23. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +33 -7
  24. package/dist/resources/extensions/gsd/bootstrap/system-context.js +10 -3
  25. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +7 -26
  26. package/dist/resources/extensions/gsd/commands-verdict.js +10 -9
  27. package/dist/resources/extensions/gsd/compat/compat-marker.js +80 -5
  28. package/dist/resources/extensions/gsd/constants.js +12 -13
  29. package/dist/resources/extensions/gsd/context-masker.js +97 -21
  30. package/dist/resources/extensions/gsd/db/engine.js +5 -2
  31. package/dist/resources/extensions/gsd/docs/preferences-reference.md +33 -2
  32. package/dist/resources/extensions/gsd/doctor-engine-checks.js +40 -12
  33. package/dist/resources/extensions/gsd/error-classifier.js +12 -2
  34. package/dist/resources/extensions/gsd/exec-sandbox.js +1 -0
  35. package/dist/resources/extensions/gsd/flat-phase-migration.js +12 -0
  36. package/dist/resources/extensions/gsd/git-service.js +19 -7
  37. package/dist/resources/extensions/gsd/gsd-db.js +75 -31
  38. package/dist/resources/extensions/gsd/guided-flow.js +11 -5
  39. package/dist/resources/extensions/gsd/markdown-renderer.js +5 -21
  40. package/dist/resources/extensions/gsd/md-importer.js +5 -6
  41. package/dist/resources/extensions/gsd/model-cost-table.js +6 -1
  42. package/dist/resources/extensions/gsd/model-router.js +16 -0
  43. package/dist/resources/extensions/gsd/paths.js +66 -15
  44. package/dist/resources/extensions/gsd/planning-subagent-policy.js +37 -0
  45. package/dist/resources/extensions/gsd/planning-subagent-registry.js +33 -0
  46. package/dist/resources/extensions/gsd/preferences-models.js +50 -10
  47. package/dist/resources/extensions/gsd/preferences-types.js +6 -0
  48. package/dist/resources/extensions/gsd/preferences-validation.js +86 -4
  49. package/dist/resources/extensions/gsd/preferences.js +24 -0
  50. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +5 -5
  51. package/dist/resources/extensions/gsd/provider-payload-policy.js +16 -5
  52. package/dist/resources/extensions/gsd/safety/destructive-guard.js +1 -1
  53. package/dist/resources/extensions/gsd/skill-activation.js +17 -3
  54. package/dist/resources/extensions/gsd/state-reconciliation/drift/external-markdown-edit.js +98 -2
  55. package/dist/resources/extensions/gsd/state-reconciliation/drift/external-planning-edit.js +4 -1
  56. package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +5 -2
  57. package/dist/resources/extensions/gsd/stop-notice.js +9 -0
  58. package/dist/resources/extensions/gsd/templates/PREFERENCES.md +8 -0
  59. package/dist/resources/extensions/gsd/tools/complete-task.js +12 -5
  60. package/dist/resources/extensions/gsd/tools/plan-slice.js +5 -1
  61. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +14 -5
  62. package/dist/resources/extensions/gsd/tools/reopen-slice.js +15 -5
  63. package/dist/resources/extensions/gsd/tools/reopen-task.js +16 -10
  64. package/dist/resources/extensions/gsd/unit-context-composer.js +28 -5
  65. package/dist/resources/extensions/gsd/verification-evidence.js +5 -3
  66. package/dist/resources/extensions/gsd/workflow-projections.js +2 -3
  67. package/dist/resources/extensions/gsd/workspace.js +2 -1
  68. package/dist/resources/extensions/gsd/worktree-state-projection.js +20 -18
  69. package/dist/resources/extensions/ollama/ollama-chat-provider.js +2 -2
  70. package/dist/resources/extensions/shared/interview-ui.js +43 -6
  71. package/dist/resources/extensions/subagent/index.js +1 -1
  72. package/dist/startup-model-validation.d.ts +1 -1
  73. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  74. package/dist/web/standalone/.next/BUILD_ID +1 -1
  75. package/dist/web/standalone/.next/app-path-routes-manifest.json +9 -9
  76. package/dist/web/standalone/.next/build-manifest.json +3 -3
  77. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  78. package/dist/web/standalone/.next/required-server-files.json +3 -3
  79. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  80. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  81. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  82. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  83. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  84. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  85. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  86. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  87. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  88. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  89. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  90. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  91. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  92. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  93. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  94. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  96. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  100. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  101. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  102. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  103. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  104. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  105. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  106. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  107. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  108. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  109. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  110. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  118. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/mcp-connections/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  140. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  150. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  156. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  172. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  176. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/app/index.html +1 -1
  186. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  187. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  188. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  189. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  190. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  191. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  192. package/dist/web/standalone/.next/server/app/page.js +2 -2
  193. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  194. package/dist/web/standalone/.next/server/app-paths-manifest.json +9 -9
  195. package/dist/web/standalone/.next/server/chunks/1991.js +2 -2
  196. package/dist/web/standalone/.next/server/chunks/2842.js +4 -4
  197. package/dist/web/standalone/.next/server/chunks/5124.js +1 -1
  198. package/dist/web/standalone/.next/server/chunks/8357.js +3 -3
  199. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  200. package/dist/web/standalone/.next/server/middleware.js +3 -3
  201. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  202. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  203. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  204. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-a6fb1847f67f167c.js +1 -0
  205. package/dist/web/standalone/.next/static/chunks/app/{layout-b35cbfff38aaf4cf.js → layout-4ae2d68984392bbf.js} +1 -1
  206. package/dist/web/standalone/.next/static/chunks/app/page-72a856634ad14c10.js +1 -0
  207. package/dist/web/standalone/.next/static/chunks/{main-app-590a74400e35f685.js → main-app-90d1d8d5e5d2dc6b.js} +1 -1
  208. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-1115d46ac61b9823.js +1 -0
  209. package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
  210. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  211. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  212. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  213. package/dist/web/standalone/server.js +1 -1
  214. package/integrations/hermes/open_gsd_hermes/gsd_client.py +1 -1
  215. package/integrations/hermes/pyproject.toml +1 -1
  216. package/package.json +8 -6
  217. package/packages/cloud-mcp-gateway/package.json +2 -2
  218. package/packages/contracts/dist/rpc.d.ts +1 -1
  219. package/packages/contracts/dist/rpc.d.ts.map +1 -1
  220. package/packages/contracts/dist/rpc.js +1 -1
  221. package/packages/contracts/dist/rpc.js.map +1 -1
  222. package/packages/contracts/dist/rpc.test.js +1 -1
  223. package/packages/contracts/dist/rpc.test.js.map +1 -1
  224. package/packages/contracts/package.json +1 -1
  225. package/packages/daemon/package.json +4 -4
  226. package/packages/gsd-agent-core/dist/compaction/compaction.d.ts.map +1 -1
  227. package/packages/gsd-agent-core/dist/compaction/compaction.js +36 -4
  228. package/packages/gsd-agent-core/dist/compaction/compaction.js.map +1 -1
  229. package/packages/gsd-agent-core/dist/sdk.d.ts.map +1 -1
  230. package/packages/gsd-agent-core/dist/sdk.js +1 -0
  231. package/packages/gsd-agent-core/dist/sdk.js.map +1 -1
  232. package/packages/gsd-agent-core/package.json +5 -5
  233. package/packages/gsd-agent-modes/dist/cli/args.js +2 -2
  234. package/packages/gsd-agent-modes/dist/cli/args.js.map +1 -1
  235. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  236. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js +1 -0
  237. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js.map +1 -1
  238. package/packages/gsd-agent-modes/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  239. package/packages/gsd-agent-modes/dist/modes/interactive/components/thinking-selector.js +1 -0
  240. package/packages/gsd-agent-modes/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  241. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-autocomplete.d.ts.map +1 -1
  242. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-autocomplete.js +1 -0
  243. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-autocomplete.js.map +1 -1
  244. package/packages/gsd-agent-modes/package.json +7 -7
  245. package/packages/gsd-cloud/README.md +21 -5
  246. package/packages/gsd-cloud/dist/background-cli.test.d.ts +2 -0
  247. package/packages/gsd-cloud/dist/background-cli.test.d.ts.map +1 -0
  248. package/packages/gsd-cloud/dist/background-cli.test.js +325 -0
  249. package/packages/gsd-cloud/dist/background-cli.test.js.map +1 -0
  250. package/packages/gsd-cloud/dist/cli.d.ts.map +1 -1
  251. package/packages/gsd-cloud/dist/cli.js +146 -16
  252. package/packages/gsd-cloud/dist/cli.js.map +1 -1
  253. package/packages/gsd-cloud/dist/cloud-config.d.ts +1 -1
  254. package/packages/gsd-cloud/dist/cloud-config.d.ts.map +1 -1
  255. package/packages/gsd-cloud/dist/cloud-config.js +7 -1
  256. package/packages/gsd-cloud/dist/cloud-config.js.map +1 -1
  257. package/packages/gsd-cloud/dist/cloud-runtime.d.ts +7 -4
  258. package/packages/gsd-cloud/dist/cloud-runtime.d.ts.map +1 -1
  259. package/packages/gsd-cloud/dist/cloud-runtime.js +115 -31
  260. package/packages/gsd-cloud/dist/cloud-runtime.js.map +1 -1
  261. package/packages/gsd-cloud/dist/cloud-runtime.test.js +224 -59
  262. package/packages/gsd-cloud/dist/cloud-runtime.test.js.map +1 -1
  263. package/packages/gsd-cloud/dist/runtime-artifacts.d.ts +3 -0
  264. package/packages/gsd-cloud/dist/runtime-artifacts.d.ts.map +1 -0
  265. package/packages/gsd-cloud/dist/runtime-artifacts.js +36 -0
  266. package/packages/gsd-cloud/dist/runtime-artifacts.js.map +1 -0
  267. package/packages/gsd-cloud/dist/runtime-process.d.ts +32 -0
  268. package/packages/gsd-cloud/dist/runtime-process.d.ts.map +1 -0
  269. package/packages/gsd-cloud/dist/runtime-process.js +640 -0
  270. package/packages/gsd-cloud/dist/runtime-process.js.map +1 -0
  271. package/packages/gsd-cloud/dist/runtime-process.test.d.ts +2 -0
  272. package/packages/gsd-cloud/dist/runtime-process.test.d.ts.map +1 -0
  273. package/packages/gsd-cloud/dist/runtime-process.test.js +543 -0
  274. package/packages/gsd-cloud/dist/runtime-process.test.js.map +1 -0
  275. package/packages/gsd-cloud/dist/runtime-telemetry.d.ts +117 -0
  276. package/packages/gsd-cloud/dist/runtime-telemetry.d.ts.map +1 -0
  277. package/packages/gsd-cloud/dist/runtime-telemetry.js +291 -0
  278. package/packages/gsd-cloud/dist/runtime-telemetry.js.map +1 -0
  279. package/packages/gsd-cloud/dist/runtime-telemetry.test.d.ts +2 -0
  280. package/packages/gsd-cloud/dist/runtime-telemetry.test.d.ts.map +1 -0
  281. package/packages/gsd-cloud/dist/runtime-telemetry.test.js +434 -0
  282. package/packages/gsd-cloud/dist/runtime-telemetry.test.js.map +1 -0
  283. package/packages/gsd-cloud/package.json +2 -2
  284. package/packages/mcp-server/README.md +7 -2
  285. package/packages/mcp-server/dist/cli-runner.d.ts +3 -0
  286. package/packages/mcp-server/dist/cli-runner.d.ts.map +1 -1
  287. package/packages/mcp-server/dist/cli-runner.js +119 -33
  288. package/packages/mcp-server/dist/cli-runner.js.map +1 -1
  289. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  290. package/packages/mcp-server/dist/server.js +5 -5
  291. package/packages/mcp-server/dist/server.js.map +1 -1
  292. package/packages/mcp-server/dist/workflow-tools.d.ts +4 -3
  293. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  294. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  295. package/packages/mcp-server/package.json +4 -4
  296. package/packages/native/package.json +1 -1
  297. package/packages/pi-agent-core/dist/agent.d.ts +5 -1
  298. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  299. package/packages/pi-agent-core/dist/agent.js +2 -0
  300. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  301. package/packages/pi-agent-core/dist/types.d.ts +2 -2
  302. package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
  303. package/packages/pi-agent-core/dist/types.js.map +1 -1
  304. package/packages/pi-agent-core/package.json +1 -1
  305. package/packages/pi-ai/dist/models.d.ts.map +1 -1
  306. package/packages/pi-ai/dist/models.generated.d.ts +187 -0
  307. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  308. package/packages/pi-ai/dist/models.generated.js +145 -0
  309. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  310. package/packages/pi-ai/dist/models.js +18 -6
  311. package/packages/pi-ai/dist/models.js.map +1 -1
  312. package/packages/pi-ai/dist/providers/amazon-bedrock.js +3 -2
  313. package/packages/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
  314. package/packages/pi-ai/dist/providers/anthropic.js +6 -1
  315. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  316. package/packages/pi-ai/dist/providers/azure-openai-responses.d.ts +1 -1
  317. package/packages/pi-ai/dist/providers/azure-openai-responses.d.ts.map +1 -1
  318. package/packages/pi-ai/dist/providers/azure-openai-responses.js.map +1 -1
  319. package/packages/pi-ai/dist/providers/google-vertex.js.map +1 -1
  320. package/packages/pi-ai/dist/providers/google.js.map +1 -1
  321. package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts +1 -1
  322. package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts.map +1 -1
  323. package/packages/pi-ai/dist/providers/openai-codex-responses.js +1 -1
  324. package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
  325. package/packages/pi-ai/dist/providers/openai-completions.d.ts +1 -1
  326. package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  327. package/packages/pi-ai/dist/providers/openai-completions.js +103 -0
  328. package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
  329. package/packages/pi-ai/dist/providers/openai-responses.d.ts +1 -1
  330. package/packages/pi-ai/dist/providers/openai-responses.d.ts.map +1 -1
  331. package/packages/pi-ai/dist/providers/openai-responses.js +1 -1
  332. package/packages/pi-ai/dist/providers/openai-responses.js.map +1 -1
  333. package/packages/pi-ai/dist/providers/simple-options.d.ts +1 -1
  334. package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
  335. package/packages/pi-ai/dist/providers/simple-options.js +1 -1
  336. package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
  337. package/packages/pi-ai/dist/types.d.ts +9 -1
  338. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  339. package/packages/pi-ai/dist/types.js.map +1 -1
  340. package/packages/pi-ai/package.json +1 -1
  341. package/packages/pi-coding-agent/dist/core/capability-patches.js +1 -1
  342. package/packages/pi-coding-agent/dist/core/capability-patches.js.map +1 -1
  343. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  344. package/packages/pi-coding-agent/dist/core/model-registry.js +1 -0
  345. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  346. package/packages/pi-coding-agent/dist/core/model-resolver.js +2 -2
  347. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  348. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +14 -4
  349. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  350. package/packages/pi-coding-agent/dist/core/settings-manager.js +8 -0
  351. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  352. package/packages/pi-coding-agent/dist/core/skills.d.ts +5 -0
  353. package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
  354. package/packages/pi-coding-agent/dist/core/skills.js +54 -0
  355. package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
  356. package/packages/pi-coding-agent/dist/theme/theme.d.ts +1 -1
  357. package/packages/pi-coding-agent/dist/theme/theme.d.ts.map +1 -1
  358. package/packages/pi-coding-agent/dist/theme/theme.js +1 -0
  359. package/packages/pi-coding-agent/dist/theme/theme.js.map +1 -1
  360. package/packages/pi-coding-agent/package.json +7 -7
  361. package/packages/pi-tui/package.json +2 -2
  362. package/packages/rpc-client/package.json +2 -2
  363. package/pkg/dist/theme/theme.d.ts +1 -1
  364. package/pkg/dist/theme/theme.d.ts.map +1 -1
  365. package/pkg/dist/theme/theme.js +1 -0
  366. package/pkg/dist/theme/theme.js.map +1 -1
  367. package/pkg/package.json +1 -1
  368. package/src/resources/GSD-WORKFLOW.md +2 -2
  369. package/src/resources/extensions/gsd/artifact-verification.ts +3 -8
  370. package/src/resources/extensions/gsd/auto/loop.ts +48 -4
  371. package/src/resources/extensions/gsd/auto/run-unit.ts +20 -1
  372. package/src/resources/extensions/gsd/auto/unit-phase.ts +41 -5
  373. package/src/resources/extensions/gsd/auto-artifact-paths.ts +14 -7
  374. package/src/resources/extensions/gsd/auto-dispatch.ts +1 -0
  375. package/src/resources/extensions/gsd/auto-model-selection.ts +1 -0
  376. package/src/resources/extensions/gsd/auto-prompts.ts +118 -19
  377. package/src/resources/extensions/gsd/auto-recovery.ts +10 -8
  378. package/src/resources/extensions/gsd/auto-runtime-state.ts +12 -7
  379. package/src/resources/extensions/gsd/auto-start.ts +32 -9
  380. package/src/resources/extensions/gsd/auto-tool-tracking.ts +56 -0
  381. package/src/resources/extensions/gsd/auto-verification.ts +46 -12
  382. package/src/resources/extensions/gsd/auto-worktree-cleanup.ts +4 -0
  383. package/src/resources/extensions/gsd/auto-worktree-sync.ts +10 -3
  384. package/src/resources/extensions/gsd/auto-worktree-teardown.ts +1 -1
  385. package/src/resources/extensions/gsd/auto.ts +20 -7
  386. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +1 -0
  387. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +41 -12
  388. package/src/resources/extensions/gsd/bootstrap/system-context.ts +11 -3
  389. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +10 -31
  390. package/src/resources/extensions/gsd/commands-verdict.ts +16 -9
  391. package/src/resources/extensions/gsd/compat/compat-marker.ts +99 -5
  392. package/src/resources/extensions/gsd/constants.ts +14 -13
  393. package/src/resources/extensions/gsd/context-masker.ts +98 -2
  394. package/src/resources/extensions/gsd/db/engine.ts +5 -2
  395. package/src/resources/extensions/gsd/docs/preferences-reference.md +33 -2
  396. package/src/resources/extensions/gsd/doctor-engine-checks.ts +45 -11
  397. package/src/resources/extensions/gsd/error-classifier.ts +13 -2
  398. package/src/resources/extensions/gsd/exec-sandbox.ts +1 -0
  399. package/src/resources/extensions/gsd/flat-phase-migration.ts +14 -0
  400. package/src/resources/extensions/gsd/git-service.ts +19 -6
  401. package/src/resources/extensions/gsd/gsd-db.ts +85 -33
  402. package/src/resources/extensions/gsd/guided-flow.ts +11 -4
  403. package/src/resources/extensions/gsd/markdown-renderer.ts +5 -23
  404. package/src/resources/extensions/gsd/md-importer.ts +5 -5
  405. package/src/resources/extensions/gsd/model-cost-table.ts +14 -1
  406. package/src/resources/extensions/gsd/model-router.ts +17 -0
  407. package/src/resources/extensions/gsd/paths.ts +73 -15
  408. package/src/resources/extensions/gsd/planning-subagent-policy.ts +58 -0
  409. package/src/resources/extensions/gsd/planning-subagent-registry.ts +45 -0
  410. package/src/resources/extensions/gsd/preferences-models.ts +54 -10
  411. package/src/resources/extensions/gsd/preferences-types.ts +26 -2
  412. package/src/resources/extensions/gsd/preferences-validation.ts +108 -3
  413. package/src/resources/extensions/gsd/preferences.ts +38 -0
  414. package/src/resources/extensions/gsd/prompts/validate-milestone.md +5 -5
  415. package/src/resources/extensions/gsd/provider-payload-policy.ts +18 -4
  416. package/src/resources/extensions/gsd/safety/destructive-guard.ts +1 -1
  417. package/src/resources/extensions/gsd/skill-activation.ts +17 -3
  418. package/src/resources/extensions/gsd/state-reconciliation/drift/external-markdown-edit.ts +132 -2
  419. package/src/resources/extensions/gsd/state-reconciliation/drift/external-planning-edit.ts +4 -1
  420. package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +4 -2
  421. package/src/resources/extensions/gsd/stop-notice.ts +11 -0
  422. package/src/resources/extensions/gsd/templates/PREFERENCES.md +8 -0
  423. package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +7 -7
  424. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +264 -0
  425. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +39 -0
  426. package/src/resources/extensions/gsd/tests/auto-start-index-lock.test.ts +21 -1
  427. package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +74 -1
  428. package/src/resources/extensions/gsd/tests/before-provider-context-management.test.ts +55 -0
  429. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +10 -0
  430. package/src/resources/extensions/gsd/tests/compat-marker.test.ts +25 -0
  431. package/src/resources/extensions/gsd/tests/complete-task.test.ts +76 -1
  432. package/src/resources/extensions/gsd/tests/context-masker.test.ts +204 -8
  433. package/src/resources/extensions/gsd/tests/db-engine-cjs-compat.test.ts +12 -0
  434. package/src/resources/extensions/gsd/tests/db-tools-alias-suppression.test.ts +62 -0
  435. package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +33 -0
  436. package/src/resources/extensions/gsd/tests/destructive-guard.test.ts +14 -0
  437. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +147 -0
  438. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +33 -1
  439. package/src/resources/extensions/gsd/tests/external-markdown-edit.test.ts +38 -1
  440. package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +8 -9
  441. package/src/resources/extensions/gsd/tests/flat-phase-validation-path.test.ts +20 -1
  442. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +32 -0
  443. package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +22 -0
  444. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +13 -0
  445. package/src/resources/extensions/gsd/tests/integration/paths.test.ts +22 -4
  446. package/src/resources/extensions/gsd/tests/integration-branch-meta-location.test.ts +62 -0
  447. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +5 -5
  448. package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +23 -0
  449. package/src/resources/extensions/gsd/tests/model-isolation.test.ts +55 -0
  450. package/src/resources/extensions/gsd/tests/model-router.test.ts +1 -1
  451. package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +7 -5
  452. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +24 -0
  453. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +38 -1
  454. package/src/resources/extensions/gsd/tests/preferences.test.ts +151 -0
  455. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +7 -0
  456. package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +87 -0
  457. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +121 -1
  458. package/src/resources/extensions/gsd/tests/reactive-executor.test.ts +39 -0
  459. package/src/resources/extensions/gsd/tests/register-hooks-loop-guard-auto.test.ts +105 -0
  460. package/src/resources/extensions/gsd/tests/service-tier.test.ts +4 -0
  461. package/src/resources/extensions/gsd/tests/single-writer-v3-tool-surface.test.ts +33 -7
  462. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +20 -16
  463. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +52 -0
  464. package/src/resources/extensions/gsd/tests/stop-notice.test.ts +21 -1
  465. package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +13 -7
  466. package/src/resources/extensions/gsd/tests/terminated-transient.test.ts +14 -0
  467. package/src/resources/extensions/gsd/tests/thinking-level-resolution.test.ts +1 -1
  468. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +19 -0
  469. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +8 -0
  470. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +39 -0
  471. package/src/resources/extensions/gsd/tests/validate-milestone-prompt-verification-classes.test.ts +7 -0
  472. package/src/resources/extensions/gsd/tests/verification-evidence.test.ts +12 -0
  473. package/src/resources/extensions/gsd/tests/workflow-authority-faults.test.ts +238 -0
  474. package/src/resources/extensions/gsd/tests/workflow-authority-fixture.test.ts +48 -0
  475. package/src/resources/extensions/gsd/tests/workflow-authority-fixture.ts +141 -0
  476. package/src/resources/extensions/gsd/tests/workflow-authority-projection-conflict.test.ts +177 -0
  477. package/src/resources/extensions/gsd/tests/workflow-fault-harness.test.ts +39 -0
  478. package/src/resources/extensions/gsd/tests/workflow-fault-harness.ts +72 -0
  479. package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +4 -4
  480. package/src/resources/extensions/gsd/tests/worktree-state-projection.test.ts +2 -2
  481. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +60 -0
  482. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +74 -0
  483. package/src/resources/extensions/gsd/tools/complete-task.ts +20 -5
  484. package/src/resources/extensions/gsd/tools/plan-slice.ts +5 -1
  485. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +24 -5
  486. package/src/resources/extensions/gsd/tools/reopen-slice.ts +25 -5
  487. package/src/resources/extensions/gsd/tools/reopen-task.ts +23 -9
  488. package/src/resources/extensions/gsd/unit-context-composer.ts +34 -8
  489. package/src/resources/extensions/gsd/verification-evidence.ts +5 -2
  490. package/src/resources/extensions/gsd/workflow-projections.ts +2 -3
  491. package/src/resources/extensions/gsd/workspace.ts +2 -1
  492. package/src/resources/extensions/gsd/worktree-state-projection.ts +21 -24
  493. package/src/resources/extensions/ollama/ollama-chat-provider.ts +2 -2
  494. package/src/resources/extensions/ollama/tests/ollama-chat-provider-think.test.ts +4 -0
  495. package/src/resources/extensions/shared/interview-ui.ts +47 -8
  496. package/src/resources/extensions/shared/tests/interview-ui-border.test.ts +29 -0
  497. package/src/resources/extensions/subagent/index.ts +1 -1
  498. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-49f565245e1e4afe.js +0 -1
  499. package/dist/web/standalone/.next/static/chunks/app/page-bc4c723c6a19c6f0.js +0 -1
  500. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ec3eaffc9785ba48.js +0 -1
  501. /package/dist/web/standalone/.next/static/{BE5XoklToI6lZjRzpXih8 → xwUaOqui04jIIFVsIBLiL}/_buildManifest.js +0 -0
  502. /package/dist/web/standalone/.next/static/{BE5XoklToI6lZjRzpXih8 → xwUaOqui04jIIFVsIBLiL}/_ssgManifest.js +0 -0
@@ -130,6 +130,17 @@ function isInsideFlatProjectionBackup(backupDir, src) {
130
130
  const phaseBackupDir = join(backupDir, "__phases");
131
131
  return src === phaseBackupDir || src.startsWith(`${phaseBackupDir}/`) || src.startsWith(`${phaseBackupDir}\\`);
132
132
  }
133
+ function removeFlatProjectionBackup(backupDir) {
134
+ const phaseBackupDir = join(backupDir, "__phases");
135
+ if (!existsSync(phaseBackupDir))
136
+ return;
137
+ try {
138
+ removePathWithRetries(phaseBackupDir);
139
+ }
140
+ catch (err) {
141
+ logWarning("migration", `flat-phase migration succeeded but could not remove temporary ${LAYOUT_SEGMENTS.level1}/ backup: ${err.message}`);
142
+ }
143
+ }
133
144
  function restoreFlatProjectionFromBackup(basePath, backupDir) {
134
145
  const phaseBackupDir = join(backupDir, "__phases");
135
146
  if (!existsSync(phaseBackupDir))
@@ -433,4 +444,5 @@ export async function migrateToFlatPhase(basePath) {
433
444
  catch (err) {
434
445
  logWarning("migration", `flat-phase migration succeeded but could not remove ${LEGACY_MIGRATING_SEGMENT}: ${err.message}`);
435
446
  }
447
+ removeFlatProjectionBackup(backupDir);
436
448
  }
@@ -229,10 +229,15 @@ export const RUNTIME_EXCLUSION_PATHS = [
229
229
  const runtimeFilesCleanedUpRepos = new Set();
230
230
  // ─── Integration Branch Metadata ───────────────────────────────────────────
231
231
  /**
232
- * Path to the milestone metadata file that stores the integration branch.
233
- * Format: .gsd/milestones/<MID>/<MID>-META.json
232
+ * Path to the milestone integration-branch metadata file.
233
+ * Format: .gsd/<MID>-META.json (deliberately OUTSIDE milestones/<MID>/ so it
234
+ * cannot poison isLegacyMilestonesLayout — see ADR-045).
234
235
  */
235
- function milestoneMetaPath(basePath, milestoneId) {
236
+ export function milestoneMetaPath(basePath, milestoneId) {
237
+ return join(gsdRoot(basePath), `${milestoneId}-META.json`);
238
+ }
239
+ /** Legacy location (pre-ADR-045). Read-only fallback for existing on-disk trees. */
240
+ function legacyMilestoneMetaPath(basePath, milestoneId) {
236
241
  return join(gsdRoot(basePath), "milestones", milestoneId, `${milestoneId}-META.json`);
237
242
  }
238
243
  /**
@@ -241,9 +246,13 @@ function milestoneMetaPath(basePath, milestoneId) {
241
246
  */
242
247
  export function readIntegrationBranch(basePath, milestoneId) {
243
248
  try {
244
- const metaFile = milestoneMetaPath(basePath, milestoneId);
245
- if (!existsSync(metaFile))
246
- return null;
249
+ let metaFile = milestoneMetaPath(basePath, milestoneId);
250
+ if (!existsSync(metaFile)) {
251
+ const legacy = legacyMilestoneMetaPath(basePath, milestoneId);
252
+ if (!existsSync(legacy))
253
+ return null;
254
+ metaFile = legacy;
255
+ }
247
256
  const data = JSON.parse(readFileSync(metaFile, "utf-8"));
248
257
  const branch = data?.integrationBranch;
249
258
  if (typeof branch === "string" && branch.trim() !== "" && VALID_BRANCH_NAME.test(branch)) {
@@ -295,7 +304,10 @@ export function writeIntegrationBranch(basePath, milestoneId, branch) {
295
304
  if (existingBranch === branch)
296
305
  return;
297
306
  const metaFile = milestoneMetaPath(basePath, milestoneId);
298
- mkdirSync(join(gsdRoot(basePath), "milestones", milestoneId), { recursive: true });
307
+ // Ensure the flat .gsd/ root exists (never milestones/<MID>/ that would
308
+ // poison layout detection, ADR-045). In production .gsd/ already exists; this
309
+ // guards fresh trees so the write below can't ENOENT.
310
+ mkdirSync(gsdRoot(basePath), { recursive: true });
299
311
  // Merge with existing metadata if present
300
312
  let existing = {};
301
313
  try {
@@ -38,6 +38,7 @@ export * from "./db/queries.js";
38
38
  export * from "./db/writers/cascades.js";
39
39
  import { TERMINAL_STATUS_SQL } from "./db/sql-constants.js";
40
40
  import { applyStatusTransition } from "./db/writers/status.js";
41
+ import { LAYOUT_SEGMENTS, derivePhaseSlug, milestoneIdToPhaseNum, milestoneIdUniqueSuffix, phaseDirName, } from "./layout-policy.js";
41
42
  export function insertDecision(d) {
42
43
  if (!getDbOrNull())
43
44
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
@@ -169,6 +170,44 @@ export function insertArtifact(a) {
169
170
  ":content_hash": contentHash,
170
171
  });
171
172
  }
173
+ function canonicalPhaseDirNameForDb(milestoneId, title) {
174
+ const phaseNum = milestoneIdToPhaseNum(milestoneId);
175
+ const slug = derivePhaseSlug(title || milestoneId);
176
+ const suffix = milestoneIdUniqueSuffix(milestoneId);
177
+ return phaseDirName(phaseNum, suffix ? `${suffix}-${slug}` : slug);
178
+ }
179
+ function reconcileMilestonePhaseArtifactPaths(milestoneId, title) {
180
+ const db = getDbOrNull();
181
+ const phaseNumPrefix = String(milestoneIdToPhaseNum(milestoneId)).padStart(2, "0");
182
+ const canonicalDir = canonicalPhaseDirNameForDb(milestoneId, title);
183
+ const staleRows = db.prepare(`SELECT path
184
+ FROM artifacts
185
+ WHERE milestone_id = :milestone_id
186
+ AND path LIKE :phase_prefix`).all({
187
+ ":milestone_id": milestoneId,
188
+ ":phase_prefix": `${LAYOUT_SEGMENTS.level1}/${phaseNumPrefix}-%/%`,
189
+ });
190
+ const updatePath = db.prepare("UPDATE artifacts SET path = :new_path WHERE path = :old_path");
191
+ const deletePath = db.prepare("DELETE FROM artifacts WHERE path = :path");
192
+ const existingPath = db.prepare("SELECT 1 AS present FROM artifacts WHERE path = :path");
193
+ for (const row of staleRows) {
194
+ const parts = row.path.split("/");
195
+ if (parts.length < 3)
196
+ continue;
197
+ if (parts[0] !== LAYOUT_SEGMENTS.level1)
198
+ continue;
199
+ if (parts[1] === canonicalDir)
200
+ continue;
201
+ if (!parts[1]?.startsWith(`${phaseNumPrefix}-`))
202
+ continue;
203
+ const newPath = [LAYOUT_SEGMENTS.level1, canonicalDir, ...parts.slice(2)].join("/");
204
+ if (existingPath.get({ ":path": newPath })) {
205
+ deletePath.run({ ":path": row.path });
206
+ continue;
207
+ }
208
+ updatePath.run({ ":new_path": newPath, ":old_path": row.path });
209
+ }
210
+ }
172
211
  export function insertMilestone(m) {
173
212
  if (!getDbOrNull())
174
213
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
@@ -207,37 +246,42 @@ export function insertMilestone(m) {
207
246
  export function upsertMilestonePlanning(milestoneId, planning) {
208
247
  if (!getDbOrNull())
209
248
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
210
- getDbOrNull().prepare(`UPDATE milestones SET
211
- title = COALESCE(NULLIF(:title, ''), title),
212
- status = COALESCE(NULLIF(:status, ''), status),
213
- depends_on = COALESCE(:depends_on, depends_on),
214
- vision = COALESCE(:vision, vision),
215
- success_criteria = COALESCE(:success_criteria, success_criteria),
216
- key_risks = COALESCE(:key_risks, key_risks),
217
- proof_strategy = COALESCE(:proof_strategy, proof_strategy),
218
- verification_contract = COALESCE(:verification_contract, verification_contract),
219
- verification_integration = COALESCE(:verification_integration, verification_integration),
220
- verification_operational = COALESCE(:verification_operational, verification_operational),
221
- verification_uat = COALESCE(:verification_uat, verification_uat),
222
- definition_of_done = COALESCE(:definition_of_done, definition_of_done),
223
- requirement_coverage = COALESCE(:requirement_coverage, requirement_coverage),
224
- boundary_map_markdown = COALESCE(:boundary_map_markdown, boundary_map_markdown)
225
- WHERE id = :id`).run({
226
- ":id": milestoneId,
227
- ":title": planning.title ?? "",
228
- ":status": planning.status ?? "",
229
- ":depends_on": planning.depends_on ? JSON.stringify(planning.depends_on) : null,
230
- ":vision": planning.vision ?? null,
231
- ":success_criteria": planning.successCriteria ? JSON.stringify(planning.successCriteria) : null,
232
- ":key_risks": planning.keyRisks ? JSON.stringify(planning.keyRisks) : null,
233
- ":proof_strategy": planning.proofStrategy ? JSON.stringify(planning.proofStrategy) : null,
234
- ":verification_contract": planning.verificationContract ?? null,
235
- ":verification_integration": planning.verificationIntegration ?? null,
236
- ":verification_operational": planning.verificationOperational ?? null,
237
- ":verification_uat": planning.verificationUat ?? null,
238
- ":definition_of_done": planning.definitionOfDone ? JSON.stringify(planning.definitionOfDone) : null,
239
- ":requirement_coverage": planning.requirementCoverage ?? null,
240
- ":boundary_map_markdown": planning.boundaryMapMarkdown ?? null,
249
+ transaction(() => {
250
+ getDbOrNull().prepare(`UPDATE milestones SET
251
+ title = COALESCE(NULLIF(:title, ''), title),
252
+ status = COALESCE(NULLIF(:status, ''), status),
253
+ depends_on = COALESCE(:depends_on, depends_on),
254
+ vision = COALESCE(:vision, vision),
255
+ success_criteria = COALESCE(:success_criteria, success_criteria),
256
+ key_risks = COALESCE(:key_risks, key_risks),
257
+ proof_strategy = COALESCE(:proof_strategy, proof_strategy),
258
+ verification_contract = COALESCE(:verification_contract, verification_contract),
259
+ verification_integration = COALESCE(:verification_integration, verification_integration),
260
+ verification_operational = COALESCE(:verification_operational, verification_operational),
261
+ verification_uat = COALESCE(:verification_uat, verification_uat),
262
+ definition_of_done = COALESCE(:definition_of_done, definition_of_done),
263
+ requirement_coverage = COALESCE(:requirement_coverage, requirement_coverage),
264
+ boundary_map_markdown = COALESCE(:boundary_map_markdown, boundary_map_markdown)
265
+ WHERE id = :id`).run({
266
+ ":id": milestoneId,
267
+ ":title": planning.title ?? "",
268
+ ":status": planning.status ?? "",
269
+ ":depends_on": planning.depends_on ? JSON.stringify(planning.depends_on) : null,
270
+ ":vision": planning.vision ?? null,
271
+ ":success_criteria": planning.successCriteria ? JSON.stringify(planning.successCriteria) : null,
272
+ ":key_risks": planning.keyRisks ? JSON.stringify(planning.keyRisks) : null,
273
+ ":proof_strategy": planning.proofStrategy ? JSON.stringify(planning.proofStrategy) : null,
274
+ ":verification_contract": planning.verificationContract ?? null,
275
+ ":verification_integration": planning.verificationIntegration ?? null,
276
+ ":verification_operational": planning.verificationOperational ?? null,
277
+ ":verification_uat": planning.verificationUat ?? null,
278
+ ":definition_of_done": planning.definitionOfDone ? JSON.stringify(planning.definitionOfDone) : null,
279
+ ":requirement_coverage": planning.requirementCoverage ?? null,
280
+ ":boundary_map_markdown": planning.boundaryMapMarkdown ?? null,
281
+ });
282
+ const finalTitle = planning.title?.trim();
283
+ if (finalTitle)
284
+ reconcileMilestonePhaseArtifactPaths(milestoneId, finalTitle);
241
285
  });
242
286
  }
243
287
  export function insertSlice(s) {
@@ -11,7 +11,7 @@ import { loadFile, saveFile } from "./files.js";
11
11
  import { isDbAvailable, getMilestone, getMilestoneSlices } from "./gsd-db.js";
12
12
  import { parseRoadmapSlices } from "./roadmap-slices.js";
13
13
  import { loadPrompt, inlineTemplate } from "./prompt-loader.js";
14
- import { buildCompleteSlicePrompt, buildDiscussMilestonePrompt, buildExecuteTaskPrompt, buildPlanMilestonePrompt, buildPlanSlicePrompt, buildSkillActivationBlock, } from "./auto-prompts.js";
14
+ import { buildCompleteSlicePrompt, buildDiscussMilestonePrompt, buildExecuteTaskPrompt, buildPlanMilestonePrompt, buildPlanSlicePrompt, buildSkillActivationBlock, capPreamble, } from "./auto-prompts.js";
15
15
  import { deriveState, isGhostMilestone } from "./state.js";
16
16
  import { invalidateAllCaches } from "./cache.js";
17
17
  import { startAutoDetached } from "./auto.js";
@@ -855,7 +855,9 @@ function resolveDiscussSliceBasePath(basePath, milestoneId) {
855
855
  * slice summaries so the agent can ask grounded UX/behaviour questions
856
856
  * without wasting a turn reading files.
857
857
  */
858
- async function buildDiscussSlicePrompt(mid, sid, sTitle, base, options) {
858
+ // Exported for tests (`prompt-budget-enforcement.test.ts`) verifies the
859
+ // inlined-context cap. Not part of the public flow surface otherwise.
860
+ export async function buildDiscussSlicePrompt(mid, sid, sTitle, base, options) {
859
861
  const inlined = [];
860
862
  // Roadmap — always included so the agent sees surrounding slices
861
863
  const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
@@ -906,8 +908,12 @@ async function buildDiscussSlicePrompt(mid, sid, sTitle, base, options) {
906
908
  }
907
909
  }
908
910
  }
911
+ // Cap the inlined block: it grows unbounded with each completed slice's full
912
+ // SUMMARY. `capPreamble` truncates at `### ` section boundaries — roadmap and
913
+ // milestone context come first (survive), completed-slice summaries come last
914
+ // (dropped first) when the executor's window can't hold everything.
909
915
  const inlinedContext = inlined.length > 0
910
- ? `## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`
916
+ ? capPreamble(`## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`)
911
917
  : `## Inlined Context\n\n_(no context files found yet — go in blind and ask broad questions)_`;
912
918
  const sliceDirPath = `.gsd/milestones/${mid}/slices/${sid}`;
913
919
  const sliceContextPath = `${sliceDirPath}/${sid}-CONTEXT.md`;
@@ -916,7 +922,7 @@ async function buildDiscussSlicePrompt(mid, sid, sTitle, base, options) {
916
922
  ? `\n\n## Re-discuss Mode\n\nThis slice already has an existing context file (\`${sliceContextPath}\`) from a prior discussion. The user has chosen to re-discuss it. Read the existing context file, interview for any updates, changes, or new decisions, and rewrite the file with merged findings. Do NOT skip the interview — the user explicitly asked to revisit this slice.\n`
917
923
  : "";
918
924
  const inlinedTemplates = inlineTemplate("slice-context", "Slice Context");
919
- return loadPrompt("guided-discuss-slice", {
925
+ return prependLanguageDirective(base, loadPrompt("guided-discuss-slice", {
920
926
  milestoneId: mid,
921
927
  sliceId: sid,
922
928
  sliceTitle: sTitle,
@@ -927,7 +933,7 @@ async function buildDiscussSlicePrompt(mid, sid, sTitle, base, options) {
927
933
  inlinedTemplates,
928
934
  structuredQuestionsAvailable: options?.structuredQuestionsAvailable ?? "false",
929
935
  commitInstruction: buildDocsCommitInstruction(`docs(${mid}/${sid}): slice context from discuss`),
930
- });
936
+ }));
931
937
  }
932
938
  /**
933
939
  * /gsd discuss — show a picker of non-done slices and run a slice interview.
@@ -11,14 +11,14 @@
11
11
  import { readFileSync, existsSync, mkdirSync, statSync, unlinkSync } from "node:fs";
12
12
  import { logWarning } from "./workflow-logger.js";
13
13
  import { isClosedStatus } from "./status-guards.js";
14
- import { dirname, join, relative } from "node:path";
14
+ import { dirname, join } from "node:path";
15
15
  import { getAllMilestones, getMilestone, getMilestoneScopedArtifacts, getSliceScopedArtifacts, getMilestoneSlices, getSliceTasks, getTasksBySliceIds, getTask, getSlice, insertArtifact, deleteArtifactByPath, getGateResults, isDbAvailable, } from "./gsd-db.js";
16
- import { resolveDir, resolveSliceFile, resolveSlicePath, resolveTaskFile, resolveTasksDir, targetMilestoneFile, targetSliceFile, gsdProjectionRoot, gsdRoot, buildTaskFileName, } from "./paths.js";
16
+ import { resolveDir, resolveSliceFile, resolveSlicePath, resolveTaskFile, resolveTasksDir, targetMilestoneFile, targetSliceFile, targetTaskFile, gsdProjectionRoot, gsdRoot, buildTaskFileName, } from "./paths.js";
17
17
  import { saveFile, clearParseCache, registerCacheClearCallback } from "./files.js";
18
18
  import { parseRoadmap, parsePlan } from "./parsers-legacy.js";
19
19
  import { invalidateStateCache } from "./state.js";
20
20
  import { clearPathCache, milestonesDir, legacyMilestonesDir, isLegacyMilestonesLayout, resolveMilestonePath, relSliceFile, canonicalPhaseDirName } from "./paths.js";
21
- import { readCompatMarker, writeCompatMarker, computeProjectionSha } from "./compat/compat-marker.js";
21
+ import { readCompatMarker, writeCompatMarker, computeProjectionSha, deriveCompatProjectionKey } from "./compat/compat-marker.js";
22
22
  // ─── Compat marker invalidation ───────────────────────────────────────────
23
23
  // Every successful projection write pushes its (basePath, projectionPath,
24
24
  // entities) here; invalidateCaches() drains it and refreshes .gsd/.compat.json
@@ -71,13 +71,7 @@ function flushProjectionWritesToMarker() {
71
71
  */
72
72
  function toArtifactPath(absPath, basePath) {
73
73
  const projectionRoot = gsdProjectionRoot(basePath);
74
- const projectionRel = relative(projectionRoot, absPath);
75
- const root = projectionRel && !projectionRel.startsWith("..") && !projectionRel.startsWith("/")
76
- ? projectionRoot
77
- : gsdRoot(basePath);
78
- const rel = relative(root, absPath);
79
- // Normalize to forward slashes for consistent DB keys
80
- return rel.replace(/\\/g, "/");
74
+ return deriveCompatProjectionKey(absPath, [projectionRoot, gsdRoot(basePath)]);
81
75
  }
82
76
  /**
83
77
  * Invalidate all caches after a disk write.
@@ -612,17 +606,7 @@ export async function renderTaskSummary(basePath, milestoneId, sliceId, taskId)
612
606
  if (!task || !task.full_summary_md) {
613
607
  return false; // No summary to render — skip silently
614
608
  }
615
- // Resolve the tasks directory, creating path if needed
616
- const slicePath = resolveSlicePath(basePath, milestoneId, sliceId);
617
- if (!slicePath) {
618
- process.stderr.write(`markdown-renderer: cannot resolve slice path for ${milestoneId}/${sliceId}\n`);
619
- return false;
620
- }
621
- // Use the tasks/ subdir when it exists (legacy layout), otherwise use the
622
- // slice path directly (flat-phase: task summaries live alongside plan files).
623
- const tasksDir = resolveTasksDir(basePath, milestoneId, sliceId) ?? slicePath;
624
- const fileName = buildTaskFileName(taskId, "SUMMARY");
625
- const absPath = join(tasksDir, fileName);
609
+ const absPath = targetTaskFile(basePath, milestoneId, sliceId, taskId, "SUMMARY", getMilestone(milestoneId)?.title);
626
610
  const artifactPath = toArtifactPath(absPath, basePath);
627
611
  await writeAndStore(absPath, artifactPath, task.full_summary_md, {
628
612
  artifact_type: "SUMMARY",
@@ -7,7 +7,7 @@ import { readFileSync, readdirSync, existsSync, statSync } from 'node:fs';
7
7
  import { join, basename, dirname } from 'node:path';
8
8
  import { upsertDecision, upsertRequirement, insertArtifact, insertMilestone, insertSlice, insertTask, transaction, updateMilestoneStatus, updateSliceStatus, getMilestoneSlices, getSliceTasks, _getAdapter, } from './gsd-db.js';
9
9
  import { openWorkflowDatabasePath } from './db-workspace.js';
10
- import { resolveGsdRootFile, resolveMilestoneFile, resolveSliceFile, resolveSlicePath, resolveTasksDir, legacyMilestonesDir, gsdRoot, resolveTaskFiles, resolveMilestonePath, } from './paths.js';
10
+ import { resolveGsdRootFile, resolveMilestoneFile, resolveSliceFile, resolveSlicePath, resolveTasksDir, legacyMilestonesDir, gsdRoot, resolveTaskFiles, resolveTaskFile, resolveMilestonePath, } from './paths.js';
11
11
  import { findMilestoneIds } from './guided-flow.js';
12
12
  import { milestoneIdToPhaseNum } from './layout-policy.js';
13
13
  import { parseRoadmap, parsePlan } from './parsers-legacy.js';
@@ -762,8 +762,7 @@ export function migrateHierarchyToDb(basePath, opts) {
762
762
  legacyTasksDir = isLegacySlice
763
763
  ? resolveTasksDir(basePath, milestoneId, sliceEntry.id)
764
764
  : null;
765
- const summaryDir = legacyTasksDir ?? slicePath;
766
- taskSummaryFile = join(summaryDir, `${taskEntry.id}-SUMMARY.md`);
765
+ taskSummaryFile = resolveTaskFile(basePath, milestoneId, sliceEntry.id, taskEntry.id, 'SUMMARY');
767
766
  }
768
767
  const hasTaskSummary = taskSummaryFile !== null && existsSync(taskSummaryFile);
769
768
  // Pre-migration consistency (legacy tasks/ layout only): if a task is
@@ -783,9 +782,9 @@ export function migrateHierarchyToDb(basePath, opts) {
783
782
  // first execute-task. The surviving SUMMARY wins over a stale checkbox.
784
783
  // reopen-task removes the SUMMARY, so this never re-completes an
785
784
  // intentionally reopened task.
786
- // Flat-phase summaries are phase-scoped (T01-SUMMARY.md); when a milestone
787
- // has multiple slices, require the summary parent frontmatter to match so
788
- // one slice's completion does not attest a sibling's same-named task.
785
+ // Flat-phase summaries are phase-scoped; when a milestone has multiple
786
+ // slices, require the summary parent frontmatter to match so one slice's
787
+ // completion does not attest a sibling's same-named task.
789
788
  let summaryAttestsCompletion = hasTaskSummary;
790
789
  if (summaryAttestsCompletion && !isLegacySlice && roadmap.slices.length > 1 && taskSummaryFile) {
791
790
  try {
@@ -48,6 +48,9 @@ export const BUNDLED_COST_TABLE = [
48
48
  // GPT-5.5 API list price, also used for live Codex OAuth routing.
49
49
  // Source: https://openai.com/api/pricing/
50
50
  { id: "gpt-5.5", inputPer1k: 0.005, outputPer1k: 0.03, updatedAt: "2026-04-23" },
51
+ { id: "gpt-5.6-sol", inputPer1k: 0.005, outputPer1k: 0.03, tiers: [{ inputTokensAbove: 272000, inputPer1k: 0.01, outputPer1k: 0.045 }], updatedAt: "2026-07-11" },
52
+ { id: "gpt-5.6-terra", inputPer1k: 0.0025, outputPer1k: 0.015, tiers: [{ inputTokensAbove: 272000, inputPer1k: 0.005, outputPer1k: 0.0225 }], updatedAt: "2026-07-11" },
53
+ { id: "gpt-5.6-luna", inputPer1k: 0.001, outputPer1k: 0.006, tiers: [{ inputTokensAbove: 272000, inputPer1k: 0.002, outputPer1k: 0.009 }], updatedAt: "2026-07-11" },
51
54
  // Google
52
55
  { id: "gemini-2.0-flash", inputPer1k: 0.0001, outputPer1k: 0.0004, updatedAt: "2025-03-15" },
53
56
  { id: "gemini-flash-2.0", inputPer1k: 0.0001, outputPer1k: 0.0004, updatedAt: "2025-03-15" },
@@ -61,7 +64,9 @@ export const BUNDLED_COST_TABLE = [
61
64
  export function lookupModelCost(modelId) {
62
65
  const bareId = modelId.includes("/") ? modelId.split("/").pop() : modelId;
63
66
  return BUNDLED_COST_TABLE.find(e => e.id === bareId)
64
- ?? BUNDLED_COST_TABLE.find(e => bareId.includes(e.id) || e.id.includes(bareId));
67
+ ?? BUNDLED_COST_TABLE.find(e => bareId.startsWith(`${e.id}-`) ||
68
+ bareId.startsWith(`${e.id}:`) ||
69
+ bareId.startsWith(`${e.id}@`));
65
70
  }
66
71
  /**
67
72
  * Compare two models by input cost. Returns negative if a is cheaper.
@@ -46,10 +46,14 @@ export const MODEL_CAPABILITY_TIER = {
46
46
  "gpt-5.3-codex": "heavy",
47
47
  "gpt-5.4": "heavy",
48
48
  "gpt-5.5": "heavy",
49
+ "gpt-5.6-sol": "heavy",
50
+ "gpt-5.6-terra": "heavy",
51
+ "gpt-5.6-luna": "heavy",
49
52
  "o1": "heavy",
50
53
  "o3": "heavy",
51
54
  "o4-mini": "heavy",
52
55
  "o4-mini-deep-research": "heavy",
56
+ "grok-4.5": "heavy",
53
57
  };
54
58
  // ─── Cost Table (per 1K input tokens, approximate USD) ───────────────────────
55
59
  // Used for cross-provider cost comparison when multiple providers offer
@@ -82,11 +86,15 @@ const MODEL_COST_PER_1K_INPUT = {
82
86
  "gpt-5.3-codex-spark": 0.0003,
83
87
  "gpt-5.4": 0.005,
84
88
  "gpt-5.5": 0.005,
89
+ "gpt-5.6-sol": 0.005,
90
+ "gpt-5.6-terra": 0.0025,
91
+ "gpt-5.6-luna": 0.001,
85
92
  "o4-mini": 0.005,
86
93
  "o4-mini-deep-research": 0.005,
87
94
  "gemini-2.0-flash": 0.0001,
88
95
  "gemini-2.5-pro": 0.00125,
89
96
  "deepseek-chat": 0.00014,
97
+ "grok-4.5": 0.002,
90
98
  };
91
99
  // ─── Capability Profiles Data Table ──────────────────────────────────────────
92
100
  // Per-model capability profiles (0–100 scale). Used for capability-aware
@@ -128,6 +136,10 @@ export const MODEL_CAPABILITY_PROFILES = {
128
136
  // OpenAI's 2026-04-23 published eval deltas across coding, tool use, and long context.
129
137
  // Source: https://openai.com/index/introducing-gpt-5-5/
130
138
  "gpt-5.5": { coding: 96, debugging: 93, research: 89, reasoning: 95, speed: 42, longContext: 90, instruction: 93 },
139
+ // GPT-5.6 profiles are provisional until official eval results are available.
140
+ "gpt-5.6-sol": { coding: 97, debugging: 94, research: 90, reasoning: 96, speed: 42, longContext: 91, instruction: 94 },
141
+ "gpt-5.6-terra": { coding: 96, debugging: 93, research: 89, reasoning: 95, speed: 48, longContext: 91, instruction: 93 },
142
+ "gpt-5.6-luna": { coding: 92, debugging: 88, research: 84, reasoning: 91, speed: 72, longContext: 91, instruction: 90 },
131
143
  // ── OpenAI o-series (reasoning-first) ──────────────────────────────────────
132
144
  "o1": { coding: 78, debugging: 82, research: 78, reasoning: 90, speed: 20, longContext: 65, instruction: 82 },
133
145
  "o3": { coding: 80, debugging: 85, research: 80, reasoning: 92, speed: 25, longContext: 70, instruction: 85 },
@@ -139,6 +151,10 @@ export const MODEL_CAPABILITY_PROFILES = {
139
151
  "gemini-flash-2.0": { coding: 50, debugging: 40, research: 50, reasoning: 40, speed: 95, longContext: 60, instruction: 65 },
140
152
  // ── DeepSeek ───────────────────────────────────────────────────────────────
141
153
  "deepseek-chat": { coding: 75, debugging: 65, research: 55, reasoning: 70, speed: 70, longContext: 55, instruction: 65 },
154
+ // ── xAI ────────────────────────────────────────────────────────────────────
155
+ // Grok 4.5 (2026-07): Opus-class frontier model tuned for coding and agentic
156
+ // work; notably faster and more token-efficient than peer heavy models.
157
+ "grok-4.5": { coding: 95, debugging: 90, research: 82, reasoning: 93, speed: 55, longContext: 80, instruction: 90 },
142
158
  };
143
159
  // ─── Base Task Requirements Data Table ───────────────────────────────────────
144
160
  // Per-unit-type base requirement vectors. Weights indicate how important each
@@ -122,6 +122,14 @@ function cachedReaddir(dirPath) {
122
122
  dirListCache.set(dirPath, entries);
123
123
  return entries;
124
124
  }
125
+ function isExistingFile(path) {
126
+ try {
127
+ return statSync(path).isFile();
128
+ }
129
+ catch {
130
+ return false;
131
+ }
132
+ }
125
133
  /**
126
134
  * Clear the volatile directory listing caches.
127
135
  * Call after milestone transitions, file creation in planning directories,
@@ -198,6 +206,25 @@ export function buildTaskFileName(taskId, suffix) {
198
206
  // This helper is deprecated but kept for backward-compat callers.
199
207
  return `${taskId}-${suffix}.md`;
200
208
  }
209
+ /**
210
+ * Build a flat-phase task artifact file name.
211
+ * ("S06", "T03", "SUMMARY") → "S06-T03-SUMMARY.md"
212
+ */
213
+ export function buildFlatTaskFileName(sliceId, taskId, suffix) {
214
+ return `${sliceId}-${taskId}-${suffix}.md`;
215
+ }
216
+ /**
217
+ * Extract the task ID from a task artifact filename.
218
+ * Supports flat-phase S##-T##-SUFFIX.md plus legacy T##-SUFFIX.md and
219
+ * T##-DESCRIPTOR-SUFFIX.md names.
220
+ */
221
+ export function taskIdFromTaskFileName(fileName, suffix) {
222
+ const flat = new RegExp(`^S\\d+-(T\\d+)-${suffix}\\.md$`, "i").exec(fileName);
223
+ if (flat?.[1])
224
+ return flat[1].toUpperCase();
225
+ const legacy = new RegExp(`^(T\\d+)(?:-.*)?-${suffix}\\.md$`, "i").exec(fileName);
226
+ return legacy?.[1]?.toUpperCase() ?? null;
227
+ }
201
228
  // ─── Resolvers ─────────────────────────────────────────────────────────────
202
229
  /**
203
230
  * Find a directory entry by ID prefix within a parent directory.
@@ -238,7 +265,7 @@ export function resolveFile(dir, idPrefix, suffix) {
238
265
  return null;
239
266
  const target = `${idPrefix}-${suffix}.md`.toUpperCase();
240
267
  try {
241
- const entries = cachedReaddir(dir);
268
+ const entries = cachedReaddirWithTypes(dir).filter(e => e.isFile()).map(e => e.name);
242
269
  // Direct match: ID-SUFFIX.md
243
270
  const direct = entries.find(e => e.toUpperCase() === target);
244
271
  if (direct)
@@ -259,19 +286,18 @@ export function resolveFile(dir, idPrefix, suffix) {
259
286
  }
260
287
  }
261
288
  /**
262
- * Find all task files matching a pattern in a tasks directory.
263
- * Returns sorted file names matching T##-SUFFIX.md or legacy T##-*-SUFFIX.md
289
+ * Find all task files matching a pattern in a tasks directory or flat phase dir.
290
+ * Returns sorted file names matching S##-T##-SUFFIX.md, T##-SUFFIX.md,
291
+ * or legacy T##-*-SUFFIX.md.
264
292
  */
265
293
  export function resolveTaskFiles(tasksDir, suffix) {
266
294
  if (!existsSync(tasksDir))
267
295
  return [];
268
296
  try {
269
- // Current convention: T01-PLAN.md
270
- const currentPattern = new RegExp(`^T\\d+-${suffix}\\.md$`, "i");
271
- // Legacy convention: T01-INSTALL-PACKAGES-PLAN.md
272
- const legacyPattern = new RegExp(`^T\\d+-.*-${suffix}\\.md$`, "i");
273
- return cachedReaddir(tasksDir)
274
- .filter(f => currentPattern.test(f) || legacyPattern.test(f))
297
+ return cachedReaddirWithTypes(tasksDir)
298
+ .filter(e => e.isFile())
299
+ .map(e => e.name)
300
+ .filter(f => taskIdFromTaskFileName(f, suffix) !== null)
275
301
  .sort();
276
302
  }
277
303
  catch {
@@ -810,7 +836,7 @@ export function resolveMilestoneFile(basePath, milestoneId, suffix) {
810
836
  const prefix = `${String(phaseNum).padStart(2, "0")}`;
811
837
  const flatName = `${prefix}-${suffix}.md`;
812
838
  const flatPath = join(mDir, flatName);
813
- if (existsSync(flatPath))
839
+ if (isExistingFile(flatPath))
814
840
  return flatPath;
815
841
  // Legacy fallback: M001-SUFFIX.md
816
842
  const file = resolveFile(mDir, milestoneId, suffix);
@@ -843,12 +869,12 @@ export function resolveSliceFile(basePath, milestoneId, sliceId, suffix) {
843
869
  const planNum = sliceIdToPlanNum(sliceId);
844
870
  const flatName = planFileName(phaseNum, planNum, suffix);
845
871
  const flatPath = join(phaseDir, flatName);
846
- if (existsSync(flatPath))
872
+ if (isExistingFile(flatPath))
847
873
  return flatPath;
848
874
  // Also check plan-number-only format MM-SUFFIX.md (written by buildSliceFileName)
849
875
  const planOnlyName = `${String(planNum).padStart(2, "0")}-${suffix}.md`;
850
876
  const planOnlyPath = join(phaseDir, planOnlyName);
851
- if (existsSync(planOnlyPath))
877
+ if (isExistingFile(planOnlyPath))
852
878
  return planOnlyPath;
853
879
  // Try prefix match for the phase+plan number (handles suffix variations)
854
880
  const planPrefix = `${String(phaseNum).padStart(2, "0")}-${String(planNum).padStart(2, "0")}-`;
@@ -893,8 +919,11 @@ export function resolveTaskFile(basePath, milestoneId, sliceId, taskId, suffix)
893
919
  const legacyBase = legacyMilestonesDir(basePath);
894
920
  const isLegacy = phaseDir.startsWith(legacyBase + "/") || phaseDir.startsWith(legacyBase + "\\");
895
921
  if (suffix !== "PLAN" && !isLegacy) {
896
- const flatPath = join(phaseDir, buildTaskFileName(taskId, suffix));
897
- return existsSync(flatPath) ? flatPath : null;
922
+ const flatPath = join(phaseDir, buildFlatTaskFileName(sliceId, taskId, suffix));
923
+ if (isExistingFile(flatPath))
924
+ return flatPath;
925
+ const legacyFlatPath = join(phaseDir, buildTaskFileName(taskId, suffix));
926
+ return isExistingFile(legacyFlatPath) ? legacyFlatPath : null;
898
927
  }
899
928
  const tDir = resolveTasksDir(basePath, milestoneId, sliceId);
900
929
  if (tDir) {
@@ -1006,6 +1035,28 @@ export function targetSliceFile(basePath, milestoneId, sliceId, suffix, mileston
1006
1035
  : planFileName(milestoneIdToPhaseNum(milestoneId), sliceIdToPlanNum(sliceId), suffix);
1007
1036
  return join(dir, fileName);
1008
1037
  }
1038
+ /**
1039
+ * Build the canonical absolute write target for a task file.
1040
+ * Readers that need legacy flat-phase fallback should call resolveTaskFile.
1041
+ */
1042
+ export function targetTaskFile(basePath, milestoneId, sliceId, taskId, suffix, milestoneTitle) {
1043
+ if (suffix === "PLAN") {
1044
+ return targetSliceFile(basePath, milestoneId, sliceId, "PLAN", milestoneTitle);
1045
+ }
1046
+ const mDir = resolveMilestonePath(basePath, milestoneId);
1047
+ const legacyBase = legacyMilestonesDir(basePath);
1048
+ const isLegacy = mDir
1049
+ ? mDir.startsWith(legacyBase + "/") || mDir.startsWith(legacyBase + "\\")
1050
+ : isLegacyMilestonesLayout(basePath);
1051
+ const milestoneDir = mDir
1052
+ ?? dirname(targetMilestoneFile(basePath, milestoneId, "ROADMAP", milestoneTitle));
1053
+ if (isLegacy) {
1054
+ const slicesDir = join(milestoneDir, "slices");
1055
+ const sliceDir = join(slicesDir, resolveDir(slicesDir, sliceId) ?? sliceId);
1056
+ return join(sliceDir, "tasks", buildTaskFileName(taskId, suffix));
1057
+ }
1058
+ return join(milestoneDir, buildFlatTaskFileName(sliceId, taskId, suffix));
1059
+ }
1009
1060
  /**
1010
1061
  * Build relative .gsd/ path to a slice file.
1011
1062
  * Preserves an existing compatibility filename when present; otherwise falls
@@ -1036,5 +1087,5 @@ export function relTaskFile(basePath, milestoneId, sliceId, taskId, suffix, mile
1036
1087
  return relSliceFile(basePath, milestoneId, sliceId, "PLAN");
1037
1088
  }
1038
1089
  const relS = relSlicePath(basePath, milestoneId, sliceId, milestoneTitle);
1039
- return `${relS}/${buildTaskFileName(taskId, suffix)}`;
1090
+ return `${relS}/${buildFlatTaskFileName(sliceId, taskId, suffix)}`;
1040
1091
  }
@@ -0,0 +1,37 @@
1
+ import { CONFIGURABLE_PLANNING_SUBAGENT_UNITS } from "./preferences-types.js";
2
+ import { loadEffectiveGSDPreferences } from "./preferences.js";
3
+ const CONFIGURABLE_UNITS = new Set(CONFIGURABLE_PLANNING_SUBAGENT_UNITS);
4
+ function configuredAllowedSubagents(unitType, preferences) {
5
+ if (!CONFIGURABLE_UNITS.has(unitType))
6
+ return [];
7
+ return preferences?.planning_subagents?.[unitType]?.allowed ?? [];
8
+ }
9
+ function mergeAllowedSubagents(current, configured) {
10
+ return Array.from(new Set([...current, ...configured]));
11
+ }
12
+ export function applyPlanningSubagentPreferences(unitType, policy, preferences) {
13
+ if (!policy)
14
+ return policy;
15
+ const configured = configuredAllowedSubagents(unitType, preferences);
16
+ if (configured.length === 0)
17
+ return policy;
18
+ if (policy.mode === "planning") {
19
+ return {
20
+ mode: "planning-dispatch",
21
+ allowedSubagents: mergeAllowedSubagents([], configured),
22
+ };
23
+ }
24
+ if (policy.mode === "planning-dispatch") {
25
+ return {
26
+ ...policy,
27
+ allowedSubagents: mergeAllowedSubagents(policy.allowedSubagents, configured),
28
+ };
29
+ }
30
+ return policy;
31
+ }
32
+ export function resolveEffectivePlanningToolsPolicy(unitType, policy, basePath) {
33
+ if (!basePath)
34
+ return policy;
35
+ const preferences = loadEffectiveGSDPreferences(basePath)?.preferences;
36
+ return applyPlanningSubagentPreferences(unitType, policy, preferences);
37
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Read-only planning specialists that controlled planning dispatch may use.
3
+ *
4
+ * Unit manifests and project preferences still declare per-unit subsets. This
5
+ * registry is the global safety classification checked by the write gate and
6
+ * preference validation before any configured planning allowlist takes effect.
7
+ */
8
+ const PLANNING_DISPATCH_AGENT_REGISTRY = {
9
+ mnemo: { readOnlySpecialist: true },
10
+ scout: { readOnlySpecialist: true },
11
+ planner: { readOnlySpecialist: true },
12
+ reviewer: { readOnlySpecialist: true },
13
+ security: { readOnlySpecialist: true },
14
+ tester: { readOnlySpecialist: true },
15
+ };
16
+ export const ALLOWED_PLANNING_DISPATCH_AGENTS = new Set(Object.entries(PLANNING_DISPATCH_AGENT_REGISTRY)
17
+ .filter(([, metadata]) => metadata.readOnlySpecialist)
18
+ .map(([agentId]) => agentId));
19
+ function configuredPlanningDispatchAgents(registry) {
20
+ return Object.entries(registry ?? {})
21
+ .filter(([, metadata]) => metadata.read_only_specialist === true)
22
+ .map(([agentId]) => agentId);
23
+ }
24
+ export function isReadOnlyPlanningDispatchAgent(agentId, registry) {
25
+ const metadata = PLANNING_DISPATCH_AGENT_REGISTRY[agentId];
26
+ return metadata?.readOnlySpecialist === true || registry?.[agentId]?.read_only_specialist === true;
27
+ }
28
+ export function allowedPlanningDispatchAgentsList(registry) {
29
+ return Array.from(new Set([
30
+ ...ALLOWED_PLANNING_DISPATCH_AGENTS,
31
+ ...configuredPlanningDispatchAgents(registry),
32
+ ])).join(", ");
33
+ }