@opengsd/gsd-pi 1.3.0-dev.65546769 → 1.3.0-dev.738160b9

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 (488) hide show
  1. package/README.md +1 -1
  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/claude-code-cli/stream-adapter.js +11 -2
  10. package/dist/resources/extensions/google-cli/stream-adapter.js +82 -15
  11. package/dist/resources/extensions/gsd/artifact-verification.js +427 -0
  12. package/dist/resources/extensions/gsd/auto/orchestrator.js +12 -3
  13. package/dist/resources/extensions/gsd/auto/session.js +11 -0
  14. package/dist/resources/extensions/gsd/auto/verification-retry-policy.js +1 -1
  15. package/dist/resources/extensions/gsd/auto-artifact-paths.js +28 -1
  16. package/dist/resources/extensions/gsd/auto-budget.js +5 -1
  17. package/dist/resources/extensions/gsd/auto-dispatch.js +34 -20
  18. package/dist/resources/extensions/gsd/auto-post-unit.js +1 -1
  19. package/dist/resources/extensions/gsd/auto-prompts.js +29 -14
  20. package/dist/resources/extensions/gsd/auto-recovery.js +9 -510
  21. package/dist/resources/extensions/gsd/auto-runtime-state.js +4 -5
  22. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +3 -3
  23. package/dist/resources/extensions/gsd/auto-verification.js +5 -2
  24. package/dist/resources/extensions/gsd/auto.js +19 -10
  25. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +103 -13
  26. package/dist/resources/extensions/gsd/bootstrap/core-session-tools.js +39 -0
  27. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +11 -5
  28. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +2 -0
  29. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +2 -0
  30. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +41 -21
  31. package/dist/resources/extensions/gsd/bootstrap/system-context.js +46 -19
  32. package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +96 -10
  33. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +1 -1
  34. package/dist/resources/extensions/gsd/closeout-consistency-gate.js +3 -1
  35. package/dist/resources/extensions/gsd/commands/handlers/auto.js +1 -1
  36. package/dist/resources/extensions/gsd/commands-context.js +19 -1
  37. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +17 -11
  38. package/dist/resources/extensions/gsd/commands-usage.js +1 -1
  39. package/dist/resources/extensions/gsd/commands-worktree.js +12 -10
  40. package/dist/resources/extensions/gsd/dashboard-overlay.js +32 -3
  41. package/dist/resources/extensions/gsd/db/engine.js +4 -1
  42. package/dist/resources/extensions/gsd/db/queries.js +60 -0
  43. package/dist/resources/extensions/gsd/db-memory-fts-schema.js +34 -0
  44. package/dist/resources/extensions/gsd/db-workspace.js +55 -3
  45. package/dist/resources/extensions/gsd/delegation-policy.js +1 -1
  46. package/dist/resources/extensions/gsd/docs/preferences-reference.md +2 -2
  47. package/dist/resources/extensions/gsd/doctor-engine-checks.js +192 -4
  48. package/dist/resources/extensions/gsd/doctor-providers.js +92 -8
  49. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +3 -0
  50. package/dist/resources/extensions/gsd/exec-sandbox.js +53 -11
  51. package/dist/resources/extensions/gsd/flat-phase-migration.js +45 -0
  52. package/dist/resources/extensions/gsd/forensics.js +2 -32
  53. package/dist/resources/extensions/gsd/git-service.js +61 -4
  54. package/dist/resources/extensions/gsd/gitignore.js +4 -1
  55. package/dist/resources/extensions/gsd/guided-flow-queue.js +66 -5
  56. package/dist/resources/extensions/gsd/health-widget.js +55 -29
  57. package/dist/resources/extensions/gsd/json-persistence.js +20 -0
  58. package/dist/resources/extensions/gsd/knowledge-backfill.js +18 -11
  59. package/dist/resources/extensions/gsd/layout-policy.js +3 -1
  60. package/dist/resources/extensions/gsd/markdown-renderer.js +8 -9
  61. package/dist/resources/extensions/gsd/memory-backfill.js +28 -21
  62. package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +44 -21
  63. package/dist/resources/extensions/gsd/metrics.js +4 -4
  64. package/dist/resources/extensions/gsd/migrate-external.js +11 -2
  65. package/dist/resources/extensions/gsd/migration-auto-check.js +22 -0
  66. package/dist/resources/extensions/gsd/milestone-ids.js +32 -2
  67. package/dist/resources/extensions/gsd/milestone-implementation-evidence.js +26 -20
  68. package/dist/resources/extensions/gsd/orphan-stash-audit.js +92 -16
  69. package/dist/resources/extensions/gsd/prompts/code-review.md +6 -4
  70. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +2 -2
  71. package/dist/resources/extensions/gsd/prompts/plan-slice.md +3 -3
  72. package/dist/resources/extensions/gsd/quick.js +45 -2
  73. package/dist/resources/extensions/gsd/root-write-leak-guard.js +7 -1
  74. package/dist/resources/extensions/gsd/safety/destructive-guard.js +8 -1
  75. package/dist/resources/extensions/gsd/safety/evidence-collector.js +16 -1
  76. package/dist/resources/extensions/gsd/safety/file-change-validator.js +5 -2
  77. package/dist/resources/extensions/gsd/session-forensics.js +11 -1
  78. package/dist/resources/extensions/gsd/skills/gsd-headless/references/commands.md +1 -1
  79. package/dist/resources/extensions/gsd/state/derive/cache.js +28 -0
  80. package/dist/resources/extensions/gsd/state/derive/db-open.js +39 -0
  81. package/dist/resources/extensions/gsd/state/derive/from-db.js +452 -0
  82. package/dist/resources/extensions/gsd/state/derive/index.js +75 -0
  83. package/dist/resources/extensions/gsd/state/derive/interrupted-work.js +21 -0
  84. package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-render.js +45 -2
  85. package/dist/resources/extensions/gsd/state-reconciliation/index.js +48 -23
  86. package/dist/resources/extensions/gsd/state-reconciliation/registry.js +32 -28
  87. package/dist/resources/extensions/gsd/state.js +12 -611
  88. package/dist/resources/extensions/gsd/tools/complete-milestone.js +4 -2
  89. package/dist/resources/extensions/gsd/tools/complete-slice.js +2 -2
  90. package/dist/resources/extensions/gsd/tools/complete-task.js +43 -14
  91. package/dist/resources/extensions/gsd/tools/exec-tool.js +7 -2
  92. package/dist/resources/extensions/gsd/tools/plan-slice.js +59 -44
  93. package/dist/resources/extensions/gsd/tools/plan-task.js +28 -5
  94. package/dist/resources/extensions/gsd/undo.js +43 -6
  95. package/dist/resources/extensions/gsd/unit-context-composer.js +23 -7
  96. package/dist/resources/extensions/gsd/unit-registry.js +36 -6
  97. package/dist/resources/extensions/gsd/unmerged-milestone-guard.js +33 -3
  98. package/dist/resources/extensions/gsd/validation-block-guard.js +9 -4
  99. package/dist/resources/extensions/gsd/verification-gate.js +7 -0
  100. package/dist/resources/extensions/gsd/workflow-manifest.js +126 -13
  101. package/dist/resources/extensions/gsd/workflow-projections.js +19 -14
  102. package/dist/resources/extensions/gsd/workspace-git-preflight.js +30 -1
  103. package/dist/resources/extensions/gsd/worktree-manager.js +44 -2
  104. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  105. package/dist/web/standalone/.next/BUILD_ID +1 -1
  106. package/dist/web/standalone/.next/app-path-routes-manifest.json +10 -10
  107. package/dist/web/standalone/.next/build-manifest.json +3 -3
  108. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  109. package/dist/web/standalone/.next/react-loadable-manifest.json +9 -9
  110. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  111. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  112. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  120. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  121. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  122. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  128. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  129. package/dist/web/standalone/.next/server/app/index.html +1 -1
  130. package/dist/web/standalone/.next/server/app/index.rsc +2 -2
  131. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  132. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
  133. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  134. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  135. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  136. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app-paths-manifest.json +10 -10
  138. package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
  139. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  140. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  142. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  143. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  144. package/dist/web/standalone/.next/static/chunks/{2659.b7b129ee6a769448.js → 2659.58e950899a9bb82f.js} +1 -1
  145. package/dist/web/standalone/.next/static/chunks/2772.a7c1fcc69a4685ef.js +1 -0
  146. package/dist/web/standalone/.next/static/chunks/{3616.3c60753b8ffcbd2e.js → 3616.61a2af74bb8833c8.js} +1 -1
  147. package/dist/web/standalone/.next/static/chunks/{4283.8e446784528ed9dc.js → 4283.d0d9e0a955e441cb.js} +1 -1
  148. package/dist/web/standalone/.next/static/chunks/{5826.a46ecdd1cfe8dabc.js → 5826.5421d66c72b9f34e.js} +1 -1
  149. package/dist/web/standalone/.next/static/chunks/{8785.481aa5869991b760.js → 8785.e29b3134cab1d153.js} +1 -1
  150. package/dist/web/standalone/.next/static/chunks/8937.640dc9c2aaa1dfad.js +10 -0
  151. package/dist/web/standalone/.next/static/chunks/app/{page-6644fc6ee8ca1247.js → page-72a856634ad14c10.js} +1 -1
  152. package/dist/web/standalone/.next/static/chunks/webpack-9c401904f87ded16.js +1 -0
  153. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  154. package/package.json +1 -1
  155. package/packages/cloud-mcp-gateway/package.json +2 -2
  156. package/packages/contracts/dist/workflow.d.ts +1 -0
  157. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  158. package/packages/contracts/dist/workflow.js +2 -0
  159. package/packages/contracts/dist/workflow.js.map +1 -1
  160. package/packages/contracts/package.json +1 -1
  161. package/packages/daemon/package.json +4 -4
  162. package/packages/gsd-agent-core/dist/agent-session.d.ts +1 -0
  163. package/packages/gsd-agent-core/dist/agent-session.d.ts.map +1 -1
  164. package/packages/gsd-agent-core/dist/agent-session.js +3 -0
  165. package/packages/gsd-agent-core/dist/agent-session.js.map +1 -1
  166. package/packages/gsd-agent-core/dist/extension-ui-snapshot.d.ts +41 -0
  167. package/packages/gsd-agent-core/dist/extension-ui-snapshot.d.ts.map +1 -0
  168. package/packages/gsd-agent-core/dist/extension-ui-snapshot.js +62 -0
  169. package/packages/gsd-agent-core/dist/extension-ui-snapshot.js.map +1 -0
  170. package/packages/gsd-agent-core/dist/index.d.ts +2 -0
  171. package/packages/gsd-agent-core/dist/index.d.ts.map +1 -1
  172. package/packages/gsd-agent-core/dist/index.js +2 -0
  173. package/packages/gsd-agent-core/dist/index.js.map +1 -1
  174. package/packages/gsd-agent-core/dist/session/agent-session-events.js +1 -1
  175. package/packages/gsd-agent-core/dist/session/agent-session-events.js.map +1 -1
  176. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts +1 -0
  177. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts.map +1 -1
  178. package/packages/gsd-agent-core/dist/session/agent-session-host.js.map +1 -1
  179. package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts +5 -0
  180. package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts.map +1 -1
  181. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js +60 -3
  182. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js.map +1 -1
  183. package/packages/gsd-agent-core/dist/transcript-store.d.ts +58 -0
  184. package/packages/gsd-agent-core/dist/transcript-store.d.ts.map +1 -0
  185. package/packages/gsd-agent-core/dist/transcript-store.js +132 -0
  186. package/packages/gsd-agent-core/dist/transcript-store.js.map +1 -0
  187. package/packages/gsd-agent-core/package.json +5 -5
  188. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +2 -0
  189. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  190. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +25 -11
  191. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  192. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.d.ts +4 -0
  193. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.d.ts.map +1 -0
  194. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.js +7 -0
  195. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.js.map +1 -0
  196. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts +3 -24
  197. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  198. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +26 -829
  199. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  200. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.d.ts +58 -0
  201. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.d.ts.map +1 -0
  202. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.js +312 -0
  203. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.js.map +1 -0
  204. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.d.ts +31 -0
  205. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.d.ts.map +1 -0
  206. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.js +130 -0
  207. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.js.map +1 -0
  208. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts +15 -0
  209. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts.map +1 -0
  210. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js +258 -0
  211. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js.map +1 -0
  212. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.d.ts +13 -0
  213. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.d.ts.map +1 -0
  214. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.js +118 -0
  215. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.js.map +1 -0
  216. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts +9 -0
  217. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  218. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.js +1 -1
  219. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  220. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.d.ts +54 -0
  221. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.d.ts.map +1 -0
  222. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.js +20 -0
  223. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.js.map +1 -0
  224. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts +4 -1
  225. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  226. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +9 -0
  227. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
  228. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.d.ts +56 -0
  229. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.d.ts.map +1 -0
  230. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.js +44 -0
  231. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.js.map +1 -0
  232. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.d.ts +5 -0
  233. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.d.ts.map +1 -0
  234. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.js +77 -0
  235. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.js.map +1 -0
  236. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.d.ts +2 -0
  237. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  238. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.js +23 -5
  239. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.js.map +1 -1
  240. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  241. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +18 -0
  242. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
  243. package/packages/gsd-agent-modes/package.json +7 -7
  244. package/packages/mcp-server/README.md +1 -1
  245. package/packages/mcp-server/dist/server.d.ts +1 -1
  246. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  247. package/packages/mcp-server/dist/server.js +3 -3
  248. package/packages/mcp-server/dist/server.js.map +1 -1
  249. package/packages/mcp-server/dist/workflow-tools.d.ts +13 -1
  250. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  251. package/packages/mcp-server/dist/workflow-tools.js +35 -21
  252. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  253. package/packages/mcp-server/package.json +4 -4
  254. package/packages/native/package.json +1 -1
  255. package/packages/pi-agent-core/dist/agent-loop.js +3 -2
  256. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  257. package/packages/pi-agent-core/package.json +1 -1
  258. package/packages/pi-ai/dist/models.generated.d.ts +46 -0
  259. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  260. package/packages/pi-ai/dist/models.generated.js +38 -0
  261. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  262. package/packages/pi-ai/package.json +1 -1
  263. package/packages/pi-coding-agent/README.md +3 -2
  264. package/packages/pi-coding-agent/dist/core/session-manager-context.d.ts +9 -0
  265. package/packages/pi-coding-agent/dist/core/session-manager-context.d.ts.map +1 -0
  266. package/packages/pi-coding-agent/dist/core/session-manager-context.js +94 -0
  267. package/packages/pi-coding-agent/dist/core/session-manager-context.js.map +1 -0
  268. package/packages/pi-coding-agent/dist/core/session-manager-list.d.ts +8 -0
  269. package/packages/pi-coding-agent/dist/core/session-manager-list.d.ts.map +1 -0
  270. package/packages/pi-coding-agent/dist/core/session-manager-list.js +244 -0
  271. package/packages/pi-coding-agent/dist/core/session-manager-list.js.map +1 -0
  272. package/packages/pi-coding-agent/dist/core/session-manager-migration.d.ts +12 -0
  273. package/packages/pi-coding-agent/dist/core/session-manager-migration.d.ts.map +1 -0
  274. package/packages/pi-coding-agent/dist/core/session-manager-migration.js +84 -0
  275. package/packages/pi-coding-agent/dist/core/session-manager-migration.js.map +1 -0
  276. package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts +135 -0
  277. package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts.map +1 -0
  278. package/packages/pi-coding-agent/dist/core/session-manager-types.js +2 -0
  279. package/packages/pi-coding-agent/dist/core/session-manager-types.js.map +1 -0
  280. package/packages/pi-coding-agent/dist/core/session-manager.d.ts +6 -154
  281. package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
  282. package/packages/pi-coding-agent/dist/core/session-manager.js +22 -459
  283. package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
  284. package/packages/pi-coding-agent/dist/theme/theme-schema.d.ts +75 -75
  285. package/packages/pi-coding-agent/dist/theme/theme-schema.d.ts.map +1 -1
  286. package/packages/pi-coding-agent/dist/theme/theme-schema.js +1 -1
  287. package/packages/pi-coding-agent/dist/theme/theme-schema.js.map +1 -1
  288. package/packages/pi-coding-agent/dist/theme/theme.d.ts.map +1 -1
  289. package/packages/pi-coding-agent/dist/theme/theme.js +11 -7
  290. package/packages/pi-coding-agent/dist/theme/theme.js.map +1 -1
  291. package/packages/pi-coding-agent/package.json +7 -7
  292. package/packages/pi-tui/package.json +2 -2
  293. package/packages/rpc-client/package.json +2 -2
  294. package/pkg/dist/theme/theme-schema.d.ts +75 -75
  295. package/pkg/dist/theme/theme-schema.d.ts.map +1 -1
  296. package/pkg/dist/theme/theme-schema.js +1 -1
  297. package/pkg/dist/theme/theme-schema.js.map +1 -1
  298. package/pkg/dist/theme/theme.d.ts.map +1 -1
  299. package/pkg/dist/theme/theme.js +11 -7
  300. package/pkg/dist/theme/theme.js.map +1 -1
  301. package/pkg/package.json +1 -1
  302. package/src/resources/extensions/claude-code-cli/models.ts +9 -0
  303. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +20 -2
  304. package/src/resources/extensions/claude-code-cli/tests/index.test.ts +14 -0
  305. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +80 -0
  306. package/src/resources/extensions/google-cli/stream-adapter.ts +106 -19
  307. package/src/resources/extensions/gsd/artifact-verification.ts +464 -0
  308. package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
  309. package/src/resources/extensions/gsd/auto/orchestrator.ts +25 -11
  310. package/src/resources/extensions/gsd/auto/session.ts +14 -0
  311. package/src/resources/extensions/gsd/auto/verification-retry-policy.ts +3 -1
  312. package/src/resources/extensions/gsd/auto-artifact-paths.ts +47 -1
  313. package/src/resources/extensions/gsd/auto-budget.ts +12 -1
  314. package/src/resources/extensions/gsd/auto-dispatch.ts +35 -24
  315. package/src/resources/extensions/gsd/auto-post-unit.ts +1 -1
  316. package/src/resources/extensions/gsd/auto-prompts.ts +41 -15
  317. package/src/resources/extensions/gsd/auto-recovery.ts +13 -511
  318. package/src/resources/extensions/gsd/auto-runtime-state.ts +4 -5
  319. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +3 -2
  320. package/src/resources/extensions/gsd/auto-verification.ts +5 -1
  321. package/src/resources/extensions/gsd/auto.ts +23 -8
  322. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +125 -12
  323. package/src/resources/extensions/gsd/bootstrap/core-session-tools.ts +44 -0
  324. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +11 -5
  325. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +2 -0
  326. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +2 -0
  327. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +52 -21
  328. package/src/resources/extensions/gsd/bootstrap/system-context.ts +52 -18
  329. package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +104 -10
  330. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +1 -1
  331. package/src/resources/extensions/gsd/closeout-consistency-gate.ts +2 -1
  332. package/src/resources/extensions/gsd/commands/handlers/auto.ts +1 -1
  333. package/src/resources/extensions/gsd/commands-context.ts +18 -1
  334. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +15 -10
  335. package/src/resources/extensions/gsd/commands-usage.ts +1 -1
  336. package/src/resources/extensions/gsd/commands-worktree.ts +12 -10
  337. package/src/resources/extensions/gsd/dashboard-overlay.ts +32 -3
  338. package/src/resources/extensions/gsd/db/engine.ts +8 -1
  339. package/src/resources/extensions/gsd/db/queries.ts +79 -0
  340. package/src/resources/extensions/gsd/db-memory-fts-schema.ts +45 -0
  341. package/src/resources/extensions/gsd/db-workspace.ts +61 -3
  342. package/src/resources/extensions/gsd/delegation-policy.ts +1 -1
  343. package/src/resources/extensions/gsd/docs/preferences-reference.md +2 -2
  344. package/src/resources/extensions/gsd/doctor-engine-checks.ts +233 -5
  345. package/src/resources/extensions/gsd/doctor-providers.ts +103 -9
  346. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +3 -0
  347. package/src/resources/extensions/gsd/doctor-types.ts +3 -0
  348. package/src/resources/extensions/gsd/exec-sandbox.ts +56 -11
  349. package/src/resources/extensions/gsd/flat-phase-migration.ts +44 -0
  350. package/src/resources/extensions/gsd/forensics.ts +2 -33
  351. package/src/resources/extensions/gsd/git-service.ts +69 -5
  352. package/src/resources/extensions/gsd/gitignore.ts +4 -1
  353. package/src/resources/extensions/gsd/guided-flow-queue.ts +89 -4
  354. package/src/resources/extensions/gsd/health-widget.ts +69 -32
  355. package/src/resources/extensions/gsd/json-persistence.ts +20 -0
  356. package/src/resources/extensions/gsd/knowledge-backfill.ts +16 -10
  357. package/src/resources/extensions/gsd/layout-policy.ts +2 -1
  358. package/src/resources/extensions/gsd/markdown-renderer.ts +8 -11
  359. package/src/resources/extensions/gsd/memory-backfill.ts +26 -20
  360. package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +51 -19
  361. package/src/resources/extensions/gsd/metrics.ts +4 -4
  362. package/src/resources/extensions/gsd/migrate-external.ts +8 -2
  363. package/src/resources/extensions/gsd/migration-auto-check.ts +23 -0
  364. package/src/resources/extensions/gsd/milestone-ids.ts +31 -2
  365. package/src/resources/extensions/gsd/milestone-implementation-evidence.ts +35 -21
  366. package/src/resources/extensions/gsd/orphan-stash-audit.ts +108 -20
  367. package/src/resources/extensions/gsd/prompts/code-review.md +6 -4
  368. package/src/resources/extensions/gsd/prompts/plan-milestone.md +2 -2
  369. package/src/resources/extensions/gsd/prompts/plan-slice.md +3 -3
  370. package/src/resources/extensions/gsd/quick.ts +43 -2
  371. package/src/resources/extensions/gsd/root-write-leak-guard.ts +13 -1
  372. package/src/resources/extensions/gsd/safety/destructive-guard.ts +9 -1
  373. package/src/resources/extensions/gsd/safety/evidence-collector.ts +16 -1
  374. package/src/resources/extensions/gsd/safety/file-change-validator.ts +8 -2
  375. package/src/resources/extensions/gsd/session-forensics.ts +11 -1
  376. package/src/resources/extensions/gsd/skills/gsd-headless/references/commands.md +1 -1
  377. package/src/resources/extensions/gsd/state/derive/cache.ts +46 -0
  378. package/src/resources/extensions/gsd/state/derive/db-open.ts +45 -0
  379. package/src/resources/extensions/gsd/state/derive/from-db.ts +561 -0
  380. package/src/resources/extensions/gsd/state/derive/index.ts +104 -0
  381. package/src/resources/extensions/gsd/state/derive/interrupted-work.ts +31 -0
  382. package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +81 -7
  383. package/src/resources/extensions/gsd/state-reconciliation/index.ts +50 -24
  384. package/src/resources/extensions/gsd/state-reconciliation/registry.ts +43 -28
  385. package/src/resources/extensions/gsd/state.ts +32 -732
  386. package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +4 -3
  387. package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +98 -1
  388. package/src/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +14 -5
  389. package/src/resources/extensions/gsd/tests/auto-pause-double-entry-guard.test.ts +36 -0
  390. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +182 -4
  391. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +146 -1
  392. package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +30 -0
  393. package/src/resources/extensions/gsd/tests/commands-context.test.ts +26 -0
  394. package/src/resources/extensions/gsd/tests/commands-gsd-core.test.ts +1 -0
  395. package/src/resources/extensions/gsd/tests/commands-worktree-clean.test.ts +80 -0
  396. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +28 -0
  397. package/src/resources/extensions/gsd/tests/complete-slice-reopen-handoff.test.ts +69 -0
  398. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +11 -0
  399. package/src/resources/extensions/gsd/tests/complete-task-rollback-evidence.test.ts +48 -8
  400. package/src/resources/extensions/gsd/tests/complete-task.test.ts +75 -0
  401. package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +55 -2
  402. package/src/resources/extensions/gsd/tests/db-memory-fts-schema.test.ts +58 -3
  403. package/src/resources/extensions/gsd/tests/decisions-projection-from-memories.test.ts +51 -0
  404. package/src/resources/extensions/gsd/tests/destructive-guard.test.ts +44 -0
  405. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +143 -0
  406. package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +26 -1
  407. package/src/resources/extensions/gsd/tests/doctor-forensics-db-open-regression.test.ts +70 -2
  408. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +107 -0
  409. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +239 -2
  410. package/src/resources/extensions/gsd/tests/exec-graceful-kill.test.ts +38 -0
  411. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +16 -0
  412. package/src/resources/extensions/gsd/tests/exec-tool.test.ts +45 -1
  413. package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +40 -0
  414. package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +37 -2
  415. package/src/resources/extensions/gsd/tests/forensics-error-filter.test.ts +88 -0
  416. package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +4 -0
  417. package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +42 -0
  418. package/src/resources/extensions/gsd/tests/health-widget.test.ts +268 -3
  419. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +130 -3
  420. package/src/resources/extensions/gsd/tests/integration/queue-active-milestone-context-budget.test.ts +93 -0
  421. package/src/resources/extensions/gsd/tests/integration/quick-branch-lifecycle.test.ts +56 -9
  422. package/src/resources/extensions/gsd/tests/json-persistence-atomic.test.ts +47 -0
  423. package/src/resources/extensions/gsd/tests/knowledge-backfill-projection.test.ts +35 -0
  424. package/src/resources/extensions/gsd/tests/knowledge-cold-start.test.ts +14 -0
  425. package/src/resources/extensions/gsd/tests/memory-consolidation-scanner.test.ts +78 -0
  426. package/src/resources/extensions/gsd/tests/memory-store.test.ts +48 -0
  427. package/src/resources/extensions/gsd/tests/merge-closeout-consistency-gate.test.ts +31 -1
  428. package/src/resources/extensions/gsd/tests/metrics-prune-cache-invalidation.test.ts +6 -0
  429. package/src/resources/extensions/gsd/tests/metrics.test.ts +1 -0
  430. package/src/resources/extensions/gsd/tests/migrate-external-worktree.test.ts +57 -0
  431. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +70 -0
  432. package/src/resources/extensions/gsd/tests/orchestrator-logs.test.ts +43 -1
  433. package/src/resources/extensions/gsd/tests/orphan-stash-audit.test.ts +91 -7
  434. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +26 -0
  435. package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +4 -1
  436. package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +1 -1
  437. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +10 -0
  438. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +103 -4
  439. package/src/resources/extensions/gsd/tests/plan-task.test.ts +44 -1
  440. package/src/resources/extensions/gsd/tests/post-mutation-hook.test.ts +4 -2
  441. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +54 -1
  442. package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +50 -14
  443. package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +58 -0
  444. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +8 -6
  445. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +195 -1
  446. package/src/resources/extensions/gsd/tests/read-uat-gate-verdict.test.ts +185 -0
  447. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +87 -0
  448. package/src/resources/extensions/gsd/tests/register-hooks-loop-guard-auto.test.ts +103 -0
  449. package/src/resources/extensions/gsd/tests/root-write-leak-guard.test.ts +20 -1
  450. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +15 -3
  451. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +56 -0
  452. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +191 -0
  453. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +208 -0
  454. package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +32 -3
  455. package/src/resources/extensions/gsd/tests/undo.test.ts +74 -0
  456. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +193 -14
  457. package/src/resources/extensions/gsd/tests/unmerged-milestone-guard.test.ts +25 -0
  458. package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +38 -0
  459. package/src/resources/extensions/gsd/tests/validation-block-guard.test.ts +79 -0
  460. package/src/resources/extensions/gsd/tests/verification-retry-policy.test.ts +69 -4
  461. package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +66 -0
  462. package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +96 -15
  463. package/src/resources/extensions/gsd/tests/workflow-mcp-preflight.test.ts +1 -0
  464. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +8 -4
  465. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +6 -5
  466. package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +151 -2
  467. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +39 -0
  468. package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -2
  469. package/src/resources/extensions/gsd/tools/complete-slice.ts +2 -2
  470. package/src/resources/extensions/gsd/tools/complete-task.ts +53 -15
  471. package/src/resources/extensions/gsd/tools/exec-tool.ts +7 -3
  472. package/src/resources/extensions/gsd/tools/plan-slice.ts +60 -47
  473. package/src/resources/extensions/gsd/tools/plan-task.ts +30 -5
  474. package/src/resources/extensions/gsd/undo.ts +47 -6
  475. package/src/resources/extensions/gsd/unit-context-composer.ts +33 -7
  476. package/src/resources/extensions/gsd/unit-registry.ts +36 -6
  477. package/src/resources/extensions/gsd/unmerged-milestone-guard.ts +41 -5
  478. package/src/resources/extensions/gsd/validation-block-guard.ts +13 -7
  479. package/src/resources/extensions/gsd/verification-gate.ts +8 -0
  480. package/src/resources/extensions/gsd/workflow-manifest.ts +141 -7
  481. package/src/resources/extensions/gsd/workflow-projections.ts +20 -14
  482. package/src/resources/extensions/gsd/workspace-git-preflight.ts +31 -0
  483. package/src/resources/extensions/gsd/worktree-manager.ts +41 -1
  484. package/dist/web/standalone/.next/static/chunks/2772.bfa657f49f955239.js +0 -1
  485. package/dist/web/standalone/.next/static/chunks/796.e0bdc932325d7e03.js +0 -10
  486. package/dist/web/standalone/.next/static/chunks/webpack-f46ea08200a0227e.js +0 -1
  487. /package/dist/web/standalone/.next/static/{BTKtGFF1Y-hvVJEGhBRo9 → 2A_WqqCS-EoYZxN9_v3d2}/_buildManifest.js +0 -0
  488. /package/dist/web/standalone/.next/static/{BTKtGFF1Y-hvVJEGhBRo9 → 2A_WqqCS-EoYZxN9_v3d2}/_ssgManifest.js +0 -0
@@ -970,6 +970,93 @@ test("register-hooks agent_end does not re-arm deferred gate after workflow MCP
970
970
  });
971
971
  });
972
972
 
973
+ test("register-hooks message_update uses in-memory write-gate snapshot instead of disk reconcile", async (t) => {
974
+ const dir = makeTempDir("message-update-memory-snapshot");
975
+ const originalCwd = process.cwd();
976
+ const originalEnv = process.env.GSD_PERSIST_WRITE_GATE_STATE;
977
+ process.chdir(dir);
978
+ process.env.GSD_PERSIST_WRITE_GATE_STATE = "1";
979
+ resetWriteGateState(dir);
980
+ clearPendingAutoStart(dir);
981
+
982
+ const gateId = "depth_verification_M012_confirm";
983
+ const statePath = join(dir, ".gsd", "runtime", "write-gate-state.json");
984
+
985
+ t.after(() => {
986
+ try {
987
+ resetWriteGateState(dir);
988
+ clearPendingAutoStart(dir);
989
+ } finally {
990
+ if (originalEnv === undefined) {
991
+ delete process.env.GSD_PERSIST_WRITE_GATE_STATE;
992
+ } else {
993
+ process.env.GSD_PERSIST_WRITE_GATE_STATE = originalEnv;
994
+ }
995
+ process.chdir(originalCwd);
996
+ rmSync(dir, { recursive: true, force: true });
997
+ }
998
+ });
999
+
1000
+ const handlers = new Map<string, Array<(event: any, ctx?: any) => Promise<any> | any>>();
1001
+ const pi = {
1002
+ on(event: string, handler: (event: any, ctx?: any) => Promise<any> | any) {
1003
+ const existing = handlers.get(event) ?? [];
1004
+ existing.push(handler);
1005
+ handlers.set(event, existing);
1006
+ },
1007
+ } as any;
1008
+
1009
+ const notices: Array<{ text: string; level: string }> = [];
1010
+ const ctx = {
1011
+ cwd: dir,
1012
+ ui: { notify: (text: string, level: string) => notices.push({ text, level }) },
1013
+ } as any;
1014
+
1015
+ registerHooks(pi, []);
1016
+ setPendingAutoStart(dir, {
1017
+ basePath: dir,
1018
+ milestoneId: "M012",
1019
+ ctx,
1020
+ pi: { sendMessage: () => undefined } as any,
1021
+ });
1022
+
1023
+ mkdirSync(join(dir, ".gsd", "runtime"), { recursive: true });
1024
+ writeFileSync(statePath, JSON.stringify({
1025
+ verifiedDepthMilestones: ["M012"],
1026
+ verifiedApprovalGates: [gateId],
1027
+ activeQueuePhase: false,
1028
+ pendingGateId: null,
1029
+ }, null, 2), "utf-8");
1030
+
1031
+ const approvalMessage = {
1032
+ role: "assistant",
1033
+ content: [
1034
+ { type: "text", text: "Here is the milestone plan.\n\nDid I capture the project correctly?" },
1035
+ ],
1036
+ };
1037
+
1038
+ for (const handler of handlers.get("message_update") ?? []) {
1039
+ await handler({ message: approvalMessage }, ctx);
1040
+ }
1041
+
1042
+ assert.equal(
1043
+ notices.some((n) => /discuss-milestone M012 is waiting for your approval - pausing/.test(n.text)),
1044
+ true,
1045
+ "streaming hook must not suppress the pause from a disk-only verification",
1046
+ );
1047
+ assert.equal(
1048
+ shouldBlockContextArtifactSave("CONTEXT", "M012", null, dir).block,
1049
+ true,
1050
+ "streaming hook must not reconcile disk-only verification into the in-memory snapshot",
1051
+ );
1052
+
1053
+ for (const handler of handlers.get("agent_end") ?? []) {
1054
+ await handler({ messages: [] }, ctx);
1055
+ }
1056
+
1057
+ assert.equal(getPendingGate(dir), null, "agent_end still reconciles disk and suppresses durable re-arm");
1058
+ });
1059
+
973
1060
  // ── External-engine post-hoc gate replay (write-gate two-process sync) ──────
974
1061
  // On claude-code-cli, pi ingests the SDK turn's tool blocks after the workflow
975
1062
  // MCP child already executed them. The depth gate can therefore arrive at
@@ -0,0 +1,103 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+
4
+ import { autoSession } from "../auto-runtime-state.ts";
5
+ import { registerHooks } from "../bootstrap/register-hooks.ts";
6
+ import { resetToolCallLoopGuard } from "../bootstrap/tool-call-loop-guard.ts";
7
+
8
+ type Handler = (event: any, ctx?: any) => Promise<any> | any;
9
+
10
+ function makeHookHarness(): {
11
+ emitToolCall: (toolName: string, input: Record<string, unknown>) => Promise<any>;
12
+ } {
13
+ const handlers = new Map<string, Handler[]>();
14
+ const pi = {
15
+ on(event: string, handler: Handler) {
16
+ const existing = handlers.get(event) ?? [];
17
+ existing.push(handler);
18
+ handlers.set(event, existing);
19
+ },
20
+ };
21
+ const ctx = {
22
+ cwd: process.cwd(),
23
+ ui: { notify: () => undefined },
24
+ };
25
+ let callId = 0;
26
+
27
+ registerHooks(pi as any, []);
28
+
29
+ return {
30
+ async emitToolCall(toolName: string, input: Record<string, unknown>): Promise<any> {
31
+ callId += 1;
32
+ const loopGuardHandler = handlers.get("tool_call")?.[0];
33
+ assert.ok(loopGuardHandler, "loop-guard tool_call handler should be registered");
34
+ return loopGuardHandler({ toolCallId: `loop-${callId}`, toolName, input }, ctx);
35
+ },
36
+ };
37
+ }
38
+
39
+ test("register-hooks keeps loop-guard block reason interactive outside auto-mode", async (t) => {
40
+ autoSession.reset();
41
+ resetToolCallLoopGuard();
42
+ t.after(() => {
43
+ autoSession.reset();
44
+ resetToolCallLoopGuard();
45
+ });
46
+
47
+ const { emitToolCall } = makeHookHarness();
48
+
49
+ for (let i = 0; i < 4; i += 1) {
50
+ await emitToolCall("web_search", { query: "same query" });
51
+ }
52
+ const block = await emitToolCall("web_search", { query: "same query" });
53
+
54
+ assert.equal(block?.block, true);
55
+ assert.match(block.reason, /respond to the user in text/);
56
+ assert.doesNotMatch(block.reason, /auto-mode recovery\/replan path/);
57
+ });
58
+
59
+ test("register-hooks rewrites loop-guard block reason for auto-mode identical-args blocks", async (t) => {
60
+ autoSession.reset();
61
+ resetToolCallLoopGuard();
62
+ autoSession.active = true;
63
+ t.after(() => {
64
+ autoSession.reset();
65
+ resetToolCallLoopGuard();
66
+ });
67
+
68
+ const { emitToolCall } = makeHookHarness();
69
+
70
+ for (let i = 0; i < 4; i += 1) {
71
+ await emitToolCall("web_search", { query: "same query" });
72
+ }
73
+ const block = await emitToolCall("web_search", { query: "same query" });
74
+
75
+ assert.equal(block?.block, true);
76
+ assert.match(block.reason, /Tool loop detected \(identical args\): web_search/);
77
+ assert.match(block.reason, /Do not re-issue this blocked tool/);
78
+ assert.match(block.reason, /auto-mode recovery\/replan path/);
79
+ assert.doesNotMatch(block.reason, /respond to the user in text/);
80
+ });
81
+
82
+ test("register-hooks rewrites loop-guard block reason for auto-mode per-tool blocks", async (t) => {
83
+ autoSession.reset();
84
+ resetToolCallLoopGuard();
85
+ autoSession.active = true;
86
+ t.after(() => {
87
+ autoSession.reset();
88
+ resetToolCallLoopGuard();
89
+ });
90
+
91
+ const { emitToolCall } = makeHookHarness();
92
+
93
+ for (let i = 0; i < 6; i += 1) {
94
+ await emitToolCall("gsd_complete_milestone", { milestone: `M${i}` });
95
+ }
96
+ const block = await emitToolCall("gsd_complete_milestone", { milestone: "M7" });
97
+
98
+ assert.equal(block?.block, true);
99
+ assert.match(block.reason, /Tool loop detected \(repeated tool\): gsd_complete_milestone/);
100
+ assert.match(block.reason, /Do not re-issue this blocked tool/);
101
+ assert.match(block.reason, /auto-mode recovery\/replan path/);
102
+ assert.doesNotMatch(block.reason, /respond to the user in text/);
103
+ });
@@ -7,7 +7,26 @@ import { closeSync, ftruncateSync, openSync, statSync, writeFileSync } from "nod
7
7
  import { join } from "node:path";
8
8
 
9
9
  import { captureRootDirtySnapshot } from "../root-write-leak-guard.ts";
10
- import { cleanup, git, makeTempRepo } from "./test-utils.ts";
10
+ import { cleanup, createFile, git, makeTempRepo } from "./test-utils.ts";
11
+
12
+ test("captureRootDirtySnapshot ignores unignored GSD root runtime directories", () => {
13
+ const base = makeTempRepo("gsd-root-dirty-runtime-");
14
+ try {
15
+ createFile(base, ".gsd/STATE.md", "state\n");
16
+ createFile(base, ".gsd-backups/snap-001", "backup\n");
17
+ createFile(base, ".gsd-worktrees/M001/file.txt", "worktree\n");
18
+ createFile(base, "src/foo.ts", "export {};\n");
19
+
20
+ const snapshot = captureRootDirtySnapshot(base);
21
+
22
+ assert.equal(snapshot.has(".gsd/STATE.md"), false);
23
+ assert.equal(snapshot.has(".gsd-backups/snap-001"), false);
24
+ assert.equal(snapshot.has(".gsd-worktrees/M001/file.txt"), false);
25
+ assert.equal(snapshot.has("src/foo.ts"), true);
26
+ } finally {
27
+ cleanup(base);
28
+ }
29
+ });
11
30
 
12
31
  test("captureRootDirtySnapshot does not read dirty files larger than Node's Buffer limit", () => {
13
32
  const base = makeTempRepo("gsd-root-dirty-large-");
@@ -177,10 +177,22 @@ test("auto Unit tool scope allows status/read helpers named by closeout prompts"
177
177
  }
178
178
  });
179
179
 
180
- test("auto Unit tool scope blocks stale per-task planner in slice planning phases", () => {
181
- for (const unitType of ["plan-slice", "refine-slice", "replan-slice"]) {
180
+ test("auto Unit tool scope allows reactive-execute status and diagnostic tools", () => {
181
+ for (const toolName of ["gsd_milestone_status", "gsd_exec"]) {
182
+ const result = shouldBlockAutoUnitToolCall("reactive-execute", toolName);
183
+ assert.equal(result.block, false, `reactive-execute should be able to call ${toolName}`);
184
+ }
185
+ });
186
+
187
+ test("auto Unit tool scope allows incremental task planning during plan-slice", () => {
188
+ const result = shouldBlockAutoUnitToolCall("plan-slice", "gsd_plan_task");
189
+ assert.equal(result.block, false, "plan-slice should be able to call gsd_plan_task incrementally");
190
+ });
191
+
192
+ test("auto Unit tool scope still blocks per-task planner outside plan-slice", () => {
193
+ for (const unitType of ["refine-slice", "replan-slice"]) {
182
194
  const result = shouldBlockAutoUnitToolCall(unitType, "gsd_plan_task");
183
- assert.equal(result.block, true, `${unitType} should not call stale gsd_plan_task`);
195
+ assert.equal(result.block, true, `${unitType} should not call gsd_plan_task`);
184
196
  }
185
197
  });
186
198
 
@@ -48,6 +48,16 @@ function makeRecordingPi() {
48
48
  } as any;
49
49
  }
50
50
 
51
+ function makeRecordingCtx() {
52
+ const notifications: Array<{ message: string; level: string }> = [];
53
+ return {
54
+ notifications,
55
+ ui: {
56
+ notify: (message: string, level: string) => { notifications.push({ message, level }); },
57
+ },
58
+ } as any;
59
+ }
60
+
51
61
  // ═══ #1855: empty RecoveryContext (basePath undefined) crashes ════════════════
52
62
 
53
63
  {
@@ -111,6 +121,52 @@ function makeRecordingPi() {
111
121
  }
112
122
  }
113
123
 
124
+ // ═══ plan-slice timeout recovery verifies stale PLAN before advancing ═══════
125
+
126
+ {
127
+ console.log("\n=== plan-slice timeout recovery rejects stale placeholder PLAN ===");
128
+ const base = mkdtempSync(join(tmpdir(), "gsd-timeout-stale-plan-"));
129
+ const sliceDir = join(base, ".gsd", "milestones", "M001", "slices", "S01");
130
+ mkdirSync(sliceDir, { recursive: true });
131
+
132
+ try {
133
+ openDatabase(join(base, ".gsd", "gsd.db"));
134
+ insertMilestone({ id: "M001", title: "Milestone", status: "active" });
135
+ insertSlice({ id: "S01", milestoneId: "M001", title: "Slice", status: "pending" });
136
+ writeFileSync(
137
+ join(sliceDir, "S01-PLAN.md"),
138
+ "# S01: Slice\n\n## Tasks\n\nPlanning was interrupted before task rows were persisted.\n",
139
+ "utf-8",
140
+ );
141
+
142
+ const ctx = makeRecordingCtx();
143
+ const pi = makeRecordingPi();
144
+ const result = await recoverTimedOutUnit(ctx, pi, "plan-slice", "M001/S01", "idle", {
145
+ basePath: base,
146
+ verbose: false,
147
+ currentUnitStartedAt: Date.now(),
148
+ unitRecoveryCount: new Map(),
149
+ });
150
+
151
+ assert.equal(result, "recovered", "invalid existing plan should enter steering recovery");
152
+ assert.equal(pi.messages.length, 1, "invalid existing plan should trigger steering instead of advancing");
153
+ assert.ok(
154
+ ctx.notifications.some((entry: { message: string }) => entry.message.includes("steering plan-slice M001/S01")),
155
+ "recovery notification should describe steering, not artifact advance",
156
+ );
157
+ assert.ok(
158
+ !ctx.notifications.some((entry: { message: string }) => entry.message.includes("artifact already exists on disk. Advancing.")),
159
+ "stale placeholder plan should not use the advance-on-existence path",
160
+ );
161
+ const runtime = JSON.parse(readFileSync(join(base, ".gsd", "runtime", "units", "plan-slice-M001-S01.json"), "utf-8"));
162
+ assert.equal(runtime.phase, "recovered", "stale placeholder plan must not be finalized");
163
+ assert.equal(runtime.recoveryAttempts, 1, "steering recovery attempt should be recorded");
164
+ } finally {
165
+ closeDatabase();
166
+ rmSync(base, { recursive: true, force: true });
167
+ }
168
+ }
169
+
114
170
  // ═══ #1855: valid RecoveryContext does not crash ═════════════════════════════
115
171
 
116
172
  {
@@ -42,6 +42,8 @@ import {
42
42
  type ReconciliationDeps,
43
43
  } from "../state-reconciliation.ts";
44
44
  import { classifyFailure } from "../recovery-classification.ts";
45
+ import { handlerPhaseIndex, RECONCILIATION_REPAIR_PHASES } from "../state-reconciliation/registry.ts";
46
+ import { staleRenderHandler } from "../state-reconciliation/drift/stale-render.ts";
45
47
  import type { GSDState } from "../types.ts";
46
48
 
47
49
  function makeState(overrides: Partial<GSDState> = {}): GSDState {
@@ -159,6 +161,29 @@ test("ADR-017 (#5700): repair failure throws ReconciliationFailedError with shap
159
161
  );
160
162
  });
161
163
 
164
+ test("ADR-017 (#5700): custom registry handlers outside built-in phases are repaired", async () => {
165
+ const drift = { kind: "custom-drift", id: "D001" } as unknown as DriftRecord;
166
+ let repaired = false;
167
+ const handler = {
168
+ kind: "custom-drift",
169
+ detect: () => (repaired ? [] : [drift]),
170
+ repair: () => {
171
+ repaired = true;
172
+ },
173
+ } as unknown as DriftHandler;
174
+
175
+ const result = await reconcileBeforeDispatch("/project", {
176
+ invalidateStateCache: () => {},
177
+ deriveState: async () => makeState(),
178
+ registry: [handler],
179
+ });
180
+
181
+ assert.equal(result.ok, true);
182
+ assert.equal(repaired, true);
183
+ assert.equal(result.repaired.length, 1);
184
+ assert.equal(result.repaired[0]?.kind, "custom-drift");
185
+ });
186
+
162
187
  test("ADR-017 (#5700): a detector failure degrades to a blocker without aborting other handlers", async () => {
163
188
  // A single detector throwing (e.g. a transient file read error) must NOT
164
189
  // abort the whole cycle and hide every later handler's drift. It is collected
@@ -696,6 +721,126 @@ test("ADR-017 (#5702): stale-render drift detected and repaired end-to-end", asy
696
721
  assert.match(repairedContent, /\[x\][^\n]*\*\*T02\*\*/, "T02 checkbox should be checked after repair");
697
722
  });
698
723
 
724
+ test("#1003: stale-render plan repair reopens DB before rendering", async (t) => {
725
+ const base = mkdtempSync(join(tmpdir(), "gsd-stale-render-reopen-"));
726
+ const sliceDir = join(base, ".gsd", "phases", "01-test");
727
+ mkdirSync(sliceDir, { recursive: true });
728
+ t.after(() => {
729
+ try { closeDatabase(); } catch { /* noop */ }
730
+ rmTreeQuiet(base);
731
+ });
732
+
733
+ openDatabase(join(base, ".gsd", "gsd.db"));
734
+ clearRendererCaches();
735
+ insertMilestone({ id: "M001", title: "Test", status: "active" });
736
+ insertSlice({ id: "S01", milestoneId: "M001", title: "Slice", status: "pending" });
737
+ insertTask({ id: "T01", sliceId: "S01", milestoneId: "M001", title: "First task", status: "done" });
738
+
739
+ const planPath = join(sliceDir, "01-01-PLAN.md");
740
+ writeFileSync(planPath, makeStalePlanContent("S01", [
741
+ { id: "T01", title: "First task", done: false },
742
+ ]));
743
+ closeDatabase();
744
+
745
+ await staleRenderHandler.repair(
746
+ {
747
+ kind: "stale-render",
748
+ renderPath: planPath,
749
+ reason: "T01 is done in DB but unchecked in plan",
750
+ },
751
+ { basePath: base, state: makeState() },
752
+ );
753
+
754
+ const repairedContent = readFileSync(planPath, "utf-8");
755
+ assert.match(repairedContent, /\[x\][^\n]*\*\*T01\*\*/, "T01 checkbox should be checked after DB reopen repair");
756
+ assert.equal(getSliceTasks("M001", "S01").length, 1, "DB should be reopened on the original project database");
757
+ });
758
+
759
+ test("#1003: stale-render plan repair switches back from an open wrong DB", async (t) => {
760
+ const base = mkdtempSync(join(tmpdir(), "gsd-stale-render-wrong-db-"));
761
+ const wrongBase = mkdtempSync(join(tmpdir(), "gsd-stale-render-other-db-"));
762
+ const sliceDir = join(base, ".gsd", "phases", "01-test");
763
+ mkdirSync(sliceDir, { recursive: true });
764
+ mkdirSync(join(wrongBase, ".gsd"), { recursive: true });
765
+ t.after(() => {
766
+ try { closeDatabase(); } catch { /* noop */ }
767
+ rmTreeQuiet(base);
768
+ rmTreeQuiet(wrongBase);
769
+ });
770
+
771
+ openDatabase(join(base, ".gsd", "gsd.db"));
772
+ clearRendererCaches();
773
+ insertMilestone({ id: "M001", title: "Test", status: "active" });
774
+ insertSlice({ id: "S01", milestoneId: "M001", title: "Slice", status: "pending" });
775
+ insertTask({ id: "T01", sliceId: "S01", milestoneId: "M001", title: "First task", status: "done" });
776
+
777
+ const planPath = join(sliceDir, "01-01-PLAN.md");
778
+ writeFileSync(planPath, makeStalePlanContent("S01", [
779
+ { id: "T01", title: "First task", done: false },
780
+ ]));
781
+ closeDatabase();
782
+
783
+ openDatabase(join(wrongBase, ".gsd", "gsd.db"));
784
+
785
+ await staleRenderHandler.repair(
786
+ {
787
+ kind: "stale-render",
788
+ renderPath: planPath,
789
+ reason: "T01 is done in DB but unchecked in plan",
790
+ },
791
+ { basePath: base, state: makeState() },
792
+ );
793
+
794
+ const repairedContent = readFileSync(planPath, "utf-8");
795
+ assert.match(repairedContent, /\[x\][^\n]*\*\*T01\*\*/, "T01 checkbox should be checked after switching back to the project DB");
796
+ assert.equal(getSliceTasks("M001", "S01").length, 1, "repair should leave the project DB active");
797
+ });
798
+
799
+ test("#1034: validation-blocked milestone summary drift returns blocker instead of exhausting repair passes", async () => {
800
+ const drift: Extract<DriftRecord, { kind: "stale-render" }> = {
801
+ kind: "stale-render",
802
+ renderPath: "/repo/.gsd/milestones/M001/M001-SUMMARY.md",
803
+ reason: "M001 is complete with summary in DB but SUMMARY.md missing on disk",
804
+ };
805
+ let repairCalled = false;
806
+ const handler: DriftHandler<Extract<DriftRecord, { kind: "stale-render" }>> = {
807
+ kind: "stale-render",
808
+ detect: () => [drift],
809
+ blocker: staleRenderHandler.blocker!,
810
+ repair: () => {
811
+ repairCalled = true;
812
+ },
813
+ };
814
+
815
+ const validationBlocker = [
816
+ "Milestone M001 is blocked because milestone validation returned needs-attention.",
817
+ "Fix options:",
818
+ "1. Review the validation details: `/gsd status`",
819
+ ].join("\n");
820
+
821
+ const result = await reconcileBeforeDispatch("/repo", {
822
+ invalidateStateCache: () => {},
823
+ deriveState: async () =>
824
+ makeState({
825
+ phase: "blocked",
826
+ blockers: [validationBlocker],
827
+ nextAction: "Resolve M001 validation attention before proceeding.",
828
+ }),
829
+ registry: [handler],
830
+ });
831
+
832
+ assert.equal(result.ok, true);
833
+ assert.equal(repairCalled, false, "validation-blocked milestone summary drift should not attempt repair");
834
+ assert.ok(
835
+ result.blockers.some((blocker) => blocker.includes("milestone validation returned needs-attention")),
836
+ "validation blocker should be returned to the caller",
837
+ );
838
+ assert.ok(
839
+ result.blockers.some((blocker) => blocker.includes("Stale milestone summary render")),
840
+ "stale-render blocker should explain why repair did not run",
841
+ );
842
+ });
843
+
699
844
  test("ADR-017 (#5702): stale-render detector reason strings match repair contract", (t) => {
700
845
  t.skip("TODO(flat-phase): stale-render detection temporarily disabled during layout transition"); return;
701
846
  const base = mkdtempSync(join(tmpdir(), "gsd-adr017-render-reasons-"));
@@ -1811,3 +1956,49 @@ test("ADR-017 (#5700): cascading drift triggers second pass within cap", async (
1811
1956
  assert.equal(result.repaired.length, 2, "both passes' repairs collected");
1812
1957
  assert.equal(repaired.length, 2);
1813
1958
  });
1959
+
1960
+ test("deriveState is pure: stale sketch healed only via reconcileBeforeDispatch", async (t) => {
1961
+ const base = makeFixtureBase();
1962
+ t.after(() => cleanup(base));
1963
+
1964
+ openDatabase(join(base, ".gsd", "gsd.db"));
1965
+ insertMilestone({ id: "M001", title: "Test", status: "active" });
1966
+ insertSlice({
1967
+ id: "S02",
1968
+ milestoneId: "M001",
1969
+ title: "Feature",
1970
+ status: "pending",
1971
+ risk: "medium",
1972
+ depends: [],
1973
+ demo: "S02 demo.",
1974
+ sequence: 1,
1975
+ isSketch: true,
1976
+ sketchScope: "limited",
1977
+ });
1978
+ writeFileSync(
1979
+ join(base, ".gsd", "phases", "01-test", "01-02-PLAN.md"),
1980
+ "# S02 Plan\n",
1981
+ );
1982
+
1983
+ const { deriveState } = await import("../state.ts");
1984
+ invalidateStateCache();
1985
+
1986
+ const beforeReconcile = await deriveState(base);
1987
+ assert.equal(beforeReconcile.phase, "refining", "derive alone must not heal stale sketch flag");
1988
+ assert.equal(getSlice("M001", "S02")?.is_sketch, 1, "DB flag unchanged before reconcile");
1989
+
1990
+ const result = await reconcileBeforeDispatch(base);
1991
+ assert.equal(result.ok, true);
1992
+ assert.equal(getSlice("M001", "S02")?.is_sketch, 0, "reconcile clears sketch flag");
1993
+
1994
+ invalidateStateCache();
1995
+ const afterReconcile = await deriveState(base);
1996
+ assert.notEqual(afterReconcile.phase, "refining", "derive after reconcile advances past sketch gate");
1997
+ });
1998
+
1999
+ test("reconciliation repair phases: external edits precede re-project handlers", () => {
2000
+ assert.equal(RECONCILIATION_REPAIR_PHASES.length, 3);
2001
+ assert.ok(handlerPhaseIndex("external-markdown-edit") < handlerPhaseIndex("stale-render"));
2002
+ assert.ok(handlerPhaseIndex("external-planning-edit") < handlerPhaseIndex("roadmap-divergence"));
2003
+ assert.ok(handlerPhaseIndex("stale-sketch-flag") < handlerPhaseIndex("stale-render"));
2004
+ });