@opengsd/gsd-pi 1.3.0-dev.eed73bea → 1.4.0

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 (505) hide show
  1. package/README.md +10 -10
  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/gsd/artifact-verification.js +427 -0
  10. package/dist/resources/extensions/gsd/auto/session.js +11 -0
  11. package/dist/resources/extensions/gsd/auto/verification-retry-policy.js +1 -1
  12. package/dist/resources/extensions/gsd/auto-artifact-paths.js +28 -1
  13. package/dist/resources/extensions/gsd/auto-budget.js +5 -1
  14. package/dist/resources/extensions/gsd/auto-dispatch.js +17 -6
  15. package/dist/resources/extensions/gsd/auto-post-unit.js +1 -1
  16. package/dist/resources/extensions/gsd/auto-prompts.js +8 -24
  17. package/dist/resources/extensions/gsd/auto-recovery.js +9 -517
  18. package/dist/resources/extensions/gsd/auto-runtime-state.js +4 -5
  19. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +3 -3
  20. package/dist/resources/extensions/gsd/auto-verification.js +5 -2
  21. package/dist/resources/extensions/gsd/auto.js +19 -10
  22. package/dist/resources/extensions/gsd/bootstrap/core-session-tools.js +39 -0
  23. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +5 -4
  24. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +2 -0
  25. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +33 -18
  26. package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +48 -36
  27. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +15 -4
  28. package/dist/resources/extensions/gsd/closeout-consistency-gate.js +3 -1
  29. package/dist/resources/extensions/gsd/commands/handlers/auto.js +1 -1
  30. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +1 -1
  31. package/dist/resources/extensions/gsd/commands-usage.js +1 -1
  32. package/dist/resources/extensions/gsd/db/engine.js +4 -1
  33. package/dist/resources/extensions/gsd/db-memory-fts-schema.js +34 -0
  34. package/dist/resources/extensions/gsd/db-workspace.js +55 -3
  35. package/dist/resources/extensions/gsd/delegation-policy.js +1 -1
  36. package/dist/resources/extensions/gsd/docs/preferences-reference.md +2 -2
  37. package/dist/resources/extensions/gsd/doctor-engine-checks.js +192 -4
  38. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +3 -0
  39. package/dist/resources/extensions/gsd/exec-sandbox.js +8 -2
  40. package/dist/resources/extensions/gsd/flat-phase-migration.js +45 -0
  41. package/dist/resources/extensions/gsd/git-service.js +57 -0
  42. package/dist/resources/extensions/gsd/gitignore.js +4 -1
  43. package/dist/resources/extensions/gsd/guided-flow-queue.js +20 -13
  44. package/dist/resources/extensions/gsd/json-persistence.js +20 -0
  45. package/dist/resources/extensions/gsd/knowledge-backfill.js +18 -11
  46. package/dist/resources/extensions/gsd/layout-policy.js +3 -1
  47. package/dist/resources/extensions/gsd/markdown-renderer.js +2 -7
  48. package/dist/resources/extensions/gsd/memory-backfill.js +28 -21
  49. package/dist/resources/extensions/gsd/metrics.js +4 -4
  50. package/dist/resources/extensions/gsd/migrate-external.js +11 -2
  51. package/dist/resources/extensions/gsd/migration-auto-check.js +22 -0
  52. package/dist/resources/extensions/gsd/milestone-ids.js +32 -2
  53. package/dist/resources/extensions/gsd/orphan-stash-audit.js +92 -16
  54. package/dist/resources/extensions/gsd/prompts/code-review.md +6 -4
  55. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +2 -2
  56. package/dist/resources/extensions/gsd/prompts/plan-slice.md +3 -3
  57. package/dist/resources/extensions/gsd/root-write-leak-guard.js +7 -1
  58. package/dist/resources/extensions/gsd/safety/destructive-guard.js +8 -1
  59. package/dist/resources/extensions/gsd/safety/evidence-collector.js +16 -1
  60. package/dist/resources/extensions/gsd/safety/file-change-validator.js +5 -2
  61. package/dist/resources/extensions/gsd/skills/gsd-headless/references/commands.md +1 -1
  62. package/dist/resources/extensions/gsd/state/derive/cache.js +28 -0
  63. package/dist/resources/extensions/gsd/state/derive/db-open.js +39 -0
  64. package/dist/resources/extensions/gsd/state/derive/from-db.js +452 -0
  65. package/dist/resources/extensions/gsd/state/derive/index.js +75 -0
  66. package/dist/resources/extensions/gsd/state/derive/interrupted-work.js +21 -0
  67. package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-render.js +27 -33
  68. package/dist/resources/extensions/gsd/state-reconciliation/index.js +48 -23
  69. package/dist/resources/extensions/gsd/state-reconciliation/registry.js +32 -28
  70. package/dist/resources/extensions/gsd/state.js +12 -611
  71. package/dist/resources/extensions/gsd/tools/complete-milestone.js +4 -2
  72. package/dist/resources/extensions/gsd/tools/complete-slice.js +3 -34
  73. package/dist/resources/extensions/gsd/tools/complete-task.js +8 -41
  74. package/dist/resources/extensions/gsd/tools/plan-slice.js +59 -44
  75. package/dist/resources/extensions/gsd/tools/plan-task.js +28 -5
  76. package/dist/resources/extensions/gsd/undo.js +43 -6
  77. package/dist/resources/extensions/gsd/unit-registry.js +11 -3
  78. package/dist/resources/extensions/gsd/verification-gate.js +7 -0
  79. package/dist/resources/extensions/gsd/workflow-manifest.js +126 -13
  80. package/dist/resources/extensions/gsd/workflow-projections.js +19 -14
  81. package/dist/resources/extensions/gsd/worktree-manager.js +44 -2
  82. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  83. package/dist/web/standalone/.next/BUILD_ID +1 -1
  84. package/dist/web/standalone/.next/app-path-routes-manifest.json +10 -10
  85. package/dist/web/standalone/.next/build-manifest.json +4 -4
  86. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  87. package/dist/web/standalone/.next/react-loadable-manifest.json +9 -9
  88. package/dist/web/standalone/.next/required-server-files.json +3 -3
  89. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  90. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  91. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  100. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  101. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  102. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  103. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  104. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  106. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  110. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  116. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  128. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/mcp-connections/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  150. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  160. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  166. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  182. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  186. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  195. package/dist/web/standalone/.next/server/app/index.html +1 -1
  196. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  197. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  198. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  199. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  200. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  201. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  202. package/dist/web/standalone/.next/server/app/page.js +2 -2
  203. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  204. package/dist/web/standalone/.next/server/app-paths-manifest.json +10 -10
  205. package/dist/web/standalone/.next/server/chunks/2842.js +4 -4
  206. package/dist/web/standalone/.next/server/chunks/8357.js +3 -3
  207. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  208. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  209. package/dist/web/standalone/.next/server/middleware.js +3 -3
  210. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  211. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  212. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  213. package/dist/web/standalone/.next/static/chunks/{2659.b7b129ee6a769448.js → 2659.58e950899a9bb82f.js} +1 -1
  214. package/dist/web/standalone/.next/static/chunks/2772.a7c1fcc69a4685ef.js +1 -0
  215. package/dist/web/standalone/.next/static/chunks/{3616.3c60753b8ffcbd2e.js → 3616.61a2af74bb8833c8.js} +1 -1
  216. package/dist/web/standalone/.next/static/chunks/{4283.8e446784528ed9dc.js → 4283.d0d9e0a955e441cb.js} +1 -1
  217. package/dist/web/standalone/.next/static/chunks/{5826.a46ecdd1cfe8dabc.js → 5826.5421d66c72b9f34e.js} +1 -1
  218. package/dist/web/standalone/.next/static/chunks/{8785.481aa5869991b760.js → 8785.e29b3134cab1d153.js} +1 -1
  219. package/dist/web/standalone/.next/static/chunks/8937.640dc9c2aaa1dfad.js +10 -0
  220. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-49f565245e1e4afe.js +1 -0
  221. package/dist/web/standalone/.next/static/chunks/app/{layout-4ae2d68984392bbf.js → layout-b35cbfff38aaf4cf.js} +1 -1
  222. package/dist/web/standalone/.next/static/chunks/app/page-bc4c723c6a19c6f0.js +1 -0
  223. package/dist/web/standalone/.next/static/chunks/{main-app-90d1d8d5e5d2dc6b.js → main-app-590a74400e35f685.js} +1 -1
  224. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ec3eaffc9785ba48.js +1 -0
  225. package/dist/web/standalone/.next/static/chunks/webpack-9c401904f87ded16.js +1 -0
  226. package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
  227. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  228. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  229. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  230. package/dist/web/standalone/server.js +1 -1
  231. package/package.json +6 -6
  232. package/packages/cloud-mcp-gateway/package.json +2 -2
  233. package/packages/contracts/package.json +1 -1
  234. package/packages/daemon/package.json +4 -4
  235. package/packages/gsd-agent-core/dist/agent-session.d.ts +1 -0
  236. package/packages/gsd-agent-core/dist/agent-session.d.ts.map +1 -1
  237. package/packages/gsd-agent-core/dist/agent-session.js +3 -0
  238. package/packages/gsd-agent-core/dist/agent-session.js.map +1 -1
  239. package/packages/gsd-agent-core/dist/extension-ui-snapshot.d.ts +41 -0
  240. package/packages/gsd-agent-core/dist/extension-ui-snapshot.d.ts.map +1 -0
  241. package/packages/gsd-agent-core/dist/extension-ui-snapshot.js +62 -0
  242. package/packages/gsd-agent-core/dist/extension-ui-snapshot.js.map +1 -0
  243. package/packages/gsd-agent-core/dist/index.d.ts +2 -0
  244. package/packages/gsd-agent-core/dist/index.d.ts.map +1 -1
  245. package/packages/gsd-agent-core/dist/index.js +2 -0
  246. package/packages/gsd-agent-core/dist/index.js.map +1 -1
  247. package/packages/gsd-agent-core/dist/session/agent-session-events.js +1 -1
  248. package/packages/gsd-agent-core/dist/session/agent-session-events.js.map +1 -1
  249. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts +1 -0
  250. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts.map +1 -1
  251. package/packages/gsd-agent-core/dist/session/agent-session-host.js.map +1 -1
  252. package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts +5 -0
  253. package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts.map +1 -1
  254. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js +60 -3
  255. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js.map +1 -1
  256. package/packages/gsd-agent-core/dist/transcript-store.d.ts +58 -0
  257. package/packages/gsd-agent-core/dist/transcript-store.d.ts.map +1 -0
  258. package/packages/gsd-agent-core/dist/transcript-store.js +132 -0
  259. package/packages/gsd-agent-core/dist/transcript-store.js.map +1 -0
  260. package/packages/gsd-agent-core/package.json +5 -5
  261. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +2 -0
  262. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  263. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +25 -11
  264. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  265. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.d.ts +4 -0
  266. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.d.ts.map +1 -0
  267. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.js +7 -0
  268. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.js.map +1 -0
  269. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts +3 -24
  270. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  271. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +26 -841
  272. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  273. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.d.ts +58 -0
  274. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.d.ts.map +1 -0
  275. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.js +312 -0
  276. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.js.map +1 -0
  277. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.d.ts +31 -0
  278. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.d.ts.map +1 -0
  279. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.js +130 -0
  280. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.js.map +1 -0
  281. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts +15 -0
  282. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts.map +1 -0
  283. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js +258 -0
  284. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js.map +1 -0
  285. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.d.ts +13 -0
  286. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.d.ts.map +1 -0
  287. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.js +118 -0
  288. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.js.map +1 -0
  289. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts +9 -0
  290. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  291. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.js +1 -1
  292. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  293. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.d.ts +54 -0
  294. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.d.ts.map +1 -0
  295. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.js +20 -0
  296. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.js.map +1 -0
  297. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts +4 -1
  298. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  299. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +9 -0
  300. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
  301. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.d.ts +56 -0
  302. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.d.ts.map +1 -0
  303. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.js +44 -0
  304. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.js.map +1 -0
  305. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.d.ts +5 -0
  306. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.d.ts.map +1 -0
  307. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.js +77 -0
  308. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.js.map +1 -0
  309. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.d.ts +2 -0
  310. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  311. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.js +23 -5
  312. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.js.map +1 -1
  313. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  314. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +18 -0
  315. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
  316. package/packages/gsd-agent-modes/package.json +7 -7
  317. package/packages/mcp-server/dist/workflow-tools.js +1 -1
  318. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  319. package/packages/mcp-server/package.json +4 -4
  320. package/packages/native/package.json +1 -1
  321. package/packages/pi-agent-core/dist/agent-loop.js +3 -2
  322. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  323. package/packages/pi-agent-core/package.json +1 -1
  324. package/packages/pi-ai/dist/models.generated.d.ts +46 -0
  325. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  326. package/packages/pi-ai/dist/models.generated.js +38 -0
  327. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  328. package/packages/pi-ai/package.json +1 -1
  329. package/packages/pi-coding-agent/README.md +3 -2
  330. package/packages/pi-coding-agent/dist/core/session-manager-context.d.ts +9 -0
  331. package/packages/pi-coding-agent/dist/core/session-manager-context.d.ts.map +1 -0
  332. package/packages/pi-coding-agent/dist/core/session-manager-context.js +94 -0
  333. package/packages/pi-coding-agent/dist/core/session-manager-context.js.map +1 -0
  334. package/packages/pi-coding-agent/dist/core/session-manager-list.d.ts +8 -0
  335. package/packages/pi-coding-agent/dist/core/session-manager-list.d.ts.map +1 -0
  336. package/packages/pi-coding-agent/dist/core/session-manager-list.js +244 -0
  337. package/packages/pi-coding-agent/dist/core/session-manager-list.js.map +1 -0
  338. package/packages/pi-coding-agent/dist/core/session-manager-migration.d.ts +12 -0
  339. package/packages/pi-coding-agent/dist/core/session-manager-migration.d.ts.map +1 -0
  340. package/packages/pi-coding-agent/dist/core/session-manager-migration.js +84 -0
  341. package/packages/pi-coding-agent/dist/core/session-manager-migration.js.map +1 -0
  342. package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts +135 -0
  343. package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts.map +1 -0
  344. package/packages/pi-coding-agent/dist/core/session-manager-types.js +2 -0
  345. package/packages/pi-coding-agent/dist/core/session-manager-types.js.map +1 -0
  346. package/packages/pi-coding-agent/dist/core/session-manager.d.ts +6 -154
  347. package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
  348. package/packages/pi-coding-agent/dist/core/session-manager.js +22 -459
  349. package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
  350. package/packages/pi-coding-agent/dist/theme/theme-schema.d.ts +75 -75
  351. package/packages/pi-coding-agent/dist/theme/theme-schema.d.ts.map +1 -1
  352. package/packages/pi-coding-agent/dist/theme/theme-schema.js +1 -1
  353. package/packages/pi-coding-agent/dist/theme/theme-schema.js.map +1 -1
  354. package/packages/pi-coding-agent/dist/theme/theme.d.ts.map +1 -1
  355. package/packages/pi-coding-agent/dist/theme/theme.js +11 -7
  356. package/packages/pi-coding-agent/dist/theme/theme.js.map +1 -1
  357. package/packages/pi-coding-agent/package.json +7 -7
  358. package/packages/pi-tui/package.json +2 -2
  359. package/packages/rpc-client/package.json +2 -2
  360. package/pkg/dist/theme/theme-schema.d.ts +75 -75
  361. package/pkg/dist/theme/theme-schema.d.ts.map +1 -1
  362. package/pkg/dist/theme/theme-schema.js +1 -1
  363. package/pkg/dist/theme/theme-schema.js.map +1 -1
  364. package/pkg/dist/theme/theme.d.ts.map +1 -1
  365. package/pkg/dist/theme/theme.js +11 -7
  366. package/pkg/dist/theme/theme.js.map +1 -1
  367. package/pkg/package.json +1 -1
  368. package/src/resources/extensions/claude-code-cli/models.ts +9 -0
  369. package/src/resources/extensions/claude-code-cli/tests/index.test.ts +14 -0
  370. package/src/resources/extensions/gsd/artifact-verification.ts +464 -0
  371. package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
  372. package/src/resources/extensions/gsd/auto/session.ts +14 -0
  373. package/src/resources/extensions/gsd/auto/verification-retry-policy.ts +3 -1
  374. package/src/resources/extensions/gsd/auto-artifact-paths.ts +47 -1
  375. package/src/resources/extensions/gsd/auto-budget.ts +12 -1
  376. package/src/resources/extensions/gsd/auto-dispatch.ts +17 -7
  377. package/src/resources/extensions/gsd/auto-post-unit.ts +1 -1
  378. package/src/resources/extensions/gsd/auto-prompts.ts +7 -23
  379. package/src/resources/extensions/gsd/auto-recovery.ts +13 -518
  380. package/src/resources/extensions/gsd/auto-runtime-state.ts +4 -5
  381. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +3 -2
  382. package/src/resources/extensions/gsd/auto-verification.ts +5 -1
  383. package/src/resources/extensions/gsd/auto.ts +23 -8
  384. package/src/resources/extensions/gsd/bootstrap/core-session-tools.ts +44 -0
  385. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +5 -4
  386. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +2 -0
  387. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +43 -18
  388. package/src/resources/extensions/gsd/bootstrap/tests/write-gate-basepath.test.ts +49 -1
  389. package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +50 -37
  390. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +16 -4
  391. package/src/resources/extensions/gsd/closeout-consistency-gate.ts +2 -1
  392. package/src/resources/extensions/gsd/commands/handlers/auto.ts +1 -1
  393. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +1 -1
  394. package/src/resources/extensions/gsd/commands-usage.ts +1 -1
  395. package/src/resources/extensions/gsd/db/engine.ts +8 -1
  396. package/src/resources/extensions/gsd/db-memory-fts-schema.ts +45 -0
  397. package/src/resources/extensions/gsd/db-workspace.ts +61 -3
  398. package/src/resources/extensions/gsd/delegation-policy.ts +1 -1
  399. package/src/resources/extensions/gsd/docs/preferences-reference.md +2 -2
  400. package/src/resources/extensions/gsd/doctor-engine-checks.ts +233 -5
  401. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +3 -0
  402. package/src/resources/extensions/gsd/doctor-types.ts +3 -0
  403. package/src/resources/extensions/gsd/exec-sandbox.ts +7 -2
  404. package/src/resources/extensions/gsd/flat-phase-migration.ts +44 -0
  405. package/src/resources/extensions/gsd/git-service.ts +64 -0
  406. package/src/resources/extensions/gsd/gitignore.ts +4 -1
  407. package/src/resources/extensions/gsd/guided-flow-queue.ts +20 -13
  408. package/src/resources/extensions/gsd/json-persistence.ts +20 -0
  409. package/src/resources/extensions/gsd/knowledge-backfill.ts +16 -10
  410. package/src/resources/extensions/gsd/layout-policy.ts +2 -1
  411. package/src/resources/extensions/gsd/markdown-renderer.ts +2 -10
  412. package/src/resources/extensions/gsd/memory-backfill.ts +26 -20
  413. package/src/resources/extensions/gsd/metrics.ts +4 -4
  414. package/src/resources/extensions/gsd/migrate-external.ts +8 -2
  415. package/src/resources/extensions/gsd/migration-auto-check.ts +23 -0
  416. package/src/resources/extensions/gsd/milestone-ids.ts +31 -2
  417. package/src/resources/extensions/gsd/orphan-stash-audit.ts +108 -20
  418. package/src/resources/extensions/gsd/prompts/code-review.md +6 -4
  419. package/src/resources/extensions/gsd/prompts/plan-milestone.md +2 -2
  420. package/src/resources/extensions/gsd/prompts/plan-slice.md +3 -3
  421. package/src/resources/extensions/gsd/root-write-leak-guard.ts +13 -1
  422. package/src/resources/extensions/gsd/safety/destructive-guard.ts +9 -1
  423. package/src/resources/extensions/gsd/safety/evidence-collector.ts +16 -1
  424. package/src/resources/extensions/gsd/safety/file-change-validator.ts +8 -2
  425. package/src/resources/extensions/gsd/skills/gsd-headless/references/commands.md +1 -1
  426. package/src/resources/extensions/gsd/state/derive/cache.ts +46 -0
  427. package/src/resources/extensions/gsd/state/derive/db-open.ts +45 -0
  428. package/src/resources/extensions/gsd/state/derive/from-db.ts +561 -0
  429. package/src/resources/extensions/gsd/state/derive/index.ts +104 -0
  430. package/src/resources/extensions/gsd/state/derive/interrupted-work.ts +31 -0
  431. package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +36 -30
  432. package/src/resources/extensions/gsd/state-reconciliation/index.ts +50 -24
  433. package/src/resources/extensions/gsd/state-reconciliation/registry.ts +43 -28
  434. package/src/resources/extensions/gsd/state.ts +32 -732
  435. package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +4 -3
  436. package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +98 -1
  437. package/src/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +14 -5
  438. package/src/resources/extensions/gsd/tests/auto-pause-double-entry-guard.test.ts +36 -0
  439. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +182 -4
  440. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +35 -0
  441. package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +30 -0
  442. package/src/resources/extensions/gsd/tests/commands-gsd-core.test.ts +1 -0
  443. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +28 -0
  444. package/src/resources/extensions/gsd/tests/complete-slice-reopen-handoff.test.ts +69 -0
  445. package/src/resources/extensions/gsd/tests/db-memory-fts-schema.test.ts +58 -3
  446. package/src/resources/extensions/gsd/tests/decisions-projection-from-memories.test.ts +51 -0
  447. package/src/resources/extensions/gsd/tests/destructive-guard.test.ts +44 -0
  448. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +143 -0
  449. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +239 -2
  450. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +16 -0
  451. package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +40 -0
  452. package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +37 -2
  453. package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +4 -0
  454. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +11 -2
  455. package/src/resources/extensions/gsd/tests/json-persistence-atomic.test.ts +47 -0
  456. package/src/resources/extensions/gsd/tests/knowledge-backfill-projection.test.ts +35 -0
  457. package/src/resources/extensions/gsd/tests/memory-store.test.ts +48 -0
  458. package/src/resources/extensions/gsd/tests/merge-closeout-consistency-gate.test.ts +31 -1
  459. package/src/resources/extensions/gsd/tests/metrics-prune-cache-invalidation.test.ts +6 -0
  460. package/src/resources/extensions/gsd/tests/metrics.test.ts +1 -0
  461. package/src/resources/extensions/gsd/tests/migrate-external-worktree.test.ts +57 -0
  462. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +70 -0
  463. package/src/resources/extensions/gsd/tests/orphan-stash-audit.test.ts +91 -7
  464. package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +4 -1
  465. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +10 -0
  466. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +103 -4
  467. package/src/resources/extensions/gsd/tests/plan-task.test.ts +44 -1
  468. package/src/resources/extensions/gsd/tests/post-mutation-hook.test.ts +4 -2
  469. package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +50 -14
  470. package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +58 -0
  471. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +8 -6
  472. package/src/resources/extensions/gsd/tests/register-hooks-loop-guard-auto.test.ts +103 -0
  473. package/src/resources/extensions/gsd/tests/root-write-leak-guard.test.ts +20 -1
  474. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +15 -3
  475. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +56 -0
  476. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +115 -0
  477. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +140 -0
  478. package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +6 -3
  479. package/src/resources/extensions/gsd/tests/undo.test.ts +74 -0
  480. package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +38 -0
  481. package/src/resources/extensions/gsd/tests/verification-retry-policy.test.ts +69 -4
  482. package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +96 -15
  483. package/src/resources/extensions/gsd/tests/workflow-mcp-preflight.test.ts +1 -0
  484. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +8 -4
  485. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +6 -5
  486. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +39 -0
  487. package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -2
  488. package/src/resources/extensions/gsd/tools/complete-slice.ts +3 -30
  489. package/src/resources/extensions/gsd/tools/complete-task.ts +7 -39
  490. package/src/resources/extensions/gsd/tools/plan-slice.ts +60 -47
  491. package/src/resources/extensions/gsd/tools/plan-task.ts +30 -5
  492. package/src/resources/extensions/gsd/undo.ts +47 -6
  493. package/src/resources/extensions/gsd/unit-registry.ts +11 -3
  494. package/src/resources/extensions/gsd/verification-gate.ts +8 -0
  495. package/src/resources/extensions/gsd/workflow-manifest.ts +141 -7
  496. package/src/resources/extensions/gsd/workflow-projections.ts +20 -14
  497. package/src/resources/extensions/gsd/worktree-manager.ts +41 -1
  498. package/dist/web/standalone/.next/static/chunks/2772.bfa657f49f955239.js +0 -1
  499. package/dist/web/standalone/.next/static/chunks/796.3976108148518f7d.js +0 -10
  500. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-a6fb1847f67f167c.js +0 -1
  501. package/dist/web/standalone/.next/static/chunks/app/page-6644fc6ee8ca1247.js +0 -1
  502. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-1115d46ac61b9823.js +0 -1
  503. package/dist/web/standalone/.next/static/chunks/webpack-7c1d97e39be2da11.js +0 -1
  504. /package/dist/web/standalone/.next/static/{SzEuqWX37DR9MEpEuQjP1 → zQLcXm0Za8lexoXtgDpMG}/_buildManifest.js +0 -0
  505. /package/dist/web/standalone/.next/static/{SzEuqWX37DR9MEpEuQjP1 → zQLcXm0Za8lexoXtgDpMG}/_ssgManifest.js +0 -0
@@ -1,10 +1,24 @@
1
1
  // Project/App: gsd-pi
2
2
  // File Purpose: Workspace-facing Interface for opening and maintaining the workflow database.
3
3
  import { existsSync } from "node:fs";
4
- import { dirname } from "node:path";
4
+ import { dirname, join } from "node:path";
5
5
  import { backupDatabaseSnapshot, checkpointDatabase, closeAllDatabases, closeDatabase, closeDatabaseByWorkspace, getDbPath, getDbStatus, getDbProvider, isDbAvailable, openDatabase, openDatabaseByScope, openDatabaseByWorkspace, openIsolatedDatabase, refreshOpenDatabaseFromDisk, vacuumDatabase, wasDbOpenAttempted, } from "./gsd-db.js";
6
- import { resolveGsdPathContract } from "./paths.js";
7
- import { setLogBasePath } from "./workflow-logger.js";
6
+ import { resolveGsdPathContract, gsdRoot } from "./paths.js";
7
+ import { logWarning, setLogBasePath } from "./workflow-logger.js";
8
+ /**
9
+ * Global SQLite handle invariants:
10
+ *
11
+ * - `openWorkflowDatabase` / `openDatabase` switch the process-global handle consumed by
12
+ * deriveState, dispatch, reconciliation repairs, and domain writers. Only one active
13
+ * project database should own the global handle at a time.
14
+ * - `openWorkflowDatabaseIsolated` opens a caller-owned connection that does not clobber
15
+ * the global handle. Use for read-only observers (parallel monitor) and other background
16
+ * probes that must not disturb the active workflow session.
17
+ * - Reconciliation repairs that write markdown/DB state must use `ensureWorkflowDbForBase`
18
+ * so repairs target the correct project; those paths intentionally re-open the global handle.
19
+ * - Pair ad-hoc project switches with `closeWorkflowDatabase()` or restore via
20
+ * `ensureWorkflowDbForBase(..., { refresh: true })` before returning to derive/dispatch.
21
+ */
8
22
  export function resolveWorkflowDatabaseLocation(basePath) {
9
23
  const contract = resolveGsdPathContract(basePath);
10
24
  return {
@@ -104,6 +118,44 @@ export function getWorkflowDatabasePath() {
104
118
  export function refreshWorkflowDatabaseFromDisk() {
105
119
  return refreshOpenDatabaseFromDisk();
106
120
  }
121
+ export function expectedWorkflowDbPathForBase(basePath) {
122
+ return join(gsdRoot(basePath), "gsd.db");
123
+ }
124
+ export function ensureWorkflowDbAtPath(dbPath) {
125
+ if (!dbPath || dbPath === ":memory:")
126
+ return isDbAvailable();
127
+ if (isDbAvailable() && getWorkflowDatabasePath() === dbPath)
128
+ return true;
129
+ if (!existsSync(dbPath))
130
+ return false;
131
+ try {
132
+ return openWorkflowDatabasePath(dbPath);
133
+ }
134
+ catch (err) {
135
+ logWarning("reconcile", `ensureWorkflowDbAtPath could not reopen DB: ${err.message}`);
136
+ return false;
137
+ }
138
+ }
139
+ export function ensureWorkflowDbForBase(basePath, options = {}) {
140
+ const dbPath = expectedWorkflowDbPathForBase(basePath);
141
+ if (!existsSync(dbPath))
142
+ return false;
143
+ try {
144
+ if (options.refresh) {
145
+ if (isDbAvailable() && getWorkflowDatabasePath() === dbPath && refreshWorkflowDatabaseFromDisk()) {
146
+ return true;
147
+ }
148
+ return openWorkflowDatabasePath(dbPath);
149
+ }
150
+ if (isDbAvailable() && getWorkflowDatabasePath() === dbPath)
151
+ return true;
152
+ return openWorkflowDatabasePath(dbPath);
153
+ }
154
+ catch (err) {
155
+ logWarning("reconcile", `ensureWorkflowDbForBase could not reopen DB: ${err.message}`);
156
+ return false;
157
+ }
158
+ }
107
159
  export function checkpointWorkflowDatabase() {
108
160
  checkpointDatabase();
109
161
  }
@@ -94,7 +94,7 @@ const POLICY = {
94
94
  gsd_plan_task: {
95
95
  toolName: "gsd_plan_task",
96
96
  verdict: "no",
97
- rationale: "plan-slice prompt explicitly forbids calling gsd_plan_task separately; per-task granularity multiplies manifest writes and projection re-renders with no payoff.",
97
+ rationale: "Incremental task planning mutates the active slice plan and re-renders projections; keep it ordered in the foreground plan-slice unit.",
98
98
  },
99
99
  };
100
100
  function resolveCanonical(name) {
@@ -273,10 +273,10 @@ This config sets a parent workspace with two child repositories. The implicit `p
273
273
  - `audit_unified.enabled`: boolean — dual-write unified audit envelope events. Default: `true`.
274
274
  - `plan_v2.enabled`: boolean — enable bounded clarify/research/draft/compile planning flow. Default: `true`.
275
275
 
276
- - `context_management`: configures context hygiene for auto-mode sessions. Keys:
276
+ - `context_management`: configures context hygiene for auto-mode sessions. In step mode, the configurable threshold is a soft warning; automatic session re-rooting happens only at the fixed 90% hard context boundary. Keys:
277
277
  - `observation_masking`: boolean — mask old tool results to reduce context bloat. Default: `true`.
278
278
  - `observation_mask_turns`: number — keep this many recent turns verbatim (1-50). Default: `8`.
279
- - `compaction_threshold_percent`: number — trigger compaction at this % of context window (0.5-0.95). Lower values fire compaction earlier, reducing drift. Default: `0.60`.
279
+ - `compaction_threshold_percent`: number — show a soft context warning at this fraction of the context window (0.5-0.95). Lower values warn earlier so operators can compact manually before drift accumulates. Default: `0.60`.
280
280
  - `tool_result_max_chars`: number — max chars per tool result in GSD sessions (200-10000). Default: `800`.
281
281
 
282
282
  - `auto_visualize`: boolean — show a visualizer hint after each milestone completion in auto-mode. Default: `false`.
@@ -1,11 +1,115 @@
1
- import { existsSync, statSync } from "node:fs";
2
- import { isDbAvailable, _getAdapter } from "./gsd-db.js";
1
+ import { existsSync, readFileSync, statSync } from "node:fs";
2
+ import { isAbsolute, join, relative } from "node:path";
3
+ import { getAllMilestones, getMilestoneSlices, getSliceTasks, isDbAvailable, isMemoriesFtsAvailable, _getAdapter, } from "./gsd-db.js";
4
+ import { MEMORIES_FTS_REBUILT_KEY } from "./db-memory-fts-schema.js";
3
5
  import { isAfter, latestExplicitReopenAt } from "./milestone-reopen-events.js";
4
- import { resolveGsdPathContract, resolveMilestoneFile } from "./paths.js";
6
+ import { gsdProjectionRoot, gsdRoot, resolveGsdPathContract, resolveMilestoneFile, resolveSliceFile } from "./paths.js";
5
7
  import { deriveState } from "./state.js";
8
+ import { isClosedStatus } from "./status-guards.js";
6
9
  import { workflowEventLogPath } from "./workflow-event-ledger.js";
7
10
  import { readEvents } from "./workflow-events.js";
8
11
  import { flushWorkflowProjections } from "./projection-flush.js";
12
+ import { parseRoadmapSlices } from "./roadmap-slices.js";
13
+ import { parsePlan } from "./parsers-legacy.js";
14
+ function relativeFile(basePath, filePath) {
15
+ return relative(basePath, filePath).split("\\").join("/");
16
+ }
17
+ function reportCheckboxDbStatusDivergence(issues, basePath, filePath, scope, unitId, status, checkboxDone) {
18
+ const dbDone = isClosedStatus(status);
19
+ if (checkboxDone === dbDone)
20
+ return;
21
+ issues.push({
22
+ severity: "error",
23
+ code: "checkbox_db_status_divergence",
24
+ scope,
25
+ unitId,
26
+ message: `${scope === "slice" ? "Slice" : "Task"} ${unitId} is ${dbDone ? "closed" : "open"} in the database (status: ${status}) but the markdown checkbox is ${checkboxDone ? "checked" : "unchecked"}.`,
27
+ file: relativeFile(basePath, filePath),
28
+ fixable: false,
29
+ });
30
+ }
31
+ function checkProjectionCheckboxDbStatus(basePath, milestoneIds, issues) {
32
+ for (const milestoneId of milestoneIds) {
33
+ const roadmapPath = resolveMilestoneFile(basePath, milestoneId, "ROADMAP");
34
+ const slices = getMilestoneSlices(milestoneId);
35
+ if (roadmapPath && existsSync(roadmapPath)) {
36
+ try {
37
+ const roadmap = readFileSync(roadmapPath, "utf-8");
38
+ const sliceDoneById = new Map(parseRoadmapSlices(roadmap).map((entry) => [entry.id, entry.done]));
39
+ for (const slice of slices) {
40
+ const checkboxDone = sliceDoneById.get(slice.id);
41
+ if (checkboxDone === undefined)
42
+ continue;
43
+ reportCheckboxDbStatusDivergence(issues, basePath, roadmapPath, "slice", `${milestoneId}/${slice.id}`, slice.status, checkboxDone);
44
+ }
45
+ }
46
+ catch {
47
+ // Non-fatal — checkbox drift diagnostics must never block doctor.
48
+ }
49
+ }
50
+ for (const slice of slices) {
51
+ const planPath = resolveSliceFile(basePath, milestoneId, slice.id, "PLAN");
52
+ if (!planPath || !existsSync(planPath))
53
+ continue;
54
+ try {
55
+ const plan = readFileSync(planPath, "utf-8");
56
+ // parsePlan reads the authoritative task checkboxes (the flat-phase
57
+ // <tasks> block / ## Tasks section), so a stray task-style checkbox
58
+ // line elsewhere in PLAN.md (e.g. a Must-Haves or Verification bullet
59
+ // above <tasks>) can no longer hide real drift or fake a divergence.
60
+ const taskDoneById = new Map(parsePlan(plan).tasks.map((entry) => [entry.id, entry.done]));
61
+ for (const task of getSliceTasks(milestoneId, slice.id)) {
62
+ const checkboxDone = taskDoneById.get(task.id);
63
+ if (checkboxDone === undefined)
64
+ continue;
65
+ reportCheckboxDbStatusDivergence(issues, basePath, planPath, "task", `${milestoneId}/${slice.id}/${task.id}`, task.status, checkboxDone);
66
+ }
67
+ }
68
+ catch {
69
+ // Non-fatal — checkbox drift diagnostics must never block doctor.
70
+ }
71
+ }
72
+ }
73
+ }
74
+ function isClearedByMilestoneShellProjectionFlush(basePath, issue, reRenderedMilestoneIds) {
75
+ if (issue.code !== "checkbox_db_status_divergence")
76
+ return false;
77
+ if (issue.scope !== "slice")
78
+ return false;
79
+ const milestoneId = issue.unitId.split("/")[0] ?? "";
80
+ if (!reRenderedMilestoneIds.has(milestoneId))
81
+ return false;
82
+ const roadmapPath = resolveMilestoneFile(basePath, milestoneId, "ROADMAP");
83
+ if (!roadmapPath || !issue.file)
84
+ return false;
85
+ return issue.file === relativeFile(basePath, roadmapPath);
86
+ }
87
+ function artifactExistsOnDisk(basePath, artifactPath) {
88
+ if (isAbsolute(artifactPath))
89
+ return existsSync(artifactPath);
90
+ return [
91
+ join(gsdProjectionRoot(basePath), artifactPath),
92
+ join(gsdRoot(basePath), artifactPath),
93
+ ].some((candidate) => existsSync(candidate));
94
+ }
95
+ function artifactUnitId(row) {
96
+ if (!row.milestone_id)
97
+ return "project";
98
+ if (row.slice_id && row.task_id)
99
+ return `${row.milestone_id}/${row.slice_id}/${row.task_id}`;
100
+ if (row.slice_id)
101
+ return `${row.milestone_id}/${row.slice_id}`;
102
+ return row.milestone_id;
103
+ }
104
+ function artifactScope(row) {
105
+ if (row.task_id)
106
+ return "task";
107
+ if (row.slice_id)
108
+ return "slice";
109
+ if (row.milestone_id)
110
+ return "milestone";
111
+ return "project";
112
+ }
9
113
  export async function checkEngineHealth(basePath, issues, fixesApplied) {
10
114
  const dbPath = resolveGsdPathContract(basePath).projectDb;
11
115
  if (!isDbAvailable() && existsSync(dbPath)) {
@@ -23,6 +127,30 @@ export async function checkEngineHealth(basePath, issues, fixesApplied) {
23
127
  try {
24
128
  if (isDbAvailable()) {
25
129
  const adapter = _getAdapter();
130
+ try {
131
+ if (isMemoriesFtsAvailable(adapter)) {
132
+ const runtimeKv = adapter
133
+ .prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='runtime_kv'")
134
+ .get();
135
+ const marker = runtimeKv
136
+ ? adapter.prepare("SELECT 1 as present FROM runtime_kv WHERE scope = 'global' AND scope_id = '' AND key = :key").get({ ":key": MEMORIES_FTS_REBUILT_KEY })
137
+ : undefined;
138
+ if (!marker) {
139
+ issues.push({
140
+ severity: "warning",
141
+ code: "memories_fts_rebuild_missing",
142
+ scope: "project",
143
+ unitId: "project",
144
+ message: `Memory full-text index exists but runtime_kv has no ${MEMORIES_FTS_REBUILT_KEY} marker. The index may be stale or incomplete, so memory search can silently degrade to the LIKE fallback.`,
145
+ file: ".gsd/gsd.db",
146
+ fixable: false,
147
+ });
148
+ }
149
+ }
150
+ }
151
+ catch {
152
+ // Non-fatal — memory FTS health check failed
153
+ }
26
154
  // a. Orphaned tasks (task.slice_id points to non-existent slice)
27
155
  try {
28
156
  const orphanedTasks = adapter
@@ -172,7 +300,33 @@ export async function checkEngineHealth(basePath, issues, fixesApplied) {
172
300
  catch {
173
301
  // Non-fatal — completed-milestone reopen check failed
174
302
  }
175
- // f. Completion artifacts disagree with open DB hierarchy rows.
303
+ // f. Artifact rows reference files that no longer exist on disk.
304
+ try {
305
+ const artifactRows = adapter
306
+ .prepare(`SELECT path, artifact_type, milestone_id, slice_id, task_id
307
+ FROM artifacts
308
+ WHERE path != ''
309
+ ORDER BY path`)
310
+ .all();
311
+ for (const row of artifactRows) {
312
+ if (artifactExistsOnDisk(basePath, row.path))
313
+ continue;
314
+ const unitId = artifactUnitId(row);
315
+ issues.push({
316
+ severity: "error",
317
+ code: "artifact_file_missing",
318
+ scope: artifactScope(row),
319
+ unitId,
320
+ message: `Artifact ${row.path} is recorded in the database as ${row.artifact_type || "UNKNOWN"} but no matching file exists on disk`,
321
+ file: row.path,
322
+ fixable: false,
323
+ });
324
+ }
325
+ }
326
+ catch {
327
+ // Non-fatal — artifact file existence check failed
328
+ }
329
+ // g. Completion artifacts disagree with open DB hierarchy rows.
176
330
  try {
177
331
  const rows = adapter
178
332
  .prepare(`SELECT a.path, a.artifact_type, a.milestone_id, a.slice_id, a.task_id, a.imported_at,
@@ -189,6 +343,8 @@ export async function checkEngineHealth(basePath, issues, fixesApplied) {
189
343
  .all();
190
344
  const seen = new Set();
191
345
  for (const row of rows) {
346
+ if (!artifactExistsOnDisk(basePath, row.path))
347
+ continue;
192
348
  const reopenAt = latestExplicitReopenAt(basePath, row.milestone_id);
193
349
  if (!isAfter(row.imported_at, reopenAt))
194
350
  continue;
@@ -223,9 +379,24 @@ export async function checkEngineHealth(basePath, issues, fixesApplied) {
223
379
  catch {
224
380
  // Non-fatal — DB constraint checks failed entirely
225
381
  }
382
+ // Checkbox-vs-DB divergence detection runs before projection drift auto-fix
383
+ // so stale re-renders cannot overwrite manually edited markdown first. Runs
384
+ // inside its own try/catch: getAllMilestones / getMilestoneSlices /
385
+ // getSliceTasks issue prepared queries that can throw on a corrupt or locked
386
+ // DB, and like every other DB-touching check here this diagnostic must never
387
+ // block doctor.
388
+ try {
389
+ if (isDbAvailable()) {
390
+ checkProjectionCheckboxDbStatus(basePath, getAllMilestones().map((milestone) => milestone.id), issues);
391
+ }
392
+ }
393
+ catch {
394
+ // Non-fatal: checkbox-vs-DB divergence check must never block doctor
395
+ }
226
396
  // ── Projection drift detection ──────────────────────────────────────────
227
397
  // If the DB is available, check whether markdown projections are stale
228
398
  // relative to the event log and re-render them.
399
+ const reRenderedMilestoneIds = [];
229
400
  try {
230
401
  if (isDbAvailable()) {
231
402
  const eventLogPath = workflowEventLogPath(basePath);
@@ -241,6 +412,7 @@ export async function checkEngineHealth(basePath, issues, fixesApplied) {
241
412
  try {
242
413
  await flushWorkflowProjections(basePath, { milestoneId: milestone.id });
243
414
  fixesApplied.push(`re-rendered missing projections for ${milestone.id}`);
415
+ reRenderedMilestoneIds.push(milestone.id);
244
416
  }
245
417
  catch {
246
418
  // Non-fatal — projection re-render failed
@@ -252,6 +424,7 @@ export async function checkEngineHealth(basePath, issues, fixesApplied) {
252
424
  try {
253
425
  await flushWorkflowProjections(basePath, { milestoneId: milestone.id });
254
426
  fixesApplied.push(`re-rendered stale projections for ${milestone.id}`);
427
+ reRenderedMilestoneIds.push(milestone.id);
255
428
  }
256
429
  catch {
257
430
  // Non-fatal — projection re-render failed
@@ -264,4 +437,19 @@ export async function checkEngineHealth(basePath, issues, fixesApplied) {
264
437
  catch {
265
438
  // Non-fatal — projection drift check must never block doctor
266
439
  }
440
+ if (reRenderedMilestoneIds.length > 0) {
441
+ const reRendered = new Set(reRenderedMilestoneIds);
442
+ for (let i = issues.length - 1; i >= 0; i--) {
443
+ const issue = issues[i];
444
+ // flushWorkflowProjections re-renders milestone shell projections (not
445
+ // slice PLAN.md files), so only clear stale ROADMAP checkbox diagnostics.
446
+ if (isClearedByMilestoneShellProjectionFlush(basePath, issue, reRendered)) {
447
+ issues.splice(i, 1);
448
+ continue;
449
+ }
450
+ if (issue.code === "artifact_file_missing" && issue.file && artifactExistsOnDisk(basePath, issue.file)) {
451
+ issues.splice(i, 1);
452
+ }
453
+ }
454
+ }
267
455
  }
@@ -387,6 +387,9 @@ export async function checkRuntimeHealth(basePath, issues, fixesApplied, shouldF
387
387
  if (!existingLines.has(".gsd-worktrees/") && !existingLines.has(".gsd-worktrees")) {
388
388
  missing.push(".gsd-worktrees/");
389
389
  }
390
+ if (!existingLines.has(".gsd-backups/") && !existingLines.has(".gsd-backups")) {
391
+ missing.push(".gsd-backups/");
392
+ }
390
393
  if (!hasBlanketIgnore) {
391
394
  missing.push(...criticalPatterns.filter(p => !existingLines.has(p)));
392
395
  }
@@ -11,7 +11,7 @@ import { spawn } from "node:child_process";
11
11
  import { existsSync, mkdirSync, writeFileSync } from "node:fs";
12
12
  import { randomUUID } from "node:crypto";
13
13
  import { resolve } from "node:path";
14
- import { killProcessTree, SIGKILL_GRACE_MS, HARD_DEADLINE_MS } from "@gsd/pi-coding-agent";
14
+ import { getShellConfig, killProcessTree, SIGKILL_GRACE_MS, HARD_DEADLINE_MS } from "@gsd/pi-coding-agent";
15
15
  const ALWAYS_FORWARD_ENV = ["PATH", "HOME"];
16
16
  // SIGKILL_GRACE_MS / HARD_DEADLINE_MS are imported from @gsd/pi-coding-agent
17
17
  // (shell.ts) — the single source of truth for the graceful-kill timing ladder —
@@ -60,7 +60,13 @@ function clampTimeout(request, opts) {
60
60
  function resolveCommand(runtime) {
61
61
  switch (runtime) {
62
62
  case "bash":
63
- return { cmd: "bash", args: ["-c"] };
63
+ try {
64
+ const { shell, args } = getShellConfig();
65
+ return { cmd: shell, args };
66
+ }
67
+ catch {
68
+ return { cmd: "bash", args: ["-c"] };
69
+ }
64
70
  case "node":
65
71
  return { cmd: process.execPath, args: ["-e"] };
66
72
  case "python":
@@ -59,6 +59,51 @@ export function needsFlatPhaseMigration(basePath) {
59
59
  // Resume an interrupted migration where the legacy tree was renamed aside.
60
60
  return hasLegacyMilestoneSubdirs(legacyMigratingPath(basePath));
61
61
  }
62
+ /** Retention window before flat-phase migration backups are auto-pruned. */
63
+ export const FLAT_PHASE_BACKUP_RETENTION_MS = 30 * 24 * 60 * 60 * 1000;
64
+ /**
65
+ * Remove stale flat-phase migration backups after the retention window.
66
+ * Only runs when migration is complete (.gsd/phases/ exists, legacy layout gone).
67
+ * Returns the number of migrate-* directories removed.
68
+ */
69
+ export function pruneStaleFlatPhaseBackups(basePath) {
70
+ if (needsFlatPhaseMigration(basePath))
71
+ return 0;
72
+ const phasesPath = join(basePath, ".gsd", LAYOUT_SEGMENTS.level1);
73
+ if (!existsSync(phasesPath))
74
+ return 0;
75
+ const backupRoot = join(basePath, ".gsd-backups");
76
+ if (!existsSync(backupRoot))
77
+ return 0;
78
+ const now = Date.now();
79
+ let removed = 0;
80
+ for (const entry of readdirSync(backupRoot)) {
81
+ if (!entry.startsWith("migrate-"))
82
+ continue;
83
+ const dirPath = join(backupRoot, entry);
84
+ try {
85
+ const st = statSync(dirPath);
86
+ if (!st.isDirectory())
87
+ continue;
88
+ if (now - st.mtimeMs < FLAT_PHASE_BACKUP_RETENTION_MS)
89
+ continue;
90
+ rmSync(dirPath, { recursive: true, force: true });
91
+ removed++;
92
+ }
93
+ catch {
94
+ // Non-fatal: leave backup for manual recovery.
95
+ }
96
+ }
97
+ try {
98
+ if (readdirSync(backupRoot).length === 0) {
99
+ rmSync(backupRoot, { recursive: true, force: true });
100
+ }
101
+ }
102
+ catch {
103
+ // Non-fatal.
104
+ }
105
+ return removed;
106
+ }
62
107
  /**
63
108
  * Migrate from legacy nested .gsd/milestones/ to flat-phase .gsd/phases/.
64
109
  *
@@ -208,6 +208,7 @@ export class MergeConflictError extends GSDError {
208
208
  */
209
209
  export const RUNTIME_EXCLUSION_PATHS = [
210
210
  ".gsd-worktrees/",
211
+ ".gsd-backups/**",
211
212
  ".gsd/activity/",
212
213
  ".gsd/audit/",
213
214
  ".gsd/forensics/",
@@ -1027,6 +1028,7 @@ function collectRepositoryDirtyStatus(basePath) {
1027
1028
  const preferences = loadEffectiveGSDPreferences(basePath)?.preferences;
1028
1029
  const registry = createRepositoryRegistryFromPreferences(basePath, preferences);
1029
1030
  const dirtyByRepository = {};
1031
+ const registeredRoots = new Set(registry.repositories.map((repo) => resolve(repo.root)));
1030
1032
  for (const repo of registry.repositories) {
1031
1033
  try {
1032
1034
  dirtyByRepository[repo.id] = runGit(repo.root, ["status", "--porcelain"]).length > 0;
@@ -1036,8 +1038,63 @@ function collectRepositoryDirtyStatus(basePath) {
1036
1038
  dirtyByRepository[repo.id] = nativeHasChanges(repo.root);
1037
1039
  }
1038
1040
  }
1041
+ for (const repoRoot of findUndeclaredNestedGitRepositories(registry.projectRoot, registeredRoots)) {
1042
+ let dirty = false;
1043
+ try {
1044
+ dirty = runGit(repoRoot, ["status", "--porcelain"]).length > 0;
1045
+ }
1046
+ catch {
1047
+ dirty = nativeHasChanges(repoRoot);
1048
+ }
1049
+ if (!dirty)
1050
+ continue;
1051
+ const relPath = relative(registry.projectRoot, repoRoot).split(sep).join("/") || repoRoot;
1052
+ const label = `${relPath} (undeclared)`;
1053
+ dirtyByRepository[label] = true;
1054
+ logWarning("engine", `undeclared dirty nested git repo ${relPath}; declare it under workspace.repositories or commit manually`, { file: "git-service.ts" });
1055
+ }
1039
1056
  return dirtyByRepository;
1040
1057
  }
1058
+ const UNDECLARED_NESTED_REPO_SCAN_MAX_DEPTH = 4;
1059
+ const UNDECLARED_NESTED_REPO_SKIP_DIRS = new Set([
1060
+ ".git",
1061
+ ".gsd",
1062
+ ".gsd-worktrees",
1063
+ "node_modules",
1064
+ "dist",
1065
+ "dist-test",
1066
+ ]);
1067
+ function findUndeclaredNestedGitRepositories(projectRoot, registeredRoots) {
1068
+ const found = [];
1069
+ function visit(dir, depth) {
1070
+ if (depth >= UNDECLARED_NESTED_REPO_SCAN_MAX_DEPTH)
1071
+ return;
1072
+ let entries;
1073
+ try {
1074
+ entries = readdirSync(dir, { withFileTypes: true });
1075
+ }
1076
+ catch {
1077
+ return;
1078
+ }
1079
+ for (const entry of entries) {
1080
+ if (!entry.isDirectory())
1081
+ continue;
1082
+ if (UNDECLARED_NESTED_REPO_SKIP_DIRS.has(entry.name))
1083
+ continue;
1084
+ const child = join(dir, entry.name);
1085
+ const childRoot = resolve(child);
1086
+ const hasGitDir = existsSync(join(child, ".git"));
1087
+ const isRegistered = registeredRoots.has(childRoot);
1088
+ if (hasGitDir && !isRegistered) {
1089
+ found.push(childRoot);
1090
+ continue;
1091
+ }
1092
+ visit(child, depth + 1);
1093
+ }
1094
+ }
1095
+ visit(projectRoot, 0);
1096
+ return found;
1097
+ }
1041
1098
  function runPerRepositoryCommitAction(args) {
1042
1099
  const preferences = loadEffectiveGSDPreferences(args.basePath)?.preferences;
1043
1100
  const registry = createRepositoryRegistryFromPreferences(args.basePath, preferences);
@@ -22,8 +22,9 @@ import { GIT_NO_PROMPT_ENV } from "./git-constants.js";
22
22
  * With external state (symlink), these are a no-op in most cases,
23
23
  * but retained for backwards compatibility during migration.
24
24
  */
25
- const GSD_RUNTIME_PATTERNS = [
25
+ export const GSD_RUNTIME_PATTERNS = [
26
26
  ".gsd-worktrees/",
27
+ ".gsd-backups/",
27
28
  ".gsd/activity/",
28
29
  ".gsd/audit/",
29
30
  ".gsd/forensics/",
@@ -48,6 +49,8 @@ const BASELINE_PATTERNS = [
48
49
  ".gsd",
49
50
  // Worktree container sibling — NOT covered by the ".gsd" pattern above.
50
51
  ".gsd-worktrees/",
52
+ // Flat-phase migration snapshots — NOT covered by the ".gsd" pattern above.
53
+ ".gsd-backups/",
51
54
  ".gsd-id",
52
55
  ".mcp.json",
53
56
  ".bg-shell/",
@@ -274,21 +274,28 @@ function capExistingMilestonesContext(sections, cap = QUEUE_EXISTING_MILESTONES_
274
274
  if (fullContext.length <= cap)
275
275
  return fullContext;
276
276
  const notice = `[Existing milestones context truncated to ${cap} chars. Read source paths in this prompt or the corresponding .gsd artifacts for full details.]`;
277
- const compactSections = sections.map(compactSectionForQueueBudget);
277
+ const noticeSuffix = `${QUEUE_CONTEXT_SECTION_SEPARATOR}${notice}`;
278
278
  const selected = [];
279
- for (let i = 0; i < sections.length; i++) {
280
- const withFullSection = [
281
- ...selected,
282
- sections[i],
283
- ...compactSections.slice(i + 1),
284
- notice,
285
- ].join(QUEUE_CONTEXT_SECTION_SEPARATOR);
286
- selected.push(withFullSection.length <= cap ? sections[i] : compactSections[i]);
279
+ for (const section of sections) {
280
+ const candidate = [...selected, section].join(QUEUE_CONTEXT_SECTION_SEPARATOR) + noticeSuffix;
281
+ if (candidate.length <= cap) {
282
+ selected.push(section);
283
+ continue;
284
+ }
285
+ break;
286
+ }
287
+ if (selected.length === sections.length) {
288
+ return selected.join(QUEUE_CONTEXT_SECTION_SEPARATOR) + noticeSuffix;
287
289
  }
288
- const capped = [...selected, notice].join(QUEUE_CONTEXT_SECTION_SEPARATOR);
289
- if (capped.length <= cap)
290
- return capped;
291
- return `${capped.slice(0, Math.max(0, cap - notice.length - 2)).trimEnd()}\n\n${notice}`;
290
+ const compactTail = sections.slice(selected.length).map(compactSectionForQueueBudget);
291
+ const hybrid = [...selected, ...compactTail].join(QUEUE_CONTEXT_SECTION_SEPARATOR) + noticeSuffix;
292
+ if (hybrid.length <= cap)
293
+ return hybrid;
294
+ const compact = sections.map(compactSectionForQueueBudget);
295
+ const compactContext = compact.join(QUEUE_CONTEXT_SECTION_SEPARATOR) + noticeSuffix;
296
+ if (compactContext.length <= cap)
297
+ return compactContext;
298
+ return `${compactContext.slice(0, Math.max(0, cap - notice.length - 2)).trimEnd()}\n\n${notice}`;
292
299
  }
293
300
  function compactSectionForQueueBudget(section) {
294
301
  const lines = section.split("\n");
@@ -56,6 +56,26 @@ export function saveJsonFile(filePath, data) {
56
56
  // Non-fatal — don't let persistence failures break operation
57
57
  }
58
58
  }
59
+ /**
60
+ * Save a JSON file atomically using compact serialization.
61
+ *
62
+ * Intended for machine-only ledgers where pretty-printing has no consumer.
63
+ * Keeps the same write-tmp-rename safety and non-fatal error behavior as
64
+ * saveJsonFile.
65
+ */
66
+ export function saveJsonFileCompact(filePath, data) {
67
+ try {
68
+ mkdirSync(dirname(filePath), { recursive: true });
69
+ // Use randomized tmp suffix to prevent concurrent-write data loss
70
+ const tmp = `${filePath}.tmp.${randomBytes(4).toString("hex")}`;
71
+ writeFileSync(tmp, JSON.stringify(data) + "\n", "utf-8");
72
+ renameSync(tmp, filePath);
73
+ // No cleanup needed — renameSync atomically removes tmp on success
74
+ }
75
+ catch {
76
+ // Non-fatal — don't let persistence failures break operation
77
+ }
78
+ }
59
79
  /**
60
80
  * Write a JSON file atomically (write to .tmp, then rename).
61
81
  * Creates parent directories as needed. Non-fatal on error.
@@ -24,8 +24,8 @@ import { logWarning } from "./workflow-logger.js";
24
24
  * - Idempotent (per-row): each migrated memory carries
25
25
  * `structured_fields.sourceKnowledgeId = "<P|L>NNN"`. Rows whose ID is
26
26
  * already present in the memory store are skipped.
27
- * - Best-effort: never throws. Logs and returns 0 on failure so a broken
28
- * backfill cannot block agent startup.
27
+ * - Best-effort: never throws. Failed memory inserts are logged and skipped;
28
+ * setup/read failures log and return 0 so backfill cannot block startup.
29
29
  * - Rules (K###) are intentionally skipped — they remain manually maintained
30
30
  * in `KNOWLEDGE.md` per ADR-013.
31
31
  *
@@ -56,15 +56,22 @@ export function backfillKnowledgeToMemories(basePath) {
56
56
  const matchPattern = `%"sourceKnowledgeId":"${synth.id}"%`;
57
57
  if (checkExisting.get({ ":pattern": matchPattern }))
58
58
  continue;
59
- const id = createMemory({
60
- category: synth.category,
61
- content: synth.content,
62
- scope: synth.scope,
63
- confidence: 0.85,
64
- structuredFields: synth.structuredFields,
65
- });
66
- if (id)
67
- written += 1;
59
+ try {
60
+ const id = createMemory({
61
+ category: synth.category,
62
+ content: synth.content,
63
+ scope: synth.scope,
64
+ confidence: 0.85,
65
+ structuredFields: synth.structuredFields,
66
+ });
67
+ if (id)
68
+ written += 1;
69
+ }
70
+ catch (rowErr) {
71
+ const message = rowErr instanceof Error ? rowErr.message : String(rowErr);
72
+ logWarning("knowledge-backfill", `KNOWLEDGE.md -> memories backfill skipped ${synth.id}: ${message}`);
73
+ continue;
74
+ }
68
75
  }
69
76
  return written;
70
77
  }