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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (488) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.js +17 -4
  3. package/dist/headless-answers.js +1 -1
  4. package/dist/headless-ui.d.ts +1 -1
  5. package/dist/headless-ui.js +1 -1
  6. package/dist/headless.js +1 -1
  7. package/dist/resources/.managed-resources-content-hash +1 -1
  8. package/dist/resources/extensions/claude-code-cli/models.js +9 -0
  9. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +11 -2
  10. package/dist/resources/extensions/google-cli/stream-adapter.js +82 -15
  11. package/dist/resources/extensions/gsd/artifact-verification.js +427 -0
  12. package/dist/resources/extensions/gsd/auto/orchestrator.js +12 -3
  13. package/dist/resources/extensions/gsd/auto/session.js +11 -0
  14. package/dist/resources/extensions/gsd/auto/verification-retry-policy.js +1 -1
  15. package/dist/resources/extensions/gsd/auto-artifact-paths.js +28 -1
  16. package/dist/resources/extensions/gsd/auto-budget.js +5 -1
  17. package/dist/resources/extensions/gsd/auto-dispatch.js +34 -20
  18. package/dist/resources/extensions/gsd/auto-post-unit.js +1 -1
  19. package/dist/resources/extensions/gsd/auto-prompts.js +29 -14
  20. package/dist/resources/extensions/gsd/auto-recovery.js +9 -510
  21. package/dist/resources/extensions/gsd/auto-runtime-state.js +4 -5
  22. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +3 -3
  23. package/dist/resources/extensions/gsd/auto-verification.js +5 -2
  24. package/dist/resources/extensions/gsd/auto.js +19 -10
  25. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +103 -13
  26. package/dist/resources/extensions/gsd/bootstrap/core-session-tools.js +39 -0
  27. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +11 -5
  28. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +2 -0
  29. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +2 -0
  30. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +41 -21
  31. package/dist/resources/extensions/gsd/bootstrap/system-context.js +46 -19
  32. package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +96 -10
  33. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +1 -1
  34. package/dist/resources/extensions/gsd/closeout-consistency-gate.js +3 -1
  35. package/dist/resources/extensions/gsd/commands/handlers/auto.js +1 -1
  36. package/dist/resources/extensions/gsd/commands-context.js +19 -1
  37. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +17 -11
  38. package/dist/resources/extensions/gsd/commands-usage.js +1 -1
  39. package/dist/resources/extensions/gsd/commands-worktree.js +12 -10
  40. package/dist/resources/extensions/gsd/dashboard-overlay.js +32 -3
  41. package/dist/resources/extensions/gsd/db/engine.js +4 -1
  42. package/dist/resources/extensions/gsd/db/queries.js +60 -0
  43. package/dist/resources/extensions/gsd/db-memory-fts-schema.js +34 -0
  44. package/dist/resources/extensions/gsd/db-workspace.js +55 -3
  45. package/dist/resources/extensions/gsd/delegation-policy.js +1 -1
  46. package/dist/resources/extensions/gsd/docs/preferences-reference.md +2 -2
  47. package/dist/resources/extensions/gsd/doctor-engine-checks.js +192 -4
  48. package/dist/resources/extensions/gsd/doctor-providers.js +92 -8
  49. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +3 -0
  50. package/dist/resources/extensions/gsd/exec-sandbox.js +53 -11
  51. package/dist/resources/extensions/gsd/flat-phase-migration.js +45 -0
  52. package/dist/resources/extensions/gsd/forensics.js +2 -32
  53. package/dist/resources/extensions/gsd/git-service.js +61 -4
  54. package/dist/resources/extensions/gsd/gitignore.js +4 -1
  55. package/dist/resources/extensions/gsd/guided-flow-queue.js +66 -5
  56. package/dist/resources/extensions/gsd/health-widget.js +55 -29
  57. package/dist/resources/extensions/gsd/json-persistence.js +20 -0
  58. package/dist/resources/extensions/gsd/knowledge-backfill.js +18 -11
  59. package/dist/resources/extensions/gsd/layout-policy.js +3 -1
  60. package/dist/resources/extensions/gsd/markdown-renderer.js +8 -9
  61. package/dist/resources/extensions/gsd/memory-backfill.js +28 -21
  62. package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +44 -21
  63. package/dist/resources/extensions/gsd/metrics.js +4 -4
  64. package/dist/resources/extensions/gsd/migrate-external.js +11 -2
  65. package/dist/resources/extensions/gsd/migration-auto-check.js +22 -0
  66. package/dist/resources/extensions/gsd/milestone-ids.js +32 -2
  67. package/dist/resources/extensions/gsd/milestone-implementation-evidence.js +26 -20
  68. package/dist/resources/extensions/gsd/orphan-stash-audit.js +92 -16
  69. package/dist/resources/extensions/gsd/prompts/code-review.md +6 -4
  70. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +2 -2
  71. package/dist/resources/extensions/gsd/prompts/plan-slice.md +3 -3
  72. package/dist/resources/extensions/gsd/quick.js +45 -2
  73. package/dist/resources/extensions/gsd/root-write-leak-guard.js +7 -1
  74. package/dist/resources/extensions/gsd/safety/destructive-guard.js +8 -1
  75. package/dist/resources/extensions/gsd/safety/evidence-collector.js +16 -1
  76. package/dist/resources/extensions/gsd/safety/file-change-validator.js +5 -2
  77. package/dist/resources/extensions/gsd/session-forensics.js +11 -1
  78. package/dist/resources/extensions/gsd/skills/gsd-headless/references/commands.md +1 -1
  79. package/dist/resources/extensions/gsd/state/derive/cache.js +28 -0
  80. package/dist/resources/extensions/gsd/state/derive/db-open.js +39 -0
  81. package/dist/resources/extensions/gsd/state/derive/from-db.js +452 -0
  82. package/dist/resources/extensions/gsd/state/derive/index.js +75 -0
  83. package/dist/resources/extensions/gsd/state/derive/interrupted-work.js +21 -0
  84. package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-render.js +45 -2
  85. package/dist/resources/extensions/gsd/state-reconciliation/index.js +48 -23
  86. package/dist/resources/extensions/gsd/state-reconciliation/registry.js +32 -28
  87. package/dist/resources/extensions/gsd/state.js +12 -611
  88. package/dist/resources/extensions/gsd/tools/complete-milestone.js +4 -2
  89. package/dist/resources/extensions/gsd/tools/complete-slice.js +2 -2
  90. package/dist/resources/extensions/gsd/tools/complete-task.js +43 -14
  91. package/dist/resources/extensions/gsd/tools/exec-tool.js +7 -2
  92. package/dist/resources/extensions/gsd/tools/plan-slice.js +59 -44
  93. package/dist/resources/extensions/gsd/tools/plan-task.js +28 -5
  94. package/dist/resources/extensions/gsd/undo.js +43 -6
  95. package/dist/resources/extensions/gsd/unit-context-composer.js +23 -7
  96. package/dist/resources/extensions/gsd/unit-registry.js +36 -6
  97. package/dist/resources/extensions/gsd/unmerged-milestone-guard.js +33 -3
  98. package/dist/resources/extensions/gsd/validation-block-guard.js +9 -4
  99. package/dist/resources/extensions/gsd/verification-gate.js +7 -0
  100. package/dist/resources/extensions/gsd/workflow-manifest.js +126 -13
  101. package/dist/resources/extensions/gsd/workflow-projections.js +19 -14
  102. package/dist/resources/extensions/gsd/workspace-git-preflight.js +30 -1
  103. package/dist/resources/extensions/gsd/worktree-manager.js +44 -2
  104. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  105. package/dist/web/standalone/.next/BUILD_ID +1 -1
  106. package/dist/web/standalone/.next/app-path-routes-manifest.json +10 -10
  107. package/dist/web/standalone/.next/build-manifest.json +3 -3
  108. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  109. package/dist/web/standalone/.next/react-loadable-manifest.json +9 -9
  110. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  111. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  112. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  120. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  121. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  122. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  128. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  129. package/dist/web/standalone/.next/server/app/index.html +1 -1
  130. package/dist/web/standalone/.next/server/app/index.rsc +2 -2
  131. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  132. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
  133. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  134. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  135. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  136. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app-paths-manifest.json +10 -10
  138. package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
  139. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  140. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  142. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  143. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  144. package/dist/web/standalone/.next/static/chunks/{2659.b7b129ee6a769448.js → 2659.58e950899a9bb82f.js} +1 -1
  145. package/dist/web/standalone/.next/static/chunks/2772.a7c1fcc69a4685ef.js +1 -0
  146. package/dist/web/standalone/.next/static/chunks/{3616.3c60753b8ffcbd2e.js → 3616.61a2af74bb8833c8.js} +1 -1
  147. package/dist/web/standalone/.next/static/chunks/{4283.8e446784528ed9dc.js → 4283.d0d9e0a955e441cb.js} +1 -1
  148. package/dist/web/standalone/.next/static/chunks/{5826.a46ecdd1cfe8dabc.js → 5826.5421d66c72b9f34e.js} +1 -1
  149. package/dist/web/standalone/.next/static/chunks/{8785.481aa5869991b760.js → 8785.e29b3134cab1d153.js} +1 -1
  150. package/dist/web/standalone/.next/static/chunks/8937.640dc9c2aaa1dfad.js +10 -0
  151. package/dist/web/standalone/.next/static/chunks/app/{page-6644fc6ee8ca1247.js → page-72a856634ad14c10.js} +1 -1
  152. package/dist/web/standalone/.next/static/chunks/webpack-9c401904f87ded16.js +1 -0
  153. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  154. package/package.json +1 -1
  155. package/packages/cloud-mcp-gateway/package.json +2 -2
  156. package/packages/contracts/dist/workflow.d.ts +1 -0
  157. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  158. package/packages/contracts/dist/workflow.js +2 -0
  159. package/packages/contracts/dist/workflow.js.map +1 -1
  160. package/packages/contracts/package.json +1 -1
  161. package/packages/daemon/package.json +4 -4
  162. package/packages/gsd-agent-core/dist/agent-session.d.ts +1 -0
  163. package/packages/gsd-agent-core/dist/agent-session.d.ts.map +1 -1
  164. package/packages/gsd-agent-core/dist/agent-session.js +3 -0
  165. package/packages/gsd-agent-core/dist/agent-session.js.map +1 -1
  166. package/packages/gsd-agent-core/dist/extension-ui-snapshot.d.ts +41 -0
  167. package/packages/gsd-agent-core/dist/extension-ui-snapshot.d.ts.map +1 -0
  168. package/packages/gsd-agent-core/dist/extension-ui-snapshot.js +62 -0
  169. package/packages/gsd-agent-core/dist/extension-ui-snapshot.js.map +1 -0
  170. package/packages/gsd-agent-core/dist/index.d.ts +2 -0
  171. package/packages/gsd-agent-core/dist/index.d.ts.map +1 -1
  172. package/packages/gsd-agent-core/dist/index.js +2 -0
  173. package/packages/gsd-agent-core/dist/index.js.map +1 -1
  174. package/packages/gsd-agent-core/dist/session/agent-session-events.js +1 -1
  175. package/packages/gsd-agent-core/dist/session/agent-session-events.js.map +1 -1
  176. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts +1 -0
  177. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts.map +1 -1
  178. package/packages/gsd-agent-core/dist/session/agent-session-host.js.map +1 -1
  179. package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts +5 -0
  180. package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts.map +1 -1
  181. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js +60 -3
  182. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js.map +1 -1
  183. package/packages/gsd-agent-core/dist/transcript-store.d.ts +58 -0
  184. package/packages/gsd-agent-core/dist/transcript-store.d.ts.map +1 -0
  185. package/packages/gsd-agent-core/dist/transcript-store.js +132 -0
  186. package/packages/gsd-agent-core/dist/transcript-store.js.map +1 -0
  187. package/packages/gsd-agent-core/package.json +5 -5
  188. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +2 -0
  189. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  190. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +25 -11
  191. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  192. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.d.ts +4 -0
  193. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.d.ts.map +1 -0
  194. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.js +7 -0
  195. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.js.map +1 -0
  196. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts +3 -24
  197. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  198. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +26 -829
  199. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  200. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.d.ts +58 -0
  201. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.d.ts.map +1 -0
  202. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.js +312 -0
  203. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.js.map +1 -0
  204. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.d.ts +31 -0
  205. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.d.ts.map +1 -0
  206. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.js +130 -0
  207. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.js.map +1 -0
  208. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts +15 -0
  209. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts.map +1 -0
  210. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js +258 -0
  211. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js.map +1 -0
  212. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.d.ts +13 -0
  213. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.d.ts.map +1 -0
  214. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.js +118 -0
  215. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.js.map +1 -0
  216. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts +9 -0
  217. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  218. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.js +1 -1
  219. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  220. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.d.ts +54 -0
  221. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.d.ts.map +1 -0
  222. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.js +20 -0
  223. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.js.map +1 -0
  224. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts +4 -1
  225. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  226. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +9 -0
  227. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
  228. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.d.ts +56 -0
  229. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.d.ts.map +1 -0
  230. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.js +44 -0
  231. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.js.map +1 -0
  232. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.d.ts +5 -0
  233. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.d.ts.map +1 -0
  234. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.js +77 -0
  235. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.js.map +1 -0
  236. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.d.ts +2 -0
  237. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  238. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.js +23 -5
  239. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.js.map +1 -1
  240. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  241. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +18 -0
  242. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
  243. package/packages/gsd-agent-modes/package.json +7 -7
  244. package/packages/mcp-server/README.md +1 -1
  245. package/packages/mcp-server/dist/server.d.ts +1 -1
  246. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  247. package/packages/mcp-server/dist/server.js +3 -3
  248. package/packages/mcp-server/dist/server.js.map +1 -1
  249. package/packages/mcp-server/dist/workflow-tools.d.ts +13 -1
  250. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  251. package/packages/mcp-server/dist/workflow-tools.js +35 -21
  252. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  253. package/packages/mcp-server/package.json +4 -4
  254. package/packages/native/package.json +1 -1
  255. package/packages/pi-agent-core/dist/agent-loop.js +3 -2
  256. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  257. package/packages/pi-agent-core/package.json +1 -1
  258. package/packages/pi-ai/dist/models.generated.d.ts +46 -0
  259. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  260. package/packages/pi-ai/dist/models.generated.js +38 -0
  261. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  262. package/packages/pi-ai/package.json +1 -1
  263. package/packages/pi-coding-agent/README.md +3 -2
  264. package/packages/pi-coding-agent/dist/core/session-manager-context.d.ts +9 -0
  265. package/packages/pi-coding-agent/dist/core/session-manager-context.d.ts.map +1 -0
  266. package/packages/pi-coding-agent/dist/core/session-manager-context.js +94 -0
  267. package/packages/pi-coding-agent/dist/core/session-manager-context.js.map +1 -0
  268. package/packages/pi-coding-agent/dist/core/session-manager-list.d.ts +8 -0
  269. package/packages/pi-coding-agent/dist/core/session-manager-list.d.ts.map +1 -0
  270. package/packages/pi-coding-agent/dist/core/session-manager-list.js +244 -0
  271. package/packages/pi-coding-agent/dist/core/session-manager-list.js.map +1 -0
  272. package/packages/pi-coding-agent/dist/core/session-manager-migration.d.ts +12 -0
  273. package/packages/pi-coding-agent/dist/core/session-manager-migration.d.ts.map +1 -0
  274. package/packages/pi-coding-agent/dist/core/session-manager-migration.js +84 -0
  275. package/packages/pi-coding-agent/dist/core/session-manager-migration.js.map +1 -0
  276. package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts +135 -0
  277. package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts.map +1 -0
  278. package/packages/pi-coding-agent/dist/core/session-manager-types.js +2 -0
  279. package/packages/pi-coding-agent/dist/core/session-manager-types.js.map +1 -0
  280. package/packages/pi-coding-agent/dist/core/session-manager.d.ts +6 -154
  281. package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
  282. package/packages/pi-coding-agent/dist/core/session-manager.js +22 -459
  283. package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
  284. package/packages/pi-coding-agent/dist/theme/theme-schema.d.ts +75 -75
  285. package/packages/pi-coding-agent/dist/theme/theme-schema.d.ts.map +1 -1
  286. package/packages/pi-coding-agent/dist/theme/theme-schema.js +1 -1
  287. package/packages/pi-coding-agent/dist/theme/theme-schema.js.map +1 -1
  288. package/packages/pi-coding-agent/dist/theme/theme.d.ts.map +1 -1
  289. package/packages/pi-coding-agent/dist/theme/theme.js +11 -7
  290. package/packages/pi-coding-agent/dist/theme/theme.js.map +1 -1
  291. package/packages/pi-coding-agent/package.json +7 -7
  292. package/packages/pi-tui/package.json +2 -2
  293. package/packages/rpc-client/package.json +2 -2
  294. package/pkg/dist/theme/theme-schema.d.ts +75 -75
  295. package/pkg/dist/theme/theme-schema.d.ts.map +1 -1
  296. package/pkg/dist/theme/theme-schema.js +1 -1
  297. package/pkg/dist/theme/theme-schema.js.map +1 -1
  298. package/pkg/dist/theme/theme.d.ts.map +1 -1
  299. package/pkg/dist/theme/theme.js +11 -7
  300. package/pkg/dist/theme/theme.js.map +1 -1
  301. package/pkg/package.json +1 -1
  302. package/src/resources/extensions/claude-code-cli/models.ts +9 -0
  303. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +20 -2
  304. package/src/resources/extensions/claude-code-cli/tests/index.test.ts +14 -0
  305. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +80 -0
  306. package/src/resources/extensions/google-cli/stream-adapter.ts +106 -19
  307. package/src/resources/extensions/gsd/artifact-verification.ts +464 -0
  308. package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
  309. package/src/resources/extensions/gsd/auto/orchestrator.ts +25 -11
  310. package/src/resources/extensions/gsd/auto/session.ts +14 -0
  311. package/src/resources/extensions/gsd/auto/verification-retry-policy.ts +3 -1
  312. package/src/resources/extensions/gsd/auto-artifact-paths.ts +47 -1
  313. package/src/resources/extensions/gsd/auto-budget.ts +12 -1
  314. package/src/resources/extensions/gsd/auto-dispatch.ts +35 -24
  315. package/src/resources/extensions/gsd/auto-post-unit.ts +1 -1
  316. package/src/resources/extensions/gsd/auto-prompts.ts +41 -15
  317. package/src/resources/extensions/gsd/auto-recovery.ts +13 -511
  318. package/src/resources/extensions/gsd/auto-runtime-state.ts +4 -5
  319. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +3 -2
  320. package/src/resources/extensions/gsd/auto-verification.ts +5 -1
  321. package/src/resources/extensions/gsd/auto.ts +23 -8
  322. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +125 -12
  323. package/src/resources/extensions/gsd/bootstrap/core-session-tools.ts +44 -0
  324. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +11 -5
  325. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +2 -0
  326. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +2 -0
  327. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +52 -21
  328. package/src/resources/extensions/gsd/bootstrap/system-context.ts +52 -18
  329. package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +104 -10
  330. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +1 -1
  331. package/src/resources/extensions/gsd/closeout-consistency-gate.ts +2 -1
  332. package/src/resources/extensions/gsd/commands/handlers/auto.ts +1 -1
  333. package/src/resources/extensions/gsd/commands-context.ts +18 -1
  334. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +15 -10
  335. package/src/resources/extensions/gsd/commands-usage.ts +1 -1
  336. package/src/resources/extensions/gsd/commands-worktree.ts +12 -10
  337. package/src/resources/extensions/gsd/dashboard-overlay.ts +32 -3
  338. package/src/resources/extensions/gsd/db/engine.ts +8 -1
  339. package/src/resources/extensions/gsd/db/queries.ts +79 -0
  340. package/src/resources/extensions/gsd/db-memory-fts-schema.ts +45 -0
  341. package/src/resources/extensions/gsd/db-workspace.ts +61 -3
  342. package/src/resources/extensions/gsd/delegation-policy.ts +1 -1
  343. package/src/resources/extensions/gsd/docs/preferences-reference.md +2 -2
  344. package/src/resources/extensions/gsd/doctor-engine-checks.ts +233 -5
  345. package/src/resources/extensions/gsd/doctor-providers.ts +103 -9
  346. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +3 -0
  347. package/src/resources/extensions/gsd/doctor-types.ts +3 -0
  348. package/src/resources/extensions/gsd/exec-sandbox.ts +56 -11
  349. package/src/resources/extensions/gsd/flat-phase-migration.ts +44 -0
  350. package/src/resources/extensions/gsd/forensics.ts +2 -33
  351. package/src/resources/extensions/gsd/git-service.ts +69 -5
  352. package/src/resources/extensions/gsd/gitignore.ts +4 -1
  353. package/src/resources/extensions/gsd/guided-flow-queue.ts +89 -4
  354. package/src/resources/extensions/gsd/health-widget.ts +69 -32
  355. package/src/resources/extensions/gsd/json-persistence.ts +20 -0
  356. package/src/resources/extensions/gsd/knowledge-backfill.ts +16 -10
  357. package/src/resources/extensions/gsd/layout-policy.ts +2 -1
  358. package/src/resources/extensions/gsd/markdown-renderer.ts +8 -11
  359. package/src/resources/extensions/gsd/memory-backfill.ts +26 -20
  360. package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +51 -19
  361. package/src/resources/extensions/gsd/metrics.ts +4 -4
  362. package/src/resources/extensions/gsd/migrate-external.ts +8 -2
  363. package/src/resources/extensions/gsd/migration-auto-check.ts +23 -0
  364. package/src/resources/extensions/gsd/milestone-ids.ts +31 -2
  365. package/src/resources/extensions/gsd/milestone-implementation-evidence.ts +35 -21
  366. package/src/resources/extensions/gsd/orphan-stash-audit.ts +108 -20
  367. package/src/resources/extensions/gsd/prompts/code-review.md +6 -4
  368. package/src/resources/extensions/gsd/prompts/plan-milestone.md +2 -2
  369. package/src/resources/extensions/gsd/prompts/plan-slice.md +3 -3
  370. package/src/resources/extensions/gsd/quick.ts +43 -2
  371. package/src/resources/extensions/gsd/root-write-leak-guard.ts +13 -1
  372. package/src/resources/extensions/gsd/safety/destructive-guard.ts +9 -1
  373. package/src/resources/extensions/gsd/safety/evidence-collector.ts +16 -1
  374. package/src/resources/extensions/gsd/safety/file-change-validator.ts +8 -2
  375. package/src/resources/extensions/gsd/session-forensics.ts +11 -1
  376. package/src/resources/extensions/gsd/skills/gsd-headless/references/commands.md +1 -1
  377. package/src/resources/extensions/gsd/state/derive/cache.ts +46 -0
  378. package/src/resources/extensions/gsd/state/derive/db-open.ts +45 -0
  379. package/src/resources/extensions/gsd/state/derive/from-db.ts +561 -0
  380. package/src/resources/extensions/gsd/state/derive/index.ts +104 -0
  381. package/src/resources/extensions/gsd/state/derive/interrupted-work.ts +31 -0
  382. package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +81 -7
  383. package/src/resources/extensions/gsd/state-reconciliation/index.ts +50 -24
  384. package/src/resources/extensions/gsd/state-reconciliation/registry.ts +43 -28
  385. package/src/resources/extensions/gsd/state.ts +32 -732
  386. package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +4 -3
  387. package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +98 -1
  388. package/src/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +14 -5
  389. package/src/resources/extensions/gsd/tests/auto-pause-double-entry-guard.test.ts +36 -0
  390. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +182 -4
  391. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +146 -1
  392. package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +30 -0
  393. package/src/resources/extensions/gsd/tests/commands-context.test.ts +26 -0
  394. package/src/resources/extensions/gsd/tests/commands-gsd-core.test.ts +1 -0
  395. package/src/resources/extensions/gsd/tests/commands-worktree-clean.test.ts +80 -0
  396. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +28 -0
  397. package/src/resources/extensions/gsd/tests/complete-slice-reopen-handoff.test.ts +69 -0
  398. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +11 -0
  399. package/src/resources/extensions/gsd/tests/complete-task-rollback-evidence.test.ts +48 -8
  400. package/src/resources/extensions/gsd/tests/complete-task.test.ts +75 -0
  401. package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +55 -2
  402. package/src/resources/extensions/gsd/tests/db-memory-fts-schema.test.ts +58 -3
  403. package/src/resources/extensions/gsd/tests/decisions-projection-from-memories.test.ts +51 -0
  404. package/src/resources/extensions/gsd/tests/destructive-guard.test.ts +44 -0
  405. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +143 -0
  406. package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +26 -1
  407. package/src/resources/extensions/gsd/tests/doctor-forensics-db-open-regression.test.ts +70 -2
  408. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +107 -0
  409. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +239 -2
  410. package/src/resources/extensions/gsd/tests/exec-graceful-kill.test.ts +38 -0
  411. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +16 -0
  412. package/src/resources/extensions/gsd/tests/exec-tool.test.ts +45 -1
  413. package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +40 -0
  414. package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +37 -2
  415. package/src/resources/extensions/gsd/tests/forensics-error-filter.test.ts +88 -0
  416. package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +4 -0
  417. package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +42 -0
  418. package/src/resources/extensions/gsd/tests/health-widget.test.ts +268 -3
  419. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +130 -3
  420. package/src/resources/extensions/gsd/tests/integration/queue-active-milestone-context-budget.test.ts +93 -0
  421. package/src/resources/extensions/gsd/tests/integration/quick-branch-lifecycle.test.ts +56 -9
  422. package/src/resources/extensions/gsd/tests/json-persistence-atomic.test.ts +47 -0
  423. package/src/resources/extensions/gsd/tests/knowledge-backfill-projection.test.ts +35 -0
  424. package/src/resources/extensions/gsd/tests/knowledge-cold-start.test.ts +14 -0
  425. package/src/resources/extensions/gsd/tests/memory-consolidation-scanner.test.ts +78 -0
  426. package/src/resources/extensions/gsd/tests/memory-store.test.ts +48 -0
  427. package/src/resources/extensions/gsd/tests/merge-closeout-consistency-gate.test.ts +31 -1
  428. package/src/resources/extensions/gsd/tests/metrics-prune-cache-invalidation.test.ts +6 -0
  429. package/src/resources/extensions/gsd/tests/metrics.test.ts +1 -0
  430. package/src/resources/extensions/gsd/tests/migrate-external-worktree.test.ts +57 -0
  431. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +70 -0
  432. package/src/resources/extensions/gsd/tests/orchestrator-logs.test.ts +43 -1
  433. package/src/resources/extensions/gsd/tests/orphan-stash-audit.test.ts +91 -7
  434. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +26 -0
  435. package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +4 -1
  436. package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +1 -1
  437. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +10 -0
  438. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +103 -4
  439. package/src/resources/extensions/gsd/tests/plan-task.test.ts +44 -1
  440. package/src/resources/extensions/gsd/tests/post-mutation-hook.test.ts +4 -2
  441. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +54 -1
  442. package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +50 -14
  443. package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +58 -0
  444. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +8 -6
  445. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +195 -1
  446. package/src/resources/extensions/gsd/tests/read-uat-gate-verdict.test.ts +185 -0
  447. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +87 -0
  448. package/src/resources/extensions/gsd/tests/register-hooks-loop-guard-auto.test.ts +103 -0
  449. package/src/resources/extensions/gsd/tests/root-write-leak-guard.test.ts +20 -1
  450. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +15 -3
  451. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +56 -0
  452. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +191 -0
  453. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +208 -0
  454. package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +32 -3
  455. package/src/resources/extensions/gsd/tests/undo.test.ts +74 -0
  456. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +193 -14
  457. package/src/resources/extensions/gsd/tests/unmerged-milestone-guard.test.ts +25 -0
  458. package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +38 -0
  459. package/src/resources/extensions/gsd/tests/validation-block-guard.test.ts +79 -0
  460. package/src/resources/extensions/gsd/tests/verification-retry-policy.test.ts +69 -4
  461. package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +66 -0
  462. package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +96 -15
  463. package/src/resources/extensions/gsd/tests/workflow-mcp-preflight.test.ts +1 -0
  464. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +8 -4
  465. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +6 -5
  466. package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +151 -2
  467. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +39 -0
  468. package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -2
  469. package/src/resources/extensions/gsd/tools/complete-slice.ts +2 -2
  470. package/src/resources/extensions/gsd/tools/complete-task.ts +53 -15
  471. package/src/resources/extensions/gsd/tools/exec-tool.ts +7 -3
  472. package/src/resources/extensions/gsd/tools/plan-slice.ts +60 -47
  473. package/src/resources/extensions/gsd/tools/plan-task.ts +30 -5
  474. package/src/resources/extensions/gsd/undo.ts +47 -6
  475. package/src/resources/extensions/gsd/unit-context-composer.ts +33 -7
  476. package/src/resources/extensions/gsd/unit-registry.ts +36 -6
  477. package/src/resources/extensions/gsd/unmerged-milestone-guard.ts +41 -5
  478. package/src/resources/extensions/gsd/validation-block-guard.ts +13 -7
  479. package/src/resources/extensions/gsd/verification-gate.ts +8 -0
  480. package/src/resources/extensions/gsd/workflow-manifest.ts +141 -7
  481. package/src/resources/extensions/gsd/workflow-projections.ts +20 -14
  482. package/src/resources/extensions/gsd/workspace-git-preflight.ts +31 -0
  483. package/src/resources/extensions/gsd/worktree-manager.ts +41 -1
  484. package/dist/web/standalone/.next/static/chunks/2772.bfa657f49f955239.js +0 -1
  485. package/dist/web/standalone/.next/static/chunks/796.e0bdc932325d7e03.js +0 -10
  486. package/dist/web/standalone/.next/static/chunks/webpack-f46ea08200a0227e.js +0 -1
  487. /package/dist/web/standalone/.next/static/{BTKtGFF1Y-hvVJEGhBRo9 → 2A_WqqCS-EoYZxN9_v3d2}/_buildManifest.js +0 -0
  488. /package/dist/web/standalone/.next/static/{BTKtGFF1Y-hvVJEGhBRo9 → 2A_WqqCS-EoYZxN9_v3d2}/_ssgManifest.js +0 -0
@@ -20,6 +20,7 @@ import { invalidateAllCaches } from "./cache.js";
20
20
  import {
21
21
  gsdRoot, resolveMilestoneFile, resolveSliceFile,
22
22
  resolveGsdRootFile, relGsdRootFile, relSliceFile,
23
+ relMilestoneFile,
23
24
  } from "./paths.js";
24
25
  import { readFileSync, writeFileSync, existsSync } from "node:fs";
25
26
  import { atomicWriteSync } from "./atomic-write.js";
@@ -29,6 +30,10 @@ import { loadQueueOrder, sortByQueueOrder, saveQueueOrder } from "./queue-order.
29
30
  import { findMilestoneIds, nextMilestoneId } from "./milestone-ids.js";
30
31
  import { isFutureMilestoneStatus } from "./status-guards.js";
31
32
 
33
+ const QUEUE_ARTIFACT_EXCERPT_MAX_CHARS = 20_000;
34
+ const QUEUE_EXISTING_MILESTONES_CONTEXT_MAX_CHARS = 120_000;
35
+ const QUEUE_CONTEXT_SECTION_SEPARATOR = "\n\n---\n\n";
36
+
32
37
  // ─── Queue Entry Point ──────────────────────────────────────────────────────
33
38
 
34
39
  /**
@@ -280,7 +285,9 @@ export async function buildExistingMilestonesContext(
280
285
  if (contextFile) {
281
286
  const content = await loadFile(contextFile);
282
287
  if (content) {
283
- parts.push(`\n**Context:**\n${content.trim()}`);
288
+ parts.push(
289
+ `\n**Context:**\n${summarizeArtifactForQueue(content, relMilestoneFile(basePath, mid, "CONTEXT"))}`,
290
+ );
284
291
  }
285
292
  } else {
286
293
  // No full CONTEXT.md — check for CONTEXT-DRAFT.md (draft seed from prior discussion)
@@ -288,7 +295,9 @@ export async function buildExistingMilestonesContext(
288
295
  if (draftFile) {
289
296
  const draftContent = await loadFile(draftFile);
290
297
  if (draftContent) {
291
- parts.push(`\n**Draft context available:**\n${draftContent.trim()}`);
298
+ parts.push(
299
+ `\n**Draft context available:**\n${summarizeArtifactForQueue(draftContent, relMilestoneFile(basePath, mid, "CONTEXT-DRAFT"))}`,
300
+ );
292
301
  }
293
302
  }
294
303
  }
@@ -300,7 +309,9 @@ export async function buildExistingMilestonesContext(
300
309
  if (roadmapFile) {
301
310
  const content = await loadFile(roadmapFile);
302
311
  if (content) {
303
- parts.push(`\n**Roadmap:**\n${content.trim()}`);
312
+ parts.push(
313
+ `\n**Roadmap:**\n${summarizeArtifactForQueue(content, relMilestoneFile(basePath, mid, "ROADMAP"))}`,
314
+ );
304
315
  }
305
316
  }
306
317
  }
@@ -317,7 +328,81 @@ export async function buildExistingMilestonesContext(
317
328
  }
318
329
  }
319
330
 
320
- return sections.join("\n\n---\n\n");
331
+ return capExistingMilestonesContext(sections);
332
+ }
333
+
334
+ function summarizeArtifactForQueue(
335
+ content: string,
336
+ sourcePath: string,
337
+ cap = QUEUE_ARTIFACT_EXCERPT_MAX_CHARS,
338
+ ): string {
339
+ const trimmed = content.trim();
340
+ if (trimmed.length <= cap) {
341
+ return `Source: \`${sourcePath}\`\n\n${trimmed}`;
342
+ }
343
+
344
+ const excerpt = trimmed.slice(0, cap).trimEnd();
345
+ const omittedChars = trimmed.length - excerpt.length;
346
+ return [
347
+ `Source: \`${sourcePath}\``,
348
+ "",
349
+ excerpt,
350
+ "",
351
+ `[Truncated ${omittedChars} chars. Read \`${sourcePath}\` for full content.]`,
352
+ ].join("\n");
353
+ }
354
+
355
+ function capExistingMilestonesContext(
356
+ sections: string[],
357
+ cap = QUEUE_EXISTING_MILESTONES_CONTEXT_MAX_CHARS,
358
+ ): string {
359
+ const fullContext = sections.join(QUEUE_CONTEXT_SECTION_SEPARATOR);
360
+ if (fullContext.length <= cap) return fullContext;
361
+
362
+ const notice = `[Existing milestones context truncated to ${cap} chars. Read source paths in this prompt or the corresponding .gsd artifacts for full details.]`;
363
+ const noticeSuffix = `${QUEUE_CONTEXT_SECTION_SEPARATOR}${notice}`;
364
+
365
+ const selected: string[] = [];
366
+ for (const section of sections) {
367
+ const candidate = [...selected, section].join(QUEUE_CONTEXT_SECTION_SEPARATOR) + noticeSuffix;
368
+ if (candidate.length <= cap) {
369
+ selected.push(section);
370
+ continue;
371
+ }
372
+ break;
373
+ }
374
+
375
+ if (selected.length === sections.length) {
376
+ return selected.join(QUEUE_CONTEXT_SECTION_SEPARATOR) + noticeSuffix;
377
+ }
378
+
379
+ const compactTail = sections.slice(selected.length).map(compactSectionForQueueBudget);
380
+ const hybrid = [...selected, ...compactTail].join(QUEUE_CONTEXT_SECTION_SEPARATOR) + noticeSuffix;
381
+ if (hybrid.length <= cap) return hybrid;
382
+
383
+ const compact = sections.map(compactSectionForQueueBudget);
384
+ const compactContext = compact.join(QUEUE_CONTEXT_SECTION_SEPARATOR) + noticeSuffix;
385
+ if (compactContext.length <= cap) return compactContext;
386
+
387
+ return `${compactContext.slice(0, Math.max(0, cap - notice.length - 2)).trimEnd()}\n\n${notice}`;
388
+ }
389
+
390
+ function compactSectionForQueueBudget(section: string): string {
391
+ const lines = section.split("\n");
392
+ const compact: string[] = [];
393
+
394
+ if (lines[0]) compact.push(lines[0]);
395
+
396
+ const statusLine = lines.find(line => line.startsWith("**Status:**"));
397
+ if (statusLine) compact.push(statusLine);
398
+
399
+ const sourceLines = lines.filter(line => line.startsWith("Source: `"));
400
+ if (sourceLines.length > 0) {
401
+ compact.push("", "**Sources:**", ...sourceLines);
402
+ compact.push("", "[Artifact excerpts omitted due to total queue/rethink context budget.]");
403
+ }
404
+
405
+ return compact.join("\n");
321
406
  }
322
407
 
323
408
  // ─── Internal Helpers ───────────────────────────────────────────────────────
@@ -2,11 +2,12 @@
2
2
  // File Purpose: Always-on ambient health signal rendered below the editor.
3
3
 
4
4
  import type { ExtensionContext } from "@gsd/pi-coding-agent";
5
+ import { execFile } from "node:child_process";
5
6
  import type { GSDState } from "./types.js";
6
- import { runProviderChecks, summariseProviderIssues } from "./doctor-providers.js";
7
+ import { runProviderChecks, runProviderChecksAsync, summariseProviderIssues } from "./doctor-providers.js";
7
8
  import { runEnvironmentChecks, runEnvironmentChecksAsync } from "./doctor-environment.js";
8
9
  import { loadEffectiveGSDPreferences } from "./preferences.js";
9
- import { nativeIsRepo, nativeLastCommitEpoch, nativeGetCurrentBranch, nativeCommitSubject } from "./native-git-bridge.js";
10
+ import { GIT_NO_PROMPT_ENV } from "./git-constants.js";
10
11
  import { loadLedgerFromDisk, getProjectTotals } from "./metrics.js";
11
12
  import { describeNextUnit, estimateTimeRemaining, updateSliceProgressCache } from "./auto-dashboard.js";
12
13
  import { projectRoot } from "./commands/context.js";
@@ -15,32 +16,75 @@ import {
15
16
  buildHealthLines,
16
17
  detectHealthWidgetProjectState,
17
18
  type HealthWidgetData,
19
+ type HealthWidgetProjectState,
18
20
  } from "./health-widget-core.js";
19
21
 
20
22
  export const HEALTH_WIDGET_ACTIVE_HINTS =
21
23
  " /gsd auto to run · /gsd status to inspect · /gsd report for snapshots · /gsd notifications for history · /gsd help";
22
24
 
25
+ const LAST_COMMIT_LOOKUP_TIMEOUT_MS = 3_000;
26
+ const REFRESH_INTERVAL_MS = 60_000;
27
+ const PROJECT_STATE_CACHE_TTL_MS = REFRESH_INTERVAL_MS;
28
+
23
29
  // ── Data loader ────────────────────────────────────────────────────────────────
24
30
 
25
- // Last-commit lookup is subprocess-backed (native-git-bridge git spawns),
26
- // so it is treated like the other expensive checks: skipped on first paint,
27
- // run only by the background refresh.
28
- function loadLastCommitInfo(basePath: string): { epoch: number | null; message: string | null } {
31
+ const projectStateCache = new Map<string, { state: HealthWidgetProjectState; computedAt: number }>();
32
+
33
+ export function getCachedProjectState(basePath: string, force?: boolean): HealthWidgetProjectState {
34
+ const now = Date.now();
35
+ const cached = projectStateCache.get(basePath);
36
+ if (!force && cached && now - cached.computedAt <= PROJECT_STATE_CACHE_TTL_MS) {
37
+ return cached.state;
38
+ }
39
+
40
+ const state = detectHealthWidgetProjectState(basePath);
41
+ projectStateCache.set(basePath, { state, computedAt: now });
42
+ return state;
43
+ }
44
+
45
+ function runHealthWidgetGit(basePath: string, args: string[]): Promise<string | null> {
46
+ return new Promise((resolve) => {
47
+ const child = execFile(
48
+ "git",
49
+ args,
50
+ {
51
+ cwd: basePath,
52
+ timeout: LAST_COMMIT_LOOKUP_TIMEOUT_MS,
53
+ encoding: "utf-8",
54
+ env: GIT_NO_PROMPT_ENV,
55
+ },
56
+ (err, stdout) => resolve(err ? null : String(stdout).trimEnd()),
57
+ );
58
+ child.on("error", () => resolve(null));
59
+ });
60
+ }
61
+
62
+ async function loadLastCommitInfoAsync(basePath: string): Promise<{ epoch: number | null; message: string | null }> {
29
63
  try {
30
- if (nativeIsRepo(basePath)) {
31
- const branch = nativeGetCurrentBranch(basePath);
32
- const epoch = nativeLastCommitEpoch(basePath, branch || "HEAD");
33
- if (epoch > 0) {
34
- return { epoch, message: nativeCommitSubject(basePath, branch || "HEAD") || null };
35
- }
64
+ if ((await runHealthWidgetGit(basePath, ["rev-parse", "--git-dir"])) === null) {
65
+ return { epoch: null, message: null };
36
66
  }
37
- } catch { /* non-fatal */ }
38
- return { epoch: null, message: null };
67
+
68
+ const branch = await runHealthWidgetGit(basePath, ["branch", "--show-current"]);
69
+ const ref = branch || "HEAD";
70
+ const raw = await runHealthWidgetGit(basePath, ["log", "-1", "--format=%ct%x00%s", ref]);
71
+ if (!raw) return { epoch: null, message: null };
72
+
73
+ const separator = raw.indexOf("\0");
74
+ const epochText = separator >= 0 ? raw.slice(0, separator) : raw;
75
+ const epoch = parseInt(epochText.trim(), 10) || 0;
76
+ if (epoch <= 0) return { epoch: null, message: null };
77
+
78
+ const message = separator >= 0 ? raw.slice(separator + 1).trim() : "";
79
+ return { epoch, message: message || null };
80
+ } catch {
81
+ return { epoch: null, message: null };
82
+ }
39
83
  }
40
84
 
41
85
  function loadHealthWidgetData(
42
86
  basePath: string,
43
- options?: { includeChecks?: boolean },
87
+ options?: { includeChecks?: boolean; forceProjectState?: boolean },
44
88
  ): HealthWidgetData {
45
89
  // `includeChecks` gates the expensive subprocess-backed checks (provider +
46
90
  // environment doctor: `lsof`, `docker`, `node --version`, ...). The initial
@@ -55,7 +99,7 @@ function loadHealthWidgetData(
55
99
  let lastCommitEpoch: number | null = null;
56
100
  let lastCommitMessage: string | null = null;
57
101
 
58
- const projectState = detectHealthWidgetProjectState(basePath);
102
+ const projectState = getCachedProjectState(basePath, options?.forceProjectState);
59
103
 
60
104
  try {
61
105
  const prefs = loadEffectiveGSDPreferences();
@@ -83,13 +127,6 @@ function loadHealthWidgetData(
83
127
  } catch { /* non-fatal */ }
84
128
  }
85
129
 
86
- // ── Last commit info ── (git spawns — gated like the other expensive checks)
87
- if (includeChecks) {
88
- const commit = loadLastCommitInfo(basePath);
89
- lastCommitEpoch = commit.epoch;
90
- lastCommitMessage = commit.message;
91
- }
92
-
93
130
  return {
94
131
  projectState,
95
132
  budgetCeiling,
@@ -104,10 +141,8 @@ function loadHealthWidgetData(
104
141
  }
105
142
 
106
143
  // Non-blocking variant used by the widget's background refresh: the cheap fields
107
- // come from the synchronous snapshot, then provider + environment checks are
108
- // layered in off the event-loop critical path (env checks run concurrently via
109
- // runEnvironmentChecksAsync). Keeps the always-on widget from stalling the UI on
110
- // its initial enrichment or its 60s refresh.
144
+ // come from the synchronous snapshot, then provider, environment, and last-commit
145
+ // checks are layered in off the event-loop critical path.
111
146
  async function loadHealthWidgetDataAsync(basePath: string): Promise<HealthWidgetData> {
112
147
  const data = loadHealthWidgetData(basePath, { includeChecks: false });
113
148
  let providerIssue = data.providerIssue;
@@ -115,7 +150,7 @@ async function loadHealthWidgetDataAsync(basePath: string): Promise<HealthWidget
115
150
  let environmentWarningCount = 0;
116
151
 
117
152
  try {
118
- providerIssue = summariseProviderIssues(runProviderChecks());
153
+ providerIssue = summariseProviderIssues(await runProviderChecksAsync());
119
154
  } catch { /* non-fatal */ }
120
155
 
121
156
  try {
@@ -126,7 +161,7 @@ async function loadHealthWidgetDataAsync(basePath: string): Promise<HealthWidget
126
161
  }
127
162
  } catch { /* non-fatal */ }
128
163
 
129
- const commit = loadLastCommitInfo(basePath);
164
+ const commit = await loadLastCommitInfoAsync(basePath);
130
165
 
131
166
  return {
132
167
  ...data,
@@ -141,8 +176,6 @@ async function loadHealthWidgetDataAsync(basePath: string): Promise<HealthWidget
141
176
 
142
177
  // ── Widget init ────────────────────────────────────────────────────────────────
143
178
 
144
- const REFRESH_INTERVAL_MS = 60_000;
145
-
146
179
  /**
147
180
  * Initialize the always-on gsd-health widget (belowEditor).
148
181
  * Call once from the extension entry point after context is available.
@@ -152,13 +185,17 @@ export function initHealthWidget(ctx: ExtensionContext): void {
152
185
 
153
186
  const basePath = projectRoot();
154
187
 
188
+ // Re-init must reflect filesystem changes immediately; the TTL cache is for
189
+ // interval refreshes, not this one-off synchronous paint.
190
+ projectStateCache.delete(basePath);
191
+
155
192
  // String-array fallback — used in RPC mode (factory is a no-op there).
156
193
  // Skip the expensive provider/environment doctor checks here: this runs
157
194
  // synchronously on the interactive-startup path, where running them would
158
195
  // block first paint by ~0.9s (lsof/docker probes, otherwise run again
159
196
  // immediately by the factory below). The factory's async refresh fills in
160
197
  // real health once the screen is up.
161
- const initialData = loadHealthWidgetData(basePath, { includeChecks: false });
198
+ const initialData = loadHealthWidgetData(basePath, { includeChecks: false, forceProjectState: true });
162
199
  ctx.ui.setWidget("gsd-health", buildHealthLines(initialData), { placement: "belowEditor" });
163
200
 
164
201
  // Factory-based widget for TUI mode — replaces the string-array above
@@ -62,6 +62,26 @@ export function saveJsonFile<T>(filePath: string, data: T): void {
62
62
  }
63
63
  }
64
64
 
65
+ /**
66
+ * Save a JSON file atomically using compact serialization.
67
+ *
68
+ * Intended for machine-only ledgers where pretty-printing has no consumer.
69
+ * Keeps the same write-tmp-rename safety and non-fatal error behavior as
70
+ * saveJsonFile.
71
+ */
72
+ export function saveJsonFileCompact<T>(filePath: string, data: T): void {
73
+ try {
74
+ mkdirSync(dirname(filePath), { recursive: true });
75
+ // Use randomized tmp suffix to prevent concurrent-write data loss
76
+ const tmp = `${filePath}.tmp.${randomBytes(4).toString("hex")}`;
77
+ writeFileSync(tmp, JSON.stringify(data) + "\n", "utf-8");
78
+ renameSync(tmp, filePath);
79
+ // No cleanup needed — renameSync atomically removes tmp on success
80
+ } catch {
81
+ // Non-fatal — don't let persistence failures break operation
82
+ }
83
+ }
84
+
65
85
  /**
66
86
  * Write a JSON file atomically (write to .tmp, then rename).
67
87
  * Creates parent directories as needed. Non-fatal on error.
@@ -35,8 +35,8 @@ interface SynthesizedRow {
35
35
  * - Idempotent (per-row): each migrated memory carries
36
36
  * `structured_fields.sourceKnowledgeId = "<P|L>NNN"`. Rows whose ID is
37
37
  * already present in the memory store are skipped.
38
- * - Best-effort: never throws. Logs and returns 0 on failure so a broken
39
- * backfill cannot block agent startup.
38
+ * - Best-effort: never throws. Failed memory inserts are logged and skipped;
39
+ * setup/read failures log and return 0 so backfill cannot block startup.
40
40
  * - Rules (K###) are intentionally skipped — they remain manually maintained
41
41
  * in `KNOWLEDGE.md` per ADR-013.
42
42
  *
@@ -69,14 +69,20 @@ export function backfillKnowledgeToMemories(basePath: string): number {
69
69
  const matchPattern = `%"sourceKnowledgeId":"${synth.id}"%`;
70
70
  if (checkExisting.get({ ":pattern": matchPattern })) continue;
71
71
 
72
- const id = createMemory({
73
- category: synth.category,
74
- content: synth.content,
75
- scope: synth.scope,
76
- confidence: 0.85,
77
- structuredFields: synth.structuredFields,
78
- });
79
- if (id) written += 1;
72
+ try {
73
+ const id = createMemory({
74
+ category: synth.category,
75
+ content: synth.content,
76
+ scope: synth.scope,
77
+ confidence: 0.85,
78
+ structuredFields: synth.structuredFields,
79
+ });
80
+ if (id) written += 1;
81
+ } catch (rowErr) {
82
+ const message = rowErr instanceof Error ? rowErr.message : String(rowErr);
83
+ logWarning("knowledge-backfill", `KNOWLEDGE.md -> memories backfill skipped ${synth.id}: ${message}`);
84
+ continue;
85
+ }
80
86
  }
81
87
 
82
88
  return written;
@@ -47,8 +47,9 @@ export function dbPath(basePath: string): string {
47
47
  * Used by the renderer to derive the phase number from the DB's milestone_id.
48
48
  */
49
49
  export function milestoneIdToPhaseNum(milestoneId: string): number {
50
- // No $ anchor: accepts bare (M012) and team-suffixed (M012-abc123) IDs.
50
+ // No $ anchor: accepts bare (M012), team-suffixed (M012-abc123), and legacy numeric IDs.
51
51
  const m = milestoneId.match(/^M0*(\d+)/i);
52
+ if (!m && /^\d+$/.test(milestoneId)) return Number.parseInt(milestoneId, 10);
52
53
  return m ? Number.parseInt(m[1]!, 10) : 1;
53
54
  }
54
55
 
@@ -25,6 +25,7 @@ import {
25
25
  insertArtifact,
26
26
  deleteArtifactByPath,
27
27
  getGateResults,
28
+ isDbAvailable,
28
29
  } from "./gsd-db.js";
29
30
  import type { MilestoneRow, ArtifactRow } from "./db-milestone-artifact-rows.js";
30
31
  import type { SliceRow, TaskRow } from "./db-task-slice-rows.js";
@@ -631,16 +632,8 @@ export async function renderRoadmapCheckboxes(
631
632
  basePath: string,
632
633
  milestoneId: string,
633
634
  ): Promise<boolean> {
634
- const slices = getMilestoneSlices(milestoneId);
635
- if (slices.length === 0) {
636
- process.stderr.write(
637
- `markdown-renderer: no slices found for milestone ${milestoneId}\n`,
638
- );
639
- return false;
640
- }
641
-
642
- await renderRoadmapFromDb(basePath, milestoneId);
643
- return true;
635
+ const rendered = await renderRoadmapFromDb(basePath, milestoneId);
636
+ return !("skipped" in rendered);
644
637
  }
645
638
 
646
639
  /**
@@ -737,7 +730,8 @@ function isAutoRecoveryPlaceholderPlan(content: string): boolean {
737
730
  * projection (the 4S/0T-vs-5S/13T drift class). The artifacts table is an
738
731
  * output sink, never a render input.
739
732
  *
740
- * @returns true if the plan was written, false on skip/error
733
+ * @returns true if the plan was written, false when the DB slice has no tasks
734
+ * @throws when the DB connection is unavailable or the render write fails
741
735
  */
742
736
  export async function renderPlanCheckboxes(
743
737
  basePath: string,
@@ -747,6 +741,9 @@ export async function renderPlanCheckboxes(
747
741
  ): Promise<boolean> {
748
742
  const tasks = getSliceTasks(milestoneId, sliceId);
749
743
  if (tasks.length === 0) {
744
+ if (!isDbAvailable()) {
745
+ throw new Error(`database unavailable while rendering plan checkboxes for ${milestoneId}/${sliceId}`);
746
+ }
750
747
  process.stderr.write(
751
748
  `markdown-renderer: no tasks found for ${milestoneId}/${sliceId}\n`,
752
749
  );
@@ -49,8 +49,8 @@ type DecisionContentFields = Pick<DecisionRow, "decision" | "choice" | "rational
49
49
  * decision is checked individually; only decisions whose id is already
50
50
  * present in the memory store are skipped. A user-authored memory with
51
51
  * their own `sourceDecisionId` does NOT abort the backfill.
52
- * - Best-effort: never throws. Logs and returns 0 on failure so a broken
53
- * backfill cannot block agent startup.
52
+ * - Best-effort: never throws. Failed memory inserts are logged and skipped;
53
+ * setup/read failures log and return 0 so backfill cannot block startup.
54
54
  * - Full migration (ADR-013 Stage 2a): both active and superseded rows are
55
55
  * migrated. `structured_fields.superseded_by` preserves the supersedes
56
56
  * chain so the DECISIONS.md projection regen can source from memories
@@ -146,24 +146,30 @@ export function backfillDecisionsToMemories(): number {
146
146
  }
147
147
 
148
148
  const content = synthesizeDecisionMemoryContent(row);
149
- const id = createMemory({
150
- category: "architecture",
151
- content,
152
- scope: row.scope || "project",
153
- confidence: 0.85,
154
- structuredFields: {
155
- sourceDecisionId: row.id,
156
- when_context: row.when_context,
157
- scope: row.scope,
158
- decision: row.decision,
159
- choice: row.choice,
160
- rationale: row.rationale,
161
- made_by: row.made_by,
162
- revisable: row.revisable,
163
- superseded_by: row.superseded_by,
164
- },
165
- });
166
- if (id) written += 1;
149
+ try {
150
+ const id = createMemory({
151
+ category: "architecture",
152
+ content,
153
+ scope: row.scope || "project",
154
+ confidence: 0.85,
155
+ structuredFields: {
156
+ sourceDecisionId: row.id,
157
+ when_context: row.when_context,
158
+ scope: row.scope,
159
+ decision: row.decision,
160
+ choice: row.choice,
161
+ rationale: row.rationale,
162
+ made_by: row.made_by,
163
+ revisable: row.revisable,
164
+ superseded_by: row.superseded_by,
165
+ },
166
+ });
167
+ if (id) written += 1;
168
+ } catch (rowErr) {
169
+ const message = rowErr instanceof Error ? rowErr.message : String(rowErr);
170
+ logWarning("memory-backfill", `decisions->memories backfill skipped ${row.id}: ${message}`);
171
+ continue;
172
+ }
167
173
  }
168
174
 
169
175
  if (healed > 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
  }
@@ -19,7 +19,7 @@ import { openSync, closeSync, unlinkSync, statSync, writeFileSync } from "node:f
19
19
  import type { ExtensionContext } from "@gsd/pi-coding-agent";
20
20
  import { gsdRoot } from "./paths.js";
21
21
  import { getAndClearSkills } from "./skill-telemetry.js";
22
- import { loadJsonFile, loadJsonFileOrNull, saveJsonFile } from "./json-persistence.js";
22
+ import { loadJsonFile, loadJsonFileOrNull, saveJsonFileCompact } from "./json-persistence.js";
23
23
  import { parseUnitId } from "./unit-id.js";
24
24
  import { buildAuditEnvelope, emitUokAuditEvent } from "./uok/audit.js";
25
25
  import { isUnifiedAuditEnabled } from "./uok/audit-toggle.js";
@@ -873,7 +873,7 @@ export function pruneMetricsLedger(base: string, keepCount: number): number {
873
873
  if (!disk || disk.units.length <= keepCount) return 0;
874
874
  const removed = disk.units.length - keepCount;
875
875
  disk.units = keepNewestUnits(disk.units, keepCount);
876
- saveJsonFile(metricsPath(base), disk);
876
+ saveJsonFileCompact(metricsPath(base), disk);
877
877
  // Keep the in-memory ledger in sync if it is loaded for this session.
878
878
  if (ledger) {
879
879
  ledger.units = keepNewestUnits(ledger.units, keepCount);
@@ -1041,7 +1041,7 @@ function saveLedger(base: string, data: MetricsLedger): void {
1041
1041
  : dataUnits;
1042
1042
  merged.sort(compareUnitsByTime);
1043
1043
  data.units = keepNewestUnits(merged);
1044
- saveJsonFile(path, data);
1044
+ saveJsonFileCompact(path, data);
1045
1045
  } finally {
1046
1046
  releaseLock(lockPath);
1047
1047
  }
@@ -1053,6 +1053,6 @@ function saveLedger(base: string, data: MetricsLedger): void {
1053
1053
  // read-merge-write sequence without mutual exclusion.
1054
1054
  logWarning("fs", "saveLedger: lock not acquired — falling back to direct write (no merge)");
1055
1055
  data.units = keepNewestUnits(data.units);
1056
- saveJsonFile(path, data);
1056
+ saveJsonFileCompact(path, data);
1057
1057
  }
1058
1058
  }