@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
@@ -16,6 +16,7 @@ import { execSync } from "node:child_process";
16
16
 
17
17
  import { captureIntegrationBranch, getCurrentBranch } from "../../worktree.ts";
18
18
  import { readIntegrationBranch, QUICK_BRANCH_RE } from "../../git-service.ts";
19
+ import { disableDebug, enableDebug, getDebugCounters } from "../../debug-logger.ts";
19
20
 
20
21
  function run(command: string, cwd: string): string {
21
22
  return execSync(command, { cwd, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }).trim();
@@ -205,16 +206,25 @@ test('cleanupQuickBranch: recovers from disk state (cross-session)', async () =>
205
206
  test('cleanupQuickBranch: no-op without pending state', async () => {
206
207
  const repo = createTestRepo();
207
208
  const origCwd = process.cwd();
208
- process.chdir(repo);
209
-
210
- const { cleanupQuickBranch } = await import("../../quick.ts");
211
- const result = cleanupQuickBranch();
212
-
213
- assert.ok(!result, "returns false when no pending state");
214
- assert.deepStrictEqual(getCurrentBranch(repo), "main", "stays on main");
209
+ try {
210
+ process.chdir(repo);
211
+ enableDebug(repo);
215
212
 
216
- process.chdir(origCwd);
217
- rmSync(repo, { recursive: true, force: true });
213
+ const { cleanupQuickBranch } = await import("../../quick.ts");
214
+ const result = cleanupQuickBranch();
215
+ const firstGitInvocations = getDebugCounters().gitInvocations;
216
+ const secondResult = cleanupQuickBranch();
217
+
218
+ assert.ok(!result, "returns false when no pending state");
219
+ assert.ok(!secondResult, "still returns false when no pending state");
220
+ assert.deepStrictEqual(getDebugCounters().gitInvocations, firstGitInvocations,
221
+ "cached no-state cleanup does not re-run git branch inference");
222
+ assert.deepStrictEqual(getCurrentBranch(repo), "main", "stays on main");
223
+ } finally {
224
+ disableDebug();
225
+ process.chdir(origCwd);
226
+ rmSync(repo, { recursive: true, force: true });
227
+ }
218
228
  });
219
229
 
220
230
  test('cleanupQuickBranch: infers return state from current gsd/quick branch', async () => {
@@ -240,6 +250,43 @@ test('cleanupQuickBranch: infers return state from current gsd/quick branch', as
240
250
  }
241
251
  });
242
252
 
253
+ // ═══════════════════════════════════════════════════════════════════════
254
+ // cleanupQuickBranch: stale miss invalidated after mid-session branch switch
255
+ // ═══════════════════════════════════════════════════════════════════════
256
+ test('cleanupQuickBranch: clears stale miss when branch switches to gsd/quick mid-session', async () => {
257
+ const repo = createTestRepo();
258
+ const origCwd = process.cwd();
259
+ try {
260
+ // Create a quick branch with real product work (so inference finds a diff)
261
+ run("git checkout -b gsd/quick/3-stale-miss", repo);
262
+ writeFileSync(join(repo, "stale.txt"), "stale miss test\n");
263
+ run("git add stale.txt", repo);
264
+ run('git commit -m "test: stale miss"', repo);
265
+ // Return to main so the first cleanupQuickBranch call records a miss
266
+ run("git checkout main", repo);
267
+
268
+ process.chdir(repo);
269
+ const { cleanupQuickBranch } = await import("../../quick.ts");
270
+
271
+ // First call: on main with no disk state → miss recorded (keyed to "main")
272
+ const result1 = cleanupQuickBranch();
273
+ assert.ok(!result1, "first call (on main) returns false — miss recorded");
274
+
275
+ // Simulate mid-session external branch switch to the stranded quick branch
276
+ run("git checkout gsd/quick/3-stale-miss", repo);
277
+
278
+ // Second call: branch changed from the recorded miss, so cache is invalidated
279
+ // and inferQuickReturnFromBranch runs — cleanup must succeed
280
+ const result2 = cleanupQuickBranch();
281
+ assert.ok(result2, "second call returns true after mid-session switch to quick branch");
282
+ assert.deepStrictEqual(getCurrentBranch(repo), "main",
283
+ "cleanup merged back to main after stale-miss invalidation");
284
+ } finally {
285
+ process.chdir(origCwd);
286
+ rmSync(repo, { recursive: true, force: true });
287
+ }
288
+ });
289
+
243
290
  // ═══════════════════════════════════════════════════════════════════════
244
291
  // End-to-end: quick branch does NOT contaminate integration branch
245
292
  // ═══════════════════════════════════════════════════════════════════════
@@ -19,6 +19,7 @@ import { tmpdir } from "node:os";
19
19
 
20
20
  import {
21
21
  saveJsonFile,
22
+ saveJsonFileCompact,
22
23
  loadJsonFile,
23
24
  writeJsonFileAtomic,
24
25
  } from "../json-persistence.ts";
@@ -56,6 +57,37 @@ test("saveJsonFile creates file with valid JSON content", () => {
56
57
  }
57
58
  });
58
59
 
60
+ test("saveJsonFile keeps pretty-printed output for human-readable state", () => {
61
+ const dir = makeTempDir();
62
+ const filePath = join(dir, "pretty.json");
63
+
64
+ try {
65
+ const data = { foo: "bar", nested: { count: 42 } };
66
+ saveJsonFile(filePath, data);
67
+
68
+ const content = readFileSync(filePath, "utf-8");
69
+ assert.equal(content, JSON.stringify(data, null, 2) + "\n");
70
+ } finally {
71
+ cleanup(dir);
72
+ }
73
+ });
74
+
75
+ test("saveJsonFileCompact writes valid compact JSON content", () => {
76
+ const dir = makeTempDir();
77
+ const filePath = join(dir, "compact.json");
78
+
79
+ try {
80
+ const data = { foo: "bar", nested: { count: 42 } };
81
+ saveJsonFileCompact(filePath, data);
82
+
83
+ const content = readFileSync(filePath, "utf-8");
84
+ assert.equal(content, JSON.stringify(data) + "\n");
85
+ assert.deepEqual(JSON.parse(content), data);
86
+ } finally {
87
+ cleanup(dir);
88
+ }
89
+ });
90
+
59
91
  test("saveJsonFile does not leave .tmp files on success", () => {
60
92
  const dir = makeTempDir();
61
93
  const filePath = join(dir, "clean.json");
@@ -72,6 +104,21 @@ test("saveJsonFile does not leave .tmp files on success", () => {
72
104
  }
73
105
  });
74
106
 
107
+ test("saveJsonFileCompact does not leave .tmp files on success", () => {
108
+ const dir = makeTempDir();
109
+ const filePath = join(dir, "compact-clean.json");
110
+
111
+ try {
112
+ saveJsonFileCompact(filePath, { test: true });
113
+
114
+ const files = readdirSync(dir);
115
+ const tmpFiles = files.filter(f => f.includes(".tmp"));
116
+ assert.equal(tmpFiles.length, 0, `Unexpected .tmp files: ${tmpFiles.join(", ")}`);
117
+ } finally {
118
+ cleanup(dir);
119
+ }
120
+ });
121
+
75
122
  test("saveJsonFile creates parent directories", () => {
76
123
  const dir = makeTempDir();
77
124
  const filePath = join(dir, "deep", "nested", "data.json");
@@ -161,6 +161,41 @@ test("backfill is idempotent — second run on the same file is a no-op", () =>
161
161
  }
162
162
  });
163
163
 
164
+ test("backfill skips a knowledge row whose memory insert throws and continues later rows", () => {
165
+ const base = makeTmpBase();
166
+ try {
167
+ writeKnowledgeMd(base, FIXTURE);
168
+
169
+ const adapter = _getAdapter();
170
+ assert.ok(adapter);
171
+ adapter.exec(`
172
+ CREATE TRIGGER fail_p002_memory_insert
173
+ BEFORE INSERT ON memories
174
+ WHEN json_extract(NEW.structured_fields, '$.sourceKnowledgeId') = 'P002'
175
+ BEGIN
176
+ SELECT RAISE(ABORT, 'poison knowledge P002');
177
+ END
178
+ `);
179
+
180
+ const written = backfillKnowledgeToMemories(base);
181
+ assert.equal(written, 2, "one poisoned row should not abort the batch");
182
+
183
+ const rows = adapter
184
+ .prepare(
185
+ "SELECT structured_fields FROM memories WHERE structured_fields LIKE '%\"sourceKnowledgeId\":\"%' ORDER BY seq",
186
+ )
187
+ .all() as Array<{ structured_fields: string }>;
188
+
189
+ assert.deepEqual(
190
+ rows.map((row) => JSON.parse(row.structured_fields).sourceKnowledgeId),
191
+ ["P001", "L001"],
192
+ "rows after the poisoned knowledge entry should still be migrated",
193
+ );
194
+ } finally {
195
+ cleanup(base);
196
+ }
197
+ });
198
+
164
199
  test("backfill returns 0 when KNOWLEDGE.md is absent", () => {
165
200
  const base = makeTmpBase();
166
201
  try {
@@ -136,8 +136,10 @@ test("#896 startup maintenance skips repeated sentinel work in one session", asy
136
136
  closeDatabase();
137
137
  assert.equal(isDbAvailable(), false);
138
138
 
139
+ let sessionId = "session-one";
139
140
  const ctx = {
140
141
  projectRoot: base,
142
+ sessionManager: { getSessionId: () => sessionId },
141
143
  ui: { notify: () => undefined },
142
144
  } as unknown as ExtensionContext;
143
145
 
@@ -190,6 +192,18 @@ test("#896 startup maintenance skips repeated sentinel work in one session", asy
190
192
  .prepare("SELECT COUNT(*) AS count FROM memories WHERE structured_fields LIKE '%\"sourceKnowledgeId\":\"P002\"%'")
191
193
  .get() as { count: number };
192
194
  assert.equal(secondPass.count, 0, "second startup in same session should not re-run KNOWLEDGE.md sentinel backfill");
195
+
196
+ sessionId = "session-two";
197
+ await buildBeforeAgentStartResult(
198
+ { prompt: "Inspect project knowledge in a new session", systemPrompt: "base system prompt" },
199
+ ctx,
200
+ );
201
+ await _flushDeferredContextMaintenanceForTest(base);
202
+
203
+ const nextSessionPass = adapter
204
+ .prepare("SELECT COUNT(*) AS count FROM memories WHERE structured_fields LIKE '%\"sourceKnowledgeId\":\"P002\"%'")
205
+ .get() as { count: number };
206
+ assert.equal(nextSessionPass.count, 1, "startup maintenance should run once for a later session");
193
207
  });
194
208
 
195
209
  test("#896 later turns reopen the project DB after startup maintenance is complete", async (t) => {
@@ -16,6 +16,7 @@ import {
16
16
  openDatabase,
17
17
  closeDatabase,
18
18
  insertDecision,
19
+ _getAdapter,
19
20
  } from "../gsd-db.ts";
20
21
  import { createMemory } from "../memory-store.ts";
21
22
  import {
@@ -271,6 +272,83 @@ test("scanConsolidationGaps combines decisions and KNOWLEDGE.md gaps in summary"
271
272
  }
272
273
  });
273
274
 
275
+ test("scanConsolidationGaps collects memory source markers with one memories scan", () => {
276
+ const base = makeTmpBase();
277
+ try {
278
+ insertDecision({
279
+ id: "D001",
280
+ when_context: "2026-01-01",
281
+ scope: "M001",
282
+ decision: "Unmigrated decision",
283
+ choice: "A",
284
+ rationale: "x",
285
+ revisable: "yes",
286
+ made_by: "agent",
287
+ superseded_by: null,
288
+ });
289
+ insertDecision({
290
+ id: "D002",
291
+ when_context: "2026-01-02",
292
+ scope: "M001",
293
+ decision: "Migrated decision",
294
+ choice: "B",
295
+ rationale: "y",
296
+ revisable: "yes",
297
+ made_by: "agent",
298
+ superseded_by: null,
299
+ });
300
+ createMemory({
301
+ category: "architecture",
302
+ content: "Migrated decision Chose: B. Rationale: y.",
303
+ scope: "M001",
304
+ structuredFields: { sourceDecisionId: "D002" },
305
+ });
306
+ createMemory({
307
+ category: "pattern",
308
+ content: "Migrated knowledge pattern",
309
+ scope: "project",
310
+ structuredFields: { sourceKnowledgeId: "P001" },
311
+ });
312
+ writeKnowledgeMd(
313
+ base,
314
+ `## Patterns
315
+
316
+ | # | Pattern | Where | Notes |
317
+ |---|---------|-------|-------|
318
+ | P001 | Migrated knowledge pattern | scanner | covered |
319
+ | P002 | Unmigrated knowledge pattern | scanner | gap |
320
+ `,
321
+ );
322
+
323
+ const adapter = _getAdapter();
324
+ assert.ok(adapter);
325
+ const originalPrepare = adapter.prepare.bind(adapter);
326
+ const memorySql: string[] = [];
327
+ adapter.prepare = (sql: string) => {
328
+ if (sql.includes("FROM memories")) memorySql.push(sql);
329
+ return originalPrepare(sql);
330
+ };
331
+
332
+ const report = scanConsolidationGaps(base);
333
+ assert.equal(report.decisions.migrated, 1);
334
+ assert.equal(report.decisions.unmigrated, 1);
335
+ assert.equal(report.knowledge.migrated, 1);
336
+ assert.equal(report.knowledge.unmigrated, 1);
337
+ assert.equal(
338
+ memorySql.filter((sql) => sql.includes("SELECT structured_fields FROM memories")).length,
339
+ 1,
340
+ "source marker detection should read memories once",
341
+ );
342
+ assert.equal(
343
+ memorySql.some((sql) => sql.includes("LIKE :pattern")),
344
+ false,
345
+ "scanner must not reintroduce per-row LIKE marker probes",
346
+ );
347
+ } finally {
348
+ cleanup(base);
349
+ }
350
+ });
351
+
274
352
  // ─── reportConsolidationGaps ───────────────────────────────────────────────
275
353
 
276
354
  test("reportConsolidationGaps emits a notification + warning when gaps exist", () => {
@@ -5,6 +5,9 @@ import {
5
5
  SCHEMA_VERSION,
6
6
  _getAdapter,
7
7
  } from '../gsd-db.ts';
8
+ import * as fs from 'node:fs';
9
+ import * as path from 'node:path';
10
+ import * as os from 'node:os';
8
11
  import {
9
12
  _resetLogs,
10
13
  peekLogs,
@@ -22,6 +25,7 @@ import {
22
25
  markUnitProcessed,
23
26
  decayStaleMemories,
24
27
  enforceMemoryCap,
28
+ queryMemoriesRanked,
25
29
  applyMemoryActions,
26
30
  formatMemoriesForPrompt,
27
31
  } from '../memory-store.ts';
@@ -29,6 +33,16 @@ import type { MemoryAction } from '../memory-store.ts';
29
33
  import { describe, test, beforeEach, afterEach } from 'node:test';
30
34
  import assert from 'node:assert/strict';
31
35
 
36
+ function tempDbPath(): string {
37
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-memory-store-test-'));
38
+ return path.join(dir, 'test.db');
39
+ }
40
+
41
+ function cleanupDbPath(dbPath: string): void {
42
+ closeDatabase();
43
+ fs.rmSync(path.dirname(dbPath), { recursive: true, force: true });
44
+ }
45
+
32
46
  // ═══════════════════════════════════════════════════════════════════════════
33
47
  // memory-store: fallback when DB not open
34
48
  // ═══════════════════════════════════════════════════════════════════════════
@@ -366,6 +380,40 @@ test('memory-store: schema includes memories table', () => {
366
380
  closeDatabase();
367
381
  });
368
382
 
383
+ test('memory-store: reopening rebuilds FTS index for pre-FTS memories', () => {
384
+ const dbPath = tempDbPath();
385
+ try {
386
+ openDatabase(dbPath);
387
+ const id = createMemory({ category: 'gotcha', content: 'pre FTS auth memory must become searchable' });
388
+ assert.equal(id, 'MEM001');
389
+
390
+ const adapter = _getAdapter()!;
391
+ const fts = adapter.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='memories_fts'").get();
392
+ if (!fts) return;
393
+
394
+ adapter.exec('DROP TRIGGER IF EXISTS memories_ai');
395
+ adapter.exec('DROP TRIGGER IF EXISTS memories_ad');
396
+ adapter.exec('DROP TRIGGER IF EXISTS memories_au');
397
+ adapter.exec('DROP TABLE IF EXISTS memories_fts');
398
+ adapter.prepare(
399
+ "DELETE FROM runtime_kv WHERE scope = 'global' AND scope_id = '' AND key = 'memories_fts_rebuilt_at'",
400
+ ).run();
401
+ closeDatabase();
402
+
403
+ openDatabase(dbPath);
404
+ const reopened = _getAdapter()!;
405
+ const marker = reopened.prepare(
406
+ "SELECT value_json FROM runtime_kv WHERE scope = 'global' AND scope_id = '' AND key = 'memories_fts_rebuilt_at'",
407
+ ).get();
408
+ assert.ok(marker, 'FTS rebuild marker should be set after reopening');
409
+
410
+ const hits = queryMemoriesRanked({ query: 'auth', k: 5 }).map((hit) => hit.memory.id);
411
+ assert.deepEqual(hits, ['MEM001']);
412
+ } finally {
413
+ cleanupDbPath(dbPath);
414
+ }
415
+ });
416
+
369
417
  // ═══════════════════════════════════════════════════════════════════════════
370
418
  // regression #4967 — createMemory must not silently swallow SQL errors
371
419
  // ═══════════════════════════════════════════════════════════════════════════
@@ -9,7 +9,15 @@ import { tmpdir } from "node:os";
9
9
  import { execFileSync } from "node:child_process";
10
10
 
11
11
  import { mergeMilestoneToMain } from "../auto-worktree.ts";
12
- import { closeDatabase, insertMilestone, openDatabase } from "../gsd-db.ts";
12
+ import { checkCloseoutConsistencyGate } from "../closeout-consistency-gate.ts";
13
+ import {
14
+ closeDatabase,
15
+ insertAssessment,
16
+ insertMilestone,
17
+ insertSlice,
18
+ insertTask,
19
+ openDatabase,
20
+ } from "../gsd-db.ts";
13
21
 
14
22
  function git(args: string[], cwd: string): string {
15
23
  return execFileSync("git", args, {
@@ -61,3 +69,25 @@ test("mergeMilestoneToMain blocks when project DB closeout is still open", () =>
61
69
  if (existsSync(repo)) rmSync(repo, { recursive: true, force: true });
62
70
  }
63
71
  });
72
+
73
+ test("closeout consistency treats deferred slices as inactive", () => {
74
+ try {
75
+ assert.equal(openDatabase(":memory:"), true);
76
+ insertMilestone({ id: "M001", title: "Milestone One", status: "complete" });
77
+ insertSlice({ milestoneId: "M001", id: "S01", title: "Done", status: "complete" });
78
+ insertTask({ milestoneId: "M001", sliceId: "S01", id: "T01", title: "Done", status: "complete" });
79
+ insertSlice({ milestoneId: "M001", id: "S02", title: "Deferred", status: "deferred" });
80
+ insertTask({ milestoneId: "M001", sliceId: "S02", id: "T02", title: "Deferred", status: "pending" });
81
+ insertAssessment({
82
+ path: "milestones/M001/M001-VALIDATION.md",
83
+ milestoneId: "M001",
84
+ status: "pass",
85
+ scope: "milestone-validation",
86
+ fullContent: "verdict: pass",
87
+ });
88
+
89
+ assert.deepEqual(checkCloseoutConsistencyGate("M001"), { ok: true });
90
+ } finally {
91
+ closeDatabase();
92
+ }
93
+ });
@@ -112,6 +112,12 @@ describe("pruneMetricsLedger: invalidates scoped ledger cache", () => {
112
112
  // 3. Prune to keepCount=2 — should evict 3 old units from disk AND clear scopedLedgers.
113
113
  const removed = pruneMetricsLedger(tmpDir, 2);
114
114
  assert.equal(removed, 3, "pruneMetricsLedger should report 3 removed units");
115
+ const prunedRaw = readFileSync(metricsPath(tmpDir), "utf-8");
116
+ assert.equal(
117
+ prunedRaw,
118
+ JSON.stringify(JSON.parse(prunedRaw)) + "\n",
119
+ "pruneMetricsLedger should persist compact metrics.json",
120
+ );
115
121
 
116
122
  // 4. Snapshot a new unit via scope. This exercises the lazy-reload path
117
123
  // (scopedLedgers was cleared by prune) and writes the result to disk.
@@ -259,6 +259,7 @@ test("initMetrics creates ledger, snapshotUnitMetrics persists across resets", (
259
259
  // Verify file content
260
260
  const raw = readFileSync(join(tmpBase, ".gsd", "metrics.json"), "utf-8");
261
261
  const parsed: MetricsLedger = JSON.parse(raw);
262
+ assert.equal(raw, JSON.stringify(parsed) + "\n", "metrics.json should be serialized compactly");
262
263
  assert.equal(parsed.version, 1);
263
264
  assert.equal(parsed.units.length, 1);
264
265
 
@@ -7,7 +7,10 @@ import {
7
7
  existsSync,
8
8
  mkdirSync,
9
9
  realpathSync,
10
+ readFileSync,
10
11
  } from "node:fs";
12
+ import fs from "node:fs";
13
+ import { syncBuiltinESMExports } from "node:module";
11
14
  import { join } from "node:path";
12
15
  import { tmpdir } from "node:os";
13
16
  import { execSync } from "node:child_process";
@@ -116,6 +119,60 @@ describe("migrate-external worktree guard (#2970)", () => {
116
119
  });
117
120
  });
118
121
 
122
+ describe("migrateToExternalState copy failure rollback (#1047)", () => {
123
+ test("restores .gsd when a source entry fails to copy", () => {
124
+ const base = realpathSync(mkdtempSync(join(tmpdir(), "gsd-migrate-copy-fail-")));
125
+ const stateDir = realpathSync(mkdtempSync(join(tmpdir(), "gsd-state-copy-fail-")));
126
+ const previousStateDir = process.env.GSD_STATE_DIR;
127
+ const previousProjectId = process.env.GSD_PROJECT_ID;
128
+ const originalCpSync = fs.cpSync;
129
+ process.env.GSD_STATE_DIR = stateDir;
130
+ process.env.GSD_PROJECT_ID = "copy-fail";
131
+
132
+ try {
133
+ run("git init -b main", base);
134
+ mkdirSync(join(base, ".gsd"), { recursive: true });
135
+ writeFileSync(join(base, ".gsd", "PREFERENCES.md"), "# prefs\n", "utf-8");
136
+ writeFileSync(join(base, ".gsd", "gsd.db"), "state", "utf-8");
137
+ const failingSource = join(base, ".gsd.migrating", "gsd.db");
138
+ fs.cpSync = ((...args: Parameters<typeof fs.cpSync>) => {
139
+ const src = args[0];
140
+ if (String(src) === failingSource) {
141
+ const error = new Error("simulated copy failure") as NodeJS.ErrnoException;
142
+ error.code = "EACCES";
143
+ throw error;
144
+ }
145
+ return originalCpSync(...args);
146
+ }) as typeof fs.cpSync;
147
+ syncBuiltinESMExports();
148
+
149
+ const result = migrateToExternalState(base);
150
+
151
+ assert.equal(result.migrated, false, "copy failure must fail the migration");
152
+ assert.match(result.error ?? "", /Migration copy failed/);
153
+ assert.ok(existsSync(join(base, ".gsd", "gsd.db")), "source .gsd must be restored");
154
+ assert.equal(readFileSync(join(base, ".gsd", "PREFERENCES.md"), "utf-8"), "# prefs\n");
155
+ assert.ok(!existsSync(join(base, ".gsd.migrating")), "backup staging dir must not remain after restore");
156
+ assert.ok(!existsSync(join(stateDir, "projects", "copy-fail", "gsd.db")), "failed file must not be reported as migrated");
157
+ } finally {
158
+ fs.cpSync = originalCpSync;
159
+ syncBuiltinESMExports();
160
+ if (previousStateDir === undefined) {
161
+ delete process.env.GSD_STATE_DIR;
162
+ } else {
163
+ process.env.GSD_STATE_DIR = previousStateDir;
164
+ }
165
+ if (previousProjectId === undefined) {
166
+ delete process.env.GSD_PROJECT_ID;
167
+ } else {
168
+ process.env.GSD_PROJECT_ID = previousProjectId;
169
+ }
170
+ rmSync(base, { recursive: true, force: true });
171
+ rmSync(stateDir, { recursive: true, force: true });
172
+ }
173
+ });
174
+ });
175
+
119
176
  // Regression tests for #5571 — recoverFailedMigration handles orphaned .gsd.migrating
120
177
  describe("recoverFailedMigration (#5571)", () => {
121
178
  test("returns false when .gsd.migrating does not exist", () => {
@@ -429,3 +429,73 @@ test("rebuildMarkdownProjectionsFromDb realigns markdown when DB holds extra row
429
429
  cleanup(base);
430
430
  }
431
431
  });
432
+
433
+ test("rebuildMarkdownProjectionsFromDb realigns markdown for numeric milestone IDs", async () => {
434
+ const base = makeBase();
435
+ try {
436
+ await writeGSDDirectory({ projectContent: "# P\n", decisionsContent: "", requirements: [], milestones: [] }, base);
437
+ assert.equal(await ensureDbOpen(base), true);
438
+ insertMilestone({ id: "15", title: "Numeric milestone", status: "active" });
439
+ insertSlice({
440
+ id: "S01",
441
+ milestoneId: "15",
442
+ title: "Numeric slice",
443
+ status: "pending",
444
+ risk: "medium",
445
+ depends: [],
446
+ demo: "d",
447
+ sequence: 1,
448
+ });
449
+ insertTask({
450
+ id: "T01",
451
+ sliceId: "S01",
452
+ milestoneId: "15",
453
+ title: "Numeric task",
454
+ status: "pending",
455
+ });
456
+
457
+ const before = await checkMarkdownHierarchyAgainstDb(base);
458
+ assert.equal(before.recoveryCommand, "/gsd rebuild markdown");
459
+
460
+ const { rebuildMarkdownProjectionsFromDb } = await import("../commands-maintenance.ts");
461
+ const rebuild = await rebuildMarkdownProjectionsFromDb(base);
462
+ assert.ok(rebuild.rendered > 0, "expected markdown projections to render");
463
+
464
+ const after = await checkMarkdownHierarchyAgainstDb(base);
465
+ assert.equal(after.action, "none");
466
+ assert.equal(after.reason, "in-sync");
467
+ assert.deepEqual(after.markdown, { milestones: 1, slices: 1, tasks: 1 });
468
+ assert.deepEqual(after.beforeDb, { milestones: 1, slices: 1, tasks: 1 });
469
+ } finally {
470
+ cleanup(base);
471
+ }
472
+ });
473
+
474
+ test("rebuildMarkdownProjectionsFromDb realigns markdown for planned zero-slice milestones", async () => {
475
+ const base = makeBase();
476
+ try {
477
+ await writeGSDDirectory({ projectContent: "# P\n", decisionsContent: "", requirements: [], milestones: [] }, base);
478
+ assert.equal(await ensureDbOpen(base), true);
479
+ insertMilestone({
480
+ id: "M016",
481
+ title: "Queued milestone",
482
+ status: "queued",
483
+ planning: { vision: "Defined but not sliced yet" },
484
+ });
485
+
486
+ const before = await checkMarkdownHierarchyAgainstDb(base);
487
+ assert.equal(before.recoveryCommand, "/gsd rebuild markdown");
488
+
489
+ const { rebuildMarkdownProjectionsFromDb } = await import("../commands-maintenance.ts");
490
+ const rebuild = await rebuildMarkdownProjectionsFromDb(base);
491
+ assert.ok(rebuild.rendered > 0, "expected markdown projections to render");
492
+
493
+ const after = await checkMarkdownHierarchyAgainstDb(base);
494
+ assert.equal(after.action, "none");
495
+ assert.equal(after.reason, "in-sync");
496
+ assert.deepEqual(after.markdown, { milestones: 1, slices: 0, tasks: 0 });
497
+ assert.deepEqual(after.beforeDb, { milestones: 1, slices: 0, tasks: 0 });
498
+ } finally {
499
+ cleanup(base);
500
+ }
501
+ });