@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
@@ -12,6 +12,7 @@
12
12
  */
13
13
 
14
14
  import { existsSync, readFileSync } from "node:fs";
15
+ import { access, readFile } from "node:fs/promises";
15
16
  import { delimiter, join } from "node:path";
16
17
  import { AuthStorage } from "@gsd/pi-coding-agent";
17
18
  import { getEnvApiKey } from "@gsd/pi-ai";
@@ -166,15 +167,11 @@ const CLI_AUTH_PATH_CHECK_PROVIDERS = new Set([
166
167
  "google-antigravity",
167
168
  ]);
168
169
 
169
- /**
170
- * Check if a CLI provider's binary exists anywhere in PATH.
171
- * Fast filesystem scan — no subprocess, no network, sub-1ms.
172
- */
173
- function isCliBinaryInPath(providerId: string): boolean {
174
- const binaries = CLI_BINARY_MAP[providerId];
175
- if (!binaries) return false;
170
+ let asyncCliBinaryPathCache: Map<string, boolean> | null = null;
176
171
 
177
- const pathDirs = (process.env.PATH ?? "").split(delimiter).filter(Boolean);
172
+ function cliExecutableNames(providerId: string): string[] {
173
+ const binaries = CLI_BINARY_MAP[providerId];
174
+ if (!binaries) return [];
178
175
 
179
176
  // On Windows, command shims are commonly installed as .cmd/.exe/.bat/.com.
180
177
  // Scan PATHEXT candidates in addition to the bare binary name.
@@ -196,9 +193,51 @@ function isCliBinaryInPath(providerId: string): boolean {
196
193
  }
197
194
  }
198
195
 
196
+ return executableNames;
197
+ }
198
+
199
+ /**
200
+ * Check if a CLI provider's binary exists anywhere in PATH.
201
+ * Fast filesystem scan — no subprocess, no network, sub-1ms.
202
+ */
203
+ function isCliBinaryInPath(providerId: string): boolean {
204
+ const cached = asyncCliBinaryPathCache?.get(providerId);
205
+ if (cached !== undefined) return cached;
206
+
207
+ const executableNames = cliExecutableNames(providerId);
208
+ if (executableNames.length === 0) return false;
209
+
210
+ const pathDirs = (process.env.PATH ?? "").split(delimiter).filter(Boolean);
211
+
199
212
  return pathDirs.some(dir => executableNames.some(name => existsSync(join(dir, name))));
200
213
  }
201
214
 
215
+ async function isCliBinaryInPathAsync(providerId: string): Promise<boolean> {
216
+ const executableNames = cliExecutableNames(providerId);
217
+ if (executableNames.length === 0) return false;
218
+
219
+ const pathDirs = (process.env.PATH ?? "").split(delimiter).filter(Boolean);
220
+ const candidates = pathDirs.flatMap(dir => executableNames.map(name => join(dir, name)));
221
+ if (candidates.length === 0) return false;
222
+
223
+ try {
224
+ await Promise.any(candidates.map(candidate => access(candidate)));
225
+ return true;
226
+ } catch {
227
+ return false;
228
+ }
229
+ }
230
+
231
+ async function loadCliBinaryPathCache(): Promise<Map<string, boolean>> {
232
+ const entries = await Promise.all(
233
+ Object.keys(CLI_BINARY_MAP).map(async providerId => [
234
+ providerId,
235
+ await isCliBinaryInPathAsync(providerId),
236
+ ] as const),
237
+ );
238
+ return new Map(entries);
239
+ }
240
+
202
241
  function modelsJsonPaths(): string[] {
203
242
  const home = homedir();
204
243
  return [
@@ -208,7 +247,13 @@ function modelsJsonPaths(): string[] {
208
247
  ];
209
248
  }
210
249
 
250
+ let asyncModelsJsonApiKeyCache: Set<string> | null = null;
251
+
211
252
  function hasModelsJsonApiKey(providerId: string): boolean {
253
+ if (asyncModelsJsonApiKeyCache) {
254
+ return asyncModelsJsonApiKeyCache.has(providerId);
255
+ }
256
+
212
257
  for (const path of modelsJsonPaths()) {
213
258
  if (!existsSync(path)) continue;
214
259
  try {
@@ -226,7 +271,27 @@ function hasModelsJsonApiKey(providerId: string): boolean {
226
271
  return false;
227
272
  }
228
273
 
229
- function resolveKey(providerId: string): KeyLookup {
274
+ async function loadModelsJsonApiKeyCache(): Promise<Set<string>> {
275
+ const providersWithKeys = new Set<string>();
276
+ for (const path of modelsJsonPaths()) {
277
+ try {
278
+ const parsed = JSON.parse(await readFile(path, "utf-8")) as {
279
+ providers?: Record<string, { apiKey?: unknown }>;
280
+ };
281
+ for (const [providerId, provider] of Object.entries(parsed.providers ?? {})) {
282
+ const apiKey = provider.apiKey;
283
+ if (typeof apiKey === "string" && apiKey.trim().length > 0) {
284
+ providersWithKeys.add(providerId);
285
+ }
286
+ }
287
+ } catch {
288
+ // Missing or malformed models.json should not break dashboard health checks.
289
+ }
290
+ }
291
+ return providersWithKeys;
292
+ }
293
+
294
+ function resolveKeyFromAuthOrEnv(providerId: string): KeyLookup | null {
230
295
  const info = PROVIDER_REGISTRY.find(p => p.id === providerId);
231
296
 
232
297
  if (providerId === "anthropic-vertex" && process.env.ANTHROPIC_VERTEX_PROJECT_ID) {
@@ -276,6 +341,13 @@ function resolveKey(providerId: string): KeyLookup {
276
341
  return { found: true, source: "env", backedOff: false };
277
342
  }
278
343
 
344
+ return null;
345
+ }
346
+
347
+ function resolveKey(providerId: string): KeyLookup {
348
+ const direct = resolveKeyFromAuthOrEnv(providerId);
349
+ if (direct) return direct;
350
+
279
351
  if (hasModelsJsonApiKey(providerId)) {
280
352
  return { found: true, source: "models.json", backedOff: false };
281
353
  }
@@ -495,6 +567,28 @@ export function runProviderChecks(): ProviderCheckResult[] {
495
567
  return results;
496
568
  }
497
569
 
570
+ /**
571
+ * Non-blocking equivalent of `runProviderChecks` for the health-widget
572
+ * background refresh. PATH checks and custom models.json discovery use async
573
+ * filesystem APIs so periodic widget refreshes do not stall the input loop.
574
+ */
575
+ export async function runProviderChecksAsync(): Promise<ProviderCheckResult[]> {
576
+ const [cliCache, modelsJsonCache] = await Promise.all([
577
+ loadCliBinaryPathCache(),
578
+ loadModelsJsonApiKeyCache(),
579
+ ]);
580
+ const previousCliCache = asyncCliBinaryPathCache;
581
+ const previousModelsJsonCache = asyncModelsJsonApiKeyCache;
582
+ asyncCliBinaryPathCache = cliCache;
583
+ asyncModelsJsonApiKeyCache = modelsJsonCache;
584
+ try {
585
+ return runProviderChecks();
586
+ } finally {
587
+ asyncCliBinaryPathCache = previousCliCache;
588
+ asyncModelsJsonApiKeyCache = previousModelsJsonCache;
589
+ }
590
+ }
591
+
498
592
  /**
499
593
  * Format provider check results as a human-readable report string.
500
594
  */
@@ -408,6 +408,9 @@ export async function checkRuntimeHealth(
408
408
  if (!existingLines.has(".gsd-worktrees/") && !existingLines.has(".gsd-worktrees")) {
409
409
  missing.push(".gsd-worktrees/");
410
410
  }
411
+ if (!existingLines.has(".gsd-backups/") && !existingLines.has(".gsd-backups")) {
412
+ missing.push(".gsd-backups/");
413
+ }
411
414
  if (!hasBlanketIgnore) {
412
415
  missing.push(...criticalPatterns.filter(p => !existingLines.has(p)));
413
416
  }
@@ -84,10 +84,13 @@ export type DoctorIssueCode =
84
84
  | "db_orphaned_task"
85
85
  | "db_orphaned_slice"
86
86
  | "db_done_task_no_summary"
87
+ | "artifact_file_missing"
87
88
  | "artifact_db_status_divergence"
89
+ | "checkbox_db_status_divergence"
88
90
  | "completed_milestone_reopened"
89
91
  | "db_duplicate_id"
90
92
  | "db_unavailable"
93
+ | "memories_fts_rebuild_missing"
91
94
  | "projection_drift"
92
95
  // Milestone filesystem/DB drift (#4996)
93
96
  | "orphan_milestone_dir"
@@ -12,7 +12,7 @@ import { spawn } from "node:child_process";
12
12
  import { existsSync, mkdirSync, writeFileSync } from "node:fs";
13
13
  import { randomUUID } from "node:crypto";
14
14
  import { resolve } from "node:path";
15
- import { killProcessTree, SIGKILL_GRACE_MS, HARD_DEADLINE_MS } from "@gsd/pi-coding-agent";
15
+ import { getShellConfig, killProcessTree, SIGKILL_GRACE_MS, HARD_DEADLINE_MS } from "@gsd/pi-coding-agent";
16
16
 
17
17
  export interface ExecSandboxRequest {
18
18
  /** Interpreter to use. */
@@ -48,6 +48,8 @@ export interface ExecSandboxOptions {
48
48
  now?: () => Date;
49
49
  /** Optional override for id generation (tests). */
50
50
  generateId?: () => string;
51
+ /** Optional request cancellation signal. Aborting kills the child process tree. */
52
+ signal?: AbortSignal;
51
53
  /**
52
54
  * Grace period (ms) between SIGTERM and SIGKILL on timeout.
53
55
  * Defaults to SIGKILL_GRACE_MS. Exposed as a test seam.
@@ -67,6 +69,8 @@ export interface ExecSandboxResult {
67
69
  exit_code: number | null;
68
70
  signal: NodeJS.Signals | null;
69
71
  timed_out: boolean;
72
+ /** True when an external AbortSignal terminated the child process tree. */
73
+ aborted?: boolean;
70
74
  /**
71
75
  * True when the result came from the hard-deadline force-resolve (a non-closing
72
76
  * D-state child that never emitted 'close') rather than an observed process exit.
@@ -134,7 +138,12 @@ function clampTimeout(request: ExecSandboxRequest, opts: ExecSandboxOptions): nu
134
138
  function resolveCommand(runtime: ExecSandboxRequest["runtime"]): { cmd: string; args: string[] } {
135
139
  switch (runtime) {
136
140
  case "bash":
137
- return { cmd: "bash", args: ["-c"] };
141
+ try {
142
+ const { shell, args } = getShellConfig();
143
+ return { cmd: shell, args };
144
+ } catch {
145
+ return { cmd: "bash", args: ["-c"] };
146
+ }
138
147
  case "node":
139
148
  return { cmd: process.execPath, args: ["-e"] };
140
149
  case "python":
@@ -260,11 +269,23 @@ export function runExecSandbox(
260
269
  const effectiveForceResolveDelay = opts.force_resolve_delay_ms ?? (effectiveGraceMs + HARD_DEADLINE_MS);
261
270
 
262
271
  let timedOut = false;
272
+ let aborted = false;
263
273
  let settled = false;
274
+ let killInitiated = false;
275
+ let timer: NodeJS.Timeout | undefined;
264
276
  let forceResolveTimer: NodeJS.Timeout | undefined;
277
+ let abortListener: (() => void) | undefined;
265
278
 
266
- const timer = setTimeout(() => {
267
- timedOut = true;
279
+ const removeAbortListener = () => {
280
+ if (opts.signal && abortListener) {
281
+ opts.signal.removeEventListener("abort", abortListener);
282
+ abortListener = undefined;
283
+ }
284
+ };
285
+
286
+ const initiateKill = () => {
287
+ if (killInitiated) return;
288
+ killInitiated = true;
268
289
  // killProcessTree handles both platforms and kills the whole tree: on Unix
269
290
  // it signals the process group (SIGTERM -> grace -> SIGKILL); on Windows it
270
291
  // force-kills the tree via taskkill /F /T. Using child.kill("SIGTERM") here
@@ -281,14 +302,14 @@ export function runExecSandbox(
281
302
  finalize(null, "SIGKILL", true);
282
303
  }, effectiveForceResolveDelay);
283
304
  forceResolveTimer.unref?.();
284
- }, timeoutMs);
285
- timer.unref?.();
305
+ };
286
306
 
287
307
  const finalize = (exitCode: number | null, signal: NodeJS.Signals | null, forceResolved = false) => {
288
308
  if (settled) return;
289
309
  settled = true;
290
310
  clearTimeout(timer);
291
311
  clearTimeout(forceResolveTimer);
312
+ removeAbortListener();
292
313
  const duration = Date.now() - started;
293
314
  const stdoutBuf = Buffer.concat(stdoutChunks);
294
315
  const stderrBuf = Buffer.concat(stderrChunks);
@@ -301,11 +322,13 @@ export function runExecSandbox(
301
322
  const digest =
302
323
  digestBody.length > 0
303
324
  ? digestBody
304
- : timedOut
305
- ? "[no stdout — timed out]"
306
- : stderrBuf.length > 0
307
- ? `[no stdout — tail of stderr]\n${tail(stderrBuf, opts.digest_chars)}`
308
- : "[no output]";
325
+ : aborted
326
+ ? "[no stdout — aborted]"
327
+ : timedOut
328
+ ? "[no stdout — timed out]"
329
+ : stderrBuf.length > 0
330
+ ? `[no stdout — tail of stderr]\n${tail(stderrBuf, opts.digest_chars)}`
331
+ : "[no output]";
309
332
 
310
333
  const result: ExecSandboxResult = {
311
334
  id,
@@ -313,6 +336,7 @@ export function runExecSandbox(
313
336
  exit_code: exitCode,
314
337
  signal,
315
338
  timed_out: timedOut,
339
+ aborted,
316
340
  force_resolved: forceResolved,
317
341
  duration_ms: duration,
318
342
  stdout_bytes: stdoutBytes,
@@ -328,6 +352,26 @@ export function runExecSandbox(
328
352
  resolveP(result);
329
353
  };
330
354
 
355
+ timer = setTimeout(() => {
356
+ timedOut = true;
357
+ initiateKill();
358
+ }, timeoutMs);
359
+ timer.unref?.();
360
+
361
+ if (opts.signal) {
362
+ abortListener = () => {
363
+ if (settled || timedOut) return;
364
+ aborted = true;
365
+ clearTimeout(timer);
366
+ initiateKill();
367
+ };
368
+ if (opts.signal.aborted) {
369
+ abortListener();
370
+ } else {
371
+ opts.signal.addEventListener("abort", abortListener, { once: true });
372
+ }
373
+ }
374
+
331
375
  child.on("error", (err) => {
332
376
  const message = err instanceof Error ? err.message : String(err);
333
377
  const line = `child error: ${message}\n`;
@@ -364,6 +408,7 @@ function writeMeta(
364
408
  exit_code: result.exit_code,
365
409
  signal: result.signal,
366
410
  timed_out: result.timed_out,
411
+ aborted: result.aborted === true,
367
412
  force_resolved: result.force_resolved,
368
413
  duration_ms: result.duration_ms,
369
414
  stdout_bytes: result.stdout_bytes,
@@ -70,6 +70,50 @@ export function needsFlatPhaseMigration(basePath: string): boolean {
70
70
  return hasLegacyMilestoneSubdirs(legacyMigratingPath(basePath));
71
71
  }
72
72
 
73
+ /** Retention window before flat-phase migration backups are auto-pruned. */
74
+ export const FLAT_PHASE_BACKUP_RETENTION_MS = 30 * 24 * 60 * 60 * 1000;
75
+
76
+ /**
77
+ * Remove stale flat-phase migration backups after the retention window.
78
+ * Only runs when migration is complete (.gsd/phases/ exists, legacy layout gone).
79
+ * Returns the number of migrate-* directories removed.
80
+ */
81
+ export function pruneStaleFlatPhaseBackups(basePath: string): number {
82
+ if (needsFlatPhaseMigration(basePath)) return 0;
83
+
84
+ const phasesPath = join(basePath, ".gsd", LAYOUT_SEGMENTS.level1);
85
+ if (!existsSync(phasesPath)) return 0;
86
+
87
+ const backupRoot = join(basePath, ".gsd-backups");
88
+ if (!existsSync(backupRoot)) return 0;
89
+
90
+ const now = Date.now();
91
+ let removed = 0;
92
+ for (const entry of readdirSync(backupRoot)) {
93
+ if (!entry.startsWith("migrate-")) continue;
94
+ const dirPath = join(backupRoot, entry);
95
+ try {
96
+ const st = statSync(dirPath);
97
+ if (!st.isDirectory()) continue;
98
+ if (now - st.mtimeMs < FLAT_PHASE_BACKUP_RETENTION_MS) continue;
99
+ rmSync(dirPath, { recursive: true, force: true });
100
+ removed++;
101
+ } catch {
102
+ // Non-fatal: leave backup for manual recovery.
103
+ }
104
+ }
105
+
106
+ try {
107
+ if (readdirSync(backupRoot).length === 0) {
108
+ rmSync(backupRoot, { recursive: true, force: true });
109
+ }
110
+ } catch {
111
+ // Non-fatal.
112
+ }
113
+
114
+ return removed;
115
+ }
116
+
73
117
  /**
74
118
  * Migrate from legacy nested .gsd/milestones/ to flat-phase .gsd/phases/.
75
119
  *
@@ -28,8 +28,7 @@ import { deriveState } from "./state.js";
28
28
  import { isAutoActive } from "./auto.js";
29
29
  import { loadPrompt } from "./prompt-loader.js";
30
30
  import { gsdRoot } from "./paths.js";
31
- import { isDbAvailable, getAllMilestones, getMilestoneSlices, getSliceTasks } from "./gsd-db.js";
32
- import { isClosedStatus } from "./status-guards.js";
31
+ import { isDbAvailable, getHierarchyCompletionCounts } from "./gsd-db.js";
33
32
  import { formatDuration } from "../shared/format-utils.js";
34
33
  import { getAutoWorktreePath } from "./auto-worktree.js";
35
34
  import { clearGSDPreferencesCache, loadEffectiveGSDPreferences, loadGlobalGSDPreferences, getGlobalGSDPreferencesPath } from "./preferences.js";
@@ -759,37 +758,7 @@ function loadCompletedKeys(basePath: string): string[] {
759
758
  function getDbCompletionCounts(): DbCompletionCounts | null {
760
759
  if (!isDbAvailable()) return null;
761
760
 
762
- const milestones = getAllMilestones();
763
- let completedMilestones = 0;
764
- let totalSlices = 0;
765
- let completedSlices = 0;
766
- let totalTasks = 0;
767
- let completedTasks = 0;
768
-
769
- for (const m of milestones) {
770
- if (isClosedStatus(m.status)) completedMilestones++;
771
-
772
- const slices = getMilestoneSlices(m.id);
773
- for (const s of slices) {
774
- totalSlices++;
775
- if (isClosedStatus(s.status)) completedSlices++;
776
-
777
- const tasks = getSliceTasks(m.id, s.id);
778
- for (const t of tasks) {
779
- totalTasks++;
780
- if (isClosedStatus(t.status)) completedTasks++;
781
- }
782
- }
783
- }
784
-
785
- return {
786
- milestones: completedMilestones,
787
- milestonesTotal: milestones.length,
788
- slices: completedSlices,
789
- slicesTotal: totalSlices,
790
- tasks: completedTasks,
791
- tasksTotal: totalTasks,
792
- };
761
+ return getHierarchyCompletionCounts();
793
762
  }
794
763
 
795
764
  // ─── Anomaly Detectors ───────────────────────────────────────────────────────
@@ -12,6 +12,7 @@
12
12
 
13
13
  import { execFileSync } from "node:child_process";
14
14
  import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
15
+ import type { Dirent } from "node:fs";
15
16
  import { isAbsolute, join, normalize, relative, resolve, sep } from "node:path";
16
17
  import { gsdRoot } from "./paths.js";
17
18
  import { GIT_NO_PROMPT_ENV } from "./git-constants.js";
@@ -360,6 +361,7 @@ export interface PreMergeCheckResult {
360
361
  */
361
362
  export const RUNTIME_EXCLUSION_PATHS: readonly string[] = [
362
363
  ".gsd-worktrees/",
364
+ ".gsd-backups/**",
363
365
  ".gsd/activity/",
364
366
  ".gsd/audit/",
365
367
  ".gsd/forensics/",
@@ -378,6 +380,8 @@ export const RUNTIME_EXCLUSION_PATHS: readonly string[] = [
378
380
  ".gsd/DISCUSSION-MANIFEST.json",
379
381
  ];
380
382
 
383
+ const runtimeFilesCleanedUpRepos = new Set<string>();
384
+
381
385
  // ─── Integration Branch Metadata ───────────────────────────────────────────
382
386
 
383
387
  /**
@@ -755,7 +759,8 @@ export class GitServiceImpl {
755
759
  // and the worktree is torn down. This prevents a mid-execution behavioral
756
760
  // discontinuity where the first half of a milestone has .gsd/ artifacts
757
761
  // committed but the second half doesn't (#1326).
758
- if (!this._runtimeFilesCleanedUp) {
762
+ const cleanupRepoKey = resolve(this.basePath);
763
+ if (!runtimeFilesCleanedUpRepos.has(cleanupRepoKey)) {
759
764
  let cleaned = false;
760
765
  for (const exclusion of RUNTIME_EXCLUSION_PATHS) {
761
766
  const removed = nativeRmCached(this.basePath, [exclusion]);
@@ -764,7 +769,7 @@ export class GitServiceImpl {
764
769
  if (cleaned) {
765
770
  nativeCommit(this.basePath, "chore: untrack .gsd/ runtime files from git index", { allowEmpty: false });
766
771
  }
767
- this._runtimeFilesCleanedUp = true;
772
+ runtimeFilesCleanedUpRepos.add(cleanupRepoKey);
768
773
  }
769
774
 
770
775
  // Stage everything using pathspec exclusions so excluded paths are never
@@ -893,9 +898,6 @@ export class GitServiceImpl {
893
898
  }
894
899
  }
895
900
 
896
- /** Tracks whether runtime file cleanup has run this session. */
897
- private _runtimeFilesCleanedUp = false;
898
-
899
901
  /**
900
902
  * Stage files (smart staging) and commit.
901
903
  * Returns the commit message string on success, or null if nothing to commit.
@@ -1268,6 +1270,7 @@ function collectRepositoryDirtyStatus(basePath: string): Record<string, boolean>
1268
1270
  const preferences = loadEffectiveGSDPreferences(basePath)?.preferences;
1269
1271
  const registry = createRepositoryRegistryFromPreferences(basePath, preferences);
1270
1272
  const dirtyByRepository: Record<string, boolean> = {};
1273
+ const registeredRoots = new Set(registry.repositories.map((repo) => resolve(repo.root)));
1271
1274
  for (const repo of registry.repositories) {
1272
1275
  try {
1273
1276
  dirtyByRepository[repo.id] = runGit(repo.root, ["status", "--porcelain"]).length > 0;
@@ -1276,9 +1279,70 @@ function collectRepositoryDirtyStatus(basePath: string): Record<string, boolean>
1276
1279
  dirtyByRepository[repo.id] = nativeHasChanges(repo.root);
1277
1280
  }
1278
1281
  }
1282
+ for (const repoRoot of findUndeclaredNestedGitRepositories(registry.projectRoot, registeredRoots)) {
1283
+ let dirty = false;
1284
+ try {
1285
+ dirty = runGit(repoRoot, ["status", "--porcelain"]).length > 0;
1286
+ } catch {
1287
+ dirty = nativeHasChanges(repoRoot);
1288
+ }
1289
+ if (!dirty) continue;
1290
+
1291
+ const relPath = relative(registry.projectRoot, repoRoot).split(sep).join("/") || repoRoot;
1292
+ const label = `${relPath} (undeclared)`;
1293
+ dirtyByRepository[label] = true;
1294
+ logWarning(
1295
+ "engine",
1296
+ `undeclared dirty nested git repo ${relPath}; declare it under workspace.repositories or commit manually`,
1297
+ { file: "git-service.ts" },
1298
+ );
1299
+ }
1279
1300
  return dirtyByRepository;
1280
1301
  }
1281
1302
 
1303
+ const UNDECLARED_NESTED_REPO_SCAN_MAX_DEPTH = 4;
1304
+ const UNDECLARED_NESTED_REPO_SKIP_DIRS = new Set([
1305
+ ".git",
1306
+ ".gsd",
1307
+ ".gsd-worktrees",
1308
+ "node_modules",
1309
+ "dist",
1310
+ "dist-test",
1311
+ ]);
1312
+
1313
+ function findUndeclaredNestedGitRepositories(projectRoot: string, registeredRoots: ReadonlySet<string>): string[] {
1314
+ const found: string[] = [];
1315
+
1316
+ function visit(dir: string, depth: number): void {
1317
+ if (depth >= UNDECLARED_NESTED_REPO_SCAN_MAX_DEPTH) return;
1318
+
1319
+ let entries: Dirent[];
1320
+ try {
1321
+ entries = readdirSync(dir, { withFileTypes: true });
1322
+ } catch {
1323
+ return;
1324
+ }
1325
+
1326
+ for (const entry of entries) {
1327
+ if (!entry.isDirectory()) continue;
1328
+ if (UNDECLARED_NESTED_REPO_SKIP_DIRS.has(entry.name)) continue;
1329
+
1330
+ const child = join(dir, entry.name);
1331
+ const childRoot = resolve(child);
1332
+ const hasGitDir = existsSync(join(child, ".git"));
1333
+ const isRegistered = registeredRoots.has(childRoot);
1334
+ if (hasGitDir && !isRegistered) {
1335
+ found.push(childRoot);
1336
+ continue;
1337
+ }
1338
+ visit(child, depth + 1);
1339
+ }
1340
+ }
1341
+
1342
+ visit(projectRoot, 0);
1343
+ return found;
1344
+ }
1345
+
1282
1346
  function runPerRepositoryCommitAction(args: {
1283
1347
  basePath: string;
1284
1348
  unitType: string;
@@ -24,8 +24,9 @@ import { GIT_NO_PROMPT_ENV } from "./git-constants.js";
24
24
  * With external state (symlink), these are a no-op in most cases,
25
25
  * but retained for backwards compatibility during migration.
26
26
  */
27
- const GSD_RUNTIME_PATTERNS = [
27
+ export const GSD_RUNTIME_PATTERNS = [
28
28
  ".gsd-worktrees/",
29
+ ".gsd-backups/",
29
30
  ".gsd/activity/",
30
31
  ".gsd/audit/",
31
32
  ".gsd/forensics/",
@@ -51,6 +52,8 @@ const BASELINE_PATTERNS = [
51
52
  ".gsd",
52
53
  // Worktree container sibling — NOT covered by the ".gsd" pattern above.
53
54
  ".gsd-worktrees/",
55
+ // Flat-phase migration snapshots — NOT covered by the ".gsd" pattern above.
56
+ ".gsd-backups/",
54
57
  ".gsd-id",
55
58
  ".mcp.json",
56
59
  ".bg-shell/",