gsd-pi 2.73.1 → 2.74.0-dev.b741afb

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 (378) hide show
  1. package/dist/cli-web-branch.d.ts +4 -3
  2. package/dist/cli-web-branch.js +10 -7
  3. package/dist/cli.js +184 -206
  4. package/dist/headless-query.js +4 -1
  5. package/dist/help-text.js +23 -0
  6. package/dist/logo.d.ts +1 -1
  7. package/dist/logo.js +1 -1
  8. package/dist/onboarding.js +59 -53
  9. package/dist/resource-loader.js +2 -2
  10. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +68 -4
  11. package/dist/resources/extensions/gsd/auto/detect-stuck.js +11 -4
  12. package/dist/resources/extensions/gsd/auto/phases.js +60 -10
  13. package/dist/resources/extensions/gsd/auto-dispatch.js +11 -3
  14. package/dist/resources/extensions/gsd/auto-model-selection.js +54 -11
  15. package/dist/resources/extensions/gsd/auto-post-unit.js +93 -57
  16. package/dist/resources/extensions/gsd/auto-prompts.js +12 -0
  17. package/dist/resources/extensions/gsd/auto-start.js +23 -6
  18. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +13 -0
  19. package/dist/resources/extensions/gsd/auto-verification.js +88 -3
  20. package/dist/resources/extensions/gsd/auto.js +37 -10
  21. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +21 -8
  22. package/dist/resources/extensions/gsd/commands/catalog.js +26 -1
  23. package/dist/resources/extensions/gsd/commands/handlers/ops.js +20 -0
  24. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +68 -9
  25. package/dist/resources/extensions/gsd/commands-add-tests.js +111 -0
  26. package/dist/resources/extensions/gsd/commands-backlog.js +140 -0
  27. package/dist/resources/extensions/gsd/commands-do.js +79 -0
  28. package/dist/resources/extensions/gsd/commands-handlers.js +8 -2
  29. package/dist/resources/extensions/gsd/commands-maintenance.js +6 -6
  30. package/dist/resources/extensions/gsd/commands-pr-branch.js +180 -0
  31. package/dist/resources/extensions/gsd/commands-session-report.js +82 -0
  32. package/dist/resources/extensions/gsd/commands-ship.js +187 -0
  33. package/dist/resources/extensions/gsd/db-writer.js +3 -5
  34. package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  35. package/dist/resources/extensions/gsd/graph-context.js +66 -0
  36. package/dist/resources/extensions/gsd/gsd-db.js +321 -0
  37. package/dist/resources/extensions/gsd/index.js +15 -2
  38. package/dist/resources/extensions/gsd/md-importer.js +3 -4
  39. package/dist/resources/extensions/gsd/memory-store.js +19 -51
  40. package/dist/resources/extensions/gsd/milestone-validation-gates.js +13 -12
  41. package/dist/resources/extensions/gsd/native-git-bridge.js +7 -4
  42. package/dist/resources/extensions/gsd/notification-widget.js +2 -2
  43. package/dist/resources/extensions/gsd/preferences-models.js +43 -0
  44. package/dist/resources/extensions/gsd/preferences-types.js +1 -0
  45. package/dist/resources/extensions/gsd/preferences-validation.js +22 -0
  46. package/dist/resources/extensions/gsd/prompts/add-tests.md +35 -0
  47. package/dist/resources/extensions/gsd/state.js +66 -15
  48. package/dist/resources/extensions/gsd/tools/complete-slice.js +15 -0
  49. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +3 -14
  50. package/dist/resources/extensions/gsd/triage-resolution.js +2 -5
  51. package/dist/resources/extensions/gsd/workflow-manifest.js +8 -69
  52. package/dist/resources/extensions/gsd/workflow-migration.js +21 -22
  53. package/dist/resources/extensions/gsd/workflow-projections.js +4 -1
  54. package/dist/resources/extensions/gsd/workflow-reconcile.js +14 -11
  55. package/dist/tsconfig.extensions.tsbuildinfo +1 -0
  56. package/dist/update-check.d.ts +1 -0
  57. package/dist/update-check.js +13 -5
  58. package/dist/update-cmd.js +4 -3
  59. package/dist/web/standalone/.next/BUILD_ID +1 -1
  60. package/dist/web/standalone/.next/app-path-routes-manifest.json +9 -9
  61. package/dist/web/standalone/.next/build-manifest.json +3 -3
  62. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  63. package/dist/web/standalone/.next/required-server-files.json +3 -3
  64. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  65. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  66. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  67. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  68. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  69. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  70. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  71. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  72. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  73. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  74. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  75. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  76. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  77. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  78. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  79. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  80. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  81. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  82. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  83. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  84. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  85. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  86. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  87. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  88. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  89. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  90. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  91. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  92. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  93. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  94. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  95. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  96. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  97. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  98. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  99. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  100. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  101. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  102. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  103. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  104. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  105. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  106. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  107. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  108. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  109. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  110. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  123. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  133. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  139. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  153. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  155. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  157. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  159. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  168. package/dist/web/standalone/.next/server/app/index.html +1 -1
  169. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  170. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  171. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  172. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  173. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  174. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  175. package/dist/web/standalone/.next/server/app/page.js +2 -2
  176. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/app-paths-manifest.json +9 -9
  178. package/dist/web/standalone/.next/server/chunks/63.js +3 -3
  179. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  180. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  182. package/dist/web/standalone/.next/server/middleware.js +2 -2
  183. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  184. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  185. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  186. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  187. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  188. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  189. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  190. package/dist/web/standalone/.next/static/chunks/app/page-f1e30ab6bb269149.js +1 -0
  191. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  192. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  193. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  194. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  195. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  196. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  197. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  198. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  199. package/dist/web/standalone/server.js +1 -1
  200. package/package.json +3 -3
  201. package/packages/daemon/package.json +2 -2
  202. package/packages/mcp-server/dist/index.d.ts +3 -0
  203. package/packages/mcp-server/dist/index.d.ts.map +1 -1
  204. package/packages/mcp-server/dist/index.js +3 -0
  205. package/packages/mcp-server/dist/index.js.map +1 -1
  206. package/packages/mcp-server/dist/readers/graph.d.ts +87 -0
  207. package/packages/mcp-server/dist/readers/graph.d.ts.map +1 -0
  208. package/packages/mcp-server/dist/readers/graph.js +548 -0
  209. package/packages/mcp-server/dist/readers/graph.js.map +1 -0
  210. package/packages/mcp-server/dist/readers/index.d.ts +2 -0
  211. package/packages/mcp-server/dist/readers/index.d.ts.map +1 -1
  212. package/packages/mcp-server/dist/readers/index.js +1 -0
  213. package/packages/mcp-server/dist/readers/index.js.map +1 -1
  214. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  215. package/packages/mcp-server/dist/server.js +65 -0
  216. package/packages/mcp-server/dist/server.js.map +1 -1
  217. package/packages/mcp-server/package.json +2 -2
  218. package/packages/mcp-server/src/index.ts +15 -0
  219. package/packages/mcp-server/src/readers/graph.test.ts +426 -0
  220. package/packages/mcp-server/src/readers/graph.ts +708 -0
  221. package/packages/mcp-server/src/readers/index.ts +12 -0
  222. package/packages/mcp-server/src/server.ts +83 -0
  223. package/packages/mcp-server/tsconfig.json +1 -0
  224. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -0
  225. package/packages/native/package.json +2 -2
  226. package/packages/native/tsconfig.tsbuildinfo +1 -0
  227. package/packages/pi-agent-core/package.json +1 -1
  228. package/packages/pi-agent-core/tsconfig.json +1 -0
  229. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -0
  230. package/packages/pi-ai/dist/index.d.ts +1 -0
  231. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  232. package/packages/pi-ai/dist/index.js +1 -0
  233. package/packages/pi-ai/dist/index.js.map +1 -1
  234. package/packages/pi-ai/dist/utils/overflow.d.ts.map +1 -1
  235. package/packages/pi-ai/dist/utils/overflow.js +12 -0
  236. package/packages/pi-ai/dist/utils/overflow.js.map +1 -1
  237. package/packages/pi-ai/dist/utils/tests/overflow.test.d.ts +2 -0
  238. package/packages/pi-ai/dist/utils/tests/overflow.test.d.ts.map +1 -0
  239. package/packages/pi-ai/dist/utils/tests/overflow.test.js +50 -0
  240. package/packages/pi-ai/dist/utils/tests/overflow.test.js.map +1 -0
  241. package/packages/pi-ai/package.json +1 -1
  242. package/packages/pi-ai/src/index.ts +4 -0
  243. package/packages/pi-ai/src/utils/overflow.ts +14 -1
  244. package/packages/pi-ai/src/utils/tests/overflow.test.ts +58 -0
  245. package/packages/pi-ai/tsconfig.json +1 -0
  246. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -0
  247. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +313 -8
  248. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
  249. package/packages/pi-coding-agent/dist/core/compaction/utils.js +5 -5
  250. package/packages/pi-coding-agent/dist/core/compaction/utils.js.map +1 -1
  251. package/packages/pi-coding-agent/dist/core/compaction-utils.test.d.ts +2 -0
  252. package/packages/pi-coding-agent/dist/core/compaction-utils.test.d.ts.map +1 -0
  253. package/packages/pi-coding-agent/dist/core/compaction-utils.test.js +45 -0
  254. package/packages/pi-coding-agent/dist/core/compaction-utils.test.js.map +1 -0
  255. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts +12 -2
  256. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  257. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +61 -28
  258. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
  259. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.d.ts +2 -1
  260. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  261. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.js +9 -3
  262. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  263. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.d.ts +2 -0
  264. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.d.ts.map +1 -0
  265. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js +52 -0
  266. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js.map +1 -0
  267. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  268. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +94 -16
  269. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  270. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  271. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +11 -3
  272. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  273. package/packages/pi-coding-agent/package.json +1 -1
  274. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +355 -8
  275. package/packages/pi-coding-agent/src/core/compaction/utils.ts +5 -5
  276. package/packages/pi-coding-agent/src/core/compaction-utils.test.ts +50 -0
  277. package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +74 -32
  278. package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.test.ts +73 -0
  279. package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.ts +9 -3
  280. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +113 -21
  281. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +11 -3
  282. package/packages/pi-coding-agent/tsconfig.json +1 -0
  283. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -0
  284. package/packages/pi-tui/dist/__tests__/tui.test.js +60 -1
  285. package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
  286. package/packages/pi-tui/dist/tui.d.ts +8 -0
  287. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  288. package/packages/pi-tui/dist/tui.js +32 -3
  289. package/packages/pi-tui/dist/tui.js.map +1 -1
  290. package/packages/pi-tui/package.json +1 -1
  291. package/packages/pi-tui/src/__tests__/tui.test.ts +76 -1
  292. package/packages/pi-tui/src/tui.ts +31 -3
  293. package/packages/pi-tui/tsconfig.json +1 -0
  294. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -0
  295. package/packages/rpc-client/package.json +1 -1
  296. package/packages/rpc-client/tsconfig.json +1 -0
  297. package/packages/rpc-client/tsconfig.tsbuildinfo +1 -0
  298. package/pkg/package.json +1 -1
  299. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +107 -5
  300. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +111 -2
  301. package/src/resources/extensions/gsd/auto/detect-stuck.ts +12 -4
  302. package/src/resources/extensions/gsd/auto/loop-deps.ts +6 -0
  303. package/src/resources/extensions/gsd/auto/phases.ts +90 -10
  304. package/src/resources/extensions/gsd/auto-dispatch.ts +10 -4
  305. package/src/resources/extensions/gsd/auto-model-selection.ts +85 -11
  306. package/src/resources/extensions/gsd/auto-post-unit.ts +107 -58
  307. package/src/resources/extensions/gsd/auto-prompts.ts +13 -0
  308. package/src/resources/extensions/gsd/auto-start.ts +30 -6
  309. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +17 -0
  310. package/src/resources/extensions/gsd/auto-verification.ts +98 -3
  311. package/src/resources/extensions/gsd/auto.ts +38 -14
  312. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +24 -8
  313. package/src/resources/extensions/gsd/commands/catalog.ts +26 -1
  314. package/src/resources/extensions/gsd/commands/handlers/ops.ts +20 -0
  315. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +74 -9
  316. package/src/resources/extensions/gsd/commands-add-tests.ts +137 -0
  317. package/src/resources/extensions/gsd/commands-backlog.ts +182 -0
  318. package/src/resources/extensions/gsd/commands-do.ts +109 -0
  319. package/src/resources/extensions/gsd/commands-handlers.ts +8 -2
  320. package/src/resources/extensions/gsd/commands-maintenance.ts +6 -6
  321. package/src/resources/extensions/gsd/commands-pr-branch.ts +234 -0
  322. package/src/resources/extensions/gsd/commands-session-report.ts +101 -0
  323. package/src/resources/extensions/gsd/commands-ship.ts +219 -0
  324. package/src/resources/extensions/gsd/db-writer.ts +3 -5
  325. package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  326. package/src/resources/extensions/gsd/graph-context.ts +85 -0
  327. package/src/resources/extensions/gsd/gsd-db.ts +467 -0
  328. package/src/resources/extensions/gsd/index.ts +18 -2
  329. package/src/resources/extensions/gsd/md-importer.ts +3 -5
  330. package/src/resources/extensions/gsd/memory-store.ts +31 -62
  331. package/src/resources/extensions/gsd/milestone-validation-gates.ts +13 -14
  332. package/src/resources/extensions/gsd/native-git-bridge.ts +11 -12
  333. package/src/resources/extensions/gsd/notification-widget.ts +2 -2
  334. package/src/resources/extensions/gsd/preferences-models.ts +41 -0
  335. package/src/resources/extensions/gsd/preferences-types.ts +12 -0
  336. package/src/resources/extensions/gsd/preferences-validation.ts +23 -0
  337. package/src/resources/extensions/gsd/prompts/add-tests.md +35 -0
  338. package/src/resources/extensions/gsd/state.ts +80 -17
  339. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +2 -2
  340. package/src/resources/extensions/gsd/tests/auto-post-unit-step-message.test.ts +53 -0
  341. package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +51 -2
  342. package/src/resources/extensions/gsd/tests/commands-backlog.test.ts +158 -0
  343. package/src/resources/extensions/gsd/tests/commands-do.test.ts +127 -0
  344. package/src/resources/extensions/gsd/tests/commands-pr-branch.test.ts +68 -0
  345. package/src/resources/extensions/gsd/tests/commands-session-report.test.ts +82 -0
  346. package/src/resources/extensions/gsd/tests/commands-ship.test.ts +71 -0
  347. package/src/resources/extensions/gsd/tests/commands-workflow-custom.test.ts +14 -0
  348. package/src/resources/extensions/gsd/tests/complete-milestone-false-merge.test.ts +142 -0
  349. package/src/resources/extensions/gsd/tests/completed-at-reconcile.test.ts +42 -0
  350. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +3 -2
  351. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +3 -2
  352. package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +68 -8
  353. package/src/resources/extensions/gsd/tests/derive-state.test.ts +3 -3
  354. package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +154 -0
  355. package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +137 -1
  356. package/src/resources/extensions/gsd/tests/graph-context.test.ts +337 -0
  357. package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +4 -2
  358. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +68 -1
  359. package/src/resources/extensions/gsd/tests/model-isolation.test.ts +91 -2
  360. package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +140 -0
  361. package/src/resources/extensions/gsd/tests/preferences.test.ts +47 -0
  362. package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +180 -0
  363. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +5 -7
  364. package/src/resources/extensions/gsd/tests/token-profile.test.ts +1 -1
  365. package/src/resources/extensions/gsd/tests/validate-milestone-stuck-guard.test.ts +179 -0
  366. package/src/resources/extensions/gsd/tests/workflow-logger-wiring.test.ts +223 -0
  367. package/src/resources/extensions/gsd/tools/complete-slice.ts +19 -0
  368. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +3 -11
  369. package/src/resources/extensions/gsd/triage-resolution.ts +2 -7
  370. package/src/resources/extensions/gsd/workflow-manifest.ts +9 -104
  371. package/src/resources/extensions/gsd/workflow-migration.ts +21 -29
  372. package/src/resources/extensions/gsd/workflow-projections.ts +8 -1
  373. package/src/resources/extensions/gsd/workflow-reconcile.ts +15 -15
  374. package/dist/web/standalone/.next/static/chunks/app/page-7115e62689b5fd84.js +0 -1
  375. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  376. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  377. /package/dist/web/standalone/.next/static/{Qr27MOHx0lxRGnJvlhxxu → XnHY5eXUsTCFmNodWHetD}/_buildManifest.js +0 -0
  378. /package/dist/web/standalone/.next/static/{Qr27MOHx0lxRGnJvlhxxu → XnHY5eXUsTCFmNodWHetD}/_ssgManifest.js +0 -0
@@ -0,0 +1,223 @@
1
+ // GSD Extension — workflow-logger wiring regression tests
2
+ //
3
+ // Verifies the plumbing between workflow-logger and the rest of the state
4
+ // system (auto-loop phases, detect-stuck, notification store). Without this
5
+ // wiring, warnings/errors logged during a unit leak across units, never
6
+ // reach the user as a consolidated post-unit alert, and don't enrich
7
+ // stuck-detection reasons.
8
+
9
+ import test from "node:test";
10
+ import assert from "node:assert/strict";
11
+ import { readFileSync } from "node:fs";
12
+ import { join } from "node:path";
13
+
14
+ import {
15
+ logWarning,
16
+ logError,
17
+ peekLogs,
18
+ _resetLogs,
19
+ setStderrLoggingEnabled,
20
+ } from "../workflow-logger.ts";
21
+ import { detectStuck } from "../auto/detect-stuck.ts";
22
+
23
+ const phasesSrc = readFileSync(
24
+ join(import.meta.dirname, "..", "auto", "phases.ts"),
25
+ "utf-8",
26
+ );
27
+ const autoSrc = readFileSync(
28
+ join(import.meta.dirname, "..", "auto.ts"),
29
+ "utf-8",
30
+ );
31
+
32
+ // ─── Source-scan: phases.ts calls the logger lifecycle API ─────────────────
33
+
34
+ test("auto/phases.ts imports _resetLogs, drainAndSummarize, formatForNotification, hasAnyIssues", () => {
35
+ assert.match(
36
+ phasesSrc,
37
+ /from\s+"\.\.\/workflow-logger\.js"/,
38
+ "phases.ts imports from workflow-logger",
39
+ );
40
+ for (const name of [
41
+ "_resetLogs",
42
+ "drainLogs",
43
+ "drainAndSummarize",
44
+ "formatForNotification",
45
+ "hasAnyIssues",
46
+ ]) {
47
+ assert.ok(
48
+ phasesSrc.includes(name),
49
+ `phases.ts should reference ${name}`,
50
+ );
51
+ }
52
+ });
53
+
54
+ test("runUnitPhase calls _resetLogs() before assigning s.currentUnit", () => {
55
+ // Find the "s.currentUnit = { type: unitType" assignment line and check
56
+ // the preceding ~500 chars contain a _resetLogs() call.
57
+ const idx = phasesSrc.indexOf("s.currentUnit = { type: unitType");
58
+ assert.ok(idx > 0, "runUnitPhase should assign s.currentUnit");
59
+ const before = phasesSrc.slice(Math.max(0, idx - 500), idx);
60
+ assert.match(
61
+ before,
62
+ /_resetLogs\(\)/,
63
+ "_resetLogs() must be called immediately before s.currentUnit assignment",
64
+ );
65
+ });
66
+
67
+ test("runFinalize drains and surfaces logger buffer via ctx.ui.notify", () => {
68
+ // Locate the runFinalize success path and verify it calls drainAndSummarize
69
+ // and routes the result through ctx.ui.notify.
70
+ const runFinalizeIdx = phasesSrc.indexOf("export async function runFinalize");
71
+ assert.ok(runFinalizeIdx > 0, "runFinalize export should exist");
72
+ const finalizeBody = phasesSrc.slice(runFinalizeIdx);
73
+ assert.match(
74
+ finalizeBody,
75
+ /hasAnyIssues\(\)/,
76
+ "runFinalize should gate drain on hasAnyIssues",
77
+ );
78
+ assert.match(
79
+ finalizeBody,
80
+ /drainAndSummarize\(\)/,
81
+ "runFinalize should call drainAndSummarize on success",
82
+ );
83
+ assert.match(
84
+ finalizeBody,
85
+ /formatForNotification\(logs\)/,
86
+ "runFinalize should format drained logs for the notification",
87
+ );
88
+ });
89
+
90
+ test("runFinalize timeout branches drain the buffer to prevent bleed", () => {
91
+ // Both timeout branches null out s.currentUnit — they should also drain
92
+ // so accumulated logs for the timed-out unit don't leak into the next.
93
+ const runFinalizeIdx = phasesSrc.indexOf("export async function runFinalize");
94
+ const finalizeBody = phasesSrc.slice(runFinalizeIdx);
95
+ const drainCallCount =
96
+ (finalizeBody.match(/drainLogs\(\)/g) ?? []).length;
97
+ assert.ok(
98
+ drainCallCount >= 2,
99
+ `runFinalize timeout branches should each call drainLogs() (found ${drainCallCount}, expected >= 2)`,
100
+ );
101
+ });
102
+
103
+ // ─── Source-scan: auto.ts calls setLogBasePath in startAuto ────────────────
104
+
105
+ test("startAuto calls setLogBasePath(base) so audit log is pinned on resume", () => {
106
+ const startAutoIdx = autoSrc.indexOf("export async function startAuto");
107
+ assert.ok(startAutoIdx > 0, "startAuto export should exist");
108
+ const body = autoSrc.slice(startAutoIdx);
109
+ assert.match(
110
+ body,
111
+ /setLogBasePath\(base\)/,
112
+ "startAuto must call setLogBasePath(base) to pin the audit log",
113
+ );
114
+ });
115
+
116
+ // ─── Runtime: detect-stuck enriches reason with summarizeLogs() ────────────
117
+
118
+ test("detectStuck reason includes workflow-logger summary when logs present", () => {
119
+ setStderrLoggingEnabled(false);
120
+ try {
121
+ _resetLogs();
122
+ logWarning("projection", "STATE.md render failed");
123
+ logError("db", "WAL checkpoint failed");
124
+
125
+ const result = detectStuck([
126
+ { key: "execute-task/slice-A/task-1", error: "ENOENT: no such file" },
127
+ { key: "execute-task/slice-A/task-1", error: "ENOENT: no such file" },
128
+ ]);
129
+
130
+ assert.notEqual(result, null);
131
+ assert.equal(result!.stuck, true);
132
+ assert.match(
133
+ result!.reason,
134
+ /Same error repeated:/,
135
+ "reason should still start with the rule string",
136
+ );
137
+ assert.match(
138
+ result!.reason,
139
+ /STATE\.md render failed/,
140
+ "reason should include the accumulated logger warning",
141
+ );
142
+ assert.match(
143
+ result!.reason,
144
+ /WAL checkpoint failed/,
145
+ "reason should include the accumulated logger error",
146
+ );
147
+
148
+ // Critical: summarizeLogs must not drain — the auto-loop's finalize
149
+ // step owns the buffer lifecycle, detect-stuck is read-only.
150
+ assert.equal(
151
+ peekLogs().length,
152
+ 2,
153
+ "detect-stuck must not drain the buffer",
154
+ );
155
+ } finally {
156
+ _resetLogs();
157
+ setStderrLoggingEnabled(true);
158
+ }
159
+ });
160
+
161
+ test("detectStuck reason unchanged when logger buffer is empty", () => {
162
+ setStderrLoggingEnabled(false);
163
+ try {
164
+ _resetLogs();
165
+ const result = detectStuck([
166
+ { key: "A", error: "boom" },
167
+ { key: "A", error: "boom" },
168
+ ]);
169
+ assert.notEqual(result, null);
170
+ // No trailing " — " suffix when there are no logs to summarize.
171
+ assert.doesNotMatch(
172
+ result!.reason,
173
+ / — \d+ (error|warning)/,
174
+ "reason should have no logger suffix when buffer is empty",
175
+ );
176
+ } finally {
177
+ setStderrLoggingEnabled(true);
178
+ }
179
+ });
180
+
181
+ // ─── Runtime: readTransaction rollback failure surfaces via logError ────────
182
+ //
183
+ // snapshotState now delegates its transaction to readTransaction() in
184
+ // gsd-db.ts (single-writer refactor in #4198), so the split-brain
185
+ // ROLLBACK-failure log lives there, not in workflow-manifest.ts.
186
+
187
+ test("readTransaction logs ROLLBACK failures as split-brain signal", () => {
188
+ const dbSrc = readFileSync(
189
+ join(import.meta.dirname, "..", "gsd-db.ts"),
190
+ "utf-8",
191
+ );
192
+ assert.match(
193
+ dbSrc,
194
+ /logError\("db",\s*"snapshotState ROLLBACK failed"/,
195
+ "readTransaction ROLLBACK catch should call logError",
196
+ );
197
+ });
198
+
199
+ // ─── Runtime: state.ts and workflow-projections.ts log silent bailouts ─────
200
+
201
+ test("state.ts logs roadmap read failures instead of silently continuing", () => {
202
+ const stateSrc = readFileSync(
203
+ join(import.meta.dirname, "..", "state.ts"),
204
+ "utf-8",
205
+ );
206
+ assert.match(
207
+ stateSrc,
208
+ /logWarning\("state",\s*"reconcileDiskToDb: roadmap read failed/,
209
+ "state.ts reconcileDiskToDb should log roadmap read failures",
210
+ );
211
+ });
212
+
213
+ test("workflow-projections.ts logs DB probe failures instead of silent return", () => {
214
+ const projectionsSrc = readFileSync(
215
+ join(import.meta.dirname, "..", "workflow-projections.ts"),
216
+ "utf-8",
217
+ );
218
+ assert.match(
219
+ projectionsSrc,
220
+ /logWarning\("projection",\s*"renderStateProjection: DB handle probe failed/,
221
+ "renderStateProjection DB probe should log on failure",
222
+ );
223
+ });
@@ -424,6 +424,25 @@ export async function handleCompleteSlice(
424
424
  logError("tool", `complete-slice event log FAILED — completion invisible to reconciliation`, { error: (eventErr as Error).message });
425
425
  }
426
426
 
427
+ // Fire-and-forget graph rebuild — must NOT await, must NOT crash slice completion.
428
+ // Dynamic import of the package name (not a relative path) so it resolves
429
+ // correctly via package.json#exports in both development and production.
430
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
431
+ (async () => {
432
+ try {
433
+ const graphMod = await import("@gsd-build/mcp-server") as {
434
+ buildGraph: (dir: string) => Promise<{ nodes: unknown[]; edges: unknown[]; builtAt: string }>;
435
+ writeGraph: (gsdRoot: string, graph: unknown) => Promise<void>;
436
+ resolveGsdRoot: (basePath: string) => string;
437
+ };
438
+ const g = await graphMod.buildGraph(basePath);
439
+ await graphMod.writeGraph(graphMod.resolveGsdRoot(basePath), g);
440
+ } catch (graphErr) {
441
+ // Graph rebuild is best-effort — log at warning level but never propagate
442
+ logWarning("tool", `complete-slice graph rebuild failed (non-fatal): ${(graphErr as Error).message ?? String(graphErr)}`);
443
+ }
444
+ })();
445
+
427
446
  return {
428
447
  sliceId: params.sliceId,
429
448
  milestoneId: params.milestoneId,
@@ -5,7 +5,7 @@ import {
5
5
  getMilestone,
6
6
  getSliceStatusSummary,
7
7
  getSliceTaskCounts,
8
- _getAdapter,
8
+ readTransaction,
9
9
  saveGateResult,
10
10
  } from "../gsd-db.js";
11
11
  import { GATE_REGISTRY } from "../gate-registry.js";
@@ -616,12 +616,9 @@ export async function executeMilestoneStatus(
616
616
  };
617
617
  }
618
618
 
619
- const adapter = _getAdapter()!;
620
- adapter.exec("BEGIN");
621
- try {
619
+ return readTransaction(() => {
622
620
  const milestone = getMilestone(params.milestoneId);
623
621
  if (!milestone) {
624
- adapter.exec("COMMIT");
625
622
  return {
626
623
  content: [{ type: "text", text: `Milestone ${params.milestoneId} not found in database.` }],
627
624
  details: { operation: "milestone_status", milestoneId: params.milestoneId, found: false },
@@ -635,8 +632,6 @@ export async function executeMilestoneStatus(
635
632
  taskCounts: getSliceTaskCounts(params.milestoneId, s.id),
636
633
  }));
637
634
 
638
- adapter.exec("COMMIT");
639
-
640
635
  const result = {
641
636
  milestoneId: milestone.id,
642
637
  title: milestone.title,
@@ -651,10 +646,7 @@ export async function executeMilestoneStatus(
651
646
  content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
652
647
  details: { operation: "milestone_status", milestoneId: milestone.id, sliceCount: slices.length },
653
648
  };
654
- } catch (txErr) {
655
- try { adapter.exec("ROLLBACK"); } catch { /* swallow */ }
656
- throw txErr;
657
- }
649
+ });
658
650
  } catch (err) {
659
651
  const msg = err instanceof Error ? err.message : String(err);
660
652
  logWarning("tool", `gsd_milestone_status tool failed: ${msg}`);
@@ -111,14 +111,9 @@ export function executeReplan(
111
111
  // Also write replan_triggered_at column for DB-backed detection
112
112
  try {
113
113
  const req = createRequire(import.meta.url);
114
- const { isDbAvailable, _getAdapter } = req("./gsd-db.js");
114
+ const { isDbAvailable, setSliceReplanTriggeredAt } = req("./gsd-db.js");
115
115
  if (isDbAvailable()) {
116
- const adapter = _getAdapter();
117
- if (adapter) {
118
- adapter.prepare(
119
- "UPDATE slices SET replan_triggered_at = :ts WHERE milestone_id = :mid AND id = :sid",
120
- ).run({ ":ts": ts, ":mid": mid, ":sid": sid });
121
- }
116
+ setSliceReplanTriggeredAt(mid, sid, ts);
122
117
  }
123
118
  } catch {
124
119
  // DB write is best-effort — disk file is the primary trigger for fallback path
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  _getAdapter,
3
- transaction,
3
+ readTransaction,
4
+ restoreManifest,
4
5
  type MilestoneRow,
5
6
  type SliceRow,
6
7
  type TaskRow,
@@ -74,9 +75,7 @@ export function snapshotState(): StateManifest {
74
75
 
75
76
  // Wrap all reads in a deferred transaction so the snapshot is consistent
76
77
  // (all SELECTs see the same DB state even if a concurrent write lands between them).
77
- db.exec("BEGIN DEFERRED");
78
-
79
- try {
78
+ return readTransaction(() => {
80
79
  const rawMilestones = db.prepare("SELECT * FROM milestones ORDER BY id").all() as Record<string, unknown>[];
81
80
  const milestones: MilestoneRow[] = rawMilestones.map((r) => ({
82
81
  id: r["id"] as string,
@@ -186,109 +185,15 @@ export function snapshotState(): StateManifest {
186
185
  verification_evidence,
187
186
  };
188
187
 
189
- db.exec("COMMIT");
190
188
  return result;
191
- } catch (err) {
192
- try { db.exec("ROLLBACK"); } catch { /* ignore rollback failure */ }
193
- throw err;
194
- }
189
+ });
195
190
  }
196
191
 
197
192
  // ─── restore ─────────────────────────────────────────────────────────────
198
-
199
- /**
200
- * Atomically replace all workflow state from a manifest.
201
- * Runs inside a transaction — if any insert fails, no tables are modified.
202
- * Only touches engine tables + decisions. Does NOT modify artifacts or memories.
203
- */
204
- function restore(manifest: StateManifest): void {
205
- const db = requireDb();
206
-
207
- transaction(() => {
208
- // Clear engine tables (order matters for foreign-key-like consistency)
209
- db.exec("DELETE FROM verification_evidence");
210
- db.exec("DELETE FROM tasks");
211
- db.exec("DELETE FROM slices");
212
- db.exec("DELETE FROM milestones");
213
- db.exec("DELETE FROM decisions WHERE 1=1");
214
-
215
- // Restore milestones
216
- const msStmt = db.prepare(
217
- `INSERT INTO milestones (id, title, status, depends_on, created_at, completed_at,
218
- vision, success_criteria, key_risks, proof_strategy,
219
- verification_contract, verification_integration, verification_operational, verification_uat,
220
- definition_of_done, requirement_coverage, boundary_map_markdown)
221
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
222
- );
223
- for (const m of manifest.milestones) {
224
- msStmt.run(
225
- m.id, m.title, m.status,
226
- JSON.stringify(m.depends_on), m.created_at, m.completed_at,
227
- m.vision, JSON.stringify(m.success_criteria), JSON.stringify(m.key_risks),
228
- JSON.stringify(m.proof_strategy),
229
- m.verification_contract, m.verification_integration, m.verification_operational, m.verification_uat,
230
- JSON.stringify(m.definition_of_done), m.requirement_coverage, m.boundary_map_markdown,
231
- );
232
- }
233
-
234
- // Restore slices
235
- const slStmt = db.prepare(
236
- `INSERT INTO slices (milestone_id, id, title, status, risk, depends, demo,
237
- created_at, completed_at, full_summary_md, full_uat_md,
238
- goal, success_criteria, proof_level, integration_closure, observability_impact,
239
- sequence, replan_triggered_at)
240
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
241
- );
242
- for (const s of manifest.slices) {
243
- slStmt.run(
244
- s.milestone_id, s.id, s.title, s.status, s.risk,
245
- JSON.stringify(s.depends), s.demo,
246
- s.created_at, s.completed_at, s.full_summary_md, s.full_uat_md,
247
- s.goal, s.success_criteria, s.proof_level, s.integration_closure, s.observability_impact,
248
- s.sequence, s.replan_triggered_at,
249
- );
250
- }
251
-
252
- // Restore tasks
253
- const tkStmt = db.prepare(
254
- `INSERT INTO tasks (milestone_id, slice_id, id, title, status,
255
- one_liner, narrative, verification_result, duration, completed_at,
256
- blocker_discovered, deviations, known_issues, key_files, key_decisions,
257
- full_summary_md, description, estimate, files, verify,
258
- inputs, expected_output, observability_impact, sequence)
259
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
260
- );
261
- for (const t of manifest.tasks) {
262
- tkStmt.run(
263
- t.milestone_id, t.slice_id, t.id, t.title, t.status,
264
- t.one_liner, t.narrative, t.verification_result, t.duration, t.completed_at,
265
- t.blocker_discovered ? 1 : 0, t.deviations, t.known_issues,
266
- JSON.stringify(t.key_files), JSON.stringify(t.key_decisions),
267
- t.full_summary_md, t.description, t.estimate, JSON.stringify(t.files), t.verify,
268
- JSON.stringify(t.inputs), JSON.stringify(t.expected_output),
269
- t.observability_impact, t.sequence,
270
- );
271
- }
272
-
273
- // Restore decisions
274
- const dcStmt = db.prepare(
275
- `INSERT INTO decisions (seq, id, when_context, scope, decision, choice, rationale, revisable, made_by, superseded_by)
276
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
277
- );
278
- for (const d of manifest.decisions) {
279
- dcStmt.run(d.seq, d.id, d.when_context, d.scope, d.decision, d.choice, d.rationale, d.revisable, d.made_by, d.superseded_by);
280
- }
281
-
282
- // Restore verification evidence
283
- const evStmt = db.prepare(
284
- `INSERT INTO verification_evidence (task_id, slice_id, milestone_id, command, exit_code, verdict, duration_ms, created_at)
285
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
286
- );
287
- for (const e of manifest.verification_evidence) {
288
- evStmt.run(e.task_id, e.slice_id, e.milestone_id, e.command, e.exit_code, e.verdict, e.duration_ms, e.created_at);
289
- }
290
- });
291
- }
193
+ //
194
+ // The actual restore() implementation lives in gsd-db.ts (single-writer
195
+ // invariant). This module only orchestrates reading the manifest file
196
+ // and handing it to the writer.
292
197
 
293
198
  // ─── writeManifest ───────────────────────────────────────────────────────
294
199
 
@@ -346,6 +251,6 @@ export function bootstrapFromManifest(basePath: string): boolean {
346
251
  return false;
347
252
  }
348
253
 
349
- restore(manifest);
254
+ restoreManifest(manifest);
350
255
  return true;
351
256
  }
@@ -5,7 +5,7 @@
5
5
 
6
6
  import { existsSync, readdirSync, readFileSync } from "node:fs";
7
7
  import { join } from "node:path";
8
- import { _getAdapter, transaction } from "./gsd-db.js";
8
+ import { _getAdapter, bulkInsertLegacyHierarchy } from "./gsd-db.js";
9
9
  import { parseRoadmap, parsePlan } from "./parsers-legacy.js";
10
10
  import { logWarning } from "./workflow-logger.js";
11
11
 
@@ -219,34 +219,26 @@ export function migrateFromMarkdown(basePath: string): void {
219
219
  return;
220
220
  }
221
221
 
222
- const placeholders = migratedMilestoneIds.map(() => "?").join(",");
223
- transaction(() => {
224
- // Clear existing data to handle stale DB shape (DELETE ... IN (...))
225
- db.prepare(`DELETE FROM tasks WHERE milestone_id IN (${placeholders})`).run(...migratedMilestoneIds);
226
- db.prepare(`DELETE FROM slices WHERE milestone_id IN (${placeholders})`).run(...migratedMilestoneIds);
227
- db.prepare(`DELETE FROM milestones WHERE id IN (${placeholders})`).run(...migratedMilestoneIds);
228
-
229
- // Insert milestones
230
- const insertMilestone = db.prepare("INSERT INTO milestones (id, title, status, created_at) VALUES (?, ?, ?, ?)");
231
- for (const m of milestoneInserts) {
232
- insertMilestone.run(m.id, m.title, m.status, now);
233
- }
234
-
235
- // Insert slices (using v10 column names: depends, sequence)
236
- const insertSlice = db.prepare(
237
- "INSERT INTO slices (id, milestone_id, title, status, risk, depends, sequence, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
238
- );
239
- for (const s of sliceInserts) {
240
- insertSlice.run(s.id, s.milestoneId, s.title, s.status, s.risk, "[]", s.sequence, now);
241
- }
242
-
243
- // Insert tasks (using v10 column names: sequence, blocker_discovered, full_summary_md)
244
- const insertTask = db.prepare(
245
- "INSERT INTO tasks (id, slice_id, milestone_id, title, description, status, estimate, files, sequence) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"
246
- );
247
- for (const t of taskInserts) {
248
- insertTask.run(t.id, t.sliceId, t.milestoneId, t.title, "", t.status, "", "[]", t.sequence);
249
- }
222
+ bulkInsertLegacyHierarchy({
223
+ milestones: milestoneInserts,
224
+ slices: sliceInserts.map(s => ({
225
+ id: s.id,
226
+ milestoneId: s.milestoneId,
227
+ title: s.title,
228
+ status: s.status,
229
+ risk: s.risk,
230
+ sequence: s.sequence,
231
+ })),
232
+ tasks: taskInserts.map(t => ({
233
+ id: t.id,
234
+ sliceId: t.sliceId,
235
+ milestoneId: t.milestoneId,
236
+ title: t.title,
237
+ status: t.status,
238
+ sequence: t.sequence,
239
+ })),
240
+ clearMilestoneIds: migratedMilestoneIds,
241
+ createdAt: now,
250
242
  });
251
243
  }
252
244
 
@@ -350,7 +350,14 @@ export async function renderStateProjection(basePath: string): Promise<void> {
350
350
  // Probe DB handle — adapter may be set but underlying handle closed
351
351
  const adapter = _getAdapter();
352
352
  if (!adapter) return;
353
- try { adapter.prepare("SELECT 1").get(); } catch { return; }
353
+ try {
354
+ adapter.prepare("SELECT 1").get();
355
+ } catch (err) {
356
+ logWarning("projection", "renderStateProjection: DB handle probe failed, skipping render", {
357
+ error: (err as Error).message,
358
+ });
359
+ return;
360
+ }
354
361
  const state = await deriveState(basePath);
355
362
  const content = renderStateContent(state);
356
363
  const dir = join(basePath, ".gsd");
@@ -10,12 +10,13 @@ import {
10
10
  updateMilestoneStatus,
11
11
  getSliceTasks,
12
12
  insertMilestone,
13
- _getAdapter,
14
13
  getMilestoneSlices,
15
14
  insertVerificationEvidence,
16
15
  upsertDecision,
17
16
  openDatabase,
18
17
  setTaskBlockerDiscovered,
18
+ insertOrIgnoreSlice,
19
+ insertOrIgnoreTask,
19
20
  } from "./gsd-db.js";
20
21
  import { isClosedStatus } from "./status-guards.js";
21
22
  import { invalidateStateCache } from "./state.js";
@@ -164,13 +165,12 @@ function replayEvents(events: WorkflowEvent[]): void {
164
165
  const milestoneId = p["milestoneId"] as string;
165
166
  const sliceId = p["sliceId"] as string;
166
167
  if (milestoneId && sliceId) {
167
- const adapter = _getAdapter();
168
- if (adapter) {
169
- adapter.prepare(
170
- `INSERT OR IGNORE INTO slices (milestone_id, id, title, status, created_at)
171
- VALUES (:mid, :sid, :title, 'pending', :ts)`,
172
- ).run({ ":mid": milestoneId, ":sid": sliceId, ":title": (p["title"] as string) ?? sliceId, ":ts": event.ts });
173
- }
168
+ insertOrIgnoreSlice({
169
+ milestoneId,
170
+ sliceId,
171
+ title: (p["title"] as string) ?? sliceId,
172
+ createdAt: event.ts,
173
+ });
174
174
  }
175
175
  break;
176
176
  }
@@ -182,13 +182,13 @@ function replayEvents(events: WorkflowEvent[]): void {
182
182
  const sliceId = p["sliceId"] as string;
183
183
  const taskId = p["taskId"] as string;
184
184
  if (milestoneId && sliceId && taskId) {
185
- const adapter = _getAdapter();
186
- if (adapter) {
187
- adapter.prepare(
188
- `INSERT OR IGNORE INTO tasks (milestone_id, slice_id, id, title, status, created_at)
189
- VALUES (:mid, :sid, :tid, :title, 'pending', :ts)`,
190
- ).run({ ":mid": milestoneId, ":sid": sliceId, ":tid": taskId, ":title": (p["title"] as string) ?? taskId, ":ts": event.ts });
191
- }
185
+ insertOrIgnoreTask({
186
+ milestoneId,
187
+ sliceId,
188
+ taskId,
189
+ title: (p["title"] as string) ?? taskId,
190
+ createdAt: event.ts,
191
+ });
192
192
  }
193
193
  break;
194
194
  }
@@ -1 +0,0 @@
1
- (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[8974],{5214:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"workAsyncStorage",{enumerable:!0,get:function(){return r.workAsyncStorageInstance}});let r=n(17828)},15726:(e,t,n)=>{Promise.resolve().then(n.bind(n,66919))},17828:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"workAsyncStorageInstance",{enumerable:!0,get:function(){return r}});let r=(0,n(64054).createAsyncLocalStorage)()},21957:(e,t,n)=>{"use strict";function r({moduleIds:e}){return null}Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"PreloadChunks",{enumerable:!0,get:function(){return r}}),n(95155),n(47650),n(5214),n(2451),n(53887)},37206:(e,t,n)=>{"use strict";n.d(t,{default:()=>u.a});var r=n(75707),u=n.n(r)},41112:(e,t,n)=>{"use strict";function r({reason:e,children:t}){return t}Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"BailoutToCSR",{enumerable:!0,get:function(){return r}}),n(1980)},64054:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n={bindSnapshot:function(){return s},createAsyncLocalStorage:function(){return a},createSnapshot:function(){return i}};for(var r in n)Object.defineProperty(t,r,{enumerable:!0,get:n[r]});let u=Object.defineProperty(Error("Invariant: AsyncLocalStorage accessed in runtime where it is not available"),"__NEXT_ERROR_CODE",{value:"E504",enumerable:!1,configurable:!0});class l{disable(){throw u}getStore(){}run(){throw u}exit(){throw u}enterWith(){throw u}static bind(e){return e}}let o="u">typeof globalThis&&globalThis.AsyncLocalStorage;function a(){return o?new o:new l}function s(e){return o?o.bind(e):l.bind(e)}function i(){return o?o.snapshot():function(e,...t){return e(...t)}}},66919:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>l});var r=n(95155);let u=(0,n(37206).default)(()=>Promise.all([n.e(1838),n.e(6079),n.e(4986),n.e(2008),n.e(2826)]).then(n.bind(n,62826)).then(e=>e.GSDAppShell),{loadableGenerated:{webpack:()=>[62826]},ssr:!1,loading:()=>(0,r.jsx)("div",{className:"flex h-screen items-center justify-center bg-background text-sm text-muted-foreground",children:"Loading workspace…"})});function l(){return(0,r.jsx)(u,{})}},68635:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return s}});let r=n(95155),u=n(12115),l=n(41112);function o(e){return{default:e&&"default"in e?e.default:e}}n(21957);let a={loader:()=>Promise.resolve(o(()=>null)),loading:null,ssr:!0},s=function(e){let t={...a,...e},n=(0,u.lazy)(()=>t.loader().then(o)),s=t.loading;function i(e){let o=s?(0,r.jsx)(s,{isLoading:!0,pastDelay:!0,error:null}):null,a=!t.ssr||!!t.loading,i=a?u.Suspense:u.Fragment,c=t.ssr?(0,r.jsxs)(r.Fragment,{children:[null,(0,r.jsx)(n,{...e})]}):(0,r.jsx)(l.BailoutToCSR,{reason:"next/dynamic",children:(0,r.jsx)(n,{...e})});return(0,r.jsx)(i,{...a?{fallback:o}:{},children:c})}return i.displayName="LoadableComponent",i}},75707:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return u}});let r=n(73623)._(n(68635));function u(e,t){let n={};"function"==typeof e&&(n.loader=e);let u={...n,...t};return(0,r.default)({...u,modules:u.loadableGenerated?.modules})}("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),e.exports=t.default)}},e=>{e.O(0,[8441,3794,7358],()=>e(e.s=15726)),_N_E=e.O()}]);
@@ -1 +0,0 @@
1
- (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[7358],{2852:(e,s,n)=>{Promise.resolve().then(n.t.bind(n,27123,23)),Promise.resolve().then(n.t.bind(n,61304,23)),Promise.resolve().then(n.t.bind(n,78616,23)),Promise.resolve().then(n.t.bind(n,64777,23)),Promise.resolve().then(n.t.bind(n,57121,23)),Promise.resolve().then(n.t.bind(n,74581,23)),Promise.resolve().then(n.t.bind(n,90484,23)),Promise.resolve().then(n.bind(n,86869))},19393:()=>{}},e=>{var s=s=>e(e.s=s);e.O(0,[8441,3794],()=>(s(83861),s(2852))),_N_E=e.O()}]);
@@ -1 +0,0 @@
1
- (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[9337],{52560:(e,s,_)=>{Promise.resolve().then(_.t.bind(_,27123,23))}},e=>{e.O(0,[8441,3794,7358],()=>e(e.s=52560)),_N_E=e.O()}]);