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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (357) hide show
  1. package/dist/resources/.managed-resources-content-hash +1 -1
  2. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +11 -2
  3. package/dist/resources/extensions/google-cli/stream-adapter.js +82 -15
  4. package/dist/resources/extensions/gsd/artifact-verification.js +427 -0
  5. package/dist/resources/extensions/gsd/auto/orchestrator.js +12 -3
  6. package/dist/resources/extensions/gsd/auto/session.js +3 -0
  7. package/dist/resources/extensions/gsd/auto-artifact-paths.js +28 -1
  8. package/dist/resources/extensions/gsd/auto-dispatch.js +20 -19
  9. package/dist/resources/extensions/gsd/auto-prompts.js +26 -11
  10. package/dist/resources/extensions/gsd/auto-recovery.js +6 -507
  11. package/dist/resources/extensions/gsd/auto-runtime-state.js +4 -5
  12. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +3 -3
  13. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +103 -13
  14. package/dist/resources/extensions/gsd/bootstrap/core-session-tools.js +38 -0
  15. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +6 -1
  16. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +2 -0
  17. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +10 -19
  18. package/dist/resources/extensions/gsd/bootstrap/system-context.js +46 -19
  19. package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +68 -10
  20. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +1 -1
  21. package/dist/resources/extensions/gsd/commands-context.js +19 -1
  22. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +16 -10
  23. package/dist/resources/extensions/gsd/commands-worktree.js +12 -10
  24. package/dist/resources/extensions/gsd/dashboard-overlay.js +32 -3
  25. package/dist/resources/extensions/gsd/db/queries.js +60 -0
  26. package/dist/resources/extensions/gsd/db-workspace.js +55 -3
  27. package/dist/resources/extensions/gsd/doctor-providers.js +92 -8
  28. package/dist/resources/extensions/gsd/exec-sandbox.js +45 -9
  29. package/dist/resources/extensions/gsd/forensics.js +2 -32
  30. package/dist/resources/extensions/gsd/git-service.js +4 -4
  31. package/dist/resources/extensions/gsd/guided-flow-queue.js +66 -5
  32. package/dist/resources/extensions/gsd/health-widget.js +55 -29
  33. package/dist/resources/extensions/gsd/layout-policy.js +3 -1
  34. package/dist/resources/extensions/gsd/markdown-renderer.js +8 -9
  35. package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +44 -21
  36. package/dist/resources/extensions/gsd/migration-auto-check.js +22 -0
  37. package/dist/resources/extensions/gsd/milestone-ids.js +32 -2
  38. package/dist/resources/extensions/gsd/milestone-implementation-evidence.js +26 -20
  39. package/dist/resources/extensions/gsd/prompts/code-review.md +6 -4
  40. package/dist/resources/extensions/gsd/quick.js +45 -2
  41. package/dist/resources/extensions/gsd/session-forensics.js +11 -1
  42. package/dist/resources/extensions/gsd/skills/gsd-headless/references/commands.md +1 -1
  43. package/dist/resources/extensions/gsd/state/derive/cache.js +28 -0
  44. package/dist/resources/extensions/gsd/state/derive/db-open.js +39 -0
  45. package/dist/resources/extensions/gsd/state/derive/from-db.js +452 -0
  46. package/dist/resources/extensions/gsd/state/derive/index.js +75 -0
  47. package/dist/resources/extensions/gsd/state/derive/interrupted-work.js +21 -0
  48. package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-render.js +45 -2
  49. package/dist/resources/extensions/gsd/state-reconciliation/index.js +48 -23
  50. package/dist/resources/extensions/gsd/state-reconciliation/registry.js +32 -28
  51. package/dist/resources/extensions/gsd/state.js +12 -611
  52. package/dist/resources/extensions/gsd/tools/complete-slice.js +2 -2
  53. package/dist/resources/extensions/gsd/tools/complete-task.js +43 -14
  54. package/dist/resources/extensions/gsd/tools/exec-tool.js +7 -2
  55. package/dist/resources/extensions/gsd/unit-context-composer.js +23 -7
  56. package/dist/resources/extensions/gsd/unit-registry.js +32 -4
  57. package/dist/resources/extensions/gsd/unmerged-milestone-guard.js +33 -3
  58. package/dist/resources/extensions/gsd/validation-block-guard.js +9 -4
  59. package/dist/resources/extensions/gsd/workflow-projections.js +19 -14
  60. package/dist/resources/extensions/gsd/workspace-git-preflight.js +30 -1
  61. package/dist/resources/extensions/gsd/worktree-manager.js +44 -2
  62. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  63. package/dist/web/standalone/.next/BUILD_ID +1 -1
  64. package/dist/web/standalone/.next/app-path-routes-manifest.json +10 -10
  65. package/dist/web/standalone/.next/build-manifest.json +3 -3
  66. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  67. package/dist/web/standalone/.next/react-loadable-manifest.json +9 -9
  68. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  69. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  70. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  71. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  72. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  73. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  74. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  75. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  76. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  77. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  78. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  79. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  80. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  81. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  82. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  83. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  84. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  85. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  86. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  87. package/dist/web/standalone/.next/server/app/index.html +1 -1
  88. package/dist/web/standalone/.next/server/app/index.rsc +2 -2
  89. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  90. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
  91. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  95. package/dist/web/standalone/.next/server/app-paths-manifest.json +10 -10
  96. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  97. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  98. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  99. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  100. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  101. package/dist/web/standalone/.next/static/chunks/{2659.b7b129ee6a769448.js → 2659.58e950899a9bb82f.js} +1 -1
  102. package/dist/web/standalone/.next/static/chunks/2772.a7c1fcc69a4685ef.js +1 -0
  103. package/dist/web/standalone/.next/static/chunks/{3616.3c60753b8ffcbd2e.js → 3616.61a2af74bb8833c8.js} +1 -1
  104. package/dist/web/standalone/.next/static/chunks/{4283.8e446784528ed9dc.js → 4283.d0d9e0a955e441cb.js} +1 -1
  105. package/dist/web/standalone/.next/static/chunks/{5826.a46ecdd1cfe8dabc.js → 5826.5421d66c72b9f34e.js} +1 -1
  106. package/dist/web/standalone/.next/static/chunks/{8785.481aa5869991b760.js → 8785.e29b3134cab1d153.js} +1 -1
  107. package/dist/web/standalone/.next/static/chunks/8937.640dc9c2aaa1dfad.js +10 -0
  108. package/dist/web/standalone/.next/static/chunks/app/{page-6644fc6ee8ca1247.js → page-72a856634ad14c10.js} +1 -1
  109. package/dist/web/standalone/.next/static/chunks/webpack-9c401904f87ded16.js +1 -0
  110. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  111. package/package.json +1 -1
  112. package/packages/cloud-mcp-gateway/package.json +2 -2
  113. package/packages/contracts/dist/workflow.d.ts +1 -0
  114. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  115. package/packages/contracts/dist/workflow.js +2 -0
  116. package/packages/contracts/dist/workflow.js.map +1 -1
  117. package/packages/contracts/package.json +1 -1
  118. package/packages/daemon/package.json +4 -4
  119. package/packages/gsd-agent-core/dist/agent-session.d.ts +1 -0
  120. package/packages/gsd-agent-core/dist/agent-session.d.ts.map +1 -1
  121. package/packages/gsd-agent-core/dist/agent-session.js +3 -0
  122. package/packages/gsd-agent-core/dist/agent-session.js.map +1 -1
  123. package/packages/gsd-agent-core/dist/extension-ui-snapshot.d.ts +41 -0
  124. package/packages/gsd-agent-core/dist/extension-ui-snapshot.d.ts.map +1 -0
  125. package/packages/gsd-agent-core/dist/extension-ui-snapshot.js +62 -0
  126. package/packages/gsd-agent-core/dist/extension-ui-snapshot.js.map +1 -0
  127. package/packages/gsd-agent-core/dist/index.d.ts +2 -0
  128. package/packages/gsd-agent-core/dist/index.d.ts.map +1 -1
  129. package/packages/gsd-agent-core/dist/index.js +2 -0
  130. package/packages/gsd-agent-core/dist/index.js.map +1 -1
  131. package/packages/gsd-agent-core/dist/session/agent-session-events.js +1 -1
  132. package/packages/gsd-agent-core/dist/session/agent-session-events.js.map +1 -1
  133. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts +1 -0
  134. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts.map +1 -1
  135. package/packages/gsd-agent-core/dist/session/agent-session-host.js.map +1 -1
  136. package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts +5 -0
  137. package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts.map +1 -1
  138. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js +60 -3
  139. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js.map +1 -1
  140. package/packages/gsd-agent-core/dist/transcript-store.d.ts +58 -0
  141. package/packages/gsd-agent-core/dist/transcript-store.d.ts.map +1 -0
  142. package/packages/gsd-agent-core/dist/transcript-store.js +132 -0
  143. package/packages/gsd-agent-core/dist/transcript-store.js.map +1 -0
  144. package/packages/gsd-agent-core/package.json +5 -5
  145. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +2 -0
  146. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  147. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +25 -11
  148. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  149. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.d.ts +4 -0
  150. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.d.ts.map +1 -0
  151. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.js +7 -0
  152. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.js.map +1 -0
  153. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts +3 -24
  154. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  155. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +26 -829
  156. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  157. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.d.ts +58 -0
  158. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.d.ts.map +1 -0
  159. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.js +312 -0
  160. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.js.map +1 -0
  161. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.d.ts +31 -0
  162. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.d.ts.map +1 -0
  163. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.js +130 -0
  164. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.js.map +1 -0
  165. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts +15 -0
  166. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts.map +1 -0
  167. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js +258 -0
  168. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js.map +1 -0
  169. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.d.ts +13 -0
  170. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.d.ts.map +1 -0
  171. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.js +118 -0
  172. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.js.map +1 -0
  173. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts +9 -0
  174. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  175. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.js +1 -1
  176. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  177. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.d.ts +54 -0
  178. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.d.ts.map +1 -0
  179. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.js +20 -0
  180. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.js.map +1 -0
  181. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts +4 -1
  182. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  183. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +9 -0
  184. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
  185. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.d.ts +56 -0
  186. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.d.ts.map +1 -0
  187. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.js +44 -0
  188. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.js.map +1 -0
  189. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.d.ts +5 -0
  190. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.d.ts.map +1 -0
  191. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.js +77 -0
  192. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.js.map +1 -0
  193. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  194. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +18 -0
  195. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
  196. package/packages/gsd-agent-modes/package.json +7 -7
  197. package/packages/mcp-server/README.md +1 -1
  198. package/packages/mcp-server/dist/server.d.ts +1 -1
  199. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  200. package/packages/mcp-server/dist/server.js +3 -3
  201. package/packages/mcp-server/dist/server.js.map +1 -1
  202. package/packages/mcp-server/dist/workflow-tools.d.ts +13 -1
  203. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  204. package/packages/mcp-server/dist/workflow-tools.js +34 -20
  205. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  206. package/packages/mcp-server/package.json +4 -4
  207. package/packages/native/package.json +1 -1
  208. package/packages/pi-agent-core/package.json +1 -1
  209. package/packages/pi-ai/package.json +1 -1
  210. package/packages/pi-coding-agent/README.md +3 -2
  211. package/packages/pi-coding-agent/dist/core/session-manager-context.d.ts +9 -0
  212. package/packages/pi-coding-agent/dist/core/session-manager-context.d.ts.map +1 -0
  213. package/packages/pi-coding-agent/dist/core/session-manager-context.js +94 -0
  214. package/packages/pi-coding-agent/dist/core/session-manager-context.js.map +1 -0
  215. package/packages/pi-coding-agent/dist/core/session-manager-list.d.ts +8 -0
  216. package/packages/pi-coding-agent/dist/core/session-manager-list.d.ts.map +1 -0
  217. package/packages/pi-coding-agent/dist/core/session-manager-list.js +244 -0
  218. package/packages/pi-coding-agent/dist/core/session-manager-list.js.map +1 -0
  219. package/packages/pi-coding-agent/dist/core/session-manager-migration.d.ts +12 -0
  220. package/packages/pi-coding-agent/dist/core/session-manager-migration.d.ts.map +1 -0
  221. package/packages/pi-coding-agent/dist/core/session-manager-migration.js +84 -0
  222. package/packages/pi-coding-agent/dist/core/session-manager-migration.js.map +1 -0
  223. package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts +135 -0
  224. package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts.map +1 -0
  225. package/packages/pi-coding-agent/dist/core/session-manager-types.js +2 -0
  226. package/packages/pi-coding-agent/dist/core/session-manager-types.js.map +1 -0
  227. package/packages/pi-coding-agent/dist/core/session-manager.d.ts +6 -154
  228. package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
  229. package/packages/pi-coding-agent/dist/core/session-manager.js +22 -459
  230. package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
  231. package/packages/pi-coding-agent/dist/theme/theme-schema.d.ts +75 -75
  232. package/packages/pi-coding-agent/dist/theme/theme-schema.d.ts.map +1 -1
  233. package/packages/pi-coding-agent/dist/theme/theme-schema.js +1 -1
  234. package/packages/pi-coding-agent/dist/theme/theme-schema.js.map +1 -1
  235. package/packages/pi-coding-agent/dist/theme/theme.d.ts.map +1 -1
  236. package/packages/pi-coding-agent/dist/theme/theme.js +11 -7
  237. package/packages/pi-coding-agent/dist/theme/theme.js.map +1 -1
  238. package/packages/pi-coding-agent/package.json +7 -7
  239. package/packages/pi-tui/package.json +2 -2
  240. package/packages/rpc-client/package.json +2 -2
  241. package/pkg/dist/theme/theme-schema.d.ts +75 -75
  242. package/pkg/dist/theme/theme-schema.d.ts.map +1 -1
  243. package/pkg/dist/theme/theme-schema.js +1 -1
  244. package/pkg/dist/theme/theme-schema.js.map +1 -1
  245. package/pkg/dist/theme/theme.d.ts.map +1 -1
  246. package/pkg/dist/theme/theme.js +11 -7
  247. package/pkg/dist/theme/theme.js.map +1 -1
  248. package/pkg/package.json +1 -1
  249. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +20 -2
  250. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +80 -0
  251. package/src/resources/extensions/google-cli/stream-adapter.ts +106 -19
  252. package/src/resources/extensions/gsd/artifact-verification.ts +464 -0
  253. package/src/resources/extensions/gsd/auto/orchestrator.ts +25 -11
  254. package/src/resources/extensions/gsd/auto/session.ts +5 -0
  255. package/src/resources/extensions/gsd/auto-artifact-paths.ts +47 -1
  256. package/src/resources/extensions/gsd/auto-dispatch.ts +21 -23
  257. package/src/resources/extensions/gsd/auto-prompts.ts +38 -12
  258. package/src/resources/extensions/gsd/auto-recovery.ts +10 -508
  259. package/src/resources/extensions/gsd/auto-runtime-state.ts +4 -5
  260. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +3 -2
  261. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +125 -12
  262. package/src/resources/extensions/gsd/bootstrap/core-session-tools.ts +43 -0
  263. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +6 -1
  264. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +2 -0
  265. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +11 -19
  266. package/src/resources/extensions/gsd/bootstrap/system-context.ts +52 -18
  267. package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +74 -10
  268. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +1 -1
  269. package/src/resources/extensions/gsd/commands-context.ts +18 -1
  270. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +14 -9
  271. package/src/resources/extensions/gsd/commands-worktree.ts +12 -10
  272. package/src/resources/extensions/gsd/dashboard-overlay.ts +32 -3
  273. package/src/resources/extensions/gsd/db/queries.ts +79 -0
  274. package/src/resources/extensions/gsd/db-workspace.ts +61 -3
  275. package/src/resources/extensions/gsd/doctor-providers.ts +103 -9
  276. package/src/resources/extensions/gsd/exec-sandbox.ts +49 -9
  277. package/src/resources/extensions/gsd/forensics.ts +2 -33
  278. package/src/resources/extensions/gsd/git-service.ts +5 -5
  279. package/src/resources/extensions/gsd/guided-flow-queue.ts +89 -4
  280. package/src/resources/extensions/gsd/health-widget.ts +69 -32
  281. package/src/resources/extensions/gsd/layout-policy.ts +2 -1
  282. package/src/resources/extensions/gsd/markdown-renderer.ts +8 -11
  283. package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +51 -19
  284. package/src/resources/extensions/gsd/migration-auto-check.ts +23 -0
  285. package/src/resources/extensions/gsd/milestone-ids.ts +31 -2
  286. package/src/resources/extensions/gsd/milestone-implementation-evidence.ts +35 -21
  287. package/src/resources/extensions/gsd/prompts/code-review.md +6 -4
  288. package/src/resources/extensions/gsd/quick.ts +43 -2
  289. package/src/resources/extensions/gsd/session-forensics.ts +11 -1
  290. package/src/resources/extensions/gsd/skills/gsd-headless/references/commands.md +1 -1
  291. package/src/resources/extensions/gsd/state/derive/cache.ts +46 -0
  292. package/src/resources/extensions/gsd/state/derive/db-open.ts +45 -0
  293. package/src/resources/extensions/gsd/state/derive/from-db.ts +561 -0
  294. package/src/resources/extensions/gsd/state/derive/index.ts +104 -0
  295. package/src/resources/extensions/gsd/state/derive/interrupted-work.ts +31 -0
  296. package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +81 -7
  297. package/src/resources/extensions/gsd/state-reconciliation/index.ts +50 -24
  298. package/src/resources/extensions/gsd/state-reconciliation/registry.ts +43 -28
  299. package/src/resources/extensions/gsd/state.ts +32 -732
  300. package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +98 -1
  301. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +111 -1
  302. package/src/resources/extensions/gsd/tests/commands-context.test.ts +26 -0
  303. package/src/resources/extensions/gsd/tests/commands-gsd-core.test.ts +1 -0
  304. package/src/resources/extensions/gsd/tests/commands-worktree-clean.test.ts +80 -0
  305. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +11 -0
  306. package/src/resources/extensions/gsd/tests/complete-task-rollback-evidence.test.ts +48 -8
  307. package/src/resources/extensions/gsd/tests/complete-task.test.ts +75 -0
  308. package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +55 -2
  309. package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +26 -1
  310. package/src/resources/extensions/gsd/tests/doctor-forensics-db-open-regression.test.ts +70 -2
  311. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +107 -0
  312. package/src/resources/extensions/gsd/tests/exec-graceful-kill.test.ts +38 -0
  313. package/src/resources/extensions/gsd/tests/exec-tool.test.ts +45 -1
  314. package/src/resources/extensions/gsd/tests/forensics-error-filter.test.ts +88 -0
  315. package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +42 -0
  316. package/src/resources/extensions/gsd/tests/health-widget.test.ts +268 -3
  317. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +119 -1
  318. package/src/resources/extensions/gsd/tests/integration/queue-active-milestone-context-budget.test.ts +93 -0
  319. package/src/resources/extensions/gsd/tests/integration/quick-branch-lifecycle.test.ts +56 -9
  320. package/src/resources/extensions/gsd/tests/knowledge-cold-start.test.ts +14 -0
  321. package/src/resources/extensions/gsd/tests/memory-consolidation-scanner.test.ts +78 -0
  322. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +70 -0
  323. package/src/resources/extensions/gsd/tests/orchestrator-logs.test.ts +43 -1
  324. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +26 -0
  325. package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +2 -1
  326. package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +1 -1
  327. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +54 -1
  328. package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +50 -14
  329. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +195 -1
  330. package/src/resources/extensions/gsd/tests/read-uat-gate-verdict.test.ts +185 -0
  331. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +87 -0
  332. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +7 -0
  333. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +56 -0
  334. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +191 -0
  335. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +151 -0
  336. package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +26 -0
  337. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +193 -14
  338. package/src/resources/extensions/gsd/tests/unmerged-milestone-guard.test.ts +25 -0
  339. package/src/resources/extensions/gsd/tests/validation-block-guard.test.ts +79 -0
  340. package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +66 -0
  341. package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +151 -2
  342. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +39 -0
  343. package/src/resources/extensions/gsd/tools/complete-slice.ts +2 -2
  344. package/src/resources/extensions/gsd/tools/complete-task.ts +53 -15
  345. package/src/resources/extensions/gsd/tools/exec-tool.ts +7 -3
  346. package/src/resources/extensions/gsd/unit-context-composer.ts +33 -7
  347. package/src/resources/extensions/gsd/unit-registry.ts +32 -4
  348. package/src/resources/extensions/gsd/unmerged-milestone-guard.ts +41 -5
  349. package/src/resources/extensions/gsd/validation-block-guard.ts +13 -7
  350. package/src/resources/extensions/gsd/workflow-projections.ts +20 -14
  351. package/src/resources/extensions/gsd/workspace-git-preflight.ts +31 -0
  352. package/src/resources/extensions/gsd/worktree-manager.ts +41 -1
  353. package/dist/web/standalone/.next/static/chunks/2772.bfa657f49f955239.js +0 -1
  354. package/dist/web/standalone/.next/static/chunks/796.e0bdc932325d7e03.js +0 -10
  355. package/dist/web/standalone/.next/static/chunks/webpack-f46ea08200a0227e.js +0 -1
  356. /package/dist/web/standalone/.next/static/{BTKtGFF1Y-hvVJEGhBRo9 → O7xDYXO0r4zFhIzY1hrWV}/_buildManifest.js +0 -0
  357. /package/dist/web/standalone/.next/static/{BTKtGFF1Y-hvVJEGhBRo9 → O7xDYXO0r4zFhIzY1hrWV}/_ssgManifest.js +0 -0
@@ -142,23 +142,53 @@ function getActiveDecisions(): DecisionRow[] {
142
142
  }
143
143
 
144
144
  /**
145
- * True when a memory row has a `structured_fields` JSON payload containing
146
- * the given `markerKey: "value"` pair. Matches the LIKE pattern used by
147
- * `backfillDecisionsToMemories` so the scanner is consistent with the
148
- * backfill's idempotency check.
145
+ * Source IDs already present in memory `structured_fields`. Collected with one
146
+ * pass over the memories table so the scanner does not perform a non-indexable
147
+ * LIKE probe for every decision and KNOWLEDGE.md row.
149
148
  */
150
- function memoryHasSourceMarker(markerKey: string, value: string): boolean {
151
- if (!isDbAvailable()) return false;
149
+ interface MemorySourceMarkers {
150
+ decisionIds: Set<string>;
151
+ knowledgeIds: Set<string>;
152
+ }
153
+
154
+ function emptyMemorySourceMarkers(): MemorySourceMarkers {
155
+ return { decisionIds: new Set(), knowledgeIds: new Set() };
156
+ }
157
+
158
+ function getMemorySourceMarkers(): MemorySourceMarkers {
159
+ const markers = emptyMemorySourceMarkers();
160
+ if (!isDbAvailable()) return markers;
152
161
  const adapter = _getAdapter();
153
- if (!adapter) return false;
162
+ if (!adapter) return markers;
163
+ try {
164
+ const rows = adapter
165
+ .prepare("SELECT structured_fields FROM memories WHERE structured_fields IS NOT NULL")
166
+ .all() as Array<Record<string, unknown>>;
167
+ for (const row of rows) {
168
+ collectMemorySourceMarker(markers, row["structured_fields"]);
169
+ }
170
+ } catch {
171
+ return markers;
172
+ }
173
+ return markers;
174
+ }
175
+
176
+ function collectMemorySourceMarker(markers: MemorySourceMarkers, raw: unknown): void {
177
+ if (typeof raw !== "string" || raw.length === 0) return;
154
178
  try {
155
- const pattern = `%"${markerKey}":"${value}"%`;
156
- const row = adapter
157
- .prepare("SELECT 1 FROM memories WHERE structured_fields LIKE :pattern LIMIT 1")
158
- .get({ ":pattern": pattern });
159
- return row !== undefined;
179
+ const parsed = JSON.parse(raw);
180
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return;
181
+ const fields = parsed as Record<string, unknown>;
182
+ const decisionId = fields["sourceDecisionId"];
183
+ if (typeof decisionId === "string" && decisionId.length > 0) {
184
+ markers.decisionIds.add(decisionId);
185
+ }
186
+ const knowledgeId = fields["sourceKnowledgeId"];
187
+ if (typeof knowledgeId === "string" && knowledgeId.length > 0) {
188
+ markers.knowledgeIds.add(knowledgeId);
189
+ }
160
190
  } catch {
161
- return false;
191
+ return;
162
192
  }
163
193
  }
164
194
 
@@ -174,10 +204,14 @@ const SAMPLE_LIMIT = 5;
174
204
  export function scanConsolidationGaps(basePath: string): ConsolidationGapReport {
175
205
  // ── Decisions ────────────────────────────────────────────────────────
176
206
  const decisions = getActiveDecisions();
207
+ const knowledgeRows = parseKnowledgeRows(knowledgeMdContent(basePath));
208
+ const memorySourceMarkers = decisions.length > 0 || knowledgeRows.length > 0
209
+ ? getMemorySourceMarkers()
210
+ : emptyMemorySourceMarkers();
177
211
  const decisionSamples: DecisionsSurfaceReport["samples"] = [];
178
212
  let decisionMigrated = 0;
179
213
  for (const decision of decisions) {
180
- if (memoryHasSourceMarker("sourceDecisionId", decision.id)) {
214
+ if (memorySourceMarkers.decisionIds.has(decision.id)) {
181
215
  decisionMigrated += 1;
182
216
  continue;
183
217
  }
@@ -190,16 +224,14 @@ export function scanConsolidationGaps(basePath: string): ConsolidationGapReport
190
224
  }
191
225
 
192
226
  // ── KNOWLEDGE.md ─────────────────────────────────────────────────────
193
- const knowledgeRows = parseKnowledgeRows(knowledgeMdContent(basePath));
194
227
  const knowledgeByTable = { rules: 0, patterns: 0, lessons: 0 };
195
228
  const knowledgeSamples: KnowledgeSurfaceReport["samples"] = [];
196
229
  let knowledgeMigrated = 0;
197
230
  for (const row of knowledgeRows) {
198
231
  knowledgeByTable[row.table] += 1;
199
- // Phase 6 will introduce a `sourceKnowledgeId` marker as part of the
200
- // KNOWLEDGE.md backfill. Until that path ships, this check returns
201
- // false for every row, which is the honest state of the consolidation.
202
- if (memoryHasSourceMarker("sourceKnowledgeId", row.id)) {
232
+ // KNOWLEDGE.md backfill writes `sourceKnowledgeId`; rows without that
233
+ // marker are still reported as consolidation gaps.
234
+ if (memorySourceMarkers.knowledgeIds.has(row.id)) {
203
235
  knowledgeMigrated += 1;
204
236
  continue;
205
237
  }
@@ -90,6 +90,28 @@ function scanHasExtraIdentities(a: HierarchyScan, b: HierarchyScan): boolean {
90
90
  );
91
91
  }
92
92
 
93
+ function paddedMilestoneId(id: string): string | null {
94
+ return /^\d+$/.test(id) ? `M${id.padStart(3, "0")}` : null;
95
+ }
96
+
97
+ function replaceSetPrefix(values: Set<string>, from: string, to: string): void {
98
+ for (const value of [...values]) {
99
+ if (value !== from && !value.startsWith(`${from}/`)) continue;
100
+ values.delete(value);
101
+ values.add(`${to}${value.slice(from.length)}`);
102
+ }
103
+ }
104
+
105
+ function alignNumericMarkdownIdsWithDb(markdownScan: HierarchyScan, dbScan: HierarchyScan): void {
106
+ for (const dbId of dbScan.milestones) {
107
+ const paddedId = paddedMilestoneId(dbId);
108
+ if (!paddedId || dbScan.milestones.has(paddedId) || !markdownScan.milestones.has(paddedId)) continue;
109
+ replaceSetPrefix(markdownScan.milestones, paddedId, dbId);
110
+ replaceSetPrefix(markdownScan.slices, paddedId, dbId);
111
+ replaceSetPrefix(markdownScan.tasks, paddedId, dbId);
112
+ }
113
+ }
114
+
93
115
  /**
94
116
  * True when the DB holds any milestone/slice/task identity the markdown lacks —
95
117
  * i.e. a `/gsd recover --confirm` (markdown → DB) would DELETE authoritative DB
@@ -185,6 +207,7 @@ export async function checkMarkdownHierarchyAgainstDb(
185
207
 
186
208
  const dbScan = scanDbHierarchy();
187
209
  const beforeDb = dbScan.counts;
210
+ alignNumericMarkdownIdsWithDb(markdownScan, dbScan);
188
211
 
189
212
  // Discussion-phase scratch: a milestone dir with no ROADMAP and no DB row is
190
213
  // a pre-registration discussion artifact (CONTEXT/CONTEXT-DRAFT only — the
@@ -141,7 +141,8 @@ export function clearReservedMilestoneIds(): void {
141
141
 
142
142
  // ─── Discovery ──────────────────────────────────────────────────────────────
143
143
 
144
- function scanMilestoneIdsFromDir(dir: string): string[] {
144
+ function scanMilestoneIdsFromDir(basePath: string, dir: string): string[] {
145
+ const legacyNumericIds = idsWithLegacyNumericDirs(basePath);
145
146
  return readdirSync(dir, { withFileTypes: true })
146
147
  .filter((d) => d.isDirectory())
147
148
  .map((d) => {
@@ -149,6 +150,12 @@ function scanMilestoneIdsFromDir(dir: string): string[] {
149
150
  if (MILESTONE_ID_RE.test(d.name)) {
150
151
  return d.name;
151
152
  }
153
+ // Legacy recovery/imports may contain bare numeric milestone directories
154
+ // (for example `milestones/15/15-ROADMAP.md`). The DB can preserve that
155
+ // id, and rebuild renders it, so drift scans must see it too.
156
+ if (/^\d+$/.test(d.name)) {
157
+ return d.name;
158
+ }
152
159
  // Legacy layout: M001-abcdef-slug descriptor directories
153
160
  const legacyMatch = d.name.match(/^(M\d{3}(?:-[a-z0-9]{6})?)-/);
154
161
  if (legacyMatch) {
@@ -162,6 +169,10 @@ function scanMilestoneIdsFromDir(dir: string): string[] {
162
169
  if (MILESTONE_ID_RE.test(fromSlug)) {
163
170
  return fromSlug;
164
171
  }
172
+ const numericId = String(phaseNum);
173
+ if (legacyNumericIds.has(numericId)) {
174
+ return numericId;
175
+ }
165
176
  return `M${String(phaseNum).padStart(3, "0")}`;
166
177
  }
167
178
  return null;
@@ -169,6 +180,24 @@ function scanMilestoneIdsFromDir(dir: string): string[] {
169
180
  .filter((id): id is string => id !== null);
170
181
  }
171
182
 
183
+ function idsWithLegacyNumericDirs(basePath: string): Set<string> {
184
+ const legacyDir = join(gsdProjectionRoot(basePath), "milestones");
185
+ const ids = new Set<string>();
186
+ try {
187
+ for (const entry of readdirSync(legacyDir, { withFileTypes: true })) {
188
+ if (entry.isDirectory() && /^\d+$/.test(entry.name)) ids.add(entry.name);
189
+ }
190
+ } catch (err) {
191
+ // A missing legacy directory is the common, benign case (nothing to
192
+ // consult). Only surface a real failure when the directory exists but
193
+ // could not be read.
194
+ if (existsSync(legacyDir)) {
195
+ logWarning("engine", `idsWithLegacyNumericDirs: ${legacyDir} exists but readdirSync failed — ${getErrorMessage(err)}`);
196
+ }
197
+ }
198
+ return ids;
199
+ }
200
+
172
201
  /** Scan the milestones directory and return IDs sorted by queue order (or numeric fallback). */
173
202
  export function findMilestoneIds(basePath: string): string[] {
174
203
  const root = gsdProjectionRoot(basePath);
@@ -181,7 +210,7 @@ export function findMilestoneIds(basePath: string): string[] {
181
210
  const ids = new Set<string>();
182
211
  for (const dir of dirs) {
183
212
  try {
184
- for (const id of scanMilestoneIdsFromDir(dir)) ids.add(id);
213
+ for (const id of scanMilestoneIdsFromDir(basePath, dir)) ids.add(id);
185
214
  } catch (err) {
186
215
  if (existsSync(dir)) {
187
216
  logWarning("engine", `findMilestoneIds: ${dir} exists but readdirSync failed — ${getErrorMessage(err)}`);
@@ -19,6 +19,16 @@ import { resolveTasksDir } from "./paths.js";
19
19
 
20
20
  /** Large enough for unbounded milestone-history git log scans in big repos. */
21
21
  const GIT_LOG_MAX_BUFFER = 16 * 1024 * 1024;
22
+ const LOG_FIELD_SEPARATOR = "\x1f";
23
+ const LOG_RECORD_SEPARATOR = "\x1e";
24
+
25
+ type CommitRecord = {
26
+ hash: string;
27
+ parents: string;
28
+ committedAt: string;
29
+ message: string;
30
+ files: string[];
31
+ };
22
32
 
23
33
  /**
24
34
  * Check whether a milestone produced implementation artifacts (non-`.gsd/`
@@ -198,7 +208,7 @@ function getChangedFilesFromMilestoneTaggedCommits(
198
208
  // Primary: path-scoped log against .gsd/milestones/<id>. Fast and unbounded
199
209
  // by depth when .gsd/ is tracked in git.
200
210
  const scoped = scanGsdTaggedCommits(basePath, milestoneId, [
201
- "log", "--format=%H%x1f%B%x1e", "HEAD", "--", `.gsd/milestones/${milestoneId}`,
211
+ "log", "--full-diff", "--name-only", "--format=%x1e%H%x1f%B%x1f", "HEAD", "--", `.gsd/milestones/${milestoneId}`,
202
212
  ]);
203
213
  if (!scoped.ok) return scoped;
204
214
  if (scoped.matched && classifyImplementationFiles(scoped.files) === "present") return scoped;
@@ -213,7 +223,7 @@ function getChangedFilesFromMilestoneTaggedCommits(
213
223
  // reintroducing the rolling-depth failure class removed in #4699 where
214
224
  // milestone evidence aged out behind unrelated activity.
215
225
  const unscoped = scanGsdTaggedCommits(basePath, milestoneId, [
216
- "log", "--format=%H%x1f%B%x1e", "HEAD",
226
+ "log", "--name-only", "--format=%x1e%H%x1f%B%x1f", "HEAD",
217
227
  ]);
218
228
  if (!unscoped.ok) return scoped.matched ? scoped : unscoped;
219
229
  if (!unscoped.matched) return scoped;
@@ -299,8 +309,7 @@ function backfillChangedFilesFromUntaggedMilestoneCommits(
299
309
  if (record.parents.trim().split(/\s+/).filter(Boolean).length > 1) continue;
300
310
  if (commitMessageHasGsdTrailer(record.message)) continue;
301
311
 
302
- const commitFiles = getChangedFilesForCommit(basePath, record.hash);
303
- const implementationFiles = commitFiles.map(normalizeRepoPath).filter(isImplementationPath);
312
+ const implementationFiles = record.files.map(normalizeRepoPath).filter(isImplementationPath);
304
313
  if (implementationFiles.length === 0) continue;
305
314
  if (!implementationFiles.some((file) => hintSet.has(file))) continue;
306
315
 
@@ -323,25 +332,30 @@ function backfillChangedFilesFromUntaggedMilestoneCommits(
323
332
  }
324
333
  }
325
334
 
326
- function getCommitRecords(basePath: string): Array<{ hash: string; parents: string; committedAt: string; message: string }> {
327
- const logOutput = execFileSync("git", ["log", "--format=%H%x1f%P%x1f%cI%x1f%B%x1e", "HEAD"], {
335
+ function getCommitRecords(basePath: string): CommitRecord[] {
336
+ const logOutput = execFileSync("git", ["log", "--name-only", "--format=%x1e%H%x1f%P%x1f%cI%x1f%B%x1f", "HEAD"], {
328
337
  cwd: basePath,
329
338
  stdio: ["ignore", "pipe", "pipe"],
330
339
  encoding: "utf-8",
331
340
  maxBuffer: GIT_LOG_MAX_BUFFER,
332
341
  });
333
342
  return logOutput
334
- .split("\x1e")
335
- .map((record) => record.trim())
343
+ .split(LOG_RECORD_SEPARATOR)
336
344
  .filter(Boolean)
337
345
  .flatMap((record) => {
338
- const parts = record.split("\x1f");
339
- if (parts.length < 4) return [];
340
- const [hash, parents, committedAt, ...messageParts] = parts;
341
- return [{ hash: hash.trim(), parents: parents.trim(), committedAt: committedAt.trim(), message: messageParts.join("\x1f") }];
346
+ const parts = record.split(LOG_FIELD_SEPARATOR);
347
+ if (parts.length < 5) return [];
348
+ const [hash, parents, committedAt] = parts;
349
+ const files = parseNameOnlyFiles(parts.at(-1) ?? "");
350
+ const message = parts.slice(3, -1).join(LOG_FIELD_SEPARATOR);
351
+ return [{ hash: hash.trim(), parents: parents.trim(), committedAt: committedAt.trim(), message, files }];
342
352
  });
343
353
  }
344
354
 
355
+ function parseNameOnlyFiles(rawFiles: string): string[] {
356
+ return rawFiles.split(/\r?\n/).map((file) => file.trim()).filter(Boolean);
357
+ }
358
+
345
359
  function isFullCommitSha(value: string): boolean {
346
360
  return /^[0-9a-f]{40}$/i.test(value);
347
361
  }
@@ -359,23 +373,23 @@ function scanGsdTaggedCommits(
359
373
  maxBuffer: GIT_LOG_MAX_BUFFER,
360
374
  });
361
375
  const records = logOutput
362
- .split("\x1e")
363
- .map((record) => record.trim())
376
+ .split(LOG_RECORD_SEPARATOR)
364
377
  .filter(Boolean)
365
378
  .flatMap((record) => {
366
- const sep = record.indexOf("\x1f");
367
- if (sep === -1) return [];
368
- const hash = record.slice(0, sep).trim();
369
- const message = record.slice(sep + 1);
370
- return [{ hash, message }];
379
+ const parts = record.split(LOG_FIELD_SEPARATOR);
380
+ if (parts.length < 3) return [];
381
+ const hash = parts[0].trim();
382
+ if (!hash) return [];
383
+ const files = parseNameOnlyFiles(parts.at(-1) ?? "");
384
+ const message = parts.slice(1, -1).join(LOG_FIELD_SEPARATOR);
385
+ return [{ message, files }];
371
386
  });
372
387
 
373
388
  const files = new Set<string>();
374
389
  let matched = false;
375
- for (const { hash, message } of records) {
390
+ for (const { message, files: commitFiles } of records) {
376
391
  if (!commitMessageHasGsdTrailer(message)) continue;
377
392
 
378
- const commitFiles = getChangedFilesForCommit(basePath, hash);
379
393
  if (!commitMatchesMilestone(basePath, message, milestoneId, commitFiles)) continue;
380
394
 
381
395
  matched = true;
@@ -16,18 +16,20 @@ You are running the GSD **code-review** workflow — review source files changed
16
16
 
17
17
  1. **Determine the file set.** Use the explicit `--files` list if provided. Otherwise derive the changed source files from the active slice's recent commits / SUMMARY, or fall back to the git diff against the base branch. Exclude `.gsd/`, lockfiles, generated/vendored code, and docs unless `--files` names them.
18
18
 
19
- 2. **Review each file** at the requested depth:
19
+ 2. **Gather diff-first context.** Run `git diff` for the file set (or the relevant commit range) and use that as the primary review evidence. Use `read` only when the diff is insufficient — new/untracked files, truncated hunks, or missing surrounding context needed for a finding. Do **not** read every changed file when the diff already covers the edits. If the Tool Call Loop Guard blocks a tool, stop calling tools for the rest of this turn and continue in text.
20
+
21
+ 3. **Review at the requested depth:**
20
22
  - **quick** — bugs, security, and correctness only.
21
23
  - **standard** (default) — quick + maintainability, error handling, edge cases.
22
24
  - **deep** — standard + performance, concurrency, API design, test coverage gaps.
23
25
 
24
26
  Ground every finding in the actual code with file path + line reference. Categorize each by severity (critical / warning / nit) and type (bug, security, quality, performance).
25
27
 
26
- 3. **Write the review.** Produce `.gsd/reviews/{{reviewId}}-REVIEW.md` with the findings table and per-finding detail (location, issue, suggested fix).
28
+ 4. **Write the review.** Produce `.gsd/reviews/{{reviewId}}-REVIEW.md` with the findings table and per-finding detail (location, issue, suggested fix).
27
29
 
28
- 4. **Present results.** Summarize counts by severity and list the critical findings first.
30
+ 5. **Present results.** Summarize counts by severity and list the critical findings first.
29
31
 
30
- 5. **Fix mode** (only when `--fix` is set): for each finding that is safely auto-fixable (deterministic, no behavior change beyond the fix), apply it. After each fix batch, run the project's tests. Commit atomically with the finding IDs referenced in the message. Do not auto-apply findings that are ambiguous or that change public behavior — surface those for a human decision instead.
32
+ 6. **Fix mode** (only when `--fix` is set): for each finding that is safely auto-fixable (deterministic, no behavior change beyond the fix), apply it. After each fix batch, run the project's tests. Commit atomically with the finding IDs referenced in the message. Do not auto-apply findings that are ambiguous or that change public behavior — surface those for a human decision instead.
31
33
 
32
34
  ## Success criteria
33
35
 
@@ -10,8 +10,8 @@
10
10
  */
11
11
 
12
12
  import type { ExtensionAPI, ExtensionCommandContext } from "@gsd/pi-coding-agent";
13
- import { existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, rmSync, writeFileSync } from "node:fs";
14
- import { isAbsolute, join, relative } from "node:path";
13
+ import { existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, rmSync, writeFileSync } from "node:fs";
14
+ import { isAbsolute, join, relative, resolve } from "node:path";
15
15
  import { QUICK_BRANCH_RE } from "./branch-patterns.js";
16
16
  import { loadPrompt } from "./prompt-loader.js";
17
17
  import { gsdRoot } from "./paths.js";
@@ -31,6 +31,7 @@ interface QuickReturnState {
31
31
  }
32
32
 
33
33
  let pendingQuickReturn: QuickReturnState | null = null;
34
+ const pendingQuickReturnMisses = new Map<string, string>();
34
35
 
35
36
  // ─── Quick Task Helpers ───────────────────────────────────────────────────────
36
37
 
@@ -189,12 +190,35 @@ export function buildQuickCommitInstruction(basePath: string, root: string): str
189
190
  ].join("\n");
190
191
  }
191
192
 
193
+ function readHeadBranchName(basePath: string): string | null {
194
+ try {
195
+ const gitPath = join(basePath, ".git");
196
+ if (!existsSync(gitPath)) return null;
197
+
198
+ let headPath: string;
199
+ if (lstatSync(gitPath).isDirectory()) {
200
+ headPath = join(gitPath, "HEAD");
201
+ } else {
202
+ const gitFile = readFileSync(gitPath, "utf-8").trim();
203
+ if (!gitFile.startsWith("gitdir: ")) return null;
204
+ headPath = join(resolve(basePath, gitFile.slice("gitdir: ".length)), "HEAD");
205
+ }
206
+
207
+ const head = readFileSync(headPath, "utf-8").trim();
208
+ if (!head.startsWith("ref: refs/heads/")) return null;
209
+ return head.slice("ref: refs/heads/".length);
210
+ } catch {
211
+ return null;
212
+ }
213
+ }
214
+
192
215
  function quickReturnStatePath(basePath: string): string {
193
216
  return join(gsdRoot(basePath), "runtime", "quick-return.json");
194
217
  }
195
218
 
196
219
  function persistPendingReturn(state: QuickReturnState): void {
197
220
  pendingQuickReturn = state;
221
+ pendingQuickReturnMisses.delete(state.basePath);
198
222
  mkdirSync(join(gsdRoot(state.basePath), "runtime"), { recursive: true });
199
223
  writeFileSync(quickReturnStatePath(state.basePath), JSON.stringify(state) + "\n", "utf-8");
200
224
  }
@@ -203,6 +227,13 @@ function readPendingReturn(basePath: string): QuickReturnState | null {
203
227
  if (pendingQuickReturn && pendingQuickReturn.basePath === basePath) {
204
228
  return pendingQuickReturn;
205
229
  }
230
+ if (pendingQuickReturnMisses.has(basePath)) {
231
+ const statePath = quickReturnStatePath(basePath);
232
+ if (!existsSync(statePath) && readHeadBranchName(basePath) === pendingQuickReturnMisses.get(basePath)) {
233
+ return null;
234
+ }
235
+ pendingQuickReturnMisses.delete(basePath);
236
+ }
206
237
 
207
238
  try {
208
239
  const raw = readFileSync(quickReturnStatePath(basePath), "utf-8");
@@ -216,6 +247,7 @@ function readPendingReturn(basePath: string): QuickReturnState | null {
216
247
  && typeof parsed.description === "string"
217
248
  ) {
218
249
  pendingQuickReturn = parsed as QuickReturnState;
250
+ pendingQuickReturnMisses.delete(basePath);
219
251
  return pendingQuickReturn;
220
252
  }
221
253
  } catch {
@@ -225,9 +257,14 @@ function readPendingReturn(basePath: string): QuickReturnState | null {
225
257
  const inferred = inferQuickReturnFromBranch(basePath);
226
258
  if (inferred) {
227
259
  pendingQuickReturn = inferred;
260
+ pendingQuickReturnMisses.delete(basePath);
228
261
  return inferred;
229
262
  }
230
263
 
264
+ const branchAtMiss = readHeadBranchName(basePath);
265
+ if (branchAtMiss) {
266
+ pendingQuickReturnMisses.set(basePath, branchAtMiss);
267
+ }
231
268
  return null;
232
269
  }
233
270
 
@@ -235,6 +272,10 @@ function clearPendingReturn(basePath: string): void {
235
272
  if (pendingQuickReturn?.basePath === basePath) {
236
273
  pendingQuickReturn = null;
237
274
  }
275
+ const branchAtMiss = readHeadBranchName(basePath);
276
+ if (branchAtMiss) {
277
+ pendingQuickReturnMisses.set(basePath, branchAtMiss);
278
+ }
238
279
  rmSync(quickReturnStatePath(basePath), { force: true });
239
280
  }
240
281
 
@@ -223,11 +223,21 @@ export function extractTrace(entries: unknown[]): ExecutionTrace {
223
223
 
224
224
  // Flush any pending tool calls that never got results (crash mid-tool)
225
225
  for (const [, pending] of pendingTools) {
226
+ const missingResultError = `Tool call ${pending.name} started but no toolResult was recorded`;
226
227
  toolCalls.push({
227
228
  name: pending.name,
228
229
  input: redactInput(pending.name, pending.input),
229
- isError: false,
230
+ result: "missing tool result (stream/tool-call abort before execution)",
231
+ isError: true,
230
232
  });
233
+ errors.push(missingResultError);
234
+
235
+ // Mark the matching commandsRun entry as failed so it is consistent with
236
+ // the isError: true on the tool call above (bash/bg_shell only).
237
+ if (pending.name === "bash" || pending.name === "bg_shell") {
238
+ const lastCmd = findLast(commandsRun, c => c.command === String(pending.input.command));
239
+ if (lastCmd) lastCmd.failed = true;
240
+ }
231
241
  }
232
242
 
233
243
  return {
@@ -66,7 +66,7 @@ These commands dispatch native GSD prompts adapted to the milestone, slice, and
66
66
  | `progress` | Summarize recent work; can route `--next` or `--do "..."` |
67
67
  | `health` | Check `.gsd/` integrity (`--repair`, `--context`) |
68
68
  | `surface` | Manage surfaced skills and extensions |
69
- | `code-review` | Review changed source for bugs, security, and quality |
69
+ | `code-review` | Review changed source diff-first for bugs, security, and quality |
70
70
  | `review` | Peer-review recent work across reviewer perspectives |
71
71
  | `audit-milestone` | Verify a milestone met its definition of done |
72
72
  | `audit-uat` | Audit outstanding UAT/verification items |
@@ -0,0 +1,46 @@
1
+ // Project/App: gsd-pi
2
+ // File Purpose: deriveState memoization cache and telemetry.
3
+
4
+ import type { GSDState } from '../../types.js';
5
+
6
+ interface StateCache {
7
+ basePath: string;
8
+ result: GSDState;
9
+ timestamp: number;
10
+ }
11
+
12
+ const CACHE_TTL_MS = 100;
13
+ let _stateCache: StateCache | null = null;
14
+
15
+ let _telemetry = { dbDeriveCount: 0 };
16
+
17
+ export function getDeriveTelemetry() {
18
+ return { ..._telemetry };
19
+ }
20
+
21
+ export function resetDeriveTelemetry() {
22
+ _telemetry = { dbDeriveCount: 0 };
23
+ }
24
+
25
+ export function incrementDbDeriveCount(): void {
26
+ _telemetry.dbDeriveCount++;
27
+ }
28
+
29
+ export function invalidateStateCache(): void {
30
+ _stateCache = null;
31
+ }
32
+
33
+ export function readCachedDeriveState(cacheKey: string): GSDState | null {
34
+ if (
35
+ _stateCache &&
36
+ _stateCache.basePath === cacheKey &&
37
+ Date.now() - _stateCache.timestamp < CACHE_TTL_MS
38
+ ) {
39
+ return _stateCache.result;
40
+ }
41
+ return null;
42
+ }
43
+
44
+ export function writeCachedDeriveState(cacheKey: string, result: GSDState): void {
45
+ _stateCache = { basePath: cacheKey, result, timestamp: Date.now() };
46
+ }
@@ -0,0 +1,45 @@
1
+ // Project/App: gsd-pi
2
+ // File Purpose: Workflow DB open helpers for state derivation.
3
+
4
+ import type { GSDState } from '../../types.js';
5
+ import { getAllMilestones, isDbAvailable, setMilestoneQueueOrder } from '../../gsd-db.js';
6
+ import { openExistingWorkflowDatabase } from '../../db-workspace.js';
7
+ import { loadQueueOrder, sortByQueueOrder } from '../../queue-order.js';
8
+
9
+ export function syncQueueOrderProjectionToDb(basePath: string): void {
10
+ const queueOrder = loadQueueOrder(basePath);
11
+ if (!queueOrder) return;
12
+
13
+ const currentIds = getAllMilestones().map((m) => m.id);
14
+ const desiredIds = sortByQueueOrder(currentIds, queueOrder);
15
+ if (currentIds.length === desiredIds.length && currentIds.every((id, i) => id === desiredIds[i])) return;
16
+
17
+ setMilestoneQueueOrder(desiredIds);
18
+ }
19
+
20
+ export function ensureExistingWorkflowDbOpen(basePath: string): boolean {
21
+ const opened = isDbAvailable() || openExistingWorkflowDatabase(basePath).ok;
22
+ if (opened) syncQueueOrderProjectionToDb(basePath);
23
+ return opened;
24
+ }
25
+
26
+ export function buildDbUnavailableState(): GSDState {
27
+ return {
28
+ activeMilestone: null,
29
+ activeSlice: null,
30
+ activeTask: null,
31
+ phase: "pre-planning",
32
+ recentDecisions: [],
33
+ blockers: ["DB unavailable — runtime markdown state derivation is disabled"],
34
+ nextAction:
35
+ "Open or create the canonical GSD database before deriving workflow state. If this project only has markdown state, run /gsd migrate explicitly.",
36
+ registry: [],
37
+ requirements: { active: 0, validated: 0, deferred: 0, outOfScope: 0, blocked: 0, total: 0 },
38
+ progress: { milestones: { done: 0, total: 0 } },
39
+ };
40
+ }
41
+
42
+ export function getRequestedMilestoneLock(): string | undefined {
43
+ const lock = process.env.GSD_MILESTONE_LOCK?.trim();
44
+ return lock || undefined;
45
+ }