@opengsd/gsd-pi 1.3.0-dev.eed73bea → 1.4.0

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 (505) hide show
  1. package/README.md +10 -10
  2. package/dist/cli.js +17 -4
  3. package/dist/headless-answers.js +1 -1
  4. package/dist/headless-ui.d.ts +1 -1
  5. package/dist/headless-ui.js +1 -1
  6. package/dist/headless.js +1 -1
  7. package/dist/resources/.managed-resources-content-hash +1 -1
  8. package/dist/resources/extensions/claude-code-cli/models.js +9 -0
  9. package/dist/resources/extensions/gsd/artifact-verification.js +427 -0
  10. package/dist/resources/extensions/gsd/auto/session.js +11 -0
  11. package/dist/resources/extensions/gsd/auto/verification-retry-policy.js +1 -1
  12. package/dist/resources/extensions/gsd/auto-artifact-paths.js +28 -1
  13. package/dist/resources/extensions/gsd/auto-budget.js +5 -1
  14. package/dist/resources/extensions/gsd/auto-dispatch.js +17 -6
  15. package/dist/resources/extensions/gsd/auto-post-unit.js +1 -1
  16. package/dist/resources/extensions/gsd/auto-prompts.js +8 -24
  17. package/dist/resources/extensions/gsd/auto-recovery.js +9 -517
  18. package/dist/resources/extensions/gsd/auto-runtime-state.js +4 -5
  19. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +3 -3
  20. package/dist/resources/extensions/gsd/auto-verification.js +5 -2
  21. package/dist/resources/extensions/gsd/auto.js +19 -10
  22. package/dist/resources/extensions/gsd/bootstrap/core-session-tools.js +39 -0
  23. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +5 -4
  24. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +2 -0
  25. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +33 -18
  26. package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +48 -36
  27. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +15 -4
  28. package/dist/resources/extensions/gsd/closeout-consistency-gate.js +3 -1
  29. package/dist/resources/extensions/gsd/commands/handlers/auto.js +1 -1
  30. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +1 -1
  31. package/dist/resources/extensions/gsd/commands-usage.js +1 -1
  32. package/dist/resources/extensions/gsd/db/engine.js +4 -1
  33. package/dist/resources/extensions/gsd/db-memory-fts-schema.js +34 -0
  34. package/dist/resources/extensions/gsd/db-workspace.js +55 -3
  35. package/dist/resources/extensions/gsd/delegation-policy.js +1 -1
  36. package/dist/resources/extensions/gsd/docs/preferences-reference.md +2 -2
  37. package/dist/resources/extensions/gsd/doctor-engine-checks.js +192 -4
  38. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +3 -0
  39. package/dist/resources/extensions/gsd/exec-sandbox.js +8 -2
  40. package/dist/resources/extensions/gsd/flat-phase-migration.js +45 -0
  41. package/dist/resources/extensions/gsd/git-service.js +57 -0
  42. package/dist/resources/extensions/gsd/gitignore.js +4 -1
  43. package/dist/resources/extensions/gsd/guided-flow-queue.js +20 -13
  44. package/dist/resources/extensions/gsd/json-persistence.js +20 -0
  45. package/dist/resources/extensions/gsd/knowledge-backfill.js +18 -11
  46. package/dist/resources/extensions/gsd/layout-policy.js +3 -1
  47. package/dist/resources/extensions/gsd/markdown-renderer.js +2 -7
  48. package/dist/resources/extensions/gsd/memory-backfill.js +28 -21
  49. package/dist/resources/extensions/gsd/metrics.js +4 -4
  50. package/dist/resources/extensions/gsd/migrate-external.js +11 -2
  51. package/dist/resources/extensions/gsd/migration-auto-check.js +22 -0
  52. package/dist/resources/extensions/gsd/milestone-ids.js +32 -2
  53. package/dist/resources/extensions/gsd/orphan-stash-audit.js +92 -16
  54. package/dist/resources/extensions/gsd/prompts/code-review.md +6 -4
  55. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +2 -2
  56. package/dist/resources/extensions/gsd/prompts/plan-slice.md +3 -3
  57. package/dist/resources/extensions/gsd/root-write-leak-guard.js +7 -1
  58. package/dist/resources/extensions/gsd/safety/destructive-guard.js +8 -1
  59. package/dist/resources/extensions/gsd/safety/evidence-collector.js +16 -1
  60. package/dist/resources/extensions/gsd/safety/file-change-validator.js +5 -2
  61. package/dist/resources/extensions/gsd/skills/gsd-headless/references/commands.md +1 -1
  62. package/dist/resources/extensions/gsd/state/derive/cache.js +28 -0
  63. package/dist/resources/extensions/gsd/state/derive/db-open.js +39 -0
  64. package/dist/resources/extensions/gsd/state/derive/from-db.js +452 -0
  65. package/dist/resources/extensions/gsd/state/derive/index.js +75 -0
  66. package/dist/resources/extensions/gsd/state/derive/interrupted-work.js +21 -0
  67. package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-render.js +27 -33
  68. package/dist/resources/extensions/gsd/state-reconciliation/index.js +48 -23
  69. package/dist/resources/extensions/gsd/state-reconciliation/registry.js +32 -28
  70. package/dist/resources/extensions/gsd/state.js +12 -611
  71. package/dist/resources/extensions/gsd/tools/complete-milestone.js +4 -2
  72. package/dist/resources/extensions/gsd/tools/complete-slice.js +3 -34
  73. package/dist/resources/extensions/gsd/tools/complete-task.js +8 -41
  74. package/dist/resources/extensions/gsd/tools/plan-slice.js +59 -44
  75. package/dist/resources/extensions/gsd/tools/plan-task.js +28 -5
  76. package/dist/resources/extensions/gsd/undo.js +43 -6
  77. package/dist/resources/extensions/gsd/unit-registry.js +11 -3
  78. package/dist/resources/extensions/gsd/verification-gate.js +7 -0
  79. package/dist/resources/extensions/gsd/workflow-manifest.js +126 -13
  80. package/dist/resources/extensions/gsd/workflow-projections.js +19 -14
  81. package/dist/resources/extensions/gsd/worktree-manager.js +44 -2
  82. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  83. package/dist/web/standalone/.next/BUILD_ID +1 -1
  84. package/dist/web/standalone/.next/app-path-routes-manifest.json +10 -10
  85. package/dist/web/standalone/.next/build-manifest.json +4 -4
  86. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  87. package/dist/web/standalone/.next/react-loadable-manifest.json +9 -9
  88. package/dist/web/standalone/.next/required-server-files.json +3 -3
  89. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  90. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  91. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  100. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  101. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  102. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  103. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  104. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  106. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  110. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  116. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  128. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/mcp-connections/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  150. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  160. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  166. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  182. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  186. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  195. package/dist/web/standalone/.next/server/app/index.html +1 -1
  196. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  197. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  198. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  199. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  200. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  201. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  202. package/dist/web/standalone/.next/server/app/page.js +2 -2
  203. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  204. package/dist/web/standalone/.next/server/app-paths-manifest.json +10 -10
  205. package/dist/web/standalone/.next/server/chunks/2842.js +4 -4
  206. package/dist/web/standalone/.next/server/chunks/8357.js +3 -3
  207. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  208. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  209. package/dist/web/standalone/.next/server/middleware.js +3 -3
  210. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  211. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  212. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  213. package/dist/web/standalone/.next/static/chunks/{2659.b7b129ee6a769448.js → 2659.58e950899a9bb82f.js} +1 -1
  214. package/dist/web/standalone/.next/static/chunks/2772.a7c1fcc69a4685ef.js +1 -0
  215. package/dist/web/standalone/.next/static/chunks/{3616.3c60753b8ffcbd2e.js → 3616.61a2af74bb8833c8.js} +1 -1
  216. package/dist/web/standalone/.next/static/chunks/{4283.8e446784528ed9dc.js → 4283.d0d9e0a955e441cb.js} +1 -1
  217. package/dist/web/standalone/.next/static/chunks/{5826.a46ecdd1cfe8dabc.js → 5826.5421d66c72b9f34e.js} +1 -1
  218. package/dist/web/standalone/.next/static/chunks/{8785.481aa5869991b760.js → 8785.e29b3134cab1d153.js} +1 -1
  219. package/dist/web/standalone/.next/static/chunks/8937.640dc9c2aaa1dfad.js +10 -0
  220. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-49f565245e1e4afe.js +1 -0
  221. package/dist/web/standalone/.next/static/chunks/app/{layout-4ae2d68984392bbf.js → layout-b35cbfff38aaf4cf.js} +1 -1
  222. package/dist/web/standalone/.next/static/chunks/app/page-bc4c723c6a19c6f0.js +1 -0
  223. package/dist/web/standalone/.next/static/chunks/{main-app-90d1d8d5e5d2dc6b.js → main-app-590a74400e35f685.js} +1 -1
  224. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ec3eaffc9785ba48.js +1 -0
  225. package/dist/web/standalone/.next/static/chunks/webpack-9c401904f87ded16.js +1 -0
  226. package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
  227. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  228. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  229. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  230. package/dist/web/standalone/server.js +1 -1
  231. package/package.json +6 -6
  232. package/packages/cloud-mcp-gateway/package.json +2 -2
  233. package/packages/contracts/package.json +1 -1
  234. package/packages/daemon/package.json +4 -4
  235. package/packages/gsd-agent-core/dist/agent-session.d.ts +1 -0
  236. package/packages/gsd-agent-core/dist/agent-session.d.ts.map +1 -1
  237. package/packages/gsd-agent-core/dist/agent-session.js +3 -0
  238. package/packages/gsd-agent-core/dist/agent-session.js.map +1 -1
  239. package/packages/gsd-agent-core/dist/extension-ui-snapshot.d.ts +41 -0
  240. package/packages/gsd-agent-core/dist/extension-ui-snapshot.d.ts.map +1 -0
  241. package/packages/gsd-agent-core/dist/extension-ui-snapshot.js +62 -0
  242. package/packages/gsd-agent-core/dist/extension-ui-snapshot.js.map +1 -0
  243. package/packages/gsd-agent-core/dist/index.d.ts +2 -0
  244. package/packages/gsd-agent-core/dist/index.d.ts.map +1 -1
  245. package/packages/gsd-agent-core/dist/index.js +2 -0
  246. package/packages/gsd-agent-core/dist/index.js.map +1 -1
  247. package/packages/gsd-agent-core/dist/session/agent-session-events.js +1 -1
  248. package/packages/gsd-agent-core/dist/session/agent-session-events.js.map +1 -1
  249. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts +1 -0
  250. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts.map +1 -1
  251. package/packages/gsd-agent-core/dist/session/agent-session-host.js.map +1 -1
  252. package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts +5 -0
  253. package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts.map +1 -1
  254. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js +60 -3
  255. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js.map +1 -1
  256. package/packages/gsd-agent-core/dist/transcript-store.d.ts +58 -0
  257. package/packages/gsd-agent-core/dist/transcript-store.d.ts.map +1 -0
  258. package/packages/gsd-agent-core/dist/transcript-store.js +132 -0
  259. package/packages/gsd-agent-core/dist/transcript-store.js.map +1 -0
  260. package/packages/gsd-agent-core/package.json +5 -5
  261. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +2 -0
  262. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  263. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +25 -11
  264. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  265. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.d.ts +4 -0
  266. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.d.ts.map +1 -0
  267. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.js +7 -0
  268. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.js.map +1 -0
  269. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts +3 -24
  270. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  271. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +26 -841
  272. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  273. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.d.ts +58 -0
  274. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.d.ts.map +1 -0
  275. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.js +312 -0
  276. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.js.map +1 -0
  277. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.d.ts +31 -0
  278. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.d.ts.map +1 -0
  279. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.js +130 -0
  280. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.js.map +1 -0
  281. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts +15 -0
  282. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts.map +1 -0
  283. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js +258 -0
  284. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js.map +1 -0
  285. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.d.ts +13 -0
  286. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.d.ts.map +1 -0
  287. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.js +118 -0
  288. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.js.map +1 -0
  289. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts +9 -0
  290. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  291. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.js +1 -1
  292. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  293. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.d.ts +54 -0
  294. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.d.ts.map +1 -0
  295. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.js +20 -0
  296. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.js.map +1 -0
  297. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts +4 -1
  298. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  299. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +9 -0
  300. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
  301. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.d.ts +56 -0
  302. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.d.ts.map +1 -0
  303. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.js +44 -0
  304. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.js.map +1 -0
  305. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.d.ts +5 -0
  306. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.d.ts.map +1 -0
  307. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.js +77 -0
  308. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.js.map +1 -0
  309. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.d.ts +2 -0
  310. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  311. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.js +23 -5
  312. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.js.map +1 -1
  313. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  314. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +18 -0
  315. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
  316. package/packages/gsd-agent-modes/package.json +7 -7
  317. package/packages/mcp-server/dist/workflow-tools.js +1 -1
  318. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  319. package/packages/mcp-server/package.json +4 -4
  320. package/packages/native/package.json +1 -1
  321. package/packages/pi-agent-core/dist/agent-loop.js +3 -2
  322. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  323. package/packages/pi-agent-core/package.json +1 -1
  324. package/packages/pi-ai/dist/models.generated.d.ts +46 -0
  325. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  326. package/packages/pi-ai/dist/models.generated.js +38 -0
  327. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  328. package/packages/pi-ai/package.json +1 -1
  329. package/packages/pi-coding-agent/README.md +3 -2
  330. package/packages/pi-coding-agent/dist/core/session-manager-context.d.ts +9 -0
  331. package/packages/pi-coding-agent/dist/core/session-manager-context.d.ts.map +1 -0
  332. package/packages/pi-coding-agent/dist/core/session-manager-context.js +94 -0
  333. package/packages/pi-coding-agent/dist/core/session-manager-context.js.map +1 -0
  334. package/packages/pi-coding-agent/dist/core/session-manager-list.d.ts +8 -0
  335. package/packages/pi-coding-agent/dist/core/session-manager-list.d.ts.map +1 -0
  336. package/packages/pi-coding-agent/dist/core/session-manager-list.js +244 -0
  337. package/packages/pi-coding-agent/dist/core/session-manager-list.js.map +1 -0
  338. package/packages/pi-coding-agent/dist/core/session-manager-migration.d.ts +12 -0
  339. package/packages/pi-coding-agent/dist/core/session-manager-migration.d.ts.map +1 -0
  340. package/packages/pi-coding-agent/dist/core/session-manager-migration.js +84 -0
  341. package/packages/pi-coding-agent/dist/core/session-manager-migration.js.map +1 -0
  342. package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts +135 -0
  343. package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts.map +1 -0
  344. package/packages/pi-coding-agent/dist/core/session-manager-types.js +2 -0
  345. package/packages/pi-coding-agent/dist/core/session-manager-types.js.map +1 -0
  346. package/packages/pi-coding-agent/dist/core/session-manager.d.ts +6 -154
  347. package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
  348. package/packages/pi-coding-agent/dist/core/session-manager.js +22 -459
  349. package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
  350. package/packages/pi-coding-agent/dist/theme/theme-schema.d.ts +75 -75
  351. package/packages/pi-coding-agent/dist/theme/theme-schema.d.ts.map +1 -1
  352. package/packages/pi-coding-agent/dist/theme/theme-schema.js +1 -1
  353. package/packages/pi-coding-agent/dist/theme/theme-schema.js.map +1 -1
  354. package/packages/pi-coding-agent/dist/theme/theme.d.ts.map +1 -1
  355. package/packages/pi-coding-agent/dist/theme/theme.js +11 -7
  356. package/packages/pi-coding-agent/dist/theme/theme.js.map +1 -1
  357. package/packages/pi-coding-agent/package.json +7 -7
  358. package/packages/pi-tui/package.json +2 -2
  359. package/packages/rpc-client/package.json +2 -2
  360. package/pkg/dist/theme/theme-schema.d.ts +75 -75
  361. package/pkg/dist/theme/theme-schema.d.ts.map +1 -1
  362. package/pkg/dist/theme/theme-schema.js +1 -1
  363. package/pkg/dist/theme/theme-schema.js.map +1 -1
  364. package/pkg/dist/theme/theme.d.ts.map +1 -1
  365. package/pkg/dist/theme/theme.js +11 -7
  366. package/pkg/dist/theme/theme.js.map +1 -1
  367. package/pkg/package.json +1 -1
  368. package/src/resources/extensions/claude-code-cli/models.ts +9 -0
  369. package/src/resources/extensions/claude-code-cli/tests/index.test.ts +14 -0
  370. package/src/resources/extensions/gsd/artifact-verification.ts +464 -0
  371. package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
  372. package/src/resources/extensions/gsd/auto/session.ts +14 -0
  373. package/src/resources/extensions/gsd/auto/verification-retry-policy.ts +3 -1
  374. package/src/resources/extensions/gsd/auto-artifact-paths.ts +47 -1
  375. package/src/resources/extensions/gsd/auto-budget.ts +12 -1
  376. package/src/resources/extensions/gsd/auto-dispatch.ts +17 -7
  377. package/src/resources/extensions/gsd/auto-post-unit.ts +1 -1
  378. package/src/resources/extensions/gsd/auto-prompts.ts +7 -23
  379. package/src/resources/extensions/gsd/auto-recovery.ts +13 -518
  380. package/src/resources/extensions/gsd/auto-runtime-state.ts +4 -5
  381. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +3 -2
  382. package/src/resources/extensions/gsd/auto-verification.ts +5 -1
  383. package/src/resources/extensions/gsd/auto.ts +23 -8
  384. package/src/resources/extensions/gsd/bootstrap/core-session-tools.ts +44 -0
  385. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +5 -4
  386. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +2 -0
  387. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +43 -18
  388. package/src/resources/extensions/gsd/bootstrap/tests/write-gate-basepath.test.ts +49 -1
  389. package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +50 -37
  390. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +16 -4
  391. package/src/resources/extensions/gsd/closeout-consistency-gate.ts +2 -1
  392. package/src/resources/extensions/gsd/commands/handlers/auto.ts +1 -1
  393. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +1 -1
  394. package/src/resources/extensions/gsd/commands-usage.ts +1 -1
  395. package/src/resources/extensions/gsd/db/engine.ts +8 -1
  396. package/src/resources/extensions/gsd/db-memory-fts-schema.ts +45 -0
  397. package/src/resources/extensions/gsd/db-workspace.ts +61 -3
  398. package/src/resources/extensions/gsd/delegation-policy.ts +1 -1
  399. package/src/resources/extensions/gsd/docs/preferences-reference.md +2 -2
  400. package/src/resources/extensions/gsd/doctor-engine-checks.ts +233 -5
  401. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +3 -0
  402. package/src/resources/extensions/gsd/doctor-types.ts +3 -0
  403. package/src/resources/extensions/gsd/exec-sandbox.ts +7 -2
  404. package/src/resources/extensions/gsd/flat-phase-migration.ts +44 -0
  405. package/src/resources/extensions/gsd/git-service.ts +64 -0
  406. package/src/resources/extensions/gsd/gitignore.ts +4 -1
  407. package/src/resources/extensions/gsd/guided-flow-queue.ts +20 -13
  408. package/src/resources/extensions/gsd/json-persistence.ts +20 -0
  409. package/src/resources/extensions/gsd/knowledge-backfill.ts +16 -10
  410. package/src/resources/extensions/gsd/layout-policy.ts +2 -1
  411. package/src/resources/extensions/gsd/markdown-renderer.ts +2 -10
  412. package/src/resources/extensions/gsd/memory-backfill.ts +26 -20
  413. package/src/resources/extensions/gsd/metrics.ts +4 -4
  414. package/src/resources/extensions/gsd/migrate-external.ts +8 -2
  415. package/src/resources/extensions/gsd/migration-auto-check.ts +23 -0
  416. package/src/resources/extensions/gsd/milestone-ids.ts +31 -2
  417. package/src/resources/extensions/gsd/orphan-stash-audit.ts +108 -20
  418. package/src/resources/extensions/gsd/prompts/code-review.md +6 -4
  419. package/src/resources/extensions/gsd/prompts/plan-milestone.md +2 -2
  420. package/src/resources/extensions/gsd/prompts/plan-slice.md +3 -3
  421. package/src/resources/extensions/gsd/root-write-leak-guard.ts +13 -1
  422. package/src/resources/extensions/gsd/safety/destructive-guard.ts +9 -1
  423. package/src/resources/extensions/gsd/safety/evidence-collector.ts +16 -1
  424. package/src/resources/extensions/gsd/safety/file-change-validator.ts +8 -2
  425. package/src/resources/extensions/gsd/skills/gsd-headless/references/commands.md +1 -1
  426. package/src/resources/extensions/gsd/state/derive/cache.ts +46 -0
  427. package/src/resources/extensions/gsd/state/derive/db-open.ts +45 -0
  428. package/src/resources/extensions/gsd/state/derive/from-db.ts +561 -0
  429. package/src/resources/extensions/gsd/state/derive/index.ts +104 -0
  430. package/src/resources/extensions/gsd/state/derive/interrupted-work.ts +31 -0
  431. package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +36 -30
  432. package/src/resources/extensions/gsd/state-reconciliation/index.ts +50 -24
  433. package/src/resources/extensions/gsd/state-reconciliation/registry.ts +43 -28
  434. package/src/resources/extensions/gsd/state.ts +32 -732
  435. package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +4 -3
  436. package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +98 -1
  437. package/src/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +14 -5
  438. package/src/resources/extensions/gsd/tests/auto-pause-double-entry-guard.test.ts +36 -0
  439. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +182 -4
  440. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +35 -0
  441. package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +30 -0
  442. package/src/resources/extensions/gsd/tests/commands-gsd-core.test.ts +1 -0
  443. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +28 -0
  444. package/src/resources/extensions/gsd/tests/complete-slice-reopen-handoff.test.ts +69 -0
  445. package/src/resources/extensions/gsd/tests/db-memory-fts-schema.test.ts +58 -3
  446. package/src/resources/extensions/gsd/tests/decisions-projection-from-memories.test.ts +51 -0
  447. package/src/resources/extensions/gsd/tests/destructive-guard.test.ts +44 -0
  448. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +143 -0
  449. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +239 -2
  450. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +16 -0
  451. package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +40 -0
  452. package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +37 -2
  453. package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +4 -0
  454. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +11 -2
  455. package/src/resources/extensions/gsd/tests/json-persistence-atomic.test.ts +47 -0
  456. package/src/resources/extensions/gsd/tests/knowledge-backfill-projection.test.ts +35 -0
  457. package/src/resources/extensions/gsd/tests/memory-store.test.ts +48 -0
  458. package/src/resources/extensions/gsd/tests/merge-closeout-consistency-gate.test.ts +31 -1
  459. package/src/resources/extensions/gsd/tests/metrics-prune-cache-invalidation.test.ts +6 -0
  460. package/src/resources/extensions/gsd/tests/metrics.test.ts +1 -0
  461. package/src/resources/extensions/gsd/tests/migrate-external-worktree.test.ts +57 -0
  462. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +70 -0
  463. package/src/resources/extensions/gsd/tests/orphan-stash-audit.test.ts +91 -7
  464. package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +4 -1
  465. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +10 -0
  466. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +103 -4
  467. package/src/resources/extensions/gsd/tests/plan-task.test.ts +44 -1
  468. package/src/resources/extensions/gsd/tests/post-mutation-hook.test.ts +4 -2
  469. package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +50 -14
  470. package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +58 -0
  471. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +8 -6
  472. package/src/resources/extensions/gsd/tests/register-hooks-loop-guard-auto.test.ts +103 -0
  473. package/src/resources/extensions/gsd/tests/root-write-leak-guard.test.ts +20 -1
  474. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +15 -3
  475. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +56 -0
  476. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +115 -0
  477. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +140 -0
  478. package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +6 -3
  479. package/src/resources/extensions/gsd/tests/undo.test.ts +74 -0
  480. package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +38 -0
  481. package/src/resources/extensions/gsd/tests/verification-retry-policy.test.ts +69 -4
  482. package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +96 -15
  483. package/src/resources/extensions/gsd/tests/workflow-mcp-preflight.test.ts +1 -0
  484. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +8 -4
  485. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +6 -5
  486. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +39 -0
  487. package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -2
  488. package/src/resources/extensions/gsd/tools/complete-slice.ts +3 -30
  489. package/src/resources/extensions/gsd/tools/complete-task.ts +7 -39
  490. package/src/resources/extensions/gsd/tools/plan-slice.ts +60 -47
  491. package/src/resources/extensions/gsd/tools/plan-task.ts +30 -5
  492. package/src/resources/extensions/gsd/undo.ts +47 -6
  493. package/src/resources/extensions/gsd/unit-registry.ts +11 -3
  494. package/src/resources/extensions/gsd/verification-gate.ts +8 -0
  495. package/src/resources/extensions/gsd/workflow-manifest.ts +141 -7
  496. package/src/resources/extensions/gsd/workflow-projections.ts +20 -14
  497. package/src/resources/extensions/gsd/worktree-manager.ts +41 -1
  498. package/dist/web/standalone/.next/static/chunks/2772.bfa657f49f955239.js +0 -1
  499. package/dist/web/standalone/.next/static/chunks/796.3976108148518f7d.js +0 -10
  500. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-a6fb1847f67f167c.js +0 -1
  501. package/dist/web/standalone/.next/static/chunks/app/page-6644fc6ee8ca1247.js +0 -1
  502. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-1115d46ac61b9823.js +0 -1
  503. package/dist/web/standalone/.next/static/chunks/webpack-7c1d97e39be2da11.js +0 -1
  504. /package/dist/web/standalone/.next/static/{SzEuqWX37DR9MEpEuQjP1 → zQLcXm0Za8lexoXtgDpMG}/_buildManifest.js +0 -0
  505. /package/dist/web/standalone/.next/static/{SzEuqWX37DR9MEpEuQjP1 → zQLcXm0Za8lexoXtgDpMG}/_ssgManifest.js +0 -0
@@ -13,7 +13,7 @@ import { existsSync } from "node:fs";
13
13
  import { transaction, getMilestone, getMilestoneSlices, getSliceTasks, getLatestAssessmentByScope, updateMilestoneStatus, } from "../gsd-db.js";
14
14
  import { clearPathCache, relMilestoneFile } from "../paths.js";
15
15
  import { resolveCanonicalMilestoneRoot } from "../worktree-manager.js";
16
- import { isClosedStatus } from "../status-guards.js";
16
+ import { isClosedStatus, isDeferredStatus } from "../status-guards.js";
17
17
  import { saveFile, clearParseCache } from "../files.js";
18
18
  import { invalidateStateCache } from "../state.js";
19
19
  import { stripIdPrefix } from "../workflow-projections.js";
@@ -118,7 +118,7 @@ export async function handleCompleteMilestone(params, basePath) {
118
118
  guardError = `no slices found for milestone ${params.milestoneId}`;
119
119
  return;
120
120
  }
121
- const incompleteSlices = slices.filter(s => !isClosedStatus(s.status));
121
+ const incompleteSlices = slices.filter(s => !isClosedStatus(s.status) && !isDeferredStatus(s.status));
122
122
  if (incompleteSlices.length > 0) {
123
123
  const incompleteIds = incompleteSlices.map(s => `${s.id} (status: ${s.status})`).join(", ");
124
124
  guardError = `incomplete slices: ${incompleteIds}`;
@@ -126,6 +126,8 @@ export async function handleCompleteMilestone(params, basePath) {
126
126
  }
127
127
  // Deep check: verify all tasks in all slices are complete
128
128
  for (const slice of slices) {
129
+ if (isDeferredStatus(slice.status))
130
+ continue;
129
131
  const tasks = getSliceTasks(params.milestoneId, slice.id);
130
132
  const incompleteTasks = tasks.filter(t => !isClosedStatus(t.status));
131
133
  if (incompleteTasks.length > 0) {
@@ -21,7 +21,7 @@ import { classifyUatContent, escalatesArtifactUatToBrowser } from "../uat-policy
21
21
  import { invalidateStateCache } from "../state.js";
22
22
  import { renderRoadmapFromDb, roadmapRenderMarksSliceDone } from "../markdown-renderer.js";
23
23
  import { isStaleWrite } from "../auto/turn-epoch.js";
24
- import { renderStateProjection, renderTopLevelQueueFromDb, renderTopLevelRoadmapFromDb } from "../workflow-projections.js";
24
+ import { renderMilestoneShellProjections } from "../workflow-projections.js";
25
25
  import { writeManifest } from "../workflow-manifest.js";
26
26
  import { appendEvent } from "../workflow-events.js";
27
27
  import { logWarning, logError } from "../workflow-logger.js";
@@ -457,42 +457,11 @@ export async function handleCompleteSlice(params, basePath) {
457
457
  // ── Post-mutation hook: projections, manifest, event log ───────────────
458
458
  // Separate try/catch per step so a projection failure doesn't prevent
459
459
  // the event log entry (critical for worktree reconciliation).
460
- //
461
- // If the primary summary/UAT/roadmap write block failed (projectionStale),
462
- // retry the milestone-level roadmap here so ROADMAP.md is not left stale
463
- // after a committed slice completion. This restores the recovery that the
464
- // removed flushWorkflowProjections/renderAllProjections provided.
465
- if (projectionStale) {
466
- try {
467
- await renderRoadmapFromDb(artifactBasePath, params.milestoneId);
468
- }
469
- catch (projErr) {
470
- logWarning("tool", `complete-slice milestone roadmap retry warning for ${params.milestoneId}/${params.sliceId}: ${projErr.message}`);
471
- }
472
- }
473
- try {
474
- await renderRoadmapFromDb(artifactBasePath, params.milestoneId);
475
- }
476
- catch (projErr) {
477
- logWarning("tool", `complete-slice milestone roadmap projection warning for ${params.milestoneId}/${params.sliceId}: ${projErr.message}`);
478
- }
479
- try {
480
- renderTopLevelRoadmapFromDb(artifactBasePath);
481
- }
482
- catch (projErr) {
483
- logWarning("tool", `complete-slice roadmap projection warning for ${params.milestoneId}/${params.sliceId}: ${projErr.message}`);
484
- }
485
- try {
486
- renderTopLevelQueueFromDb(artifactBasePath);
487
- }
488
- catch (projErr) {
489
- logWarning("tool", `complete-slice queue projection warning for ${params.milestoneId}/${params.sliceId}: ${projErr.message}`);
490
- }
491
460
  try {
492
- await renderStateProjection(artifactBasePath);
461
+ await renderMilestoneShellProjections(artifactBasePath, params.milestoneId);
493
462
  }
494
463
  catch (projErr) {
495
- logWarning("tool", `complete-slice state projection warning for ${params.milestoneId}/${params.sliceId}: ${projErr.message}`);
464
+ logWarning("tool", `complete-slice projection warning for ${params.milestoneId}/${params.sliceId}: ${projErr.message}`);
496
465
  }
497
466
  try {
498
467
  writeManifest(artifactBasePath);
@@ -12,16 +12,16 @@
12
12
  import { existsSync, unlinkSync } from "node:fs";
13
13
  import { join } from "node:path";
14
14
  import { isClosedStatus } from "../status-guards.js";
15
- import { transaction, insertMilestone, insertSlice, insertTask, insertVerificationEvidence, getMilestone, getSlice, getTask, updateTaskStatus, deleteVerificationEvidence, saveGateResult, getPendingGatesForTurn, isDbAvailable, } from "../gsd-db.js";
16
- import { getWorkflowDatabasePath, openWorkflowDatabasePath } from "../db-workspace.js";
15
+ import { transaction, insertMilestone, insertSlice, insertTask, insertVerificationEvidence, getMilestone, getSlice, getTask, updateTaskStatus, deleteVerificationEvidence, saveGateResult, getPendingGatesForTurn, } from "../gsd-db.js";
16
+ import { getWorkflowDatabasePath, ensureWorkflowDbAtPath } from "../db-workspace.js";
17
17
  import { getGatesForTurn } from "../gate-registry.js";
18
18
  import { gsdProjectionRoot, clearPathCache, resolveMilestonePath, resolveSlicePath } from "../paths.js";
19
19
  import { resolveCanonicalMilestoneRoot } from "../worktree-manager.js";
20
20
  import { checkOwnership, taskUnitKey } from "../unit-ownership.js";
21
21
  import { saveFile, clearParseCache } from "../files.js";
22
22
  import { invalidateStateCache } from "../state.js";
23
- import { renderPlanCheckboxes, renderRoadmapFromDb } from "../markdown-renderer.js";
24
- import { renderStateProjection, renderSummaryContent, renderTopLevelQueueFromDb, renderTopLevelRoadmapFromDb, } from "../workflow-projections.js";
23
+ import { renderPlanCheckboxes } from "../markdown-renderer.js";
24
+ import { renderMilestoneShellProjections, renderSummaryContent, } from "../workflow-projections.js";
25
25
  import { writeManifest } from "../workflow-manifest.js";
26
26
  import { appendEvent } from "../workflow-events.js";
27
27
  import { logWarning, logError } from "../workflow-logger.js";
@@ -45,39 +45,6 @@ function taskSummaryPath(basePath, milestoneId, sliceId, taskId) {
45
45
  // Fallback: legacy hardcoded path (milestone/slice dir not on disk yet)
46
46
  return join(gsdProjectionRoot(basePath), "milestones", milestoneId, "slices", sliceId, "tasks", `${taskId}-SUMMARY.md`);
47
47
  }
48
- async function renderCompleteTaskProjections(basePath, milestoneId) {
49
- try {
50
- await renderRoadmapFromDb(basePath, milestoneId);
51
- }
52
- catch (err) {
53
- logWarning("projection", `renderRoadmapFromDb failed for ${milestoneId}: ${err.message}`);
54
- }
55
- try {
56
- renderTopLevelRoadmapFromDb(basePath);
57
- }
58
- catch (err) {
59
- logWarning("projection", `renderTopLevelRoadmapFromDb failed: ${err.message}`);
60
- }
61
- try {
62
- renderTopLevelQueueFromDb(basePath);
63
- }
64
- catch (err) {
65
- logWarning("projection", `renderTopLevelQueueFromDb failed: ${err.message}`);
66
- }
67
- try {
68
- await renderStateProjection(basePath);
69
- }
70
- catch (err) {
71
- logWarning("projection", `renderStateProjection failed: ${err.message}`);
72
- }
73
- }
74
- function ensureCompleteTaskDbOpen(dbPath) {
75
- if (!dbPath || dbPath === ":memory:")
76
- return isDbAvailable();
77
- if (isDbAvailable() && getWorkflowDatabasePath() === dbPath)
78
- return true;
79
- return openWorkflowDatabasePath(dbPath);
80
- }
81
48
  async function repairMissingTaskSummaryProjection(artifactBasePath, taskRow) {
82
49
  const summaryPath = taskSummaryPath(artifactBasePath, taskRow.milestone_id, taskRow.slice_id, taskRow.id);
83
50
  const summaryMd = renderSummaryContent(taskRow, taskRow.slice_id, taskRow.milestone_id, []);
@@ -94,7 +61,7 @@ async function repairMissingTaskSummaryProjection(artifactBasePath, taskRow) {
94
61
  clearPathCache();
95
62
  clearParseCache();
96
63
  try {
97
- await renderCompleteTaskProjections(artifactBasePath, taskRow.milestone_id);
64
+ await renderMilestoneShellProjections(artifactBasePath, taskRow.milestone_id);
98
65
  }
99
66
  catch (projErr) {
100
67
  logWarning("tool", `complete-task repair projection warning: ${projErr.message}`);
@@ -358,7 +325,7 @@ export async function handleCompleteTask(params, basePath) {
358
325
  await saveFile(summaryPath, summaryMd);
359
326
  // Toggle or regenerate the plan projection from DB. Missing projection
360
327
  // files are rebuilt by the renderer instead of being skipped.
361
- if (!ensureCompleteTaskDbOpen(rollbackDbPath)) {
328
+ if (!ensureWorkflowDbAtPath(rollbackDbPath)) {
362
329
  throw new Error(`database unavailable before plan projection render for ${params.milestoneId}/${params.sliceId}`);
363
330
  }
364
331
  const wrotePlan = await renderPlanCheckboxes(artifactBasePath, params.milestoneId, params.sliceId);
@@ -370,7 +337,7 @@ export async function handleCompleteTask(params, basePath) {
370
337
  logWarning("projection", `complete_task projection write failed for ${params.milestoneId}/${params.sliceId}/${params.taskId}`, { error: renderErr.message });
371
338
  let rollbackSucceeded = false;
372
339
  try {
373
- ensureCompleteTaskDbOpen(rollbackDbPath);
340
+ ensureWorkflowDbAtPath(rollbackDbPath);
374
341
  deleteVerificationEvidence(params.milestoneId, params.sliceId, params.taskId);
375
342
  updateTaskStatus(params.milestoneId, params.sliceId, params.taskId, "pending");
376
343
  invalidateStateCache();
@@ -498,7 +465,7 @@ export async function handleCompleteTask(params, basePath) {
498
465
  // Separate try/catch per step so a projection failure doesn't prevent
499
466
  // the event log entry (critical for worktree reconciliation).
500
467
  try {
501
- await renderCompleteTaskProjections(artifactBasePath, params.milestoneId);
468
+ await renderMilestoneShellProjections(artifactBasePath, params.milestoneId);
502
469
  }
503
470
  catch (projErr) {
504
471
  logWarning("tool", `complete-task projection warning: ${projErr.message}`);
@@ -28,9 +28,13 @@ function validateRepositoryTargetIds(field, value) {
28
28
  return deduped;
29
29
  }
30
30
  function validateTasks(value) {
31
- if (!Array.isArray(value) || value.length === 0) {
32
- throw new Error("tasks must be a non-empty array");
31
+ if (value === undefined)
32
+ return undefined;
33
+ if (!Array.isArray(value)) {
34
+ throw new Error("tasks must be an array");
33
35
  }
36
+ if (value.length === 0)
37
+ return undefined;
34
38
  const seen = new Set();
35
39
  return value.map((entry, index) => {
36
40
  if (!entry || typeof entry !== "object") {
@@ -129,7 +133,7 @@ function validateReferencedRepositories(params, registry, defaultTargets) {
129
133
  };
130
134
  for (const id of params.targetRepositories ?? defaultTargets)
131
135
  noteMissing(id);
132
- for (const task of params.tasks) {
136
+ for (const task of params.tasks ?? []) {
133
137
  for (const id of task.targetRepositories ?? params.targetRepositories ?? defaultTargets)
134
138
  noteMissing(id);
135
139
  }
@@ -141,7 +145,7 @@ function resolveAllowedRootsForPathScope(params, registry, defaultTargets) {
141
145
  const requested = new Set();
142
146
  for (const id of params.targetRepositories ?? defaultTargets)
143
147
  requested.add(id);
144
- for (const task of params.tasks) {
148
+ for (const task of params.tasks ?? []) {
145
149
  for (const id of task.targetRepositories ?? params.targetRepositories ?? defaultTargets)
146
150
  requested.add(id);
147
151
  }
@@ -153,7 +157,7 @@ function resolveAllowedRootsForPathScope(params, registry, defaultTargets) {
153
157
  return roots.length > 0 ? roots : [registry.projectRoot];
154
158
  }
155
159
  function toTaskRows(params, defaultTargets) {
156
- return params.tasks.map((task, index) => ({
160
+ return (params.tasks ?? []).map((task, index) => ({
157
161
  milestone_id: params.milestoneId,
158
162
  slice_id: params.sliceId,
159
163
  id: task.taskId,
@@ -230,19 +234,21 @@ export async function handlePlanSlice(rawParams, basePath) {
230
234
  return { error: `validation failed: ${message}` };
231
235
  }
232
236
  const defaultTargets = defaultRepositoryTargets(repositoryRegistry);
237
+ const taskPayload = params.tasks ?? [];
238
+ const hasTaskPayload = taskPayload.length > 0;
233
239
  const repoValidationError = validateReferencedRepositories(params, repositoryRegistry, defaultTargets);
234
240
  if (repoValidationError) {
235
241
  return { error: `validation failed: ${repoValidationError}` };
236
242
  }
237
243
  const allowedAbsoluteRoots = resolveAllowedRootsForPathScope(params, repositoryRegistry, defaultTargets);
238
- const pathOnlyError = validatePathOnlyPlanningFields(params.tasks.map((task, index) => ({
244
+ const pathOnlyError = validatePathOnlyPlanningFields(taskPayload.map((task, index) => ({
239
245
  field: `tasks[${index}].expectedOutput`,
240
246
  values: task.expectedOutput,
241
247
  })));
242
248
  if (pathOnlyError) {
243
249
  return { error: `validation failed: ${pathOnlyError}` };
244
250
  }
245
- const pathScopeError = validatePlanningPathScope(basePath, params.tasks.flatMap((task, index) => [
251
+ const pathScopeError = validatePlanningPathScope(basePath, taskPayload.flatMap((task, index) => [
246
252
  { field: `tasks[${index}].files`, values: task.files },
247
253
  { field: `tasks[${index}].inputs`, values: task.inputs },
248
254
  { field: `tasks[${index}].expectedOutput`, values: task.expectedOutput },
@@ -279,15 +285,17 @@ export async function handlePlanSlice(rawParams, basePath) {
279
285
  guardError = `cannot re-plan slice ${params.sliceId}: it is already complete — use gsd_slice_reopen first`;
280
286
  return;
281
287
  }
282
- const newTaskIds = new Set(params.tasks.map((task) => task.taskId));
288
+ const newTaskIds = new Set(taskPayload.map((task) => task.taskId));
283
289
  const existingTasks = getSliceTasks(params.milestoneId, params.sliceId);
284
- omittedTaskIds = existingTasks
285
- .filter((task) => !newTaskIds.has(task.id))
286
- .map((task) => task.id);
287
- for (const task of existingTasks) {
288
- if (!newTaskIds.has(task.id) && isClosedStatus(task.status)) {
289
- guardError = `cannot remove completed task ${task.id}`;
290
- return;
290
+ if (hasTaskPayload) {
291
+ omittedTaskIds = existingTasks
292
+ .filter((task) => !newTaskIds.has(task.id))
293
+ .map((task) => task.id);
294
+ for (const task of existingTasks) {
295
+ if (!newTaskIds.has(task.id) && isClosedStatus(task.status)) {
296
+ guardError = `cannot remove completed task ${task.id}`;
297
+ return;
298
+ }
291
299
  }
292
300
  }
293
301
  if (isDeferredStatus(parentSlice.status)) {
@@ -301,34 +309,36 @@ export async function handlePlanSlice(rawParams, basePath) {
301
309
  observabilityImpact: params.observabilityImpact,
302
310
  targetRepositories: params.targetRepositories ?? defaultTargets,
303
311
  });
304
- for (const taskId of omittedTaskIds) {
305
- deleteTask(params.milestoneId, params.sliceId, taskId);
306
- }
307
- const existingTaskById = new Map(existingTasks.map((task) => [task.id, task]));
308
- for (const task of params.tasks) {
309
- const planning = {
310
- title: task.title,
311
- description: task.description,
312
- estimate: task.estimate,
313
- files: task.files,
314
- verify: task.verify,
315
- inputs: task.inputs,
316
- expectedOutput: task.expectedOutput,
317
- observabilityImpact: task.observabilityImpact ?? "",
318
- fullPlanMd: task.fullPlanMd,
319
- targetRepositories: task.targetRepositories ?? params.targetRepositories ?? defaultTargets,
320
- };
321
- const existingTask = existingTaskById.get(task.taskId);
322
- if (!existingTask || !isClosedStatus(existingTask.status)) {
323
- insertTask({
324
- id: task.taskId,
325
- sliceId: params.sliceId,
326
- milestoneId: params.milestoneId,
312
+ if (hasTaskPayload) {
313
+ for (const taskId of omittedTaskIds) {
314
+ deleteTask(params.milestoneId, params.sliceId, taskId);
315
+ }
316
+ const existingTaskById = new Map(existingTasks.map((task) => [task.id, task]));
317
+ for (const task of taskPayload) {
318
+ const planning = {
327
319
  title: task.title,
328
- status: "pending",
329
- });
320
+ description: task.description,
321
+ estimate: task.estimate,
322
+ files: task.files,
323
+ verify: task.verify,
324
+ inputs: task.inputs,
325
+ expectedOutput: task.expectedOutput,
326
+ observabilityImpact: task.observabilityImpact ?? "",
327
+ fullPlanMd: task.fullPlanMd,
328
+ targetRepositories: task.targetRepositories ?? params.targetRepositories ?? defaultTargets,
329
+ };
330
+ const existingTask = existingTaskById.get(task.taskId);
331
+ if (!existingTask || !isClosedStatus(existingTask.status)) {
332
+ insertTask({
333
+ id: task.taskId,
334
+ sliceId: params.sliceId,
335
+ milestoneId: params.milestoneId,
336
+ title: task.title,
337
+ status: "pending",
338
+ });
339
+ }
340
+ upsertTaskPlanning(params.milestoneId, params.sliceId, task.taskId, planning);
330
341
  }
331
- upsertTaskPlanning(params.milestoneId, params.sliceId, task.taskId, planning);
332
342
  }
333
343
  // Seed quality gate rows inside the transaction — all-or-nothing with
334
344
  // the plan data so a crash can't leave orphaned gates without tasks.
@@ -337,7 +347,7 @@ export async function handlePlanSlice(rawParams, basePath) {
337
347
  insertGateRow({ milestoneId: params.milestoneId, sliceId: params.sliceId, gateId: gid, scope: "slice" });
338
348
  }
339
349
  const taskGates = resolveTaskGates(gateEvaluation);
340
- for (const task of params.tasks) {
350
+ for (const task of taskPayload) {
341
351
  for (const gid of taskGates) {
342
352
  insertGateRow({ milestoneId: params.milestoneId, sliceId: params.sliceId, gateId: gid, scope: "task", taskId: task.taskId });
343
353
  }
@@ -360,8 +370,13 @@ export async function handlePlanSlice(rawParams, basePath) {
360
370
  const artifactPath = relative(gsdProjectionRoot(basePath), taskPlanPath).replace(/\\/g, "/");
361
371
  deleteArtifactByPath(artifactPath);
362
372
  }
363
- const renderResult = await renderPlanFromDb(basePath, params.milestoneId, params.sliceId);
364
- setSliceSketchFlag(params.milestoneId, params.sliceId, false);
373
+ const sliceTasks = getSliceTasks(params.milestoneId, params.sliceId);
374
+ const renderResult = sliceTasks.length === 0
375
+ ? { planPath: "", taskPlanPaths: [] }
376
+ : await renderPlanFromDb(basePath, params.milestoneId, params.sliceId);
377
+ if (sliceTasks.length > 0) {
378
+ setSliceSketchFlag(params.milestoneId, params.sliceId, false);
379
+ }
365
380
  invalidateStateCache();
366
381
  clearParseCache();
367
382
  // ── Post-mutation hook: manifest, event log ─────────────────────────
@@ -1,14 +1,16 @@
1
1
  import { clearParseCache } from "../files.js";
2
2
  import { isClosedStatus } from "../status-guards.js";
3
3
  import { isNonEmptyString, validateStringArray } from "../validation.js";
4
- import { transaction, getSlice, getTask, insertTask, upsertTaskPlanning } from "../gsd-db.js";
4
+ import { getGateIdsForTurn } from "../gate-registry.js";
5
+ import { transaction, getSlice, getTask, insertTask, upsertTaskPlanning, insertGateRow, setSliceSketchFlag } from "../gsd-db.js";
5
6
  import { invalidateStateCache } from "../state.js";
6
7
  import { renderTaskPlanFromDb, renderPlanFromDb } from "../markdown-renderer.js";
7
- import { resolveSliceFile, resolveTasksDir } from "../paths.js";
8
+ import { resolveTasksDir } from "../paths.js";
8
9
  import { flushWorkflowProjections } from "../projection-flush.js";
9
10
  import { writeManifest } from "../workflow-manifest.js";
10
11
  import { appendEvent } from "../workflow-events.js";
11
12
  import { logWarning } from "../workflow-logger.js";
13
+ import { loadEffectiveGSDPreferences } from "../preferences.js";
12
14
  import { validatePathOnlyPlanningFields, validatePlanningPathScope } from "../planning-path-scope.js";
13
15
  function validateParams(params) {
14
16
  if (!isNonEmptyString(params?.milestoneId))
@@ -35,6 +37,12 @@ function validateParams(params) {
35
37
  expectedOutput: validateStringArray(params.expectedOutput, "expectedOutput"),
36
38
  };
37
39
  }
40
+ function resolveTaskGates(basePath) {
41
+ const loaded = loadEffectiveGSDPreferences(basePath);
42
+ if (loaded?.preferences?.gate_evaluation?.task_gates === false)
43
+ return [];
44
+ return [...getGateIdsForTurn("execute-task")];
45
+ }
38
46
  export async function handlePlanTask(rawParams, basePath) {
39
47
  let params;
40
48
  try {
@@ -57,6 +65,14 @@ export async function handlePlanTask(rawParams, basePath) {
57
65
  if (pathScopeError) {
58
66
  return { error: `validation failed: ${pathScopeError}` };
59
67
  }
68
+ let taskGates;
69
+ try {
70
+ taskGates = resolveTaskGates(basePath);
71
+ }
72
+ catch (err) {
73
+ const message = err instanceof Error ? err.message : String(err);
74
+ return { error: `validation failed: ${message}` };
75
+ }
60
76
  // ── Guards + DB writes inside a single transaction (prevents TOCTOU) ───
61
77
  // Guards must be inside the transaction so the state they check cannot
62
78
  // change between the read and the write (#2723).
@@ -97,6 +113,9 @@ export async function handlePlanTask(rawParams, basePath) {
97
113
  observabilityImpact: params.observabilityImpact ?? "",
98
114
  fullPlanMd: params.fullPlanMd,
99
115
  });
116
+ for (const gid of taskGates) {
117
+ insertGateRow({ milestoneId: params.milestoneId, sliceId: params.sliceId, gateId: gid, scope: "task", taskId: params.taskId });
118
+ }
100
119
  });
101
120
  }
102
121
  catch (err) {
@@ -110,17 +129,21 @@ export async function handlePlanTask(rawParams, basePath) {
110
129
  // Flat-phase: tasks live as checkboxes in the slice plan's <tasks> block,
111
130
  // not as standalone TID-PLAN.md files. Re-render the slice plan so the
112
131
  // new/updated task appears in the plan file that gsd-core reads.
113
- // Guard: resolveTasksDir is null in flat-phase (no tasks/ subdir exists);
114
- // only sync if a slice plan already exists (guards pre-plan-slice calls).
132
+ // Guard: resolveTasksDir is null in flat-phase (no tasks/ subdir exists).
133
+ let slicePlanSynced = false;
115
134
  try {
116
135
  const tDir = resolveTasksDir(basePath, params.milestoneId, params.sliceId);
117
- if (!tDir && resolveSliceFile(basePath, params.milestoneId, params.sliceId, "PLAN")) {
136
+ if (!tDir) {
118
137
  await renderPlanFromDb(basePath, params.milestoneId, params.sliceId);
138
+ slicePlanSynced = true;
119
139
  }
120
140
  }
121
141
  catch (syncErr) {
122
142
  logWarning("tool", `plan-task: slice-plan sync failed: ${syncErr.message}`);
123
143
  }
144
+ if (slicePlanSynced) {
145
+ setSliceSketchFlag(params.milestoneId, params.sliceId, false);
146
+ }
124
147
  invalidateStateCache();
125
148
  clearParseCache();
126
149
  // ── Post-mutation hook: projections, manifest, event log ─────────────
@@ -13,6 +13,7 @@ import { gsdRoot, resolveTasksDir, resolveSlicePath, resolveSliceFile, resolveTa
13
13
  import { sendDesktopNotification } from "./notifications.js";
14
14
  import { getTask, getSlice, getSliceTasks, updateTaskStatus, resetSliceCascade } from "./gsd-db.js";
15
15
  import { renderPlanCheckboxes, renderRoadmapCheckboxes } from "./markdown-renderer.js";
16
+ import { UNIT_REGISTRY } from "./unit-registry.js";
16
17
  /**
17
18
  * Undo the last completed unit: revert git commits,
18
19
  * delete summary artifacts, and uncheck the task in PLAN.
@@ -35,15 +36,19 @@ export async function handleUndo(args, ctx, _pi, basePath) {
35
36
  ctx.ui.notify("Nothing to undo — no activity logs found.", "info");
36
37
  return;
37
38
  }
38
- // Extract unit type and ID from the most recent activity log filename
39
- // Format: <seq>-<unitType>-<unitId>.jsonl
40
- const match = files[0].match(/^\d+-(.+?)-(.+)\.jsonl$/);
41
- if (!match) {
39
+ // Extract unit type and ID from the most recent activity log filename.
40
+ // Both the unit type and the unit ID may contain hyphens, so anchor on the
41
+ // known unit-type vocabulary instead of guessing the unit-ID shape: a regex
42
+ // tuned to milestone-shaped IDs rejects project-level units whose IDs are
43
+ // symbolic (e.g. discuss-project uses PROJECT, workflow-preferences uses
44
+ // WORKFLOW-PREFS).
45
+ const parsed = parseActivityLogFilename(files[0]);
46
+ if (!parsed) {
42
47
  ctx.ui.notify("Nothing to undo — could not parse latest activity log.", "warning");
43
48
  return;
44
49
  }
45
- const unitType = match[1];
46
- const unitId = match[2].replace(/-/g, "/");
50
+ const unitType = parsed.unitType;
51
+ const unitId = parsed.unitId.replace(/-/g, "/");
47
52
  if (!force) {
48
53
  ctx.ui.notify(`Will undo: ${unitType} (${unitId})\n` +
49
54
  `This will:\n` +
@@ -87,6 +92,11 @@ export async function handleUndo(args, ctx, _pi, basePath) {
87
92
  if (unitType === "execute-task" && task !== undefined && slice !== undefined) {
88
93
  const [mid, sid, tid] = [milestone, slice, task];
89
94
  planUpdated = uncheckTaskInPlan(basePath, mid, sid, tid);
95
+ if (getTask(mid, sid, tid)) {
96
+ updateTaskStatus(mid, sid, tid, "pending");
97
+ await renderPlanCheckboxes(basePath, mid, sid);
98
+ planUpdated = true;
99
+ }
90
100
  }
91
101
  // 3. Try to revert git commits from activity log
92
102
  let commitsReverted = 0;
@@ -318,6 +328,33 @@ export async function handleResetSlice(args, ctx, _pi, basePath) {
318
328
  ctx.ui.notify(results.join("\n"), "success");
319
329
  }
320
330
  // ─── Helpers ──────────────────────────────────────────────────────────────────
331
+ // Known unit types sorted longest-first so a more specific type (e.g.
332
+ // "execute-task-simple") matches before a prefix of it ("execute-task") when
333
+ // splitting "<seq>-<unitType>-<unitId>.jsonl".
334
+ const UNIT_TYPES_BY_LENGTH_DESC = Object.keys(UNIT_REGISTRY).sort((a, b) => b.length - a.length);
335
+ /**
336
+ * Parse an activity-log filename of the form `<seq>-<unitType>-<unitId>.jsonl`
337
+ * (the format written by activity-log.ts). Both the unit type and the unit ID
338
+ * may contain hyphens, so we anchor on the known unit-type vocabulary rather
339
+ * than guessing the ID shape. This keeps non-milestone IDs (e.g. PROJECT,
340
+ * WORKFLOW-PREFS) parseable. Returns null when the name has no sequence prefix
341
+ * or does not start with a recognised unit type.
342
+ */
343
+ export function parseActivityLogFilename(filename) {
344
+ const seqMatch = filename.match(/^\d+-(.+)\.jsonl$/);
345
+ if (!seqMatch)
346
+ return null;
347
+ const rest = seqMatch[1];
348
+ for (const unitType of UNIT_TYPES_BY_LENGTH_DESC) {
349
+ const prefix = `${unitType}-`;
350
+ if (rest.startsWith(prefix)) {
351
+ const unitId = rest.slice(prefix.length);
352
+ if (unitId.length > 0)
353
+ return { unitType, unitId };
354
+ }
355
+ }
356
+ return null;
357
+ }
321
358
  export function uncheckTaskInPlan(basePath, mid, sid, tid) {
322
359
  const slicePath = resolveSlicePath(basePath, mid, sid);
323
360
  if (!slicePath)
@@ -70,10 +70,11 @@ export const UNIT_REGISTRY = {
70
70
  "gsd_milestone_status",
71
71
  "gsd_plan_milestone",
72
72
  "gsd_plan_slice",
73
+ "gsd_plan_task",
73
74
  "gsd_decision_save",
74
75
  "gsd_requirement_update",
75
76
  ],
76
- requiredWorkflowTools: ["gsd_milestone_status", "gsd_plan_milestone", "gsd_plan_slice"],
77
+ requiredWorkflowTools: ["gsd_milestone_status", "gsd_plan_milestone", "gsd_plan_slice", "gsd_plan_task"],
77
78
  },
78
79
  },
79
80
  "discuss-milestone": {
@@ -172,13 +173,14 @@ export const UNIT_REGISTRY = {
172
173
  allowedGsdTools: [
173
174
  "gsd_milestone_status",
174
175
  "gsd_plan_slice",
176
+ "gsd_plan_task",
175
177
  "gsd_reassess_roadmap",
176
178
  "gsd_decision_save",
177
179
  "gsd_exec",
178
180
  "gsd_exec_search",
179
181
  "gsd_resume",
180
182
  ],
181
- requiredWorkflowTools: ["gsd_plan_slice", "gsd_reassess_roadmap"],
183
+ requiredWorkflowTools: ["gsd_plan_slice", "gsd_plan_task", "gsd_reassess_roadmap"],
182
184
  },
183
185
  },
184
186
  "refine-slice": {
@@ -298,7 +300,13 @@ export const UNIT_REGISTRY = {
298
300
  scopeClass: "execute-task",
299
301
  phaseChain: ["execution"],
300
302
  toolContract: {
301
- allowedGsdTools: ["gsd_task_complete", "gsd_summary_save", "gsd_decision_save"],
303
+ allowedGsdTools: [
304
+ "gsd_milestone_status",
305
+ "gsd_task_complete",
306
+ "gsd_exec",
307
+ "gsd_summary_save",
308
+ "gsd_decision_save",
309
+ ],
302
310
  requiredWorkflowTools: ["gsd_task_complete", "gsd_summary_save"],
303
311
  },
304
312
  },
@@ -201,6 +201,13 @@ export function formatFailureContext(result) {
201
201
  }
202
202
  return header + body;
203
203
  }
204
+ export function formatFailureSignature(result) {
205
+ return result.checks
206
+ .filter((check) => check.exitCode !== 0)
207
+ .map((check) => `${check.command.trim()}#${check.exitCode}`)
208
+ .sort()
209
+ .join("\n");
210
+ }
204
211
  // ─── Gate Execution ─────────────────────────────────────────────────────────
205
212
  /** Characters that indicate shell control syntax when unquoted in a command string. */
206
213
  const UNQUOTED_SHELL_CONTROL_CHARS = new Set([";", "<", ">"]);