@opengsd/gsd-pi 1.3.0-dev.65546769 → 1.3.0-dev.72e3af2a

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 (357) hide show
  1. package/dist/resources/.managed-resources-content-hash +1 -1
  2. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +11 -2
  3. package/dist/resources/extensions/google-cli/stream-adapter.js +82 -15
  4. package/dist/resources/extensions/gsd/artifact-verification.js +427 -0
  5. package/dist/resources/extensions/gsd/auto/orchestrator.js +12 -3
  6. package/dist/resources/extensions/gsd/auto/session.js +3 -0
  7. package/dist/resources/extensions/gsd/auto-artifact-paths.js +28 -1
  8. package/dist/resources/extensions/gsd/auto-dispatch.js +20 -19
  9. package/dist/resources/extensions/gsd/auto-prompts.js +26 -11
  10. package/dist/resources/extensions/gsd/auto-recovery.js +6 -507
  11. package/dist/resources/extensions/gsd/auto-runtime-state.js +4 -5
  12. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +3 -3
  13. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +103 -13
  14. package/dist/resources/extensions/gsd/bootstrap/core-session-tools.js +38 -0
  15. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +6 -1
  16. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +2 -0
  17. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +10 -19
  18. package/dist/resources/extensions/gsd/bootstrap/system-context.js +46 -19
  19. package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +68 -10
  20. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +1 -1
  21. package/dist/resources/extensions/gsd/commands-context.js +19 -1
  22. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +16 -10
  23. package/dist/resources/extensions/gsd/commands-worktree.js +12 -10
  24. package/dist/resources/extensions/gsd/dashboard-overlay.js +32 -3
  25. package/dist/resources/extensions/gsd/db/queries.js +60 -0
  26. package/dist/resources/extensions/gsd/db-workspace.js +55 -3
  27. package/dist/resources/extensions/gsd/doctor-providers.js +92 -8
  28. package/dist/resources/extensions/gsd/exec-sandbox.js +45 -9
  29. package/dist/resources/extensions/gsd/forensics.js +2 -32
  30. package/dist/resources/extensions/gsd/git-service.js +4 -4
  31. package/dist/resources/extensions/gsd/guided-flow-queue.js +66 -5
  32. package/dist/resources/extensions/gsd/health-widget.js +55 -29
  33. package/dist/resources/extensions/gsd/layout-policy.js +3 -1
  34. package/dist/resources/extensions/gsd/markdown-renderer.js +8 -9
  35. package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +44 -21
  36. package/dist/resources/extensions/gsd/migration-auto-check.js +22 -0
  37. package/dist/resources/extensions/gsd/milestone-ids.js +32 -2
  38. package/dist/resources/extensions/gsd/milestone-implementation-evidence.js +26 -20
  39. package/dist/resources/extensions/gsd/prompts/code-review.md +6 -4
  40. package/dist/resources/extensions/gsd/quick.js +45 -2
  41. package/dist/resources/extensions/gsd/session-forensics.js +11 -1
  42. package/dist/resources/extensions/gsd/skills/gsd-headless/references/commands.md +1 -1
  43. package/dist/resources/extensions/gsd/state/derive/cache.js +28 -0
  44. package/dist/resources/extensions/gsd/state/derive/db-open.js +39 -0
  45. package/dist/resources/extensions/gsd/state/derive/from-db.js +452 -0
  46. package/dist/resources/extensions/gsd/state/derive/index.js +75 -0
  47. package/dist/resources/extensions/gsd/state/derive/interrupted-work.js +21 -0
  48. package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-render.js +45 -2
  49. package/dist/resources/extensions/gsd/state-reconciliation/index.js +48 -23
  50. package/dist/resources/extensions/gsd/state-reconciliation/registry.js +32 -28
  51. package/dist/resources/extensions/gsd/state.js +12 -611
  52. package/dist/resources/extensions/gsd/tools/complete-slice.js +2 -2
  53. package/dist/resources/extensions/gsd/tools/complete-task.js +43 -14
  54. package/dist/resources/extensions/gsd/tools/exec-tool.js +7 -2
  55. package/dist/resources/extensions/gsd/unit-context-composer.js +23 -7
  56. package/dist/resources/extensions/gsd/unit-registry.js +32 -4
  57. package/dist/resources/extensions/gsd/unmerged-milestone-guard.js +33 -3
  58. package/dist/resources/extensions/gsd/validation-block-guard.js +9 -4
  59. package/dist/resources/extensions/gsd/workflow-projections.js +19 -14
  60. package/dist/resources/extensions/gsd/workspace-git-preflight.js +30 -1
  61. package/dist/resources/extensions/gsd/worktree-manager.js +44 -2
  62. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  63. package/dist/web/standalone/.next/BUILD_ID +1 -1
  64. package/dist/web/standalone/.next/app-path-routes-manifest.json +10 -10
  65. package/dist/web/standalone/.next/build-manifest.json +3 -3
  66. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  67. package/dist/web/standalone/.next/react-loadable-manifest.json +9 -9
  68. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  69. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  70. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  71. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  72. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  73. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  74. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  75. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  76. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  77. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  78. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  79. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  80. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  81. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  82. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  83. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  84. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  85. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  86. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  87. package/dist/web/standalone/.next/server/app/index.html +1 -1
  88. package/dist/web/standalone/.next/server/app/index.rsc +2 -2
  89. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  90. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
  91. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  95. package/dist/web/standalone/.next/server/app-paths-manifest.json +10 -10
  96. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  97. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  98. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  99. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  100. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  101. package/dist/web/standalone/.next/static/chunks/{2659.b7b129ee6a769448.js → 2659.58e950899a9bb82f.js} +1 -1
  102. package/dist/web/standalone/.next/static/chunks/2772.a7c1fcc69a4685ef.js +1 -0
  103. package/dist/web/standalone/.next/static/chunks/{3616.3c60753b8ffcbd2e.js → 3616.61a2af74bb8833c8.js} +1 -1
  104. package/dist/web/standalone/.next/static/chunks/{4283.8e446784528ed9dc.js → 4283.d0d9e0a955e441cb.js} +1 -1
  105. package/dist/web/standalone/.next/static/chunks/{5826.a46ecdd1cfe8dabc.js → 5826.5421d66c72b9f34e.js} +1 -1
  106. package/dist/web/standalone/.next/static/chunks/{8785.481aa5869991b760.js → 8785.e29b3134cab1d153.js} +1 -1
  107. package/dist/web/standalone/.next/static/chunks/8937.640dc9c2aaa1dfad.js +10 -0
  108. package/dist/web/standalone/.next/static/chunks/app/{page-6644fc6ee8ca1247.js → page-72a856634ad14c10.js} +1 -1
  109. package/dist/web/standalone/.next/static/chunks/webpack-9c401904f87ded16.js +1 -0
  110. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  111. package/package.json +1 -1
  112. package/packages/cloud-mcp-gateway/package.json +2 -2
  113. package/packages/contracts/dist/workflow.d.ts +1 -0
  114. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  115. package/packages/contracts/dist/workflow.js +2 -0
  116. package/packages/contracts/dist/workflow.js.map +1 -1
  117. package/packages/contracts/package.json +1 -1
  118. package/packages/daemon/package.json +4 -4
  119. package/packages/gsd-agent-core/dist/agent-session.d.ts +1 -0
  120. package/packages/gsd-agent-core/dist/agent-session.d.ts.map +1 -1
  121. package/packages/gsd-agent-core/dist/agent-session.js +3 -0
  122. package/packages/gsd-agent-core/dist/agent-session.js.map +1 -1
  123. package/packages/gsd-agent-core/dist/extension-ui-snapshot.d.ts +41 -0
  124. package/packages/gsd-agent-core/dist/extension-ui-snapshot.d.ts.map +1 -0
  125. package/packages/gsd-agent-core/dist/extension-ui-snapshot.js +62 -0
  126. package/packages/gsd-agent-core/dist/extension-ui-snapshot.js.map +1 -0
  127. package/packages/gsd-agent-core/dist/index.d.ts +2 -0
  128. package/packages/gsd-agent-core/dist/index.d.ts.map +1 -1
  129. package/packages/gsd-agent-core/dist/index.js +2 -0
  130. package/packages/gsd-agent-core/dist/index.js.map +1 -1
  131. package/packages/gsd-agent-core/dist/session/agent-session-events.js +1 -1
  132. package/packages/gsd-agent-core/dist/session/agent-session-events.js.map +1 -1
  133. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts +1 -0
  134. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts.map +1 -1
  135. package/packages/gsd-agent-core/dist/session/agent-session-host.js.map +1 -1
  136. package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts +5 -0
  137. package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts.map +1 -1
  138. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js +60 -3
  139. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js.map +1 -1
  140. package/packages/gsd-agent-core/dist/transcript-store.d.ts +58 -0
  141. package/packages/gsd-agent-core/dist/transcript-store.d.ts.map +1 -0
  142. package/packages/gsd-agent-core/dist/transcript-store.js +132 -0
  143. package/packages/gsd-agent-core/dist/transcript-store.js.map +1 -0
  144. package/packages/gsd-agent-core/package.json +5 -5
  145. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +2 -0
  146. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  147. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +25 -11
  148. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  149. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.d.ts +4 -0
  150. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.d.ts.map +1 -0
  151. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.js +7 -0
  152. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.js.map +1 -0
  153. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts +3 -24
  154. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  155. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +26 -829
  156. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  157. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.d.ts +58 -0
  158. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.d.ts.map +1 -0
  159. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.js +312 -0
  160. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.js.map +1 -0
  161. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.d.ts +31 -0
  162. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.d.ts.map +1 -0
  163. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.js +130 -0
  164. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.js.map +1 -0
  165. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts +15 -0
  166. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts.map +1 -0
  167. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js +258 -0
  168. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js.map +1 -0
  169. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.d.ts +13 -0
  170. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.d.ts.map +1 -0
  171. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.js +118 -0
  172. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.js.map +1 -0
  173. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts +9 -0
  174. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  175. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.js +1 -1
  176. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  177. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.d.ts +54 -0
  178. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.d.ts.map +1 -0
  179. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.js +20 -0
  180. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.js.map +1 -0
  181. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts +4 -1
  182. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  183. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +9 -0
  184. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
  185. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.d.ts +56 -0
  186. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.d.ts.map +1 -0
  187. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.js +44 -0
  188. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.js.map +1 -0
  189. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.d.ts +5 -0
  190. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.d.ts.map +1 -0
  191. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.js +77 -0
  192. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.js.map +1 -0
  193. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  194. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +18 -0
  195. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
  196. package/packages/gsd-agent-modes/package.json +7 -7
  197. package/packages/mcp-server/README.md +1 -1
  198. package/packages/mcp-server/dist/server.d.ts +1 -1
  199. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  200. package/packages/mcp-server/dist/server.js +3 -3
  201. package/packages/mcp-server/dist/server.js.map +1 -1
  202. package/packages/mcp-server/dist/workflow-tools.d.ts +13 -1
  203. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  204. package/packages/mcp-server/dist/workflow-tools.js +34 -20
  205. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  206. package/packages/mcp-server/package.json +4 -4
  207. package/packages/native/package.json +1 -1
  208. package/packages/pi-agent-core/package.json +1 -1
  209. package/packages/pi-ai/package.json +1 -1
  210. package/packages/pi-coding-agent/README.md +3 -2
  211. package/packages/pi-coding-agent/dist/core/session-manager-context.d.ts +9 -0
  212. package/packages/pi-coding-agent/dist/core/session-manager-context.d.ts.map +1 -0
  213. package/packages/pi-coding-agent/dist/core/session-manager-context.js +94 -0
  214. package/packages/pi-coding-agent/dist/core/session-manager-context.js.map +1 -0
  215. package/packages/pi-coding-agent/dist/core/session-manager-list.d.ts +8 -0
  216. package/packages/pi-coding-agent/dist/core/session-manager-list.d.ts.map +1 -0
  217. package/packages/pi-coding-agent/dist/core/session-manager-list.js +244 -0
  218. package/packages/pi-coding-agent/dist/core/session-manager-list.js.map +1 -0
  219. package/packages/pi-coding-agent/dist/core/session-manager-migration.d.ts +12 -0
  220. package/packages/pi-coding-agent/dist/core/session-manager-migration.d.ts.map +1 -0
  221. package/packages/pi-coding-agent/dist/core/session-manager-migration.js +84 -0
  222. package/packages/pi-coding-agent/dist/core/session-manager-migration.js.map +1 -0
  223. package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts +135 -0
  224. package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts.map +1 -0
  225. package/packages/pi-coding-agent/dist/core/session-manager-types.js +2 -0
  226. package/packages/pi-coding-agent/dist/core/session-manager-types.js.map +1 -0
  227. package/packages/pi-coding-agent/dist/core/session-manager.d.ts +6 -154
  228. package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
  229. package/packages/pi-coding-agent/dist/core/session-manager.js +22 -459
  230. package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
  231. package/packages/pi-coding-agent/dist/theme/theme-schema.d.ts +75 -75
  232. package/packages/pi-coding-agent/dist/theme/theme-schema.d.ts.map +1 -1
  233. package/packages/pi-coding-agent/dist/theme/theme-schema.js +1 -1
  234. package/packages/pi-coding-agent/dist/theme/theme-schema.js.map +1 -1
  235. package/packages/pi-coding-agent/dist/theme/theme.d.ts.map +1 -1
  236. package/packages/pi-coding-agent/dist/theme/theme.js +11 -7
  237. package/packages/pi-coding-agent/dist/theme/theme.js.map +1 -1
  238. package/packages/pi-coding-agent/package.json +7 -7
  239. package/packages/pi-tui/package.json +2 -2
  240. package/packages/rpc-client/package.json +2 -2
  241. package/pkg/dist/theme/theme-schema.d.ts +75 -75
  242. package/pkg/dist/theme/theme-schema.d.ts.map +1 -1
  243. package/pkg/dist/theme/theme-schema.js +1 -1
  244. package/pkg/dist/theme/theme-schema.js.map +1 -1
  245. package/pkg/dist/theme/theme.d.ts.map +1 -1
  246. package/pkg/dist/theme/theme.js +11 -7
  247. package/pkg/dist/theme/theme.js.map +1 -1
  248. package/pkg/package.json +1 -1
  249. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +20 -2
  250. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +80 -0
  251. package/src/resources/extensions/google-cli/stream-adapter.ts +106 -19
  252. package/src/resources/extensions/gsd/artifact-verification.ts +464 -0
  253. package/src/resources/extensions/gsd/auto/orchestrator.ts +25 -11
  254. package/src/resources/extensions/gsd/auto/session.ts +5 -0
  255. package/src/resources/extensions/gsd/auto-artifact-paths.ts +47 -1
  256. package/src/resources/extensions/gsd/auto-dispatch.ts +21 -23
  257. package/src/resources/extensions/gsd/auto-prompts.ts +38 -12
  258. package/src/resources/extensions/gsd/auto-recovery.ts +10 -508
  259. package/src/resources/extensions/gsd/auto-runtime-state.ts +4 -5
  260. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +3 -2
  261. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +125 -12
  262. package/src/resources/extensions/gsd/bootstrap/core-session-tools.ts +43 -0
  263. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +6 -1
  264. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +2 -0
  265. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +11 -19
  266. package/src/resources/extensions/gsd/bootstrap/system-context.ts +52 -18
  267. package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +74 -10
  268. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +1 -1
  269. package/src/resources/extensions/gsd/commands-context.ts +18 -1
  270. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +14 -9
  271. package/src/resources/extensions/gsd/commands-worktree.ts +12 -10
  272. package/src/resources/extensions/gsd/dashboard-overlay.ts +32 -3
  273. package/src/resources/extensions/gsd/db/queries.ts +79 -0
  274. package/src/resources/extensions/gsd/db-workspace.ts +61 -3
  275. package/src/resources/extensions/gsd/doctor-providers.ts +103 -9
  276. package/src/resources/extensions/gsd/exec-sandbox.ts +49 -9
  277. package/src/resources/extensions/gsd/forensics.ts +2 -33
  278. package/src/resources/extensions/gsd/git-service.ts +5 -5
  279. package/src/resources/extensions/gsd/guided-flow-queue.ts +89 -4
  280. package/src/resources/extensions/gsd/health-widget.ts +69 -32
  281. package/src/resources/extensions/gsd/layout-policy.ts +2 -1
  282. package/src/resources/extensions/gsd/markdown-renderer.ts +8 -11
  283. package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +51 -19
  284. package/src/resources/extensions/gsd/migration-auto-check.ts +23 -0
  285. package/src/resources/extensions/gsd/milestone-ids.ts +31 -2
  286. package/src/resources/extensions/gsd/milestone-implementation-evidence.ts +35 -21
  287. package/src/resources/extensions/gsd/prompts/code-review.md +6 -4
  288. package/src/resources/extensions/gsd/quick.ts +43 -2
  289. package/src/resources/extensions/gsd/session-forensics.ts +11 -1
  290. package/src/resources/extensions/gsd/skills/gsd-headless/references/commands.md +1 -1
  291. package/src/resources/extensions/gsd/state/derive/cache.ts +46 -0
  292. package/src/resources/extensions/gsd/state/derive/db-open.ts +45 -0
  293. package/src/resources/extensions/gsd/state/derive/from-db.ts +561 -0
  294. package/src/resources/extensions/gsd/state/derive/index.ts +104 -0
  295. package/src/resources/extensions/gsd/state/derive/interrupted-work.ts +31 -0
  296. package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +81 -7
  297. package/src/resources/extensions/gsd/state-reconciliation/index.ts +50 -24
  298. package/src/resources/extensions/gsd/state-reconciliation/registry.ts +43 -28
  299. package/src/resources/extensions/gsd/state.ts +32 -732
  300. package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +98 -1
  301. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +111 -1
  302. package/src/resources/extensions/gsd/tests/commands-context.test.ts +26 -0
  303. package/src/resources/extensions/gsd/tests/commands-gsd-core.test.ts +1 -0
  304. package/src/resources/extensions/gsd/tests/commands-worktree-clean.test.ts +80 -0
  305. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +11 -0
  306. package/src/resources/extensions/gsd/tests/complete-task-rollback-evidence.test.ts +48 -8
  307. package/src/resources/extensions/gsd/tests/complete-task.test.ts +75 -0
  308. package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +55 -2
  309. package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +26 -1
  310. package/src/resources/extensions/gsd/tests/doctor-forensics-db-open-regression.test.ts +70 -2
  311. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +107 -0
  312. package/src/resources/extensions/gsd/tests/exec-graceful-kill.test.ts +38 -0
  313. package/src/resources/extensions/gsd/tests/exec-tool.test.ts +45 -1
  314. package/src/resources/extensions/gsd/tests/forensics-error-filter.test.ts +88 -0
  315. package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +42 -0
  316. package/src/resources/extensions/gsd/tests/health-widget.test.ts +268 -3
  317. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +119 -1
  318. package/src/resources/extensions/gsd/tests/integration/queue-active-milestone-context-budget.test.ts +93 -0
  319. package/src/resources/extensions/gsd/tests/integration/quick-branch-lifecycle.test.ts +56 -9
  320. package/src/resources/extensions/gsd/tests/knowledge-cold-start.test.ts +14 -0
  321. package/src/resources/extensions/gsd/tests/memory-consolidation-scanner.test.ts +78 -0
  322. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +70 -0
  323. package/src/resources/extensions/gsd/tests/orchestrator-logs.test.ts +43 -1
  324. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +26 -0
  325. package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +2 -1
  326. package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +1 -1
  327. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +54 -1
  328. package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +50 -14
  329. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +195 -1
  330. package/src/resources/extensions/gsd/tests/read-uat-gate-verdict.test.ts +185 -0
  331. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +87 -0
  332. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +7 -0
  333. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +56 -0
  334. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +191 -0
  335. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +151 -0
  336. package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +26 -0
  337. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +193 -14
  338. package/src/resources/extensions/gsd/tests/unmerged-milestone-guard.test.ts +25 -0
  339. package/src/resources/extensions/gsd/tests/validation-block-guard.test.ts +79 -0
  340. package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +66 -0
  341. package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +151 -2
  342. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +39 -0
  343. package/src/resources/extensions/gsd/tools/complete-slice.ts +2 -2
  344. package/src/resources/extensions/gsd/tools/complete-task.ts +53 -15
  345. package/src/resources/extensions/gsd/tools/exec-tool.ts +7 -3
  346. package/src/resources/extensions/gsd/unit-context-composer.ts +33 -7
  347. package/src/resources/extensions/gsd/unit-registry.ts +32 -4
  348. package/src/resources/extensions/gsd/unmerged-milestone-guard.ts +41 -5
  349. package/src/resources/extensions/gsd/validation-block-guard.ts +13 -7
  350. package/src/resources/extensions/gsd/workflow-projections.ts +20 -14
  351. package/src/resources/extensions/gsd/workspace-git-preflight.ts +31 -0
  352. package/src/resources/extensions/gsd/worktree-manager.ts +41 -1
  353. package/dist/web/standalone/.next/static/chunks/2772.bfa657f49f955239.js +0 -1
  354. package/dist/web/standalone/.next/static/chunks/796.e0bdc932325d7e03.js +0 -10
  355. package/dist/web/standalone/.next/static/chunks/webpack-f46ea08200a0227e.js +0 -1
  356. /package/dist/web/standalone/.next/static/{BTKtGFF1Y-hvVJEGhBRo9 → O7xDYXO0r4zFhIzY1hrWV}/_buildManifest.js +0 -0
  357. /package/dist/web/standalone/.next/static/{BTKtGFF1Y-hvVJEGhBRo9 → O7xDYXO0r4zFhIzY1hrWV}/_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,
@@ -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,454 +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
- if (artifactBase !== base) {
541
- const projectRoot = resolve(resolveWorktreeProjectRoot(artifactBase));
542
- if (projectRoot && projectRoot !== artifactBase) {
543
- if (!absPath || !existsSync(absPath)) {
544
- const projectPath = resolveExpectedArtifactPath(unitType, unitId, projectRoot);
545
- if (projectPath && existsSync(projectPath)) {
546
- absPath = projectPath;
547
- }
548
- }
549
- }
550
- }
551
- // For unit types with no registered artifact contract (null path), treat the
552
- // completion state as stale so the key gets evicted (#313).
553
- if (!absPath) {
554
- logWarning("recovery", `verify-fail ${unitType} ${unitId}: resolveExpectedArtifactPath returned null (no artifact contract registered for this unit type)`);
555
- return false;
556
- }
557
- if (!existsSync(absPath)) {
558
- const worktreeFailure = diagnoseWorktreeIntegrityFailure(artifactBase);
559
- if (worktreeFailure) {
560
- logError("recovery", `${worktreeFailure} Unit: ${unitType} ${unitId}.`);
561
- return false;
562
- }
563
- logWarning("recovery", `verify-fail ${unitType} ${unitId}: existsSync false for ${absPath}`);
564
- return false;
565
- }
566
-
567
- if (unitType === "validate-milestone") {
568
- const validationContent = readFileSync(absPath, "utf-8");
569
- if (!isValidationTerminal(validationContent)) {
570
- logWarning("recovery", `verify-fail ${unitType} ${unitId}: validation not terminal (len=${validationContent.length}) at ${absPath}`);
571
- return false;
572
- }
573
- }
574
-
575
- if (unitType === "run-uat") {
576
- const assessmentContent = readFileSync(absPath, "utf-8");
577
- if (!hasVerdict(assessmentContent)) {
578
- logWarning("recovery", `verify-fail ${unitType} ${unitId}: assessment missing verdict at ${absPath}`);
579
- return false;
580
- }
581
- }
582
-
583
- if (unitType === "plan-milestone") {
584
- try {
585
- const roadmap = parseRoadmapForRecovery(readFileSync(absPath, "utf-8"));
586
- if (roadmap.slices.length === 0) {
587
- logWarning("recovery", `verify-fail ${unitType} ${unitId}: roadmap has zero slices at ${absPath}`);
588
- return false;
589
- }
590
- } catch (err) {
591
- logWarning("recovery", `plan-milestone roadmap verification failed: ${err instanceof Error ? err.message : String(err)}`);
592
- return false;
593
- }
594
- }
595
-
596
- // plan-slice verification is DB-primary. The slice plan is a projection, so
597
- // DB task rows prove the slice was planned even if the rendered markdown no
598
- // longer uses legacy checkbox/heading syntax.
599
- if (unitType === "plan-slice") {
600
- const { milestone: mid, slice: sid } = parseUnitId(unitId);
601
- if (mid && sid) {
602
- try {
603
- let taskIds: string[] | null = null;
604
- let dbPrimary = false;
605
- if (isDbAvailable()) {
606
- const refreshed = refreshWorkflowDatabaseFromDisk();
607
- if (refreshed) {
608
- const tasks = getSliceTasks(mid, sid);
609
- if (tasks.length > 0) {
610
- taskIds = tasks.map(t => t.id);
611
- dbPrimary = true;
612
- }
613
- }
614
- }
615
-
616
- if (!taskIds) {
617
- // LEGACY: DB unavailable or no tasks in DB. Require actual task
618
- // entries so an empty scaffold cannot advance the pipeline (#699).
619
- const planContent = readFileSync(absPath, "utf-8");
620
- const hasCheckboxTask = /^\s*- \[[xX ]\] \*\*T\d+/m.test(planContent);
621
- const hasHeadingTask = /^\s*#{2,4}\s+T\d+\s*(?:--|—|:)/m.test(planContent);
622
- if (!hasCheckboxTask && !hasHeadingTask) {
623
- logWarning("recovery", `verify-fail ${unitType} ${unitId}: plan has no task checkbox/heading (len=${planContent.length}) at ${absPath}`);
624
- return false;
625
- }
626
- const plan = parseLegacyPlan(planContent);
627
- if (plan.tasks.length > 0) taskIds = plan.tasks.map((t: { id: string }) => t.id);
628
- }
629
-
630
- // Per-task plan file check: applies when a tasks/ directory is present on
631
- // disk (legacy layout), regardless of whether DB is primary. Flat-phase
632
- // projects have no tasks/ dir, so the check is naturally skipped there.
633
- // When DB is NOT primary and there is no tasks/ dir either, the missing
634
- // dir itself is evidence of an incomplete plan (non-flat-phase projects must
635
- // have a tasks/ dir).
636
- if (taskIds && taskIds.length > 0) {
637
- const tasksDir = join(dirname(absPath), "tasks");
638
- if (existsSync(tasksDir)) {
639
- for (const tid of taskIds) {
640
- const taskPlanFile = join(tasksDir, `${tid}-PLAN.md`);
641
- if (!existsSync(taskPlanFile)) {
642
- logWarning("recovery", `verify-fail ${unitType} ${unitId}: task plan missing ${taskPlanFile}`);
643
- return false;
644
- }
645
- }
646
- } else if (!dbPrimary && !absPath.replace(/\\/g, "/").includes(`.gsd/${LAYOUT_SEGMENTS.level1}`)) {
647
- logWarning("recovery", `verify-fail ${unitType} ${unitId}: tasks dir missing at ${tasksDir}`);
648
- return false;
649
- }
650
- }
651
- } catch (err) {
652
- // Parse failure — don't block; slice plan may have non-standard format
653
- logWarning("recovery", `plan-slice task plan verification failed: ${err instanceof Error ? err.message : String(err)}`);
654
- }
655
- }
656
- }
657
-
658
- // execute-task: DB status is authoritative. Fall back to checked-checkbox
659
- // detection when the DB is unavailable (unmigrated projects), or when the
660
- // disk artifacts already reflect completion but the DB replay is one beat
661
- // behind the completion write.
662
- if (unitType === "execute-task") {
663
- const { milestone: mid, slice: sid, task: tid } = parseUnitId(unitId);
664
- if (mid && sid && tid) {
665
- const dbTask = getTask(mid, sid, tid);
666
- if (dbTask) {
667
- if (dbTask.status !== "complete" && dbTask.status !== "done" && !hasCheckedTaskCompletionOnDisk(base, mid, sid, tid)) {
668
- return false;
669
- }
670
- } else if (!isDbAvailable()) {
671
- // LEGACY: Pre-migration fallback for projects without DB.
672
- // Require a CHECKED checkbox — a bare heading or unchecked checkbox
673
- // does not prove gsd_complete_task ran. Summary file on disk alone
674
- // is not sufficient evidence (could be a rogue write) (#3607).
675
- if (!hasCheckedTaskCompletionOnDisk(base, mid, sid, tid)) return false;
676
- } else {
677
- // DB available but task row not found — completion tool never ran (#3607)
678
- return false;
679
- }
680
- }
681
- }
682
-
683
- // complete-slice: DB status is authoritative for whether the slice is done.
684
- // Fall back to file-based check (roadmap [x]) when DB is unavailable.
685
- if (unitType === "complete-slice") {
686
- const { milestone: mid, slice: sid } = parseUnitId(unitId);
687
- if (mid && sid) {
688
- // resolveSliceFile only finds existing files; UAT may not exist yet.
689
- // Fall back to the canonical expected location so a missing UAT always
690
- // returns false (not a silent pass when resolveSliceFile returns null).
691
- const uatPath = resolveSliceFile(base, mid, sid, "UAT")
692
- ?? join(base, relSliceFile(base, mid, sid, "UAT"));
693
- if (!existsSync(uatPath)) return false;
694
-
695
- const dbSlice = getSlice(mid, sid);
696
- if (dbSlice) {
697
- // DB available — trust it
698
- if (dbSlice.status !== "complete") return false;
699
- } else if (!isDbAvailable()) {
700
- // LEGACY: Pre-migration fallback for projects without DB.
701
- // Fall back to roadmap checkbox check via parsers-legacy
702
- const roadmapFile = resolveMilestoneFile(base, mid, "ROADMAP");
703
- if (roadmapFile && existsSync(roadmapFile)) {
704
- try {
705
- const roadmapContent = readFileSync(roadmapFile, "utf-8");
706
- const roadmap = parseRoadmapForRecovery(roadmapContent);
707
- const slice = roadmap.slices.find((s) => s.id === sid);
708
- if (slice && !slice.done) return false;
709
- } catch (e) {
710
- logWarning("recovery", `roadmap parse failed: ${(e as Error).message}`);
711
- return false;
712
- }
713
- }
714
- }
715
- // else: DB available but slice not found — summary + UAT exist,
716
- // treat as verified (slice may not be imported yet)
717
- }
718
- }
719
-
720
- // complete-milestone must have produced implementation artifacts (#1703).
721
- // A milestone with only .gsd/ plan files and zero implementation code is
722
- // not genuinely complete — the LLM wrote plan files but skipped actual work.
723
- if (unitType === "complete-milestone") {
724
- const { milestone: mid } = parseUnitId(unitId);
725
- if (!mid) return false;
726
- const closeoutProof = proveMilestoneCloseout(mid, {
727
- refreshFromDisk: true,
728
- summaryArtifactBasePath: artifactBase,
729
- implementationEvidence: {
730
- basePath: base,
731
- requirement: "not-absent",
732
- },
733
- });
734
- if (!closeoutProof.ok) {
735
- if (!isDbAvailable() && closeoutProof.reason === "db-unavailable") {
736
- const summaryOutcome = classifyMilestoneSummaryContent(readFileSync(absPath, "utf-8"));
737
- return summaryOutcome !== "failure" && hasImplementationArtifacts(base, mid) !== "absent";
738
- }
739
- return false;
740
- }
741
- }
742
-
743
- return true;
744
- }
745
-
746
248
  export interface ReactiveExecuteBlockerRecovery {
747
249
  blockerPath: string;
748
250
  completedTaskIds: string[];
@@ -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,