@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
@@ -14,7 +14,6 @@ import { MILESTONE_ID_RE } from "./milestone-ids.js";
14
14
  import { appendEvent } from "./workflow-events.js";
15
15
  import { atomicWriteSync } from "./atomic-write.js";
16
16
  import { clearParseCache } from "./files.js";
17
- import { parseRoadmap as parseLegacyRoadmap, parsePlan as parseLegacyPlan } from "./parsers-legacy.js";
18
17
  import {
19
18
  isDbAvailable,
20
19
  getTask,
@@ -36,7 +35,7 @@ import { isValidationTerminal } from "./state.js";
36
35
  import { getErrorMessage } from "./error-utils.js";
37
36
  import { logWarning, logError } from "./workflow-logger.js";
38
37
  import { readIntegrationBranch } from "./git-service.js";
39
- import { isClosedStatus } from "./status-guards.js";
38
+ import { isClosedStatus, isInactiveStatus } from "./status-guards.js";
40
39
  import {
41
40
  resolveSlicePath,
42
41
  resolveSliceFile,
@@ -72,6 +71,9 @@ import { resolveCanonicalMilestoneRoot } from "./worktree-manager.js";
72
71
  import { resolveWorktreeProjectRoot } from "./worktree-root.js";
73
72
  import { hasImplementationArtifacts } from "./milestone-implementation-evidence.js";
74
73
  import { loadAllCaptures, loadPendingCaptures } from "./captures.js";
74
+ import {
75
+ resolveArtifactVerificationBase,
76
+ } from "./artifact-verification.js";
75
77
  import {
76
78
  proveMilestoneCloseout,
77
79
  type CloseoutProofFailureReason,
@@ -84,35 +86,12 @@ export {
84
86
  type MilestoneSummaryOutcome,
85
87
  } from "./milestone-summary-classifier.js";
86
88
  export { hasImplementationArtifacts } from "./milestone-implementation-evidence.js";
87
-
88
- /**
89
- * Optional override for the legacy roadmap parser used by verifyExpectedArtifact.
90
- * Production leaves this null so the real parseLegacyRoadmap runs; tests inject
91
- * a throwing function to deterministically exercise the parse-failure catches
92
- * (auto-recovery.ts:515 plan-milestone and :622 complete-slice). Those catches
93
- * are otherwise unreachable because parseLegacyRoadmap is internally defensive
94
- * against every malformed input.
95
- * @internal
96
- */
97
- let _roadmapParserFn: ((content: string) => { slices: Array<{ id: string; done: boolean; depends?: string[] }> }) | null = null;
98
-
99
- /**
100
- * Inject an override for the legacy roadmap parser, returning a function that
101
- * restores the default (real parser) behavior. No production caller.
102
- * @internal
103
- */
104
- export function _setRoadmapParserFnForTests(
105
- fn: ((content: string) => { slices: Array<{ id: string; done: boolean; depends?: string[] }> }) | null,
106
- ): () => void {
107
- const previous = _roadmapParserFn;
108
- _roadmapParserFn = fn;
109
- return () => { _roadmapParserFn = previous; };
110
- }
111
-
112
- function parseRoadmapForRecovery(content: string): ReturnType<NonNullable<typeof _roadmapParserFn>> {
113
- if (_roadmapParserFn) return _roadmapParserFn(content);
114
- return parseLegacyRoadmap(content) as unknown as ReturnType<NonNullable<typeof _roadmapParserFn>>;
115
- }
89
+ export {
90
+ verifyExpectedArtifact,
91
+ diagnoseWorktreeIntegrityFailure,
92
+ resolveArtifactVerificationBase,
93
+ _setRoadmapParserFnForTests,
94
+ } from "./artifact-verification.js";
116
95
 
117
96
  /**
118
97
  * Optional override for the detached GitHub milestone finalize invoked after DB
@@ -132,36 +111,7 @@ export function _setGithubFinalizeFnForTests(
132
111
  return () => { _githubFinalizeFn = previous; };
133
112
  }
134
113
 
135
- // ─── Artifact Resolution & Verification ───────────────────────────────────────
136
-
137
- export function diagnoseWorktreeIntegrityFailure(basePath: string): string | null {
138
- if (!isGsdWorktreePath(basePath)) return null;
139
- if (!existsSync(basePath)) {
140
- return `Worktree integrity failure: ${basePath} does not exist. Repair or recreate the worktree before retrying.`;
141
- }
142
-
143
- const gitPath = join(basePath, ".git");
144
- if (!existsSync(gitPath)) {
145
- return `Worktree integrity failure: ${basePath} is not a valid git worktree (.git missing). Repair or recreate the worktree before retrying.`;
146
- }
147
-
148
- try {
149
- execFileSync("git", ["rev-parse", "--git-dir"], {
150
- cwd: basePath,
151
- stdio: ["ignore", "pipe", "pipe"],
152
- encoding: "utf-8",
153
- });
154
- return null;
155
- } catch (err) {
156
- return `Worktree integrity failure: ${basePath} is not a valid git worktree (git rev-parse failed: ${getErrorMessage(err).split("\n")[0]}). Repair or recreate the worktree before retrying.`;
157
- }
158
- }
159
-
160
- function resolveArtifactVerificationBase(unitId: string, base: string): string {
161
- const { milestone } = parseUnitId(unitId);
162
- if (!MILESTONE_ID_RE.test(milestone)) return base;
163
- return resolveCanonicalMilestoneRoot(base, milestone);
164
- }
114
+ // ─── Recovery DB refresh ──────────────────────────────────────────────────────
165
115
 
166
116
  export type ArtifactRecoveryDbRefreshResult =
167
117
  | { ok: true }
@@ -295,461 +245,6 @@ export function refreshRecoveryDbForArtifact(
295
245
  return { ok: true };
296
246
  }
297
247
 
298
- function hasCapturedWorkflowPrefs(base: string): boolean {
299
- const prefsPath = resolveExpectedArtifactPath("workflow-preferences", "WORKFLOW-PREFS", base);
300
- if (!prefsPath || !existsSync(prefsPath)) return false;
301
- const content = readFileSync(prefsPath, "utf-8");
302
- const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
303
- return !!match && /^workflow_prefs_captured:\s*true\s*$/m.test(match[1]);
304
- }
305
-
306
- function hasValidResearchDecision(base: string): boolean {
307
- const decisionPath = resolveExpectedArtifactPath("research-decision", "RESEARCH-DECISION", base);
308
- if (!decisionPath || !existsSync(decisionPath)) return false;
309
- try {
310
- const cfg = JSON.parse(readFileSync(decisionPath, "utf-8")) as Record<string, unknown>;
311
- return cfg.decision === "research" || cfg.decision === "skip";
312
- } catch {
313
- return false;
314
- }
315
- }
316
-
317
- function hasCompleteProjectResearch(base: string): boolean {
318
- return getProjectResearchStatus(base).complete;
319
- }
320
-
321
- function escapeRegExp(value: string): string {
322
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
323
- }
324
-
325
- function hasCheckedTaskCompletionOnDisk(base: string, mid: string, sid: string, tid: string): boolean {
326
- const slicePath = resolveSlicePath(base, mid, sid);
327
- if (!slicePath) return false;
328
-
329
- const planAbs = resolveSliceFile(base, mid, sid, "PLAN");
330
- if (!planAbs || !existsSync(planAbs)) return false;
331
-
332
- const planContent = readFileSync(planAbs, "utf-8");
333
- // Match legacy (`**T01: Title**`) and flat-phase (`**T01**: Title`) checkbox lines.
334
- const cbRe = new RegExp(`^\\s*-\\s+\\[[xX]\\]\\s+\\*\\*${escapeRegExp(tid)}(?:\\*\\*)?:`, "m");
335
- return cbRe.test(planContent);
336
- }
337
-
338
- /**
339
- * Check whether the expected artifact(s) for a unit exist on disk.
340
- * Returns true if all required artifacts exist, or if the unit type has no
341
- * single verifiable artifact (e.g., replan-slice).
342
- *
343
- * complete-slice requires both SUMMARY and UAT files — verifying only
344
- * the summary allowed the unit to be marked complete when the LLM
345
- * skipped writing the UAT file (see #176).
346
- */
347
- export function verifyExpectedArtifact(
348
- unitType: string,
349
- unitId: string,
350
- base: string,
351
- ): boolean {
352
- // Hook units have no standard artifact — always pass. Their lifecycle
353
- // is managed by the hook engine, not the artifact verification system.
354
- if (unitType.startsWith("hook/")) return true;
355
-
356
- // Clear stale directory listing cache AND parse cache so artifact checks see
357
- // fresh disk state (#431). The parse cache must also be cleared because
358
- // cacheKey() uses length + first/last 100 chars — when a checkbox changes
359
- // from [ ] to [x], the key collides with the pre-edit version, returning
360
- // stale parsed results (e.g., slice.done = false when it's actually true).
361
- clearPathCache();
362
- clearParseCache();
363
-
364
- if (unitType === "rewrite-docs") {
365
- const overridesPath = resolveGsdRootFile(base, "OVERRIDES");
366
- if (!existsSync(overridesPath)) return true;
367
- const content = readFileSync(overridesPath, "utf-8");
368
- return !content.includes("**Scope:** active");
369
- }
370
-
371
- if (unitType === "workflow-preferences") {
372
- return hasCapturedWorkflowPrefs(base);
373
- }
374
-
375
- if (unitType === "triage-captures") {
376
- const pending = loadPendingCaptures(base);
377
- if (pending.length === 0) return true;
378
- logWarning("recovery", `verify-fail triage-captures ${unitId}: ${pending.length} pending capture(s) remain in CAPTURES.md`);
379
- return false;
380
- }
381
-
382
- if (unitType === "quick-task") {
383
- const { slice: captureId } = parseUnitId(unitId);
384
- const capture = captureId ? loadAllCaptures(base).find((entry) => entry.id === captureId) : undefined;
385
- if (capture?.executed === true) return true;
386
- logWarning("recovery", `verify-fail quick-task ${unitId}: capture ${captureId ?? "(missing capture id)"} not found or not marked executed`);
387
- return false;
388
- }
389
-
390
- if (unitType === "discuss-project") {
391
- const projectPath = resolveExpectedArtifactPath(unitType, unitId, base);
392
- return !!projectPath && existsSync(projectPath) && validateArtifact(projectPath, "project").ok;
393
- }
394
-
395
- if (unitType === "discuss-requirements") {
396
- const requirementsPath = resolveExpectedArtifactPath(unitType, unitId, base);
397
- return !!requirementsPath && existsSync(requirementsPath) && validateArtifact(requirementsPath, "requirements").ok;
398
- }
399
-
400
- if (unitType === "research-decision") {
401
- return hasValidResearchDecision(base);
402
- }
403
-
404
- if (unitType === "research-project") {
405
- return hasCompleteProjectResearch(base);
406
- }
407
-
408
- // Reactive-execute: verify that each dispatched task's summary exists.
409
- // The unitId encodes the batch: "{mid}/{sid}/reactive+T02,T03"
410
- if (unitType === "reactive-execute") {
411
- const { milestone: mid, slice: sid, task: batchPart } = parseUnitId(unitId);
412
- if (!mid || !sid || !batchPart) return false;
413
- const blockerPath = resolveExpectedArtifactPath(unitType, unitId, base);
414
- if (blockerPath && existsSync(blockerPath)) {
415
- return true;
416
- }
417
- const slicePath = resolveSlicePath(base, mid, sid);
418
- if (!slicePath) return false;
419
-
420
- const plusIdx = batchPart.indexOf("+");
421
- if (plusIdx === -1) {
422
- // Legacy format "reactive" without batch IDs — fall back to "any summary"
423
- const tDir = resolveTasksDir(base, mid, sid) ?? slicePath;
424
- const summaryFiles = resolveTaskFiles(tDir, "SUMMARY");
425
- return summaryFiles.length > 0;
426
- }
427
-
428
- const batchIds = batchPart.slice(plusIdx + 1).split(",").filter(Boolean);
429
- if (batchIds.length === 0) return false;
430
-
431
- const tDir = resolveTasksDir(base, mid, sid) ?? slicePath;
432
-
433
- const existingSummaries = new Set(
434
- resolveTaskFiles(tDir, "SUMMARY").map((f) =>
435
- f.replace(/-SUMMARY\.md$/i, "").toUpperCase(),
436
- ),
437
- );
438
-
439
- // Every dispatched task must have a summary file
440
- for (const tid of batchIds) {
441
- if (!existingSummaries.has(tid.toUpperCase())) return false;
442
- }
443
- return true;
444
- }
445
-
446
- // Gate-evaluate: verify that each dispatched gate has been resolved in the DB.
447
- // The unitId encodes the batch: "{mid}/{sid}/gates+Q3,Q4"
448
- if (unitType === "gate-evaluate") {
449
- const { milestone: mid, slice: sid, task: batchPart } = parseUnitId(unitId);
450
- if (!mid || !sid || !batchPart) return false;
451
-
452
- const plusIdx = batchPart.indexOf("+");
453
- if (plusIdx === -1) return true; // no specific gates encoded — pass
454
-
455
- const gateIds = batchPart.slice(plusIdx + 1).split(",").filter(Boolean);
456
- if (gateIds.length === 0) return true;
457
-
458
- try {
459
- if (!isDbAvailable()) return false;
460
- const pending = getPendingGatesForTurn(mid, sid, "gate-evaluate");
461
- const pendingIds = new Set<string>(pending.map((g) => g.gate_id));
462
- // All dispatched gates must no longer be pending
463
- for (const gid of gateIds) {
464
- if (pendingIds.has(gid)) return false;
465
- }
466
- } catch (err) {
467
- // DB unavailable — treat as verified to avoid blocking
468
- logWarning("recovery", `gate-evaluate DB check failed: ${err instanceof Error ? err.message : String(err)}`);
469
- }
470
- return true;
471
- }
472
-
473
- // #4414: research-slice parallel-research sentinel. The unitId
474
- // `{mid}/parallel-research` is not a real slice — it triggers a single agent
475
- // that fans out research across multiple slices. Verify success by checking
476
- // that every slice which was "research-ready" in the roadmap now has a
477
- // RESEARCH file. Without this, resolveExpectedArtifactPath returns null and
478
- // the retry/escalation machinery silently re-dispatches forever.
479
- //
480
- // #4068: Also treat a PARALLEL-BLOCKER placeholder as a terminal completion
481
- // so that timeout-recovery can write the blocker, have verifyExpectedArtifact
482
- // return true, and let the dispatch loop advance past this unit. Without
483
- // this, the blocker is written but verification still returns false, the unit
484
- // is never cleared from unitDispatchCount, and on the next iteration the
485
- // dispatch rule (which correctly skips parallel-research when PARALLEL-BLOCKER
486
- // exists) returns null — leaving the loop stuck re-deriving indefinitely.
487
- //
488
- // NOTE: this predicate mirrors the dispatch rule at
489
- // auto-dispatch.ts parallel-research-slices — keep the two in sync.
490
- if (unitType === "research-slice" && unitId.endsWith("/parallel-research")) {
491
- const { milestone: mid } = parseUnitId(unitId);
492
- if (!mid) return false;
493
-
494
- // #4068: PARALLEL-BLOCKER written by timeout-recovery is a terminal state.
495
- const blockerPath = resolveExpectedArtifactPath(unitType, unitId, base);
496
- if (blockerPath && existsSync(blockerPath)) {
497
- return true;
498
- }
499
-
500
- const roadmapFile = resolveExpectedArtifactPath("plan-milestone", mid, base);
501
- if (!roadmapFile || !existsSync(roadmapFile)) {
502
- logWarning("recovery", `verify-fail ${unitType} ${unitId}: roadmap missing`);
503
- return false;
504
- }
505
- try {
506
- const roadmap = parseRoadmapForRecovery(readFileSync(roadmapFile, "utf-8"));
507
- const milestoneResearchFile = resolveExpectedArtifactPath("research-milestone", mid, base);
508
- const hasMilestoneResearch = !!milestoneResearchFile && existsSync(milestoneResearchFile);
509
- for (const slice of roadmap.slices) {
510
- if (slice.done) continue;
511
- if (hasMilestoneResearch && slice.id === "S01") continue;
512
- const depsComplete = (slice.depends ?? []).every((depId) => {
513
- const summaryPath = resolveExpectedArtifactPath("complete-slice", `${mid}/${depId}`, base);
514
- return !!summaryPath && existsSync(summaryPath);
515
- });
516
- if (!depsComplete) continue;
517
- const researchPath = resolveExpectedArtifactPath("research-slice", `${mid}/${slice.id}`, base);
518
- if (!researchPath || !existsSync(researchPath)) {
519
- logWarning("recovery", `verify-fail ${unitType} ${unitId}: slice ${slice.id} missing RESEARCH`);
520
- return false;
521
- }
522
- }
523
- return true;
524
- } catch (err) {
525
- logWarning("recovery", `parallel-research verification failed: ${err instanceof Error ? err.message : String(err)}`);
526
- return false;
527
- }
528
- }
529
-
530
- const artifactBase = resolveArtifactVerificationBase(unitId, base);
531
- let absPath = resolveExpectedArtifactPath(unitType, unitId, artifactBase);
532
- // Worktree→project-root fallback: a milestone running in a worktree may not
533
- // have its CONTEXT/ROADMAP/SUMMARY projected into the worktree yet (the
534
- // worktree only has the META dir until planning writes its projections).
535
- // When the worktree base yields null or a non-existent path, fall back to the
536
- // project root — where the artifact genuinely lives. Without this, a
537
- // discuss-milestone unit with CONTEXT at phases/NN-slug/ in the project root
538
- // but not in the worktree resolves to null → "resolveExpectedArtifactPath
539
- // returned null" → finalize-retry loop (#852).
540
- //
541
- // #870: the fallback must fire whenever the artifact is missing at
542
- // `artifactBase`, NOT only when `artifactBase !== base`. When the real call
543
- // site passes the worktree path as `base` (auto-post-unit.ts:1726 uses
544
- // `s.currentUnit.workspaceRoot ?? s.basePath`), resolveCanonicalMilestoneRoot
545
- // round-trips the worktree path back to itself, so `artifactBase === base`
546
- // while still being a worktree path that lacks the projected artifact. The
547
- // old `if (artifactBase !== base)` guard skipped the fallback in exactly that
548
- // case, stranding CONTEXT at the project root and producing a stuck-loop.
549
- if (!absPath || !existsSync(absPath)) {
550
- const projectRoot = resolve(resolveWorktreeProjectRoot(artifactBase));
551
- if (projectRoot && projectRoot !== artifactBase) {
552
- const projectPath = resolveExpectedArtifactPath(unitType, unitId, projectRoot);
553
- if (projectPath && existsSync(projectPath)) {
554
- absPath = projectPath;
555
- }
556
- }
557
- }
558
- // For unit types with no registered artifact contract (null path), treat the
559
- // completion state as stale so the key gets evicted (#313).
560
- if (!absPath) {
561
- logWarning("recovery", `verify-fail ${unitType} ${unitId}: resolveExpectedArtifactPath returned null (no artifact contract registered for this unit type)`);
562
- return false;
563
- }
564
- if (!existsSync(absPath)) {
565
- const worktreeFailure = diagnoseWorktreeIntegrityFailure(artifactBase);
566
- if (worktreeFailure) {
567
- logError("recovery", `${worktreeFailure} Unit: ${unitType} ${unitId}.`);
568
- return false;
569
- }
570
- logWarning("recovery", `verify-fail ${unitType} ${unitId}: existsSync false for ${absPath}`);
571
- return false;
572
- }
573
-
574
- if (unitType === "validate-milestone") {
575
- const validationContent = readFileSync(absPath, "utf-8");
576
- if (!isValidationTerminal(validationContent)) {
577
- logWarning("recovery", `verify-fail ${unitType} ${unitId}: validation not terminal (len=${validationContent.length}) at ${absPath}`);
578
- return false;
579
- }
580
- }
581
-
582
- if (unitType === "run-uat") {
583
- const assessmentContent = readFileSync(absPath, "utf-8");
584
- if (!hasVerdict(assessmentContent)) {
585
- logWarning("recovery", `verify-fail ${unitType} ${unitId}: assessment missing verdict at ${absPath}`);
586
- return false;
587
- }
588
- }
589
-
590
- if (unitType === "plan-milestone") {
591
- try {
592
- const roadmap = parseRoadmapForRecovery(readFileSync(absPath, "utf-8"));
593
- if (roadmap.slices.length === 0) {
594
- logWarning("recovery", `verify-fail ${unitType} ${unitId}: roadmap has zero slices at ${absPath}`);
595
- return false;
596
- }
597
- } catch (err) {
598
- logWarning("recovery", `plan-milestone roadmap verification failed: ${err instanceof Error ? err.message : String(err)}`);
599
- return false;
600
- }
601
- }
602
-
603
- // plan-slice verification is DB-primary. The slice plan is a projection, so
604
- // DB task rows prove the slice was planned even if the rendered markdown no
605
- // longer uses legacy checkbox/heading syntax.
606
- if (unitType === "plan-slice") {
607
- const { milestone: mid, slice: sid } = parseUnitId(unitId);
608
- if (mid && sid) {
609
- try {
610
- let taskIds: string[] | null = null;
611
- let dbPrimary = false;
612
- if (isDbAvailable()) {
613
- const refreshed = refreshWorkflowDatabaseFromDisk();
614
- if (refreshed) {
615
- const tasks = getSliceTasks(mid, sid);
616
- if (tasks.length > 0) {
617
- taskIds = tasks.map(t => t.id);
618
- dbPrimary = true;
619
- }
620
- }
621
- }
622
-
623
- if (!taskIds) {
624
- // LEGACY: DB unavailable or no tasks in DB. Require actual task
625
- // entries so an empty scaffold cannot advance the pipeline (#699).
626
- const planContent = readFileSync(absPath, "utf-8");
627
- const hasCheckboxTask = /^\s*- \[[xX ]\] \*\*T\d+/m.test(planContent);
628
- const hasHeadingTask = /^\s*#{2,4}\s+T\d+\s*(?:--|—|:)/m.test(planContent);
629
- if (!hasCheckboxTask && !hasHeadingTask) {
630
- logWarning("recovery", `verify-fail ${unitType} ${unitId}: plan has no task checkbox/heading (len=${planContent.length}) at ${absPath}`);
631
- return false;
632
- }
633
- const plan = parseLegacyPlan(planContent);
634
- if (plan.tasks.length > 0) taskIds = plan.tasks.map((t: { id: string }) => t.id);
635
- }
636
-
637
- // Per-task plan file check: applies when a tasks/ directory is present on
638
- // disk (legacy layout), regardless of whether DB is primary. Flat-phase
639
- // projects have no tasks/ dir, so the check is naturally skipped there.
640
- // When DB is NOT primary and there is no tasks/ dir either, the missing
641
- // dir itself is evidence of an incomplete plan (non-flat-phase projects must
642
- // have a tasks/ dir).
643
- if (taskIds && taskIds.length > 0) {
644
- const tasksDir = join(dirname(absPath), "tasks");
645
- if (existsSync(tasksDir)) {
646
- for (const tid of taskIds) {
647
- const taskPlanFile = join(tasksDir, `${tid}-PLAN.md`);
648
- if (!existsSync(taskPlanFile)) {
649
- logWarning("recovery", `verify-fail ${unitType} ${unitId}: task plan missing ${taskPlanFile}`);
650
- return false;
651
- }
652
- }
653
- } else if (!dbPrimary && !absPath.replace(/\\/g, "/").includes(`.gsd/${LAYOUT_SEGMENTS.level1}`)) {
654
- logWarning("recovery", `verify-fail ${unitType} ${unitId}: tasks dir missing at ${tasksDir}`);
655
- return false;
656
- }
657
- }
658
- } catch (err) {
659
- // Parse failure — don't block; slice plan may have non-standard format
660
- logWarning("recovery", `plan-slice task plan verification failed: ${err instanceof Error ? err.message : String(err)}`);
661
- }
662
- }
663
- }
664
-
665
- // execute-task: DB status is authoritative. Fall back to checked-checkbox
666
- // detection when the DB is unavailable (unmigrated projects), or when the
667
- // disk artifacts already reflect completion but the DB replay is one beat
668
- // behind the completion write.
669
- if (unitType === "execute-task") {
670
- const { milestone: mid, slice: sid, task: tid } = parseUnitId(unitId);
671
- if (mid && sid && tid) {
672
- const dbTask = getTask(mid, sid, tid);
673
- if (dbTask) {
674
- if (dbTask.status !== "complete" && dbTask.status !== "done" && !hasCheckedTaskCompletionOnDisk(base, mid, sid, tid)) {
675
- return false;
676
- }
677
- } else if (!isDbAvailable()) {
678
- // LEGACY: Pre-migration fallback for projects without DB.
679
- // Require a CHECKED checkbox — a bare heading or unchecked checkbox
680
- // does not prove gsd_complete_task ran. Summary file on disk alone
681
- // is not sufficient evidence (could be a rogue write) (#3607).
682
- if (!hasCheckedTaskCompletionOnDisk(base, mid, sid, tid)) return false;
683
- } else {
684
- // DB available but task row not found — completion tool never ran (#3607)
685
- return false;
686
- }
687
- }
688
- }
689
-
690
- // complete-slice: DB status is authoritative for whether the slice is done.
691
- // Fall back to file-based check (roadmap [x]) when DB is unavailable.
692
- if (unitType === "complete-slice") {
693
- const { milestone: mid, slice: sid } = parseUnitId(unitId);
694
- if (mid && sid) {
695
- // resolveSliceFile only finds existing files; UAT may not exist yet.
696
- // Fall back to the canonical expected location so a missing UAT always
697
- // returns false (not a silent pass when resolveSliceFile returns null).
698
- const uatPath = resolveSliceFile(base, mid, sid, "UAT")
699
- ?? join(base, relSliceFile(base, mid, sid, "UAT"));
700
- if (!existsSync(uatPath)) return false;
701
-
702
- const dbSlice = getSlice(mid, sid);
703
- if (dbSlice) {
704
- // DB available — trust it
705
- if (dbSlice.status !== "complete") return false;
706
- } else if (!isDbAvailable()) {
707
- // LEGACY: Pre-migration fallback for projects without DB.
708
- // Fall back to roadmap checkbox check via parsers-legacy
709
- const roadmapFile = resolveMilestoneFile(base, mid, "ROADMAP");
710
- if (roadmapFile && existsSync(roadmapFile)) {
711
- try {
712
- const roadmapContent = readFileSync(roadmapFile, "utf-8");
713
- const roadmap = parseRoadmapForRecovery(roadmapContent);
714
- const slice = roadmap.slices.find((s) => s.id === sid);
715
- if (slice && !slice.done) return false;
716
- } catch (e) {
717
- logWarning("recovery", `roadmap parse failed: ${(e as Error).message}`);
718
- return false;
719
- }
720
- }
721
- }
722
- // else: DB available but slice not found — summary + UAT exist,
723
- // treat as verified (slice may not be imported yet)
724
- }
725
- }
726
-
727
- // complete-milestone must have produced implementation artifacts (#1703).
728
- // A milestone with only .gsd/ plan files and zero implementation code is
729
- // not genuinely complete — the LLM wrote plan files but skipped actual work.
730
- if (unitType === "complete-milestone") {
731
- const { milestone: mid } = parseUnitId(unitId);
732
- if (!mid) return false;
733
- const closeoutProof = proveMilestoneCloseout(mid, {
734
- refreshFromDisk: true,
735
- summaryArtifactBasePath: artifactBase,
736
- implementationEvidence: {
737
- basePath: base,
738
- requirement: "not-absent",
739
- },
740
- });
741
- if (!closeoutProof.ok) {
742
- if (!isDbAvailable() && closeoutProof.reason === "db-unavailable") {
743
- const summaryOutcome = classifyMilestoneSummaryContent(readFileSync(absPath, "utf-8"));
744
- return summaryOutcome !== "failure" && hasImplementationArtifacts(base, mid) !== "absent";
745
- }
746
- return false;
747
- }
748
- }
749
-
750
- return true;
751
- }
752
-
753
248
  export interface ReactiveExecuteBlockerRecovery {
754
249
  blockerPath: string;
755
250
  completedTaskIds: string[];
@@ -800,7 +295,7 @@ export function writeReactiveExecuteBlocker(
800
295
  transaction(() => {
801
296
  for (const tid of summaryPresent) {
802
297
  const task = getTask(mid, sid, tid);
803
- if (!task || isClosedStatus(task.status)) {
298
+ if (!task || isInactiveStatus(task.status)) {
804
299
  unchangedTaskIds.push(tid);
805
300
  continue;
806
301
  }
@@ -809,7 +304,7 @@ export function writeReactiveExecuteBlocker(
809
304
  }
810
305
  for (const tid of summaryMissing) {
811
306
  const task = getTask(mid, sid, tid);
812
- if (!task || isClosedStatus(task.status)) {
307
+ if (!task || isInactiveStatus(task.status)) {
813
308
  unchangedTaskIds.push(tid);
814
309
  continue;
815
310
  }
@@ -25,7 +25,6 @@ export type {
25
25
  } from "./tool-surface-snapshot.js";
26
26
 
27
27
  export const autoSession = new AutoSession();
28
- let currentToolSurfaceSnapshot: ToolSurfaceSnapshot | null = null;
29
28
 
30
29
  export type AutoRuntimeSnapshot = {
31
30
  active: boolean;
@@ -48,17 +47,17 @@ export function getAutoRuntimeSnapshot(): AutoRuntimeSnapshot {
48
47
  orchestrationPhase: orchestrationStatus?.phase,
49
48
  orchestrationTransitionCount: orchestrationStatus?.transitionCount,
50
49
  orchestrationLastTransitionAt: orchestrationStatus?.lastTransitionAt,
51
- toolSurface: autoSession.active || autoSession.paused ? currentToolSurfaceSnapshot : null,
50
+ toolSurface: autoSession.active || autoSession.paused ? autoSession.toolSurfaceSnapshot : null,
52
51
  };
53
52
  }
54
53
 
55
54
  export function recordAutoToolSurfaceSnapshot(input: ToolSurfaceSnapshotInput): ToolSurfaceSnapshot {
56
- currentToolSurfaceSnapshot = createToolSurfaceSnapshot(input);
57
- return currentToolSurfaceSnapshot;
55
+ autoSession.toolSurfaceSnapshot = createToolSurfaceSnapshot(input);
56
+ return autoSession.toolSurfaceSnapshot;
58
57
  }
59
58
 
60
59
  export function clearAutoToolSurfaceSnapshot(): void {
61
- currentToolSurfaceSnapshot = null;
60
+ autoSession.toolSurfaceSnapshot = null;
62
61
  }
63
62
 
64
63
  export function isAutoActive(): boolean {
@@ -14,6 +14,7 @@ import {
14
14
  import {
15
15
  resolveExpectedArtifactPath,
16
16
  diagnoseExpectedArtifact,
17
+ verifyExpectedArtifact,
17
18
  writeBlockerPlaceholder,
18
19
  } from "./auto-recovery.js";
19
20
  import { existsSync } from "node:fs";
@@ -194,10 +195,10 @@ export async function recoverTimedOutUnit(
194
195
  return "recovered";
195
196
  }
196
197
 
197
- // Check if the artifact already exists on disk — agent may have written it
198
+ // Check if the artifact is already valid on disk — agent may have written it
198
199
  // without signaling completion.
199
200
  const artifactPath = resolveExpectedArtifactPath(unitType, unitId, basePath);
200
- if (artifactPath && existsSync(artifactPath)) {
201
+ if (artifactPath && existsSync(artifactPath) && verifyExpectedArtifact(unitType, unitId, basePath)) {
201
202
  writeUnitRuntimeRecord(basePath, unitType, unitId, currentUnitStartedAt, {
202
203
  phase: "finalized",
203
204
  recoveryAttempts: recoveryAttempts + 1,
@@ -29,6 +29,7 @@ import {
29
29
  runVerificationGate,
30
30
  runVerificationGateForTargets,
31
31
  formatFailureContext,
32
+ formatFailureSignature,
32
33
  captureRuntimeErrors,
33
34
  runDependencyAudit,
34
35
  } from "./verification-gate.js";
@@ -871,10 +872,13 @@ export async function runPostUnitVerification(
871
872
  );
872
873
  }
873
874
  const nextAttempt = attempt + 1;
875
+ const failureContext = verdict.failureContext || formatFailureContext(result);
876
+ const failureSignature = formatFailureSignature(result);
874
877
  s.verificationRetryCount.set(retryKey, nextAttempt);
875
878
  s.pendingVerificationRetry = {
876
879
  unitId: s.currentUnit.id,
877
- failureContext: verdict.failureContext || formatFailureContext(result),
880
+ failureContext,
881
+ ...(failureSignature ? { signature: failureSignature } : {}),
878
882
  attempt: nextAttempt,
879
883
  };
880
884
  const failedCmds = result.checks