@opengsd/gsd-pi 1.3.0-dev.65546769 → 1.3.0-dev.965d1788

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 (411) hide show
  1. package/README.md +1 -1
  2. package/dist/resources/.managed-resources-content-hash +1 -1
  3. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +11 -2
  4. package/dist/resources/extensions/google-cli/stream-adapter.js +82 -15
  5. package/dist/resources/extensions/gsd/artifact-verification.js +427 -0
  6. package/dist/resources/extensions/gsd/auto/orchestrator.js +12 -3
  7. package/dist/resources/extensions/gsd/auto/session.js +3 -0
  8. package/dist/resources/extensions/gsd/auto/verification-retry-policy.js +1 -1
  9. package/dist/resources/extensions/gsd/auto-artifact-paths.js +28 -1
  10. package/dist/resources/extensions/gsd/auto-dispatch.js +20 -19
  11. package/dist/resources/extensions/gsd/auto-post-unit.js +1 -1
  12. package/dist/resources/extensions/gsd/auto-prompts.js +26 -11
  13. package/dist/resources/extensions/gsd/auto-recovery.js +6 -507
  14. package/dist/resources/extensions/gsd/auto-runtime-state.js +4 -5
  15. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +3 -3
  16. package/dist/resources/extensions/gsd/auto-verification.js +5 -2
  17. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +103 -13
  18. package/dist/resources/extensions/gsd/bootstrap/core-session-tools.js +38 -0
  19. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +6 -1
  20. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +2 -0
  21. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +16 -19
  22. package/dist/resources/extensions/gsd/bootstrap/system-context.js +46 -19
  23. package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +68 -10
  24. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +1 -1
  25. package/dist/resources/extensions/gsd/closeout-consistency-gate.js +3 -1
  26. package/dist/resources/extensions/gsd/commands-context.js +19 -1
  27. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +16 -10
  28. package/dist/resources/extensions/gsd/commands-worktree.js +12 -10
  29. package/dist/resources/extensions/gsd/dashboard-overlay.js +32 -3
  30. package/dist/resources/extensions/gsd/db/queries.js +60 -0
  31. package/dist/resources/extensions/gsd/db-workspace.js +55 -3
  32. package/dist/resources/extensions/gsd/doctor-providers.js +92 -8
  33. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +3 -0
  34. package/dist/resources/extensions/gsd/exec-sandbox.js +45 -9
  35. package/dist/resources/extensions/gsd/flat-phase-migration.js +45 -0
  36. package/dist/resources/extensions/gsd/forensics.js +2 -32
  37. package/dist/resources/extensions/gsd/git-service.js +5 -4
  38. package/dist/resources/extensions/gsd/gitignore.js +3 -0
  39. package/dist/resources/extensions/gsd/guided-flow-queue.js +66 -5
  40. package/dist/resources/extensions/gsd/health-widget.js +55 -29
  41. package/dist/resources/extensions/gsd/json-persistence.js +20 -0
  42. package/dist/resources/extensions/gsd/knowledge-backfill.js +18 -11
  43. package/dist/resources/extensions/gsd/layout-policy.js +3 -1
  44. package/dist/resources/extensions/gsd/markdown-renderer.js +8 -9
  45. package/dist/resources/extensions/gsd/memory-backfill.js +28 -21
  46. package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +44 -21
  47. package/dist/resources/extensions/gsd/metrics.js +4 -4
  48. package/dist/resources/extensions/gsd/migration-auto-check.js +22 -0
  49. package/dist/resources/extensions/gsd/milestone-ids.js +32 -2
  50. package/dist/resources/extensions/gsd/milestone-implementation-evidence.js +26 -20
  51. package/dist/resources/extensions/gsd/orphan-stash-audit.js +92 -16
  52. package/dist/resources/extensions/gsd/prompts/code-review.md +6 -4
  53. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  54. package/dist/resources/extensions/gsd/quick.js +45 -2
  55. package/dist/resources/extensions/gsd/safety/file-change-validator.js +5 -2
  56. package/dist/resources/extensions/gsd/session-forensics.js +11 -1
  57. package/dist/resources/extensions/gsd/skills/gsd-headless/references/commands.md +1 -1
  58. package/dist/resources/extensions/gsd/state/derive/cache.js +28 -0
  59. package/dist/resources/extensions/gsd/state/derive/db-open.js +39 -0
  60. package/dist/resources/extensions/gsd/state/derive/from-db.js +452 -0
  61. package/dist/resources/extensions/gsd/state/derive/index.js +75 -0
  62. package/dist/resources/extensions/gsd/state/derive/interrupted-work.js +21 -0
  63. package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-render.js +45 -2
  64. package/dist/resources/extensions/gsd/state-reconciliation/index.js +48 -23
  65. package/dist/resources/extensions/gsd/state-reconciliation/registry.js +32 -28
  66. package/dist/resources/extensions/gsd/state.js +12 -611
  67. package/dist/resources/extensions/gsd/tools/complete-milestone.js +4 -2
  68. package/dist/resources/extensions/gsd/tools/complete-slice.js +2 -2
  69. package/dist/resources/extensions/gsd/tools/complete-task.js +43 -14
  70. package/dist/resources/extensions/gsd/tools/exec-tool.js +7 -2
  71. package/dist/resources/extensions/gsd/undo.js +43 -6
  72. package/dist/resources/extensions/gsd/unit-context-composer.js +23 -7
  73. package/dist/resources/extensions/gsd/unit-registry.js +32 -4
  74. package/dist/resources/extensions/gsd/unmerged-milestone-guard.js +33 -3
  75. package/dist/resources/extensions/gsd/validation-block-guard.js +9 -4
  76. package/dist/resources/extensions/gsd/verification-gate.js +7 -0
  77. package/dist/resources/extensions/gsd/workflow-manifest.js +4 -1
  78. package/dist/resources/extensions/gsd/workflow-projections.js +19 -14
  79. package/dist/resources/extensions/gsd/workspace-git-preflight.js +30 -1
  80. package/dist/resources/extensions/gsd/worktree-manager.js +44 -2
  81. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  82. package/dist/web/standalone/.next/BUILD_ID +1 -1
  83. package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -12
  84. package/dist/web/standalone/.next/build-manifest.json +3 -3
  85. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  86. package/dist/web/standalone/.next/react-loadable-manifest.json +9 -9
  87. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  88. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  89. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  90. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  91. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  97. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  98. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  101. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  102. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  103. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  104. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  106. package/dist/web/standalone/.next/server/app/index.html +1 -1
  107. package/dist/web/standalone/.next/server/app/index.rsc +2 -2
  108. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  109. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
  110. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  114. package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
  115. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  116. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  118. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  119. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  120. package/dist/web/standalone/.next/static/chunks/{2659.b7b129ee6a769448.js → 2659.58e950899a9bb82f.js} +1 -1
  121. package/dist/web/standalone/.next/static/chunks/2772.a7c1fcc69a4685ef.js +1 -0
  122. package/dist/web/standalone/.next/static/chunks/{3616.3c60753b8ffcbd2e.js → 3616.61a2af74bb8833c8.js} +1 -1
  123. package/dist/web/standalone/.next/static/chunks/{4283.8e446784528ed9dc.js → 4283.d0d9e0a955e441cb.js} +1 -1
  124. package/dist/web/standalone/.next/static/chunks/{5826.a46ecdd1cfe8dabc.js → 5826.5421d66c72b9f34e.js} +1 -1
  125. package/dist/web/standalone/.next/static/chunks/{8785.481aa5869991b760.js → 8785.e29b3134cab1d153.js} +1 -1
  126. package/dist/web/standalone/.next/static/chunks/8937.640dc9c2aaa1dfad.js +10 -0
  127. package/dist/web/standalone/.next/static/chunks/app/{page-6644fc6ee8ca1247.js → page-72a856634ad14c10.js} +1 -1
  128. package/dist/web/standalone/.next/static/chunks/webpack-9c401904f87ded16.js +1 -0
  129. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  130. package/package.json +1 -1
  131. package/packages/cloud-mcp-gateway/package.json +2 -2
  132. package/packages/contracts/dist/workflow.d.ts +1 -0
  133. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  134. package/packages/contracts/dist/workflow.js +2 -0
  135. package/packages/contracts/dist/workflow.js.map +1 -1
  136. package/packages/contracts/package.json +1 -1
  137. package/packages/daemon/package.json +4 -4
  138. package/packages/gsd-agent-core/dist/agent-session.d.ts +1 -0
  139. package/packages/gsd-agent-core/dist/agent-session.d.ts.map +1 -1
  140. package/packages/gsd-agent-core/dist/agent-session.js +3 -0
  141. package/packages/gsd-agent-core/dist/agent-session.js.map +1 -1
  142. package/packages/gsd-agent-core/dist/extension-ui-snapshot.d.ts +41 -0
  143. package/packages/gsd-agent-core/dist/extension-ui-snapshot.d.ts.map +1 -0
  144. package/packages/gsd-agent-core/dist/extension-ui-snapshot.js +62 -0
  145. package/packages/gsd-agent-core/dist/extension-ui-snapshot.js.map +1 -0
  146. package/packages/gsd-agent-core/dist/index.d.ts +2 -0
  147. package/packages/gsd-agent-core/dist/index.d.ts.map +1 -1
  148. package/packages/gsd-agent-core/dist/index.js +2 -0
  149. package/packages/gsd-agent-core/dist/index.js.map +1 -1
  150. package/packages/gsd-agent-core/dist/session/agent-session-events.js +1 -1
  151. package/packages/gsd-agent-core/dist/session/agent-session-events.js.map +1 -1
  152. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts +1 -0
  153. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts.map +1 -1
  154. package/packages/gsd-agent-core/dist/session/agent-session-host.js.map +1 -1
  155. package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts +5 -0
  156. package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts.map +1 -1
  157. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js +60 -3
  158. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js.map +1 -1
  159. package/packages/gsd-agent-core/dist/transcript-store.d.ts +58 -0
  160. package/packages/gsd-agent-core/dist/transcript-store.d.ts.map +1 -0
  161. package/packages/gsd-agent-core/dist/transcript-store.js +132 -0
  162. package/packages/gsd-agent-core/dist/transcript-store.js.map +1 -0
  163. package/packages/gsd-agent-core/package.json +5 -5
  164. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +2 -0
  165. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  166. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +25 -11
  167. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  168. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.d.ts +4 -0
  169. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.d.ts.map +1 -0
  170. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.js +7 -0
  171. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.js.map +1 -0
  172. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts +3 -24
  173. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  174. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +26 -829
  175. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  176. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.d.ts +58 -0
  177. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.d.ts.map +1 -0
  178. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.js +312 -0
  179. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.js.map +1 -0
  180. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.d.ts +31 -0
  181. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.d.ts.map +1 -0
  182. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.js +130 -0
  183. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.js.map +1 -0
  184. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts +15 -0
  185. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts.map +1 -0
  186. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js +258 -0
  187. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js.map +1 -0
  188. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.d.ts +13 -0
  189. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.d.ts.map +1 -0
  190. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.js +118 -0
  191. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.js.map +1 -0
  192. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts +9 -0
  193. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  194. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.js +1 -1
  195. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  196. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.d.ts +54 -0
  197. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.d.ts.map +1 -0
  198. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.js +20 -0
  199. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.js.map +1 -0
  200. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts +4 -1
  201. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  202. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +9 -0
  203. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
  204. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.d.ts +56 -0
  205. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.d.ts.map +1 -0
  206. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.js +44 -0
  207. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.js.map +1 -0
  208. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.d.ts +5 -0
  209. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.d.ts.map +1 -0
  210. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.js +77 -0
  211. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.js.map +1 -0
  212. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  213. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +18 -0
  214. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
  215. package/packages/gsd-agent-modes/package.json +7 -7
  216. package/packages/mcp-server/README.md +1 -1
  217. package/packages/mcp-server/dist/server.d.ts +1 -1
  218. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  219. package/packages/mcp-server/dist/server.js +3 -3
  220. package/packages/mcp-server/dist/server.js.map +1 -1
  221. package/packages/mcp-server/dist/workflow-tools.d.ts +13 -1
  222. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  223. package/packages/mcp-server/dist/workflow-tools.js +34 -20
  224. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  225. package/packages/mcp-server/package.json +4 -4
  226. package/packages/native/package.json +1 -1
  227. package/packages/pi-agent-core/package.json +1 -1
  228. package/packages/pi-ai/package.json +1 -1
  229. package/packages/pi-coding-agent/README.md +3 -2
  230. package/packages/pi-coding-agent/dist/core/session-manager-context.d.ts +9 -0
  231. package/packages/pi-coding-agent/dist/core/session-manager-context.d.ts.map +1 -0
  232. package/packages/pi-coding-agent/dist/core/session-manager-context.js +94 -0
  233. package/packages/pi-coding-agent/dist/core/session-manager-context.js.map +1 -0
  234. package/packages/pi-coding-agent/dist/core/session-manager-list.d.ts +8 -0
  235. package/packages/pi-coding-agent/dist/core/session-manager-list.d.ts.map +1 -0
  236. package/packages/pi-coding-agent/dist/core/session-manager-list.js +244 -0
  237. package/packages/pi-coding-agent/dist/core/session-manager-list.js.map +1 -0
  238. package/packages/pi-coding-agent/dist/core/session-manager-migration.d.ts +12 -0
  239. package/packages/pi-coding-agent/dist/core/session-manager-migration.d.ts.map +1 -0
  240. package/packages/pi-coding-agent/dist/core/session-manager-migration.js +84 -0
  241. package/packages/pi-coding-agent/dist/core/session-manager-migration.js.map +1 -0
  242. package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts +135 -0
  243. package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts.map +1 -0
  244. package/packages/pi-coding-agent/dist/core/session-manager-types.js +2 -0
  245. package/packages/pi-coding-agent/dist/core/session-manager-types.js.map +1 -0
  246. package/packages/pi-coding-agent/dist/core/session-manager.d.ts +6 -154
  247. package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
  248. package/packages/pi-coding-agent/dist/core/session-manager.js +22 -459
  249. package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
  250. package/packages/pi-coding-agent/dist/theme/theme-schema.d.ts +75 -75
  251. package/packages/pi-coding-agent/dist/theme/theme-schema.d.ts.map +1 -1
  252. package/packages/pi-coding-agent/dist/theme/theme-schema.js +1 -1
  253. package/packages/pi-coding-agent/dist/theme/theme-schema.js.map +1 -1
  254. package/packages/pi-coding-agent/dist/theme/theme.d.ts.map +1 -1
  255. package/packages/pi-coding-agent/dist/theme/theme.js +11 -7
  256. package/packages/pi-coding-agent/dist/theme/theme.js.map +1 -1
  257. package/packages/pi-coding-agent/package.json +7 -7
  258. package/packages/pi-tui/package.json +2 -2
  259. package/packages/rpc-client/package.json +2 -2
  260. package/pkg/dist/theme/theme-schema.d.ts +75 -75
  261. package/pkg/dist/theme/theme-schema.d.ts.map +1 -1
  262. package/pkg/dist/theme/theme-schema.js +1 -1
  263. package/pkg/dist/theme/theme-schema.js.map +1 -1
  264. package/pkg/dist/theme/theme.d.ts.map +1 -1
  265. package/pkg/dist/theme/theme.js +11 -7
  266. package/pkg/dist/theme/theme.js.map +1 -1
  267. package/pkg/package.json +1 -1
  268. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +20 -2
  269. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +80 -0
  270. package/src/resources/extensions/google-cli/stream-adapter.ts +106 -19
  271. package/src/resources/extensions/gsd/artifact-verification.ts +464 -0
  272. package/src/resources/extensions/gsd/auto/orchestrator.ts +25 -11
  273. package/src/resources/extensions/gsd/auto/session.ts +6 -0
  274. package/src/resources/extensions/gsd/auto/verification-retry-policy.ts +3 -1
  275. package/src/resources/extensions/gsd/auto-artifact-paths.ts +47 -1
  276. package/src/resources/extensions/gsd/auto-dispatch.ts +21 -23
  277. package/src/resources/extensions/gsd/auto-post-unit.ts +1 -1
  278. package/src/resources/extensions/gsd/auto-prompts.ts +38 -12
  279. package/src/resources/extensions/gsd/auto-recovery.ts +10 -508
  280. package/src/resources/extensions/gsd/auto-runtime-state.ts +4 -5
  281. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +3 -2
  282. package/src/resources/extensions/gsd/auto-verification.ts +5 -1
  283. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +125 -12
  284. package/src/resources/extensions/gsd/bootstrap/core-session-tools.ts +43 -0
  285. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +6 -1
  286. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +2 -0
  287. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +20 -19
  288. package/src/resources/extensions/gsd/bootstrap/system-context.ts +52 -18
  289. package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +74 -10
  290. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +1 -1
  291. package/src/resources/extensions/gsd/closeout-consistency-gate.ts +2 -1
  292. package/src/resources/extensions/gsd/commands-context.ts +18 -1
  293. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +14 -9
  294. package/src/resources/extensions/gsd/commands-worktree.ts +12 -10
  295. package/src/resources/extensions/gsd/dashboard-overlay.ts +32 -3
  296. package/src/resources/extensions/gsd/db/queries.ts +79 -0
  297. package/src/resources/extensions/gsd/db-workspace.ts +61 -3
  298. package/src/resources/extensions/gsd/doctor-providers.ts +103 -9
  299. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +3 -0
  300. package/src/resources/extensions/gsd/exec-sandbox.ts +49 -9
  301. package/src/resources/extensions/gsd/flat-phase-migration.ts +44 -0
  302. package/src/resources/extensions/gsd/forensics.ts +2 -33
  303. package/src/resources/extensions/gsd/git-service.ts +6 -5
  304. package/src/resources/extensions/gsd/gitignore.ts +3 -0
  305. package/src/resources/extensions/gsd/guided-flow-queue.ts +89 -4
  306. package/src/resources/extensions/gsd/health-widget.ts +69 -32
  307. package/src/resources/extensions/gsd/json-persistence.ts +20 -0
  308. package/src/resources/extensions/gsd/knowledge-backfill.ts +16 -10
  309. package/src/resources/extensions/gsd/layout-policy.ts +2 -1
  310. package/src/resources/extensions/gsd/markdown-renderer.ts +8 -11
  311. package/src/resources/extensions/gsd/memory-backfill.ts +26 -20
  312. package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +51 -19
  313. package/src/resources/extensions/gsd/metrics.ts +4 -4
  314. package/src/resources/extensions/gsd/migration-auto-check.ts +23 -0
  315. package/src/resources/extensions/gsd/milestone-ids.ts +31 -2
  316. package/src/resources/extensions/gsd/milestone-implementation-evidence.ts +35 -21
  317. package/src/resources/extensions/gsd/orphan-stash-audit.ts +108 -20
  318. package/src/resources/extensions/gsd/prompts/code-review.md +6 -4
  319. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  320. package/src/resources/extensions/gsd/quick.ts +43 -2
  321. package/src/resources/extensions/gsd/safety/file-change-validator.ts +8 -2
  322. package/src/resources/extensions/gsd/session-forensics.ts +11 -1
  323. package/src/resources/extensions/gsd/skills/gsd-headless/references/commands.md +1 -1
  324. package/src/resources/extensions/gsd/state/derive/cache.ts +46 -0
  325. package/src/resources/extensions/gsd/state/derive/db-open.ts +45 -0
  326. package/src/resources/extensions/gsd/state/derive/from-db.ts +561 -0
  327. package/src/resources/extensions/gsd/state/derive/index.ts +104 -0
  328. package/src/resources/extensions/gsd/state/derive/interrupted-work.ts +31 -0
  329. package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +81 -7
  330. package/src/resources/extensions/gsd/state-reconciliation/index.ts +50 -24
  331. package/src/resources/extensions/gsd/state-reconciliation/registry.ts +43 -28
  332. package/src/resources/extensions/gsd/state.ts +32 -732
  333. package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +4 -3
  334. package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +98 -1
  335. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +111 -1
  336. package/src/resources/extensions/gsd/tests/commands-context.test.ts +26 -0
  337. package/src/resources/extensions/gsd/tests/commands-gsd-core.test.ts +1 -0
  338. package/src/resources/extensions/gsd/tests/commands-worktree-clean.test.ts +80 -0
  339. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +28 -0
  340. package/src/resources/extensions/gsd/tests/complete-slice-reopen-handoff.test.ts +69 -0
  341. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +11 -0
  342. package/src/resources/extensions/gsd/tests/complete-task-rollback-evidence.test.ts +48 -8
  343. package/src/resources/extensions/gsd/tests/complete-task.test.ts +75 -0
  344. package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +55 -2
  345. package/src/resources/extensions/gsd/tests/decisions-projection-from-memories.test.ts +51 -0
  346. package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +26 -1
  347. package/src/resources/extensions/gsd/tests/doctor-forensics-db-open-regression.test.ts +70 -2
  348. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +107 -0
  349. package/src/resources/extensions/gsd/tests/exec-graceful-kill.test.ts +38 -0
  350. package/src/resources/extensions/gsd/tests/exec-tool.test.ts +45 -1
  351. package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +40 -0
  352. package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +37 -2
  353. package/src/resources/extensions/gsd/tests/forensics-error-filter.test.ts +88 -0
  354. package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +4 -0
  355. package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +42 -0
  356. package/src/resources/extensions/gsd/tests/health-widget.test.ts +268 -3
  357. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +130 -3
  358. package/src/resources/extensions/gsd/tests/integration/queue-active-milestone-context-budget.test.ts +93 -0
  359. package/src/resources/extensions/gsd/tests/integration/quick-branch-lifecycle.test.ts +56 -9
  360. package/src/resources/extensions/gsd/tests/json-persistence-atomic.test.ts +47 -0
  361. package/src/resources/extensions/gsd/tests/knowledge-backfill-projection.test.ts +35 -0
  362. package/src/resources/extensions/gsd/tests/knowledge-cold-start.test.ts +14 -0
  363. package/src/resources/extensions/gsd/tests/memory-consolidation-scanner.test.ts +78 -0
  364. package/src/resources/extensions/gsd/tests/merge-closeout-consistency-gate.test.ts +31 -1
  365. package/src/resources/extensions/gsd/tests/metrics-prune-cache-invalidation.test.ts +6 -0
  366. package/src/resources/extensions/gsd/tests/metrics.test.ts +1 -0
  367. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +70 -0
  368. package/src/resources/extensions/gsd/tests/orchestrator-logs.test.ts +43 -1
  369. package/src/resources/extensions/gsd/tests/orphan-stash-audit.test.ts +91 -7
  370. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +26 -0
  371. package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +2 -1
  372. package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +1 -1
  373. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +10 -0
  374. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +54 -1
  375. package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +50 -14
  376. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +195 -1
  377. package/src/resources/extensions/gsd/tests/read-uat-gate-verdict.test.ts +185 -0
  378. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +87 -0
  379. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +7 -0
  380. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +56 -0
  381. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +191 -0
  382. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +151 -0
  383. package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +26 -0
  384. package/src/resources/extensions/gsd/tests/undo.test.ts +74 -0
  385. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +193 -14
  386. package/src/resources/extensions/gsd/tests/unmerged-milestone-guard.test.ts +25 -0
  387. package/src/resources/extensions/gsd/tests/validation-block-guard.test.ts +79 -0
  388. package/src/resources/extensions/gsd/tests/verification-retry-policy.test.ts +69 -4
  389. package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +66 -0
  390. package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +54 -0
  391. package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +151 -2
  392. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +39 -0
  393. package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -2
  394. package/src/resources/extensions/gsd/tools/complete-slice.ts +2 -2
  395. package/src/resources/extensions/gsd/tools/complete-task.ts +53 -15
  396. package/src/resources/extensions/gsd/tools/exec-tool.ts +7 -3
  397. package/src/resources/extensions/gsd/undo.ts +47 -6
  398. package/src/resources/extensions/gsd/unit-context-composer.ts +33 -7
  399. package/src/resources/extensions/gsd/unit-registry.ts +32 -4
  400. package/src/resources/extensions/gsd/unmerged-milestone-guard.ts +41 -5
  401. package/src/resources/extensions/gsd/validation-block-guard.ts +13 -7
  402. package/src/resources/extensions/gsd/verification-gate.ts +8 -0
  403. package/src/resources/extensions/gsd/workflow-manifest.ts +4 -1
  404. package/src/resources/extensions/gsd/workflow-projections.ts +20 -14
  405. package/src/resources/extensions/gsd/workspace-git-preflight.ts +31 -0
  406. package/src/resources/extensions/gsd/worktree-manager.ts +41 -1
  407. package/dist/web/standalone/.next/static/chunks/2772.bfa657f49f955239.js +0 -1
  408. package/dist/web/standalone/.next/static/chunks/796.e0bdc932325d7e03.js +0 -10
  409. package/dist/web/standalone/.next/static/chunks/webpack-f46ea08200a0227e.js +0 -1
  410. /package/dist/web/standalone/.next/static/{BTKtGFF1Y-hvVJEGhBRo9 → -ji77QJck2IKIwrGza1Bs}/_buildManifest.js +0 -0
  411. /package/dist/web/standalone/.next/static/{BTKtGFF1Y-hvVJEGhBRo9 → -ji77QJck2IKIwrGza1Bs}/_ssgManifest.js +0 -0
@@ -59,6 +59,51 @@ export function needsFlatPhaseMigration(basePath) {
59
59
  // Resume an interrupted migration where the legacy tree was renamed aside.
60
60
  return hasLegacyMilestoneSubdirs(legacyMigratingPath(basePath));
61
61
  }
62
+ /** Retention window before flat-phase migration backups are auto-pruned. */
63
+ export const FLAT_PHASE_BACKUP_RETENTION_MS = 30 * 24 * 60 * 60 * 1000;
64
+ /**
65
+ * Remove stale flat-phase migration backups after the retention window.
66
+ * Only runs when migration is complete (.gsd/phases/ exists, legacy layout gone).
67
+ * Returns the number of migrate-* directories removed.
68
+ */
69
+ export function pruneStaleFlatPhaseBackups(basePath) {
70
+ if (needsFlatPhaseMigration(basePath))
71
+ return 0;
72
+ const phasesPath = join(basePath, ".gsd", LAYOUT_SEGMENTS.level1);
73
+ if (!existsSync(phasesPath))
74
+ return 0;
75
+ const backupRoot = join(basePath, ".gsd-backups");
76
+ if (!existsSync(backupRoot))
77
+ return 0;
78
+ const now = Date.now();
79
+ let removed = 0;
80
+ for (const entry of readdirSync(backupRoot)) {
81
+ if (!entry.startsWith("migrate-"))
82
+ continue;
83
+ const dirPath = join(backupRoot, entry);
84
+ try {
85
+ const st = statSync(dirPath);
86
+ if (!st.isDirectory())
87
+ continue;
88
+ if (now - st.mtimeMs < FLAT_PHASE_BACKUP_RETENTION_MS)
89
+ continue;
90
+ rmSync(dirPath, { recursive: true, force: true });
91
+ removed++;
92
+ }
93
+ catch {
94
+ // Non-fatal: leave backup for manual recovery.
95
+ }
96
+ }
97
+ try {
98
+ if (readdirSync(backupRoot).length === 0) {
99
+ rmSync(backupRoot, { recursive: true, force: true });
100
+ }
101
+ }
102
+ catch {
103
+ // Non-fatal.
104
+ }
105
+ return removed;
106
+ }
62
107
  /**
63
108
  * Migrate from legacy nested .gsd/milestones/ to flat-phase .gsd/phases/.
64
109
  *
@@ -22,8 +22,7 @@ import { deriveState } from "./state.js";
22
22
  import { isAutoActive } from "./auto.js";
23
23
  import { loadPrompt } from "./prompt-loader.js";
24
24
  import { gsdRoot } from "./paths.js";
25
- import { isDbAvailable, getAllMilestones, getMilestoneSlices, getSliceTasks } from "./gsd-db.js";
26
- import { isClosedStatus } from "./status-guards.js";
25
+ import { isDbAvailable, getHierarchyCompletionCounts } from "./gsd-db.js";
27
26
  import { formatDuration } from "../shared/format-utils.js";
28
27
  import { getAutoWorktreePath } from "./auto-worktree.js";
29
28
  import { clearGSDPreferencesCache, loadEffectiveGSDPreferences, loadGlobalGSDPreferences, getGlobalGSDPreferencesPath } from "./preferences.js";
@@ -593,36 +592,7 @@ function loadCompletedKeys(basePath) {
593
592
  function getDbCompletionCounts() {
594
593
  if (!isDbAvailable())
595
594
  return null;
596
- const milestones = getAllMilestones();
597
- let completedMilestones = 0;
598
- let totalSlices = 0;
599
- let completedSlices = 0;
600
- let totalTasks = 0;
601
- let completedTasks = 0;
602
- for (const m of milestones) {
603
- if (isClosedStatus(m.status))
604
- completedMilestones++;
605
- const slices = getMilestoneSlices(m.id);
606
- for (const s of slices) {
607
- totalSlices++;
608
- if (isClosedStatus(s.status))
609
- completedSlices++;
610
- const tasks = getSliceTasks(m.id, s.id);
611
- for (const t of tasks) {
612
- totalTasks++;
613
- if (isClosedStatus(t.status))
614
- completedTasks++;
615
- }
616
- }
617
- }
618
- return {
619
- milestones: completedMilestones,
620
- milestonesTotal: milestones.length,
621
- slices: completedSlices,
622
- slicesTotal: totalSlices,
623
- tasks: completedTasks,
624
- tasksTotal: totalTasks,
625
- };
595
+ return getHierarchyCompletionCounts();
626
596
  }
627
597
  // ─── Anomaly Detectors ───────────────────────────────────────────────────────
628
598
  /**
@@ -208,6 +208,7 @@ export class MergeConflictError extends GSDError {
208
208
  */
209
209
  export const RUNTIME_EXCLUSION_PATHS = [
210
210
  ".gsd-worktrees/",
211
+ ".gsd-backups/**",
211
212
  ".gsd/activity/",
212
213
  ".gsd/audit/",
213
214
  ".gsd/forensics/",
@@ -225,6 +226,7 @@ export const RUNTIME_EXCLUSION_PATHS = [
225
226
  ".gsd/event-log.jsonl",
226
227
  ".gsd/DISCUSSION-MANIFEST.json",
227
228
  ];
229
+ const runtimeFilesCleanedUpRepos = new Set();
228
230
  // ─── Integration Branch Metadata ───────────────────────────────────────────
229
231
  /**
230
232
  * Path to the milestone metadata file that stores the integration branch.
@@ -565,7 +567,8 @@ export class GitServiceImpl {
565
567
  // and the worktree is torn down. This prevents a mid-execution behavioral
566
568
  // discontinuity where the first half of a milestone has .gsd/ artifacts
567
569
  // committed but the second half doesn't (#1326).
568
- if (!this._runtimeFilesCleanedUp) {
570
+ const cleanupRepoKey = resolve(this.basePath);
571
+ if (!runtimeFilesCleanedUpRepos.has(cleanupRepoKey)) {
569
572
  let cleaned = false;
570
573
  for (const exclusion of RUNTIME_EXCLUSION_PATHS) {
571
574
  const removed = nativeRmCached(this.basePath, [exclusion]);
@@ -575,7 +578,7 @@ export class GitServiceImpl {
575
578
  if (cleaned) {
576
579
  nativeCommit(this.basePath, "chore: untrack .gsd/ runtime files from git index", { allowEmpty: false });
577
580
  }
578
- this._runtimeFilesCleanedUp = true;
581
+ runtimeFilesCleanedUpRepos.add(cleanupRepoKey);
579
582
  }
580
583
  // Stage everything using pathspec exclusions so excluded paths are never
581
584
  // hashed by git. The old approach of `git add -A` followed by unstaging
@@ -683,8 +686,6 @@ export class GitServiceImpl {
683
686
  return false;
684
687
  }
685
688
  }
686
- /** Tracks whether runtime file cleanup has run this session. */
687
- _runtimeFilesCleanedUp = false;
688
689
  /**
689
690
  * Stage files (smart staging) and commit.
690
691
  * Returns the commit message string on success, or null if nothing to commit.
@@ -24,6 +24,7 @@ import { GIT_NO_PROMPT_ENV } from "./git-constants.js";
24
24
  */
25
25
  const GSD_RUNTIME_PATTERNS = [
26
26
  ".gsd-worktrees/",
27
+ ".gsd-backups/",
27
28
  ".gsd/activity/",
28
29
  ".gsd/audit/",
29
30
  ".gsd/forensics/",
@@ -48,6 +49,8 @@ const BASELINE_PATTERNS = [
48
49
  ".gsd",
49
50
  // Worktree container sibling — NOT covered by the ".gsd" pattern above.
50
51
  ".gsd-worktrees/",
52
+ // Flat-phase migration snapshots — NOT covered by the ".gsd" pattern above.
53
+ ".gsd-backups/",
51
54
  ".gsd-id",
52
55
  ".mcp.json",
53
56
  ".bg-shell/",
@@ -12,7 +12,7 @@ import { loadFile } from "./files.js";
12
12
  import { loadPrompt, inlineTemplate } from "./prompt-loader.js";
13
13
  import { deriveState } from "./state.js";
14
14
  import { invalidateAllCaches } from "./cache.js";
15
- import { gsdRoot, resolveMilestoneFile, resolveGsdRootFile, relGsdRootFile, } from "./paths.js";
15
+ import { gsdRoot, resolveMilestoneFile, resolveGsdRootFile, relGsdRootFile, relMilestoneFile, } from "./paths.js";
16
16
  import { readFileSync, writeFileSync, existsSync } from "node:fs";
17
17
  import { atomicWriteSync } from "./atomic-write.js";
18
18
  import { nativeAddPaths, nativeCommit } from "./native-git-bridge.js";
@@ -20,6 +20,9 @@ import { loadEffectiveGSDPreferences } from "./preferences.js";
20
20
  import { saveQueueOrder } from "./queue-order.js";
21
21
  import { findMilestoneIds, nextMilestoneId } from "./milestone-ids.js";
22
22
  import { isFutureMilestoneStatus } from "./status-guards.js";
23
+ const QUEUE_ARTIFACT_EXCERPT_MAX_CHARS = 20_000;
24
+ const QUEUE_EXISTING_MILESTONES_CONTEXT_MAX_CHARS = 120_000;
25
+ const QUEUE_CONTEXT_SECTION_SEPARATOR = "\n\n---\n\n";
23
26
  // ─── Queue Entry Point ──────────────────────────────────────────────────────
24
27
  /**
25
28
  * Queue future milestones via conversational intake.
@@ -215,7 +218,7 @@ export async function buildExistingMilestonesContext(basePath, milestoneIds, sta
215
218
  if (contextFile) {
216
219
  const content = await loadFile(contextFile);
217
220
  if (content) {
218
- parts.push(`\n**Context:**\n${content.trim()}`);
221
+ parts.push(`\n**Context:**\n${summarizeArtifactForQueue(content, relMilestoneFile(basePath, mid, "CONTEXT"))}`);
219
222
  }
220
223
  }
221
224
  else {
@@ -224,7 +227,7 @@ export async function buildExistingMilestonesContext(basePath, milestoneIds, sta
224
227
  if (draftFile) {
225
228
  const draftContent = await loadFile(draftFile);
226
229
  if (draftContent) {
227
- parts.push(`\n**Draft context available:**\n${draftContent.trim()}`);
230
+ parts.push(`\n**Draft context available:**\n${summarizeArtifactForQueue(draftContent, relMilestoneFile(basePath, mid, "CONTEXT-DRAFT"))}`);
228
231
  }
229
232
  }
230
233
  }
@@ -235,7 +238,7 @@ export async function buildExistingMilestonesContext(basePath, milestoneIds, sta
235
238
  if (roadmapFile) {
236
239
  const content = await loadFile(roadmapFile);
237
240
  if (content) {
238
- parts.push(`\n**Roadmap:**\n${content.trim()}`);
241
+ parts.push(`\n**Roadmap:**\n${summarizeArtifactForQueue(content, relMilestoneFile(basePath, mid, "ROADMAP"))}`);
239
242
  }
240
243
  }
241
244
  }
@@ -249,7 +252,65 @@ export async function buildExistingMilestonesContext(basePath, milestoneIds, sta
249
252
  sections.push(`### Previous Queue Entries\nSource: \`${relGsdRootFile("QUEUE")}\`\n\n${queueContent.trim()}`);
250
253
  }
251
254
  }
252
- return sections.join("\n\n---\n\n");
255
+ return capExistingMilestonesContext(sections);
256
+ }
257
+ function summarizeArtifactForQueue(content, sourcePath, cap = QUEUE_ARTIFACT_EXCERPT_MAX_CHARS) {
258
+ const trimmed = content.trim();
259
+ if (trimmed.length <= cap) {
260
+ return `Source: \`${sourcePath}\`\n\n${trimmed}`;
261
+ }
262
+ const excerpt = trimmed.slice(0, cap).trimEnd();
263
+ const omittedChars = trimmed.length - excerpt.length;
264
+ return [
265
+ `Source: \`${sourcePath}\``,
266
+ "",
267
+ excerpt,
268
+ "",
269
+ `[Truncated ${omittedChars} chars. Read \`${sourcePath}\` for full content.]`,
270
+ ].join("\n");
271
+ }
272
+ function capExistingMilestonesContext(sections, cap = QUEUE_EXISTING_MILESTONES_CONTEXT_MAX_CHARS) {
273
+ const fullContext = sections.join(QUEUE_CONTEXT_SECTION_SEPARATOR);
274
+ if (fullContext.length <= cap)
275
+ return fullContext;
276
+ const notice = `[Existing milestones context truncated to ${cap} chars. Read source paths in this prompt or the corresponding .gsd artifacts for full details.]`;
277
+ const noticeSuffix = `${QUEUE_CONTEXT_SECTION_SEPARATOR}${notice}`;
278
+ const selected = [];
279
+ for (const section of sections) {
280
+ const candidate = [...selected, section].join(QUEUE_CONTEXT_SECTION_SEPARATOR) + noticeSuffix;
281
+ if (candidate.length <= cap) {
282
+ selected.push(section);
283
+ continue;
284
+ }
285
+ break;
286
+ }
287
+ if (selected.length === sections.length) {
288
+ return selected.join(QUEUE_CONTEXT_SECTION_SEPARATOR) + noticeSuffix;
289
+ }
290
+ const compactTail = sections.slice(selected.length).map(compactSectionForQueueBudget);
291
+ const hybrid = [...selected, ...compactTail].join(QUEUE_CONTEXT_SECTION_SEPARATOR) + noticeSuffix;
292
+ if (hybrid.length <= cap)
293
+ return hybrid;
294
+ const compact = sections.map(compactSectionForQueueBudget);
295
+ const compactContext = compact.join(QUEUE_CONTEXT_SECTION_SEPARATOR) + noticeSuffix;
296
+ if (compactContext.length <= cap)
297
+ return compactContext;
298
+ return `${compactContext.slice(0, Math.max(0, cap - notice.length - 2)).trimEnd()}\n\n${notice}`;
299
+ }
300
+ function compactSectionForQueueBudget(section) {
301
+ const lines = section.split("\n");
302
+ const compact = [];
303
+ if (lines[0])
304
+ compact.push(lines[0]);
305
+ const statusLine = lines.find(line => line.startsWith("**Status:**"));
306
+ if (statusLine)
307
+ compact.push(statusLine);
308
+ const sourceLines = lines.filter(line => line.startsWith("Source: `"));
309
+ if (sourceLines.length > 0) {
310
+ compact.push("", "**Sources:**", ...sourceLines);
311
+ compact.push("", "[Artifact excerpts omitted due to total queue/rethink context budget.]");
312
+ }
313
+ return compact.join("\n");
253
314
  }
254
315
  // ─── Internal Helpers ───────────────────────────────────────────────────────
255
316
  /**
@@ -1,29 +1,61 @@
1
1
  // Project/App: gsd-pi
2
2
  // File Purpose: Always-on ambient health signal rendered below the editor.
3
- import { runProviderChecks, summariseProviderIssues } from "./doctor-providers.js";
3
+ import { execFile } from "node:child_process";
4
+ import { runProviderChecks, runProviderChecksAsync, summariseProviderIssues } from "./doctor-providers.js";
4
5
  import { runEnvironmentChecks, runEnvironmentChecksAsync } from "./doctor-environment.js";
5
6
  import { loadEffectiveGSDPreferences } from "./preferences.js";
6
- import { nativeIsRepo, nativeLastCommitEpoch, nativeGetCurrentBranch, nativeCommitSubject } from "./native-git-bridge.js";
7
+ import { GIT_NO_PROMPT_ENV } from "./git-constants.js";
7
8
  import { loadLedgerFromDisk, getProjectTotals } from "./metrics.js";
8
9
  import { projectRoot } from "./commands/context.js";
9
10
  import { buildHealthLines, detectHealthWidgetProjectState, } from "./health-widget-core.js";
10
11
  export const HEALTH_WIDGET_ACTIVE_HINTS = " /gsd auto to run · /gsd status to inspect · /gsd report for snapshots · /gsd notifications for history · /gsd help";
12
+ const LAST_COMMIT_LOOKUP_TIMEOUT_MS = 3_000;
13
+ const REFRESH_INTERVAL_MS = 60_000;
14
+ const PROJECT_STATE_CACHE_TTL_MS = REFRESH_INTERVAL_MS;
11
15
  // ── Data loader ────────────────────────────────────────────────────────────────
12
- // Last-commit lookup is subprocess-backed (native-git-bridge → git spawns),
13
- // so it is treated like the other expensive checks: skipped on first paint,
14
- // run only by the background refresh.
15
- function loadLastCommitInfo(basePath) {
16
+ const projectStateCache = new Map();
17
+ export function getCachedProjectState(basePath, force) {
18
+ const now = Date.now();
19
+ const cached = projectStateCache.get(basePath);
20
+ if (!force && cached && now - cached.computedAt <= PROJECT_STATE_CACHE_TTL_MS) {
21
+ return cached.state;
22
+ }
23
+ const state = detectHealthWidgetProjectState(basePath);
24
+ projectStateCache.set(basePath, { state, computedAt: now });
25
+ return state;
26
+ }
27
+ function runHealthWidgetGit(basePath, args) {
28
+ return new Promise((resolve) => {
29
+ const child = execFile("git", args, {
30
+ cwd: basePath,
31
+ timeout: LAST_COMMIT_LOOKUP_TIMEOUT_MS,
32
+ encoding: "utf-8",
33
+ env: GIT_NO_PROMPT_ENV,
34
+ }, (err, stdout) => resolve(err ? null : String(stdout).trimEnd()));
35
+ child.on("error", () => resolve(null));
36
+ });
37
+ }
38
+ async function loadLastCommitInfoAsync(basePath) {
16
39
  try {
17
- if (nativeIsRepo(basePath)) {
18
- const branch = nativeGetCurrentBranch(basePath);
19
- const epoch = nativeLastCommitEpoch(basePath, branch || "HEAD");
20
- if (epoch > 0) {
21
- return { epoch, message: nativeCommitSubject(basePath, branch || "HEAD") || null };
22
- }
40
+ if ((await runHealthWidgetGit(basePath, ["rev-parse", "--git-dir"])) === null) {
41
+ return { epoch: null, message: null };
23
42
  }
43
+ const branch = await runHealthWidgetGit(basePath, ["branch", "--show-current"]);
44
+ const ref = branch || "HEAD";
45
+ const raw = await runHealthWidgetGit(basePath, ["log", "-1", "--format=%ct%x00%s", ref]);
46
+ if (!raw)
47
+ return { epoch: null, message: null };
48
+ const separator = raw.indexOf("\0");
49
+ const epochText = separator >= 0 ? raw.slice(0, separator) : raw;
50
+ const epoch = parseInt(epochText.trim(), 10) || 0;
51
+ if (epoch <= 0)
52
+ return { epoch: null, message: null };
53
+ const message = separator >= 0 ? raw.slice(separator + 1).trim() : "";
54
+ return { epoch, message: message || null };
55
+ }
56
+ catch {
57
+ return { epoch: null, message: null };
24
58
  }
25
- catch { /* non-fatal */ }
26
- return { epoch: null, message: null };
27
59
  }
28
60
  function loadHealthWidgetData(basePath, options) {
29
61
  // `includeChecks` gates the expensive subprocess-backed checks (provider +
@@ -38,7 +70,7 @@ function loadHealthWidgetData(basePath, options) {
38
70
  let environmentWarningCount = 0;
39
71
  let lastCommitEpoch = null;
40
72
  let lastCommitMessage = null;
41
- const projectState = detectHealthWidgetProjectState(basePath);
73
+ const projectState = getCachedProjectState(basePath, options?.forceProjectState);
42
74
  try {
43
75
  const prefs = loadEffectiveGSDPreferences();
44
76
  budgetCeiling = prefs?.preferences?.budget_ceiling;
@@ -66,12 +98,6 @@ function loadHealthWidgetData(basePath, options) {
66
98
  }
67
99
  catch { /* non-fatal */ }
68
100
  }
69
- // ── Last commit info ── (git spawns — gated like the other expensive checks)
70
- if (includeChecks) {
71
- const commit = loadLastCommitInfo(basePath);
72
- lastCommitEpoch = commit.epoch;
73
- lastCommitMessage = commit.message;
74
- }
75
101
  return {
76
102
  projectState,
77
103
  budgetCeiling,
@@ -85,17 +111,15 @@ function loadHealthWidgetData(basePath, options) {
85
111
  };
86
112
  }
87
113
  // Non-blocking variant used by the widget's background refresh: the cheap fields
88
- // come from the synchronous snapshot, then provider + environment checks are
89
- // layered in off the event-loop critical path (env checks run concurrently via
90
- // runEnvironmentChecksAsync). Keeps the always-on widget from stalling the UI on
91
- // its initial enrichment or its 60s refresh.
114
+ // come from the synchronous snapshot, then provider, environment, and last-commit
115
+ // checks are layered in off the event-loop critical path.
92
116
  async function loadHealthWidgetDataAsync(basePath) {
93
117
  const data = loadHealthWidgetData(basePath, { includeChecks: false });
94
118
  let providerIssue = data.providerIssue;
95
119
  let environmentErrorCount = 0;
96
120
  let environmentWarningCount = 0;
97
121
  try {
98
- providerIssue = summariseProviderIssues(runProviderChecks());
122
+ providerIssue = summariseProviderIssues(await runProviderChecksAsync());
99
123
  }
100
124
  catch { /* non-fatal */ }
101
125
  try {
@@ -108,7 +132,7 @@ async function loadHealthWidgetDataAsync(basePath) {
108
132
  }
109
133
  }
110
134
  catch { /* non-fatal */ }
111
- const commit = loadLastCommitInfo(basePath);
135
+ const commit = await loadLastCommitInfoAsync(basePath);
112
136
  return {
113
137
  ...data,
114
138
  providerIssue,
@@ -120,7 +144,6 @@ async function loadHealthWidgetDataAsync(basePath) {
120
144
  };
121
145
  }
122
146
  // ── Widget init ────────────────────────────────────────────────────────────────
123
- const REFRESH_INTERVAL_MS = 60_000;
124
147
  /**
125
148
  * Initialize the always-on gsd-health widget (belowEditor).
126
149
  * Call once from the extension entry point after context is available.
@@ -129,13 +152,16 @@ export function initHealthWidget(ctx) {
129
152
  if (!ctx.hasUI)
130
153
  return;
131
154
  const basePath = projectRoot();
155
+ // Re-init must reflect filesystem changes immediately; the TTL cache is for
156
+ // interval refreshes, not this one-off synchronous paint.
157
+ projectStateCache.delete(basePath);
132
158
  // String-array fallback — used in RPC mode (factory is a no-op there).
133
159
  // Skip the expensive provider/environment doctor checks here: this runs
134
160
  // synchronously on the interactive-startup path, where running them would
135
161
  // block first paint by ~0.9s (lsof/docker probes, otherwise run again
136
162
  // immediately by the factory below). The factory's async refresh fills in
137
163
  // real health once the screen is up.
138
- const initialData = loadHealthWidgetData(basePath, { includeChecks: false });
164
+ const initialData = loadHealthWidgetData(basePath, { includeChecks: false, forceProjectState: true });
139
165
  ctx.ui.setWidget("gsd-health", buildHealthLines(initialData), { placement: "belowEditor" });
140
166
  // Factory-based widget for TUI mode — replaces the string-array above
141
167
  ctx.ui.setWidget("gsd-health", (_tui, _theme) => {
@@ -56,6 +56,26 @@ export function saveJsonFile(filePath, data) {
56
56
  // Non-fatal — don't let persistence failures break operation
57
57
  }
58
58
  }
59
+ /**
60
+ * Save a JSON file atomically using compact serialization.
61
+ *
62
+ * Intended for machine-only ledgers where pretty-printing has no consumer.
63
+ * Keeps the same write-tmp-rename safety and non-fatal error behavior as
64
+ * saveJsonFile.
65
+ */
66
+ export function saveJsonFileCompact(filePath, data) {
67
+ try {
68
+ mkdirSync(dirname(filePath), { recursive: true });
69
+ // Use randomized tmp suffix to prevent concurrent-write data loss
70
+ const tmp = `${filePath}.tmp.${randomBytes(4).toString("hex")}`;
71
+ writeFileSync(tmp, JSON.stringify(data) + "\n", "utf-8");
72
+ renameSync(tmp, filePath);
73
+ // No cleanup needed — renameSync atomically removes tmp on success
74
+ }
75
+ catch {
76
+ // Non-fatal — don't let persistence failures break operation
77
+ }
78
+ }
59
79
  /**
60
80
  * Write a JSON file atomically (write to .tmp, then rename).
61
81
  * Creates parent directories as needed. Non-fatal on error.
@@ -24,8 +24,8 @@ import { logWarning } from "./workflow-logger.js";
24
24
  * - Idempotent (per-row): each migrated memory carries
25
25
  * `structured_fields.sourceKnowledgeId = "<P|L>NNN"`. Rows whose ID is
26
26
  * already present in the memory store are skipped.
27
- * - Best-effort: never throws. Logs and returns 0 on failure so a broken
28
- * backfill cannot block agent startup.
27
+ * - Best-effort: never throws. Failed memory inserts are logged and skipped;
28
+ * setup/read failures log and return 0 so backfill cannot block startup.
29
29
  * - Rules (K###) are intentionally skipped — they remain manually maintained
30
30
  * in `KNOWLEDGE.md` per ADR-013.
31
31
  *
@@ -56,15 +56,22 @@ export function backfillKnowledgeToMemories(basePath) {
56
56
  const matchPattern = `%"sourceKnowledgeId":"${synth.id}"%`;
57
57
  if (checkExisting.get({ ":pattern": matchPattern }))
58
58
  continue;
59
- const id = createMemory({
60
- category: synth.category,
61
- content: synth.content,
62
- scope: synth.scope,
63
- confidence: 0.85,
64
- structuredFields: synth.structuredFields,
65
- });
66
- if (id)
67
- written += 1;
59
+ try {
60
+ const id = createMemory({
61
+ category: synth.category,
62
+ content: synth.content,
63
+ scope: synth.scope,
64
+ confidence: 0.85,
65
+ structuredFields: synth.structuredFields,
66
+ });
67
+ if (id)
68
+ written += 1;
69
+ }
70
+ catch (rowErr) {
71
+ const message = rowErr instanceof Error ? rowErr.message : String(rowErr);
72
+ logWarning("knowledge-backfill", `KNOWLEDGE.md -> memories backfill skipped ${synth.id}: ${message}`);
73
+ continue;
74
+ }
68
75
  }
69
76
  return written;
70
77
  }
@@ -40,8 +40,10 @@ export function dbPath(basePath) {
40
40
  * Used by the renderer to derive the phase number from the DB's milestone_id.
41
41
  */
42
42
  export function milestoneIdToPhaseNum(milestoneId) {
43
- // No $ anchor: accepts bare (M012) and team-suffixed (M012-abc123) IDs.
43
+ // No $ anchor: accepts bare (M012), team-suffixed (M012-abc123), and legacy numeric IDs.
44
44
  const m = milestoneId.match(/^M0*(\d+)/i);
45
+ if (!m && /^\d+$/.test(milestoneId))
46
+ return Number.parseInt(milestoneId, 10);
45
47
  return m ? Number.parseInt(m[1], 10) : 1;
46
48
  }
47
49
  /** Team-mode suffix from milestone ids like M001-abc123. */
@@ -12,7 +12,7 @@ import { readFileSync, existsSync, mkdirSync, statSync, unlinkSync } from "node:
12
12
  import { logWarning } from "./workflow-logger.js";
13
13
  import { isClosedStatus } from "./status-guards.js";
14
14
  import { dirname, join, relative } from "node:path";
15
- import { getAllMilestones, getMilestone, getMilestoneScopedArtifacts, getSliceScopedArtifacts, getMilestoneSlices, getSliceTasks, getTask, getSlice, insertArtifact, deleteArtifactByPath, getGateResults, } from "./gsd-db.js";
15
+ import { getAllMilestones, getMilestone, getMilestoneScopedArtifacts, getSliceScopedArtifacts, getMilestoneSlices, getSliceTasks, getTask, getSlice, insertArtifact, deleteArtifactByPath, getGateResults, isDbAvailable, } from "./gsd-db.js";
16
16
  import { resolveSliceFile, resolveSlicePath, resolveTaskFile, resolveTasksDir, gsdProjectionRoot, gsdRoot, buildMilestoneFileName, buildTaskFileName, } from "./paths.js";
17
17
  import { saveFile, clearParseCache, registerCacheClearCallback } from "./files.js";
18
18
  import { parseRoadmap, parsePlan } from "./parsers-legacy.js";
@@ -518,13 +518,8 @@ export async function renderRoadmapFromDb(basePath, milestoneId) {
518
518
  * @returns true if the roadmap was written, false on skip/error
519
519
  */
520
520
  export async function renderRoadmapCheckboxes(basePath, milestoneId) {
521
- const slices = getMilestoneSlices(milestoneId);
522
- if (slices.length === 0) {
523
- process.stderr.write(`markdown-renderer: no slices found for milestone ${milestoneId}\n`);
524
- return false;
525
- }
526
- await renderRoadmapFromDb(basePath, milestoneId);
527
- return true;
521
+ const rendered = await renderRoadmapFromDb(basePath, milestoneId);
522
+ return !("skipped" in rendered);
528
523
  }
529
524
  /**
530
525
  * Project milestone-level artifacts (CONTEXT, RESEARCH, VALIDATION, etc.) from
@@ -604,11 +599,15 @@ function isAutoRecoveryPlaceholderPlan(content) {
604
599
  * projection (the 4S/0T-vs-5S/13T drift class). The artifacts table is an
605
600
  * output sink, never a render input.
606
601
  *
607
- * @returns true if the plan was written, false on skip/error
602
+ * @returns true if the plan was written, false when the DB slice has no tasks
603
+ * @throws when the DB connection is unavailable or the render write fails
608
604
  */
609
605
  export async function renderPlanCheckboxes(basePath, milestoneId, sliceId, outputPath) {
610
606
  const tasks = getSliceTasks(milestoneId, sliceId);
611
607
  if (tasks.length === 0) {
608
+ if (!isDbAvailable()) {
609
+ throw new Error(`database unavailable while rendering plan checkboxes for ${milestoneId}/${sliceId}`);
610
+ }
612
611
  process.stderr.write(`markdown-renderer: no tasks found for ${milestoneId}/${sliceId}\n`);
613
612
  return false;
614
613
  }
@@ -33,8 +33,8 @@ import { logWarning } from "./workflow-logger.js";
33
33
  * decision is checked individually; only decisions whose id is already
34
34
  * present in the memory store are skipped. A user-authored memory with
35
35
  * their own `sourceDecisionId` does NOT abort the backfill.
36
- * - Best-effort: never throws. Logs and returns 0 on failure so a broken
37
- * backfill cannot block agent startup.
36
+ * - Best-effort: never throws. Failed memory inserts are logged and skipped;
37
+ * setup/read failures log and return 0 so backfill cannot block startup.
38
38
  * - Full migration (ADR-013 Stage 2a): both active and superseded rows are
39
39
  * migrated. `structured_fields.superseded_by` preserves the supersedes
40
40
  * chain so the DECISIONS.md projection regen can source from memories
@@ -117,25 +117,32 @@ export function backfillDecisionsToMemories() {
117
117
  continue;
118
118
  }
119
119
  const content = synthesizeDecisionMemoryContent(row);
120
- const id = createMemory({
121
- category: "architecture",
122
- content,
123
- scope: row.scope || "project",
124
- confidence: 0.85,
125
- structuredFields: {
126
- sourceDecisionId: row.id,
127
- when_context: row.when_context,
128
- scope: row.scope,
129
- decision: row.decision,
130
- choice: row.choice,
131
- rationale: row.rationale,
132
- made_by: row.made_by,
133
- revisable: row.revisable,
134
- superseded_by: row.superseded_by,
135
- },
136
- });
137
- if (id)
138
- written += 1;
120
+ try {
121
+ const id = createMemory({
122
+ category: "architecture",
123
+ content,
124
+ scope: row.scope || "project",
125
+ confidence: 0.85,
126
+ structuredFields: {
127
+ sourceDecisionId: row.id,
128
+ when_context: row.when_context,
129
+ scope: row.scope,
130
+ decision: row.decision,
131
+ choice: row.choice,
132
+ rationale: row.rationale,
133
+ made_by: row.made_by,
134
+ revisable: row.revisable,
135
+ superseded_by: row.superseded_by,
136
+ },
137
+ });
138
+ if (id)
139
+ written += 1;
140
+ }
141
+ catch (rowErr) {
142
+ const message = rowErr instanceof Error ? rowErr.message : String(rowErr);
143
+ logWarning("memory-backfill", `decisions->memories backfill skipped ${row.id}: ${message}`);
144
+ continue;
145
+ }
139
146
  }
140
147
  if (healed > 0) {
141
148
  logWarning("memory-backfill", `decisions->memories drift healed: ${healed} row${healed === 1 ? "" : "s"} updated superseded_by`);