@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
@@ -0,0 +1,177 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { mkdirSync, writeFileSync } from "node:fs";
4
+ import { dirname, join } from "node:path";
5
+
6
+ import { getMilestoneSlices, getSliceTasks } from "../gsd-db.ts";
7
+ import { queryDecisionsFromMemories, queryRequirements } from "../context-store.ts";
8
+ import { deriveStateFromDb } from "../state.ts";
9
+ import {
10
+ createWorkflowAuthorityFixture,
11
+ type WorkflowAuthorityFixture,
12
+ } from "./workflow-authority-fixture.ts";
13
+
14
+ function writeProjection(root: string, path: string, content: string): void {
15
+ const fullPath = join(root, ".gsd", path);
16
+ mkdirSync(dirname(fullPath), { recursive: true });
17
+ writeFileSync(fullPath, content, "utf8");
18
+ }
19
+
20
+ function writeContradictoryProjections(root: string): void {
21
+ writeProjection(
22
+ root,
23
+ "STATE.md",
24
+ [
25
+ "# GSD State",
26
+ "",
27
+ "**Active Milestone:** M999",
28
+ "**Active Slice:** S99",
29
+ "**Phase:** complete",
30
+ "**Requirements Status:** 0 active · 1 validated",
31
+ ].join("\n"),
32
+ );
33
+ writeProjection(
34
+ root,
35
+ "PROJECT.md",
36
+ [
37
+ "# Projection-only project",
38
+ "",
39
+ "## Milestone Sequence",
40
+ "- [x] M001: Falsely complete",
41
+ "- [ ] M999: Projection-only active milestone",
42
+ ].join("\n"),
43
+ );
44
+ writeProjection(
45
+ root,
46
+ "REQUIREMENTS.md",
47
+ [
48
+ "# Requirements",
49
+ "",
50
+ "## Validated",
51
+ "### R999 — Markdown controls workflow state",
52
+ "- Status: validated",
53
+ "- Primary owning slice: M999/S99",
54
+ ].join("\n"),
55
+ );
56
+ writeProjection(
57
+ root,
58
+ "DECISIONS.md",
59
+ [
60
+ "# Decisions Register",
61
+ "",
62
+ "| # | When | Scope | Decision | Choice | Rationale | Revisable? | Made By |",
63
+ "|---|------|-------|----------|--------|-----------|------------|---------|",
64
+ "| D999 | M999/S99 | architecture | Choose authority | Markdown is authoritative | projection conflict | No | human |",
65
+ ].join("\n"),
66
+ );
67
+ writeProjection(
68
+ root,
69
+ "milestones/M001/M001-ROADMAP.md",
70
+ [
71
+ "# M001: Falsely complete",
72
+ "",
73
+ "## Slices",
74
+ "- [ ] **S01: Falsely reopened** `risk:low` `depends:[]`",
75
+ "- [x] **S02: Falsely complete** `risk:low` `depends:[]`",
76
+ ].join("\n"),
77
+ );
78
+ writeProjection(
79
+ root,
80
+ "milestones/M001/slices/S02/S02-PLAN.md",
81
+ [
82
+ "# S02: Falsely complete",
83
+ "",
84
+ "## Tasks",
85
+ "- [x] **T99: Projection-only task** `est:1m`",
86
+ ].join("\n"),
87
+ );
88
+ }
89
+
90
+ async function readDirectDbAuthoritySnapshot(fixture: WorkflowAuthorityFixture) {
91
+ const state = await deriveStateFromDb(fixture.root);
92
+ return {
93
+ state: {
94
+ phase: state.phase,
95
+ milestone: state.activeMilestone?.id ?? null,
96
+ slice: state.activeSlice?.id ?? null,
97
+ task: state.activeTask?.id ?? null,
98
+ requirements: state.requirements,
99
+ },
100
+ registry: state.registry.map((milestone) => ({
101
+ id: milestone.id,
102
+ status: milestone.status,
103
+ })),
104
+ slices: getMilestoneSlices(fixture.ids.milestone).map((slice) => ({
105
+ id: slice.id,
106
+ status: slice.status,
107
+ depends: slice.depends,
108
+ })),
109
+ tasks: {
110
+ completed: getSliceTasks(fixture.ids.milestone, fixture.ids.completedSlice).map((task) => ({
111
+ id: task.id,
112
+ status: task.status,
113
+ })),
114
+ ready: getSliceTasks(fixture.ids.milestone, fixture.ids.readySlice).map((task) => ({
115
+ id: task.id,
116
+ status: task.status,
117
+ })),
118
+ },
119
+ requirements: queryRequirements({
120
+ milestoneId: fixture.ids.milestone,
121
+ sliceId: fixture.ids.readySlice,
122
+ }).map((requirement) => ({
123
+ id: requirement.id,
124
+ status: requirement.status,
125
+ owner: requirement.primary_owner,
126
+ })),
127
+ decisions: queryDecisionsFromMemories().map((decision) => ({
128
+ id: decision.id,
129
+ choice: decision.choice,
130
+ })),
131
+ };
132
+ }
133
+
134
+ test("direct DB authority queries ignore contradictory Markdown projections", async (t) => {
135
+ const fixture = await createWorkflowAuthorityFixture();
136
+ t.after(() => fixture.cleanup());
137
+ fixture.reopen();
138
+ const before = await readDirectDbAuthoritySnapshot(fixture);
139
+
140
+ assert.deepEqual(before, {
141
+ state: {
142
+ phase: "executing",
143
+ milestone: fixture.ids.milestone,
144
+ slice: fixture.ids.readySlice,
145
+ task: fixture.ids.readyTask,
146
+ requirements: {
147
+ active: 1,
148
+ validated: 0,
149
+ deferred: 0,
150
+ outOfScope: 0,
151
+ blocked: 0,
152
+ total: 1,
153
+ },
154
+ },
155
+ registry: [{ id: fixture.ids.milestone, status: "active" }],
156
+ slices: [
157
+ { id: fixture.ids.completedSlice, status: "complete", depends: [] },
158
+ { id: fixture.ids.readySlice, status: "pending", depends: [fixture.ids.completedSlice] },
159
+ ],
160
+ tasks: {
161
+ completed: [{ id: fixture.ids.completedTask, status: "complete" }],
162
+ ready: [{ id: fixture.ids.readyTask, status: "pending" }],
163
+ },
164
+ requirements: [
165
+ { id: fixture.ids.requirement, status: "active", owner: "M001/S02" },
166
+ ],
167
+ decisions: [
168
+ { id: fixture.ids.decision, choice: "SQLite is authoritative" },
169
+ ],
170
+ });
171
+
172
+ writeContradictoryProjections(fixture.root);
173
+ fixture.reopen();
174
+
175
+ const after = await readDirectDbAuthoritySnapshot(fixture);
176
+ assert.deepEqual(after, before);
177
+ });
@@ -0,0 +1,39 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+
4
+ import {
5
+ createWorkflowFaultHarness,
6
+ type WorkflowFaultPoint,
7
+ } from "./workflow-fault-harness.js";
8
+
9
+ test("fault harness throws once at the armed named boundary", () => {
10
+ const harness = createWorkflowFaultHarness("after-db-commit-before-render");
11
+
12
+ harness.hit("before-transaction-commit", "complete-task");
13
+ assert.throws(
14
+ () => harness.hit("after-db-commit-before-render", "complete-task"),
15
+ /complete-task.*after-db-commit-before-render.*hit 1/,
16
+ );
17
+
18
+ assert.equal(harness.count("before-transaction-commit"), 1);
19
+ assert.equal(harness.count("after-db-commit-before-render"), 1);
20
+ });
21
+
22
+ test("fault harness automatically disarms after its first matching hit", () => {
23
+ const point: WorkflowFaultPoint = "during-projection-write";
24
+ const harness = createWorkflowFaultHarness(point);
25
+
26
+ assert.throws(() => harness.hit(point, "complete-slice"));
27
+ assert.doesNotThrow(() => harness.hit(point, "complete-slice"));
28
+ assert.equal(harness.count(point), 2);
29
+ });
30
+
31
+ test("fault harness instances never share armed state or counts", () => {
32
+ const first = createWorkflowFaultHarness("before-independent-reopen");
33
+ const second = createWorkflowFaultHarness("before-independent-reopen");
34
+
35
+ assert.throws(() => first.hit("before-independent-reopen", "resume"));
36
+ assert.equal(first.count("before-independent-reopen"), 1);
37
+ assert.equal(second.count("before-independent-reopen"), 0);
38
+ assert.throws(() => second.hit("before-independent-reopen", "resume"));
39
+ });
@@ -0,0 +1,72 @@
1
+ import { mkdirSync } from "node:fs";
2
+
3
+ import { getDb } from "../gsd-db.js";
4
+
5
+ export type WorkflowFaultPoint =
6
+ | "before-transaction-commit"
7
+ | "after-db-commit-before-render"
8
+ | "during-projection-write"
9
+ | "before-independent-reopen"
10
+ | "after-independent-reopen";
11
+
12
+ export interface WorkflowFaultHarness {
13
+ hit(point: WorkflowFaultPoint, operation?: string): void;
14
+ count(point: WorkflowFaultPoint): number;
15
+ armDatabaseAbort(
16
+ column: "status" | "full_summary_md",
17
+ predicate:
18
+ | "NEW.status = 'complete' AND OLD.status <> 'complete'"
19
+ | "NEW.full_summary_md IS NOT OLD.full_summary_md",
20
+ ): void;
21
+ obstructProjection(path: string): void;
22
+ }
23
+
24
+ export class WorkflowFaultError extends Error {
25
+ readonly point: WorkflowFaultPoint;
26
+ readonly operation: string;
27
+ readonly hitCount: number;
28
+
29
+ constructor(point: WorkflowFaultPoint, operation: string, hitCount: number) {
30
+ super(`${operation} fault at ${point} (hit ${hitCount})`);
31
+ this.name = "WorkflowFaultError";
32
+ this.point = point;
33
+ this.operation = operation;
34
+ this.hitCount = hitCount;
35
+ }
36
+ }
37
+
38
+ export function createWorkflowFaultHarness(
39
+ armedPoint: WorkflowFaultPoint,
40
+ ): WorkflowFaultHarness {
41
+ const counts = new Map<WorkflowFaultPoint, number>();
42
+ let armed = true;
43
+
44
+ return {
45
+ hit(point, operation = "workflow-operation") {
46
+ const hitCount = (counts.get(point) ?? 0) + 1;
47
+ counts.set(point, hitCount);
48
+ if (armed && point === armedPoint) {
49
+ armed = false;
50
+ throw new WorkflowFaultError(point, operation, hitCount);
51
+ }
52
+ },
53
+ count(point) {
54
+ return counts.get(point) ?? 0;
55
+ },
56
+ armDatabaseAbort(column, predicate) {
57
+ const triggerName = `workflow_fault_${armedPoint.replaceAll("-", "_")}`;
58
+ const message = `complete-dependent-slice fault at ${armedPoint}`;
59
+ getDb().exec(`
60
+ CREATE TEMP TRIGGER ${triggerName}
61
+ BEFORE UPDATE OF ${column} ON slices
62
+ WHEN ${predicate}
63
+ BEGIN
64
+ SELECT RAISE(ABORT, '${message}');
65
+ END
66
+ `);
67
+ },
68
+ obstructProjection(path) {
69
+ mkdirSync(path, { recursive: true });
70
+ },
71
+ };
72
+ }
@@ -352,7 +352,7 @@ test('workflow-projections: regenerateIfMissing SUMMARY is idempotent for flat-p
352
352
  keyDecisions: ['Use centralized task summary paths.'],
353
353
  });
354
354
 
355
- const summaryPath = join(phaseDir, 'T01-SUMMARY.md');
355
+ const summaryPath = join(phaseDir, 'S01-T01-SUMMARY.md');
356
356
  assert.ok(!existsSync(summaryPath), 'precondition: flat-phase task summary absent');
357
357
 
358
358
  const first = await regenerateIfMissing(base, 'M001', 'S01', 'SUMMARY');
@@ -399,7 +399,7 @@ test('workflow-projections: flat-phase SUMMARY regeneration ignores stale nested
399
399
  status: 'complete',
400
400
  });
401
401
 
402
- const rootSummaryPath = join(phaseDir, 'T01-SUMMARY.md');
402
+ const rootSummaryPath = join(phaseDir, 'S01-T01-SUMMARY.md');
403
403
  assert.ok(!existsSync(rootSummaryPath), 'precondition: canonical flat-phase task summary absent');
404
404
 
405
405
  const regenerated = await regenerateIfMissing(base, 'M001', 'S01', 'SUMMARY');
@@ -440,8 +440,8 @@ test('workflow-projections: renderSummaryProjection uses milestone title when cr
440
440
  status: 'complete',
441
441
  });
442
442
 
443
- const titleSummaryPath = join(base, '.gsd', 'phases', '01-milestone', 'T01-SUMMARY.md');
444
- const idSummaryPath = join(base, '.gsd', 'phases', '01-m001', 'T01-SUMMARY.md');
443
+ const titleSummaryPath = join(base, '.gsd', 'phases', '01-milestone', 'S01-T01-SUMMARY.md');
444
+ const idSummaryPath = join(base, '.gsd', 'phases', '01-m001', 'S01-T01-SUMMARY.md');
445
445
 
446
446
  renderSummaryProjection(base, 'M001', 'S01', 'T01');
447
447
 
@@ -117,8 +117,8 @@ test("projectRootToWorktree projects flat-phase discuss artifacts before dispatc
117
117
  new WorktreeStateProjection().projectRootToWorktree(scope);
118
118
 
119
119
  assert.ok(
120
- existsSync(join(worktree, ".gsd", "milestones", "M001", "M001-META.json")),
121
- "milestone metadata is projected into the worktree",
120
+ !existsSync(join(worktree, ".gsd", "milestones")),
121
+ "stale metadata-only legacy milestones/ scaffold is not projected into the worktree",
122
122
  );
123
123
  assert.ok(
124
124
  existsSync(join(worktree, ".gsd", "phases", "01-foundation", "01-CONTEXT.md")),
@@ -246,6 +246,66 @@ describe('worktree-sync-milestones', async () => {
246
246
  }
247
247
  }
248
248
 
249
+ // ─── 7b. flat-phase sync skips empty legacy milestones root ───────────
250
+ console.log('\n=== 7b. flat-phase sync skips empty legacy milestones root ===');
251
+ {
252
+ const mainBase = mkdtempSync(join(tmpdir(), 'gsd-wt-sync-flat-main-'));
253
+ const wtBase = mkdtempSync(join(tmpdir(), 'gsd-wt-sync-flat-wt-'));
254
+
255
+ try {
256
+ const phaseDir = join(mainBase, '.gsd', 'phases', '01-foundation');
257
+ mkdirSync(phaseDir, { recursive: true });
258
+ mkdirSync(join(mainBase, '.gsd', 'milestones'), { recursive: true });
259
+ mkdirSync(join(wtBase, '.gsd'), { recursive: true });
260
+ writeFileSync(join(phaseDir, '01-CONTEXT.md'), '# Foundation\n');
261
+
262
+ syncGsdStateToWorktree(mainBase, wtBase);
263
+
264
+ assert.ok(
265
+ existsSync(join(wtBase, '.gsd', 'phases', '01-foundation', '01-CONTEXT.md')),
266
+ 'flat-phase artifact is synced to worktree',
267
+ );
268
+ assert.ok(
269
+ !existsSync(join(wtBase, '.gsd', 'milestones')),
270
+ 'empty legacy milestones/ root is not recreated in worktree',
271
+ );
272
+ } finally {
273
+ rmSync(mainBase, { recursive: true, force: true });
274
+ rmSync(wtBase, { recursive: true, force: true });
275
+ }
276
+ }
277
+
278
+ // ─── 7c. flat-phase sync skips metadata-only legacy milestone dirs ────
279
+ console.log('\n=== 7c. flat-phase sync skips metadata-only legacy milestone dirs ===');
280
+ {
281
+ const mainBase = mkdtempSync(join(tmpdir(), 'gsd-wt-sync-flat-meta-main-'));
282
+ const wtBase = mkdtempSync(join(tmpdir(), 'gsd-wt-sync-flat-meta-wt-'));
283
+
284
+ try {
285
+ const phaseDir = join(mainBase, '.gsd', 'phases', '01-foundation');
286
+ const metaDir = join(mainBase, '.gsd', 'milestones', 'M001');
287
+ mkdirSync(phaseDir, { recursive: true });
288
+ mkdirSync(metaDir, { recursive: true });
289
+ mkdirSync(join(wtBase, '.gsd'), { recursive: true });
290
+ writeFileSync(join(phaseDir, '01-CONTEXT.md'), '# Foundation\n');
291
+ writeFileSync(join(metaDir, 'M001-META.json'), '{"integrationBranch":"main"}\n');
292
+
293
+ syncGsdStateToWorktree(mainBase, wtBase);
294
+
295
+ assert.ok(
296
+ existsSync(join(wtBase, '.gsd', 'phases', '01-foundation', '01-CONTEXT.md')),
297
+ 'flat-phase artifact is synced to worktree',
298
+ );
299
+ assert.ok(
300
+ !existsSync(join(wtBase, '.gsd', 'milestones')),
301
+ 'metadata-only legacy milestones/ scaffold is not recreated in worktree',
302
+ );
303
+ } finally {
304
+ rmSync(mainBase, { recursive: true, force: true });
305
+ rmSync(wtBase, { recursive: true, force: true });
306
+ }
307
+ }
308
+
249
309
  // ─── 8. syncWorktreeStateBack does not copy task projections ───────────
250
310
  console.log('\n=== 8. syncWorktreeStateBack leaves task projections in worktree ===');
251
311
  {
@@ -7,12 +7,16 @@
7
7
 
8
8
  import test from 'node:test';
9
9
  import assert from 'node:assert/strict';
10
+ import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
11
+ import { tmpdir } from 'node:os';
10
12
  import { join, sep } from 'node:path';
11
13
 
12
14
  import { GSD_PHASE_SCOPE_DISPLAY_REASON, GSD_SECTION_CLOSE_GATE_DISPLAY_REASON } from '../auto-unit-tool-scope.ts';
13
15
  import { ALLOWED_PLANNING_DISPATCH_AGENTS, shouldBlockPlanningUnit } from '../bootstrap/write-gate.ts';
14
16
  import { extractSubagentAgentClasses } from '../bootstrap/subagent-input.ts';
15
17
  import { isDeterministicPolicyError } from '../auto-tool-tracking.ts';
18
+ import { clearGSDPreferencesCache, getProjectGSDPreferencesPath, loadEffectiveGSDPreferences } from '../preferences.ts';
19
+ import { applyPlanningSubagentPreferences } from '../planning-subagent-policy.ts';
16
20
  import type { ToolsPolicy } from '../unit-context-manifest.ts';
17
21
 
18
22
  const BASE = join('/tmp', 'fake-project');
@@ -335,6 +339,76 @@ test('planning-dispatch: still allows writes inside .gsd/', () => {
335
339
  assert.strictEqual(r.block, false);
336
340
  });
337
341
 
342
+ test('planning_subagents: upgrades plan-milestone to controlled read-only dispatch', () => {
343
+ const policy = applyPlanningSubagentPreferences('plan-milestone', PLANNING, {
344
+ planning_subagents: {
345
+ 'plan-milestone': { allowed: ['security'] },
346
+ },
347
+ });
348
+ const allowed = shouldBlockPlanningUnit('subagent', '', BASE, 'plan-milestone', policy, ['security']);
349
+ assert.strictEqual(allowed.block, false);
350
+
351
+ const blocked = shouldBlockPlanningUnit('subagent', '', BASE, 'plan-milestone', policy, ['reviewer']);
352
+ assert.strictEqual(blocked.block, true);
353
+ assert.match(blocked.reason!, /planning_subagents/);
354
+ assert.match(blocked.reason!, /permitted agents for this unit: security/);
355
+ });
356
+
357
+ test('planning_subagents: widens plan-slice manifest allowlist without allowing unsafe agents', () => {
358
+ const policy = applyPlanningSubagentPreferences('plan-slice', {
359
+ mode: 'planning-dispatch',
360
+ allowedSubagents: ['scout', 'planner'],
361
+ }, {
362
+ planning_subagents: {
363
+ 'plan-slice': { allowed: ['security'] },
364
+ },
365
+ });
366
+
367
+ const added = shouldBlockPlanningUnit('subagent', '', BASE, 'plan-slice', policy, ['security']);
368
+ assert.strictEqual(added.block, false);
369
+
370
+ const unsafe = shouldBlockPlanningUnit('subagent', '', BASE, 'plan-slice', policy, ['worker']);
371
+ assert.strictEqual(unsafe.block, true);
372
+ assert.match(unsafe.reason!, /read-only specialists/);
373
+ });
374
+
375
+ test('planning_subagents: registered custom planning agents pass runtime read-only registry', (t) => {
376
+ const tempProject = mkdtempSync(join(tmpdir(), 'gsd-custom-planning-agent-'));
377
+
378
+ t.after(() => {
379
+ clearGSDPreferencesCache();
380
+ rmSync(tempProject, { recursive: true, force: true });
381
+ });
382
+
383
+ mkdirSync(join(tempProject, '.gsd'), { recursive: true });
384
+ writeFileSync(
385
+ getProjectGSDPreferencesPath(tempProject),
386
+ [
387
+ '---',
388
+ 'version: 1',
389
+ 'planning_subagent_registry:',
390
+ ' my-custom-planner:',
391
+ ' read_only_specialist: true',
392
+ 'planning_subagents:',
393
+ ' plan-slice:',
394
+ ' allowed: [my-custom-planner]',
395
+ '---',
396
+ '',
397
+ ].join('\n'),
398
+ 'utf-8',
399
+ );
400
+ clearGSDPreferencesCache();
401
+
402
+ const preferences = loadEffectiveGSDPreferences(tempProject)?.preferences;
403
+ const policy = applyPlanningSubagentPreferences('plan-slice', PLANNING_DISPATCH, preferences);
404
+ const custom = shouldBlockPlanningUnit('subagent', '', tempProject, 'plan-slice', policy, ['my-custom-planner']);
405
+ assert.strictEqual(custom.block, false, custom.reason);
406
+
407
+ const unregistered = shouldBlockPlanningUnit('subagent', '', tempProject, 'plan-slice', policy, ['other-planner']);
408
+ assert.strictEqual(unregistered.block, true);
409
+ assert.match(unregistered.reason!, /read-only specialists/);
410
+ });
411
+
338
412
  // ─── planning mode: pass-through tools ────────────────────────────────────
339
413
 
340
414
  test('planning-unit: allows read tool', () => {
@@ -36,7 +36,15 @@ import {
36
36
  } from "../gsd-db.js";
37
37
  import { getWorkflowDatabasePath, ensureWorkflowDbAtPath } from "../db-workspace.js";
38
38
  import { getGatesForTurn } from "../gate-registry.js";
39
- import { gsdProjectionRoot, clearPathCache, resolveMilestonePath, resolveSlicePath } from "../paths.js";
39
+ import {
40
+ buildFlatTaskFileName,
41
+ buildTaskFileName,
42
+ gsdProjectionRoot,
43
+ clearPathCache,
44
+ legacyMilestonesDir,
45
+ resolveMilestonePath,
46
+ resolveSlicePath,
47
+ } from "../paths.js";
40
48
  import { resolveCanonicalMilestoneRoot } from "../worktree-manager.js";
41
49
  import { checkOwnership, taskUnitKey } from "../unit-ownership.js";
42
50
  import { saveFile, clearParseCache } from "../files.js";
@@ -89,13 +97,20 @@ function taskSummaryPath(
89
97
  // a legacy layout and breaks all subsequent path resolution for the session.
90
98
  const slicePath = resolveSlicePath(basePath, milestoneId, sliceId);
91
99
  const phaseDir = resolveMilestonePath(basePath, milestoneId);
92
- if (slicePath && phaseDir && slicePath !== phaseDir) {
93
- // Legacy layout: the slice has its own slices/SID/ subdir → tasks/ subdir
94
- return join(slicePath, "tasks", `${taskId}-SUMMARY.md`);
100
+ const legacyBase = legacyMilestonesDir(basePath);
101
+ const isLegacy = phaseDir
102
+ ? phaseDir.startsWith(legacyBase + "/") || phaseDir.startsWith(legacyBase + "\\")
103
+ : false;
104
+ if (isLegacy && phaseDir) {
105
+ // Legacy layout: the slice has its own slices/SID/ subdir → tasks/ subdir.
106
+ const legacySlicePath = slicePath && slicePath !== phaseDir
107
+ ? slicePath
108
+ : join(phaseDir, "slices", sliceId);
109
+ return join(legacySlicePath, "tasks", buildTaskFileName(taskId, "SUMMARY"));
95
110
  }
96
111
  if (phaseDir) {
97
112
  // Flat-phase: task summaries go in the phase dir (no tasks/ subdir)
98
- return join(phaseDir, `${taskId}-SUMMARY.md`);
113
+ return join(phaseDir, buildFlatTaskFileName(sliceId, taskId, "SUMMARY"));
99
114
  }
100
115
  // Fallback: legacy hardcoded path (milestone/slice dir not on disk yet)
101
116
  return join(
@@ -20,7 +20,7 @@ import {
20
20
  } from "../gsd-db.js";
21
21
  import type { GateEvaluationConfig, GateId } from "../types.js";
22
22
  import { invalidateStateCache } from "../state.js";
23
- import { renderPlanFromDb } from "../markdown-renderer.js";
23
+ import { renderPlanCheckboxes, renderPlanFromDb } from "../markdown-renderer.js";
24
24
  import { writeManifest } from "../workflow-manifest.js";
25
25
  import { appendEvent } from "../workflow-events.js";
26
26
  import { logWarning } from "../workflow-logger.js";
@@ -469,9 +469,13 @@ export async function handlePlanSlice(
469
469
  }
470
470
 
471
471
  const sliceTasks = getSliceTasks(params.milestoneId, params.sliceId);
472
+ const hasClosedTasks = sliceTasks.some((task) => isClosedStatus(task.status));
472
473
  const renderResult = sliceTasks.length === 0
473
474
  ? { planPath: "", taskPlanPaths: [] as string[] }
474
475
  : await renderPlanFromDb(basePath, params.milestoneId, params.sliceId);
476
+ if (sliceTasks.length > 0 && hasClosedTasks) {
477
+ await renderPlanCheckboxes(basePath, params.milestoneId, params.sliceId);
478
+ }
475
479
  if (sliceTasks.length > 0) {
476
480
  setSliceSketchFlag(params.milestoneId, params.sliceId, false);
477
481
  }
@@ -22,7 +22,15 @@ import { logWarning } from "../workflow-logger.js";
22
22
  import { debugLog } from "../debug-logger.js";
23
23
  import { existsSync, unlinkSync } from "node:fs";
24
24
  import { join } from "node:path";
25
- import { resolveMilestonePath, resolveSlicePath, resolveTasksDir, clearPathCache } from "../paths.js";
25
+ import {
26
+ buildFlatTaskFileName,
27
+ buildTaskFileName,
28
+ legacyMilestonesDir,
29
+ resolveMilestonePath,
30
+ resolveSlicePath,
31
+ resolveTasksDir,
32
+ clearPathCache,
33
+ } from "../paths.js";
26
34
 
27
35
  export interface ReopenMilestoneParams {
28
36
  milestoneId: string;
@@ -69,6 +77,10 @@ export async function handleReopenMilestone(
69
77
  // auto-corrects entities back to "complete", making reopen a no-op (#3161).
70
78
  try {
71
79
  const milestoneDir = resolveMilestonePath(basePath, params.milestoneId);
80
+ const legacyBase = legacyMilestonesDir(basePath);
81
+ const isLegacy = !!milestoneDir && (
82
+ milestoneDir.startsWith(legacyBase + "/") || milestoneDir.startsWith(legacyBase + "\\")
83
+ );
72
84
  if (milestoneDir) {
73
85
  const milestoneSummary = join(milestoneDir, `${params.milestoneId}-SUMMARY.md`);
74
86
  if (existsSync(milestoneSummary)) unlinkSync(milestoneSummary);
@@ -85,10 +97,17 @@ export async function handleReopenMilestone(
85
97
  }
86
98
 
87
99
  const tasksDir = resolveTasksDir(basePath, params.milestoneId, slice.id);
88
- if (tasksDir) {
89
- const tasks = getSliceTasks(params.milestoneId, slice.id);
90
- for (const task of tasks) {
91
- const taskSummary = join(tasksDir, `${task.id}-SUMMARY.md`);
100
+ const tasks = getSliceTasks(params.milestoneId, slice.id);
101
+ for (const task of tasks) {
102
+ const taskSummaries = isLegacy
103
+ ? (tasksDir ? [join(tasksDir, buildTaskFileName(task.id, "SUMMARY"))] : [])
104
+ : milestoneDir
105
+ ? [
106
+ join(milestoneDir, buildFlatTaskFileName(slice.id, task.id, "SUMMARY")),
107
+ join(milestoneDir, buildTaskFileName(task.id, "SUMMARY")),
108
+ ]
109
+ : [];
110
+ for (const taskSummary of taskSummaries) {
92
111
  if (existsSync(taskSummary)) unlinkSync(taskSummary);
93
112
  }
94
113
  }
@@ -27,7 +27,15 @@ import { appendEvent } from "../workflow-events.js";
27
27
  import { logWarning } from "../workflow-logger.js";
28
28
  import { existsSync, unlinkSync } from "node:fs";
29
29
  import { join } from "node:path";
30
- import { resolveTasksDir, resolveSlicePath, clearPathCache } from "../paths.js";
30
+ import {
31
+ buildFlatTaskFileName,
32
+ buildTaskFileName,
33
+ legacyMilestonesDir,
34
+ resolveMilestonePath,
35
+ resolveTasksDir,
36
+ resolveSlicePath,
37
+ clearPathCache,
38
+ } from "../paths.js";
31
39
 
32
40
  export interface ReopenSliceParams {
33
41
  milestoneId: string;
@@ -80,11 +88,23 @@ export async function handleReopenSlice(
80
88
  // Without this, the DB-filesystem reconciler sees SUMMARY.md files and
81
89
  // auto-corrects tasks back to "complete", making reopen a no-op (#3161).
82
90
  try {
91
+ const milestoneDir = resolveMilestonePath(basePath, params.milestoneId);
92
+ const legacyBase = legacyMilestonesDir(basePath);
93
+ const isLegacy = !!milestoneDir && (
94
+ milestoneDir.startsWith(legacyBase + "/") || milestoneDir.startsWith(legacyBase + "\\")
95
+ );
83
96
  const tasksDir = resolveTasksDir(basePath, params.milestoneId, params.sliceId);
84
- if (tasksDir) {
85
- const tasks = getSliceTasks(params.milestoneId, params.sliceId);
86
- for (const task of tasks) {
87
- const summaryPath = join(tasksDir, `${task.id}-SUMMARY.md`);
97
+ const tasks = getSliceTasks(params.milestoneId, params.sliceId);
98
+ for (const task of tasks) {
99
+ const summaryPaths = isLegacy
100
+ ? (tasksDir ? [join(tasksDir, buildTaskFileName(task.id, "SUMMARY"))] : [])
101
+ : milestoneDir
102
+ ? [
103
+ join(milestoneDir, buildFlatTaskFileName(params.sliceId, task.id, "SUMMARY")),
104
+ join(milestoneDir, buildTaskFileName(task.id, "SUMMARY")),
105
+ ]
106
+ : [];
107
+ for (const summaryPath of summaryPaths) {
88
108
  if (existsSync(summaryPath)) unlinkSync(summaryPath);
89
109
  }
90
110
  }