gsd-pi 2.42.0-dev.97e9e30 → 2.43.0-next.1

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 (272) hide show
  1. package/dist/resources/extensions/gsd/auto-post-unit.js +81 -6
  2. package/dist/resources/extensions/gsd/auto-recovery.js +58 -126
  3. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +4 -7
  4. package/dist/resources/extensions/gsd/auto-worktree.js +22 -12
  5. package/dist/resources/extensions/gsd/auto.js +1 -1
  6. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +168 -0
  7. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +28 -3
  8. package/dist/resources/extensions/gsd/commands/catalog.js +3 -1
  9. package/dist/resources/extensions/gsd/commands/handlers/ops.js +15 -1
  10. package/dist/resources/extensions/gsd/commands-handlers.js +1 -1
  11. package/dist/resources/extensions/gsd/commands-maintenance.js +60 -2
  12. package/dist/resources/extensions/gsd/doctor-types.js +0 -15
  13. package/dist/resources/extensions/gsd/doctor.js +1 -274
  14. package/dist/resources/extensions/gsd/git-constants.js +1 -0
  15. package/dist/resources/extensions/gsd/git-service.js +68 -2
  16. package/dist/resources/extensions/gsd/gsd-db.js +467 -2
  17. package/dist/resources/extensions/gsd/markdown-renderer.js +562 -0
  18. package/dist/resources/extensions/gsd/md-importer.js +154 -4
  19. package/dist/resources/extensions/gsd/native-git-bridge.js +1 -0
  20. package/dist/resources/extensions/gsd/prompts/complete-slice.md +22 -9
  21. package/dist/resources/extensions/gsd/prompts/execute-task.md +15 -5
  22. package/dist/resources/extensions/gsd/prompts/forensics.md +10 -5
  23. package/dist/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
  24. package/dist/resources/extensions/gsd/prompts/guided-execute-task.md +1 -1
  25. package/dist/resources/extensions/gsd/prompts/reactive-execute.md +3 -3
  26. package/dist/resources/extensions/gsd/state.js +451 -11
  27. package/dist/resources/extensions/gsd/tools/complete-slice.js +244 -0
  28. package/dist/resources/extensions/gsd/tools/complete-task.js +204 -0
  29. package/dist/resources/extensions/gsd/undo.js +197 -3
  30. package/dist/web/standalone/.next/BUILD_ID +1 -1
  31. package/dist/web/standalone/.next/app-path-routes-manifest.json +14 -14
  32. package/dist/web/standalone/.next/build-manifest.json +3 -3
  33. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  34. package/dist/web/standalone/.next/required-server-files.json +3 -3
  35. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  36. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  37. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  38. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  39. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  40. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  41. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  42. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  43. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  44. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  45. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  46. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  47. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  48. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  49. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  50. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  51. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  52. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  53. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  54. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  55. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  56. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  57. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  58. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  59. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  60. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  61. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  62. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  63. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  64. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  65. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  66. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  67. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  68. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  69. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  70. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  71. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  72. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  73. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  74. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  75. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  76. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  77. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  78. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  79. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  80. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  81. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  82. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  83. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  84. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  85. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  86. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  87. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  88. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  89. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  90. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  91. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  92. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  93. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  94. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  95. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  96. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  97. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  98. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  99. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +5 -5
  100. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  101. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  102. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  103. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  104. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  105. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  106. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  107. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  108. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  109. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  110. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  120. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  122. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  124. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/index.html +1 -1
  134. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  135. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  136. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  137. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  138. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  139. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  140. package/dist/web/standalone/.next/server/app/page.js +2 -2
  141. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  142. package/dist/web/standalone/.next/server/app-paths-manifest.json +14 -14
  143. package/dist/web/standalone/.next/server/chunks/229.js +2 -2
  144. package/dist/web/standalone/.next/server/chunks/471.js +3 -3
  145. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  146. package/dist/web/standalone/.next/server/middleware.js +2 -2
  147. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  148. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  149. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  150. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  151. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  152. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-e07acdb7dd069836.js +1 -0
  153. package/dist/web/standalone/.next/static/chunks/app/layout-745c6ed5fea5fb06.js +1 -0
  154. package/dist/web/standalone/.next/static/chunks/app/page-801b53eff6e83579.js +1 -0
  155. package/dist/web/standalone/.next/static/chunks/{main-app-fdab67f7802d7832.js → main-app-2f2ee7b85712c2bd.js} +1 -1
  156. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-e6255954dccfcf0a.js +1 -0
  157. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  158. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  159. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  160. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  161. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  162. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  163. package/dist/web/standalone/server.js +1 -1
  164. package/dist/web-mode.d.ts +2 -0
  165. package/dist/web-mode.js +30 -1
  166. package/package.json +1 -1
  167. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  168. package/packages/pi-agent-core/dist/agent.js +2 -0
  169. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  170. package/packages/pi-agent-core/dist/types.d.ts +6 -0
  171. package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
  172. package/packages/pi-agent-core/dist/types.js.map +1 -1
  173. package/packages/pi-agent-core/src/agent.test.ts +53 -0
  174. package/packages/pi-agent-core/src/agent.ts +3 -0
  175. package/packages/pi-agent-core/src/types.ts +6 -0
  176. package/packages/pi-agent-core/tsconfig.json +1 -1
  177. package/packages/pi-ai/dist/models.d.ts +5 -3
  178. package/packages/pi-ai/dist/models.d.ts.map +1 -1
  179. package/packages/pi-ai/dist/models.generated.d.ts +801 -1468
  180. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  181. package/packages/pi-ai/dist/models.generated.js +1135 -1588
  182. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  183. package/packages/pi-ai/dist/models.js.map +1 -1
  184. package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
  185. package/packages/pi-ai/dist/utils/oauth/github-copilot.js +60 -2
  186. package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
  187. package/packages/pi-ai/scripts/generate-models.ts +1543 -0
  188. package/packages/pi-ai/src/models.generated.ts +1140 -1593
  189. package/packages/pi-ai/src/models.ts +7 -4
  190. package/packages/pi-ai/src/utils/oauth/github-copilot.ts +74 -2
  191. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +7 -0
  192. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  193. package/packages/pi-coding-agent/dist/core/auth-storage.js +23 -0
  194. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  195. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  196. package/packages/pi-coding-agent/dist/core/model-registry.js +2 -0
  197. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  198. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  199. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +9 -6
  200. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  201. package/packages/pi-coding-agent/src/core/auth-storage.ts +25 -0
  202. package/packages/pi-coding-agent/src/core/model-registry.ts +3 -0
  203. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +10 -6
  204. package/pkg/package.json +1 -1
  205. package/src/resources/extensions/gsd/auto-post-unit.ts +93 -5
  206. package/src/resources/extensions/gsd/auto-recovery.ts +53 -134
  207. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +6 -7
  208. package/src/resources/extensions/gsd/auto-worktree.ts +21 -11
  209. package/src/resources/extensions/gsd/auto.ts +0 -2
  210. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +194 -0
  211. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +31 -3
  212. package/src/resources/extensions/gsd/commands/catalog.ts +3 -1
  213. package/src/resources/extensions/gsd/commands/handlers/ops.ts +15 -1
  214. package/src/resources/extensions/gsd/commands-handlers.ts +1 -1
  215. package/src/resources/extensions/gsd/commands-maintenance.ts +69 -2
  216. package/src/resources/extensions/gsd/doctor-types.ts +0 -23
  217. package/src/resources/extensions/gsd/doctor.ts +1 -288
  218. package/src/resources/extensions/gsd/git-constants.ts +1 -0
  219. package/src/resources/extensions/gsd/git-service.ts +71 -2
  220. package/src/resources/extensions/gsd/gsd-db.ts +638 -1
  221. package/src/resources/extensions/gsd/markdown-renderer.ts +721 -0
  222. package/src/resources/extensions/gsd/md-importer.ts +182 -2
  223. package/src/resources/extensions/gsd/native-git-bridge.ts +1 -0
  224. package/src/resources/extensions/gsd/prompts/complete-slice.md +22 -9
  225. package/src/resources/extensions/gsd/prompts/execute-task.md +15 -5
  226. package/src/resources/extensions/gsd/prompts/forensics.md +10 -5
  227. package/src/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
  228. package/src/resources/extensions/gsd/prompts/guided-execute-task.md +1 -1
  229. package/src/resources/extensions/gsd/prompts/reactive-execute.md +3 -3
  230. package/src/resources/extensions/gsd/state.ts +510 -11
  231. package/src/resources/extensions/gsd/tests/atomic-task-closeout.test.ts +8 -120
  232. package/src/resources/extensions/gsd/tests/auto-preflight.test.ts +1 -1
  233. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +3 -4
  234. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +410 -0
  235. package/src/resources/extensions/gsd/tests/complete-task.test.ts +439 -0
  236. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +527 -0
  237. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +583 -2
  238. package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +22 -80
  239. package/src/resources/extensions/gsd/tests/doctor-enhancements.test.ts +5 -7
  240. package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +38 -130
  241. package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +38 -76
  242. package/src/resources/extensions/gsd/tests/doctor.test.ts +9 -19
  243. package/src/resources/extensions/gsd/tests/forensics-issue-routing.test.ts +43 -0
  244. package/src/resources/extensions/gsd/tests/git-locale.test.ts +133 -0
  245. package/src/resources/extensions/gsd/tests/git-service.test.ts +49 -0
  246. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +1 -1
  247. package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +356 -0
  248. package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +4 -172
  249. package/src/resources/extensions/gsd/tests/integration-proof.test.ts +643 -0
  250. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +1071 -0
  251. package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -1
  252. package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
  253. package/src/resources/extensions/gsd/tests/migrate-hierarchy.test.ts +439 -0
  254. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +79 -0
  255. package/src/resources/extensions/gsd/tests/rogue-file-detection.test.ts +185 -0
  256. package/src/resources/extensions/gsd/tests/shared-wal.test.ts +216 -0
  257. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +4 -2
  258. package/src/resources/extensions/gsd/tests/undo.test.ts +321 -1
  259. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +1 -1
  260. package/src/resources/extensions/gsd/tools/complete-slice.ts +300 -0
  261. package/src/resources/extensions/gsd/tools/complete-task.ts +245 -0
  262. package/src/resources/extensions/gsd/types.ts +50 -0
  263. package/src/resources/extensions/gsd/undo.ts +247 -3
  264. package/dist/resources/extensions/gsd/roadmap-mutations.js +0 -110
  265. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-f2a7482d42a5614b.js +0 -1
  266. package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +0 -1
  267. package/dist/web/standalone/.next/static/chunks/app/page-b9367c5ae13b99c6.js +0 -1
  268. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +0 -1
  269. package/src/resources/extensions/gsd/roadmap-mutations.ts +0 -134
  270. package/src/resources/extensions/gsd/tests/doctor-task-done-missing-summary-slice-loop.test.ts +0 -174
  271. /package/dist/web/standalone/.next/static/{PXrI5DoWsm7rwAVnEU2rD → 35A5zXBIDa1N0K7NO5i0b}/_buildManifest.js +0 -0
  272. /package/dist/web/standalone/.next/static/{PXrI5DoWsm7rwAVnEU2rD → 35A5zXBIDa1N0K7NO5i0b}/_ssgManifest.js +0 -0
@@ -13,7 +13,7 @@
13
13
  import { deriveState } from "./state.js";
14
14
  import { loadFile, parseSummary, resolveAllOverrides } from "./files.js";
15
15
  import { loadPrompt } from "./prompt-loader.js";
16
- import { resolveSliceFile, resolveTaskFile, resolveMilestoneFile, resolveTasksDir, buildTaskFileName, gsdRoot, } from "./paths.js";
16
+ import { resolveSliceFile, resolveSlicePath, resolveTaskFile, resolveMilestoneFile, resolveTasksDir, buildTaskFileName, gsdRoot, } from "./paths.js";
17
17
  import { invalidateAllCaches } from "./cache.js";
18
18
  import { closeoutUnit } from "./auto-unit-closeout.js";
19
19
  import { autoCommitCurrentBranch, } from "./worktree.js";
@@ -22,16 +22,56 @@ import { writeUnitRuntimeRecord, clearUnitRuntimeRecord } from "./unit-runtime.j
22
22
  import { runGSDDoctor, rebuildState, summarizeDoctorIssues } from "./doctor.js";
23
23
  import { recordHealthSnapshot, checkHealEscalation } from "./doctor-proactive.js";
24
24
  import { syncStateToProjectRoot } from "./auto-worktree-sync.js";
25
- import { isDbAvailable } from "./gsd-db.js";
25
+ import { isDbAvailable, getTask, getSlice, updateTaskStatus } from "./gsd-db.js";
26
+ import { renderPlanCheckboxes } from "./markdown-renderer.js";
26
27
  import { consumeSignal } from "./session-status-io.js";
27
28
  import { checkPostUnitHooks, isRetryPending, consumeRetryTrigger, persistHookState, resolveHookArtifactPath, } from "./post-unit-hooks.js";
28
29
  import { hasPendingCaptures, loadPendingCaptures } from "./captures.js";
29
30
  import { debugLog } from "./debug-logger.js";
30
- import { existsSync, unlinkSync } from "node:fs";
31
+ import { existsSync, unlinkSync, readFileSync, writeFileSync } from "node:fs";
31
32
  import { join } from "node:path";
32
- import { uncheckTaskInPlan } from "./undo.js";
33
33
  import { atomicWriteSync } from "./atomic-write.js";
34
34
  import { _resetHasChangesCache } from "./native-git-bridge.js";
35
+ /**
36
+ * Detect summary files written directly to disk without the LLM calling
37
+ * the completion tool. A "rogue" file is one that exists on disk but has
38
+ * no corresponding DB row with status "complete".
39
+ *
40
+ * This is a safety-net diagnostic (D003). The existing migrateFromMarkdown()
41
+ * in postUnitPostVerification() eventually ingests rogue files, but explicit
42
+ * detection provides immediate diagnostics so operators know the prompt failed.
43
+ */
44
+ export function detectRogueFileWrites(unitType, unitId, basePath) {
45
+ if (!isDbAvailable())
46
+ return [];
47
+ const parts = unitId.split("/");
48
+ const rogues = [];
49
+ if (unitType === "execute-task") {
50
+ const [mid, sid, tid] = parts;
51
+ if (!mid || !sid || !tid)
52
+ return [];
53
+ const summaryPath = resolveTaskFile(basePath, mid, sid, tid, "SUMMARY");
54
+ if (!summaryPath || !existsSync(summaryPath))
55
+ return [];
56
+ const dbRow = getTask(mid, sid, tid);
57
+ if (!dbRow || dbRow.status !== "complete") {
58
+ rogues.push({ path: summaryPath, unitType, unitId });
59
+ }
60
+ }
61
+ else if (unitType === "complete-slice") {
62
+ const [mid, sid] = parts;
63
+ if (!mid || !sid)
64
+ return [];
65
+ const summaryPath = resolveSliceFile(basePath, mid, sid, "SUMMARY");
66
+ if (!summaryPath || !existsSync(summaryPath))
67
+ return [];
68
+ const dbRow = getSlice(mid, sid);
69
+ if (!dbRow || dbRow.status !== "complete") {
70
+ rogues.push({ path: summaryPath, unitType, unitId });
71
+ }
72
+ }
73
+ return rogues;
74
+ }
35
75
  /** Throttle STATE.md rebuilds — at most once per 30 seconds */
36
76
  const STATE_REBUILD_MIN_INTERVAL_MS = 30_000;
37
77
  /**
@@ -283,6 +323,17 @@ export async function postUnitPreVerification(pctx, opts) {
283
323
  process.stderr.write(`gsd-triage: resolution execution failed: ${err.message}\n`);
284
324
  }
285
325
  }
326
+ // Rogue file detection — safety net for LLM bypassing completion tools (D003)
327
+ try {
328
+ const rogueFiles = detectRogueFileWrites(s.currentUnit.type, s.currentUnit.id, s.basePath);
329
+ for (const rogue of rogueFiles) {
330
+ process.stderr.write(`gsd-rogue: detected rogue file write: ${rogue.path} (unit: ${rogue.unitId})\n`);
331
+ ctx.ui.notify(`Rogue file write detected: ${rogue.path}`, "warning");
332
+ }
333
+ }
334
+ catch (e) {
335
+ debugLog("postUnit", { phase: "rogue-detection", error: String(e) });
336
+ }
286
337
  // Artifact verification
287
338
  let triggerArtifactVerified = false;
288
339
  if (!s.currentUnit.type.startsWith("hook/")) {
@@ -389,9 +440,33 @@ export async function postUnitPostVerification(pctx) {
389
440
  try {
390
441
  const parts = trigger.unitId.split("/");
391
442
  const [mid, sid, tid] = parts;
392
- // 1. Uncheck [x] [ ] in PLAN.md
443
+ // 1. Reset task status in DB and re-render plan checkboxes
393
444
  if (mid && sid && tid) {
394
- uncheckTaskInPlan(s.basePath, mid, sid, tid);
445
+ try {
446
+ updateTaskStatus(mid, sid, tid, "pending");
447
+ await renderPlanCheckboxes(s.basePath, mid, sid);
448
+ }
449
+ catch {
450
+ // DB may be unavailable — fall back to direct file-based uncheck
451
+ try {
452
+ const slicePath = resolveSlicePath(s.basePath, mid, sid);
453
+ if (slicePath) {
454
+ const { readdirSync } = await import("node:fs");
455
+ const planCandidates = readdirSync(slicePath)
456
+ .filter((f) => f.includes("PLAN") && (f.startsWith(sid) || f.startsWith(`${sid}-`)));
457
+ if (planCandidates.length > 0) {
458
+ const planFile = join(slicePath, planCandidates[0]);
459
+ let content = readFileSync(planFile, "utf-8");
460
+ const regex = new RegExp(`^(\\s*-\\s*)\\[x\\](\\s*\\**${tid}\\**[:\\s])`, "mi");
461
+ if (regex.test(content)) {
462
+ content = content.replace(regex, "$1[ ]$2");
463
+ writeFileSync(planFile, content, "utf-8");
464
+ }
465
+ }
466
+ }
467
+ }
468
+ catch { /* non-fatal: file-based fallback failure */ }
469
+ }
395
470
  }
396
471
  // 2. Delete SUMMARY.md for the task
397
472
  if (mid && sid && tid) {
@@ -6,13 +6,12 @@
6
6
  * Pure functions that receive all needed state as parameters — no module-level
7
7
  * globals or AutoContext dependency.
8
8
  */
9
- import { parseUnitId } from "./unit-id.js";
10
9
  import { clearUnitRuntimeRecord } from "./unit-runtime.js";
11
10
  import { clearParseCache, parseRoadmap, parsePlan } from "./files.js";
11
+ import { isDbAvailable, getTask, getSlice } from "./gsd-db.js";
12
12
  import { isValidationTerminal } from "./state.js";
13
13
  import { nativeConflictFiles, nativeCommit, nativeCheckoutTheirs, nativeAddPaths, nativeMergeAbort, nativeResetHard, } from "./native-git-bridge.js";
14
- import { resolveMilestonePath, resolveSlicePath, resolveSliceFile, resolveTasksDir, resolveTaskFiles, relMilestoneFile, relSliceFile, relSlicePath, relTaskFile, buildMilestoneFileName, buildSliceFileName, buildTaskFileName, resolveMilestoneFile, clearPathCache, resolveGsdRootFile, } from "./paths.js";
15
- import { markSliceDoneInRoadmap } from "./roadmap-mutations.js";
14
+ import { resolveMilestonePath, resolveSlicePath, resolveSliceFile, resolveTasksDir, resolveTaskFiles, relMilestoneFile, relSliceFile, buildMilestoneFileName, buildSliceFileName, buildTaskFileName, resolveMilestoneFile, clearPathCache, resolveGsdRootFile, } from "./paths.js";
16
15
  import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync, } from "node:fs";
17
16
  import { execFileSync } from "node:child_process";
18
17
  import { dirname, join } from "node:path";
@@ -269,26 +268,37 @@ export function verifyExpectedArtifact(unitType, unitId, base) {
269
268
  if (!hasCheckboxTask && !hasHeadingTask)
270
269
  return false;
271
270
  }
272
- // execute-task must also have its checkbox marked [x] in the slice plan.
273
- // Heading-style plans (### T01 -- Title) have no checkbox — the task summary
274
- // file existence (checked above via resolveExpectedArtifactPath) is sufficient.
271
+ // execute-task: DB status is authoritative. Fall back to heading-style plan
272
+ // detection when the DB is unavailable (unmigrated projects).
275
273
  if (unitType === "execute-task") {
276
274
  const parts = unitId.split("/");
277
275
  const mid = parts[0];
278
276
  const sid = parts[1];
279
277
  const tid = parts[2];
280
278
  if (mid && sid && tid) {
281
- const planAbs = resolveSliceFile(base, mid, sid, "PLAN");
282
- if (planAbs && existsSync(planAbs)) {
283
- const planContent = readFileSync(planAbs, "utf-8");
284
- const escapedTid = tid.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
285
- const cbRe = new RegExp(`^- \\[[xX]\\] \\*\\*${escapedTid}:`, "m");
286
- const hdRe = new RegExp(`^#{2,4}\\s+${escapedTid}\\s*(?:--|—|:)`, "m");
287
- // Heading-style entries count as verified (no checkbox to toggle);
288
- // checkbox-style entries require [x].
289
- if (!cbRe.test(planContent) && !hdRe.test(planContent))
279
+ const dbTask = getTask(mid, sid, tid);
280
+ if (dbTask) {
281
+ // DB available trust it
282
+ if (dbTask.status !== "complete" && dbTask.status !== "done")
290
283
  return false;
291
284
  }
285
+ else if (!isDbAvailable()) {
286
+ // DB unavailable — fall back to plan heading check (format detection,
287
+ // not reconciliation). Heading-style entries (### T01 --) count as
288
+ // verified because the summary file existence (checked above) is the
289
+ // real signal.
290
+ const planAbs = resolveSliceFile(base, mid, sid, "PLAN");
291
+ if (planAbs && existsSync(planAbs)) {
292
+ const planContent = readFileSync(planAbs, "utf-8");
293
+ const escapedTid = tid.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
294
+ const hdRe = new RegExp(`^#{2,4}\\s+${escapedTid}\\s*(?:--|—|:)`, "m");
295
+ const cbRe = new RegExp(`^- \\[[xX]\\] \\*\\*${escapedTid}:`, "m");
296
+ if (!hdRe.test(planContent) && !cbRe.test(planContent))
297
+ return false;
298
+ }
299
+ }
300
+ // else: DB available but task not found — summary file exists (checked above),
301
+ // so treat as verified (task may not be imported yet)
292
302
  }
293
303
  }
294
304
  // plan-slice must also produce individual task plan files for every task listed
@@ -317,11 +327,8 @@ export function verifyExpectedArtifact(unitType, unitId, base) {
317
327
  }
318
328
  }
319
329
  }
320
- // complete-slice must also produce a UAT file AND mark the slice [x] in the roadmap.
321
- // Without the roadmap check, a crash after writing SUMMARY+UAT but before updating
322
- // the roadmap causes an infinite skip loop: the idempotency key says "done" but the
323
- // state machine keeps returning the same complete-slice unit (roadmap still shows
324
- // the slice incomplete), so dispatchNextUnit recurses forever.
330
+ // complete-slice: DB status is authoritative for whether the slice is done.
331
+ // Fall back to file-based check (roadmap [x]) when DB is unavailable.
325
332
  if (unitType === "complete-slice") {
326
333
  const parts = unitId.split("/");
327
334
  const mid = parts[0];
@@ -333,24 +340,30 @@ export function verifyExpectedArtifact(unitType, unitId, base) {
333
340
  if (!existsSync(uatPath))
334
341
  return false;
335
342
  }
336
- // Verify the roadmap has the slice marked [x]. If not, the completion
337
- // record is stale — the unit must re-run to update the roadmap.
338
- const roadmapFile = resolveMilestoneFile(base, mid, "ROADMAP");
339
- if (roadmapFile && existsSync(roadmapFile)) {
340
- try {
341
- const roadmapContent = readFileSync(roadmapFile, "utf-8");
342
- const roadmap = parseRoadmap(roadmapContent);
343
- const slice = roadmap.slices.find((s) => s.id === sid);
344
- if (slice && !slice.done)
345
- return false;
346
- }
347
- catch {
348
- // Corrupt/unparseable roadmap — fail verification so the unit
349
- // re-runs and has a chance to fix the roadmap. Silently passing
350
- // here could advance past an incomplete slice.
343
+ const dbSlice = getSlice(mid, sid);
344
+ if (dbSlice) {
345
+ // DB available trust it
346
+ if (dbSlice.status !== "complete")
351
347
  return false;
348
+ }
349
+ else if (!isDbAvailable()) {
350
+ // DB unavailable — fall back to roadmap checkbox check
351
+ const roadmapFile = resolveMilestoneFile(base, mid, "ROADMAP");
352
+ if (roadmapFile && existsSync(roadmapFile)) {
353
+ try {
354
+ const roadmapContent = readFileSync(roadmapFile, "utf-8");
355
+ const roadmap = parseRoadmap(roadmapContent);
356
+ const slice = roadmap.slices.find((s) => s.id === sid);
357
+ if (slice && !slice.done)
358
+ return false;
359
+ }
360
+ catch {
361
+ return false;
362
+ }
352
363
  }
353
364
  }
365
+ // else: DB available but slice not found — summary + UAT exist,
366
+ // treat as verified (slice may not be imported yet)
354
367
  }
355
368
  }
356
369
  // complete-milestone must have produced implementation artifacts (#1703).
@@ -423,52 +436,6 @@ export function diagnoseExpectedArtifact(unitType, unitId, base) {
423
436
  return null;
424
437
  }
425
438
  }
426
- // ─── Skip / Blocker Artifact Generation ───────────────────────────────────────
427
- /**
428
- * Write skip artifacts for a stuck execute-task: a blocker task summary and
429
- * the [x] checkbox in the slice plan. Returns true if artifacts were written.
430
- */
431
- export function skipExecuteTask(base, mid, sid, tid, status, reason, maxAttempts) {
432
- // Write a blocker task summary if missing.
433
- if (!status.summaryExists) {
434
- const tasksDir = resolveTasksDir(base, mid, sid);
435
- const sDir = resolveSlicePath(base, mid, sid);
436
- const targetDir = tasksDir ?? (sDir ? join(sDir, "tasks") : null);
437
- if (!targetDir)
438
- return false;
439
- if (!existsSync(targetDir))
440
- mkdirSync(targetDir, { recursive: true });
441
- const summaryPath = join(targetDir, buildTaskFileName(tid, "SUMMARY"));
442
- const content = [
443
- `# BLOCKER — task skipped by auto-mode recovery`,
444
- ``,
445
- `Task \`${tid}\` in slice \`${sid}\` (milestone \`${mid}\`) failed to complete after ${reason} recovery exhausted ${maxAttempts} attempts.`,
446
- ``,
447
- `This placeholder was written by auto-mode so the pipeline can advance.`,
448
- `Review this task manually and replace this file with a real summary.`,
449
- ].join("\n");
450
- writeFileSync(summaryPath, content, "utf-8");
451
- }
452
- // Mark [x] in the slice plan if not already checked.
453
- if (!status.taskChecked) {
454
- const planAbs = resolveSliceFile(base, mid, sid, "PLAN");
455
- if (planAbs && existsSync(planAbs)) {
456
- const planContent = readFileSync(planAbs, "utf-8");
457
- const escapedTid = tid.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
458
- const re = new RegExp(`^(- \\[) \\] (\\*\\*${escapedTid}:)`, "m");
459
- if (re.test(planContent)) {
460
- writeFileSync(planAbs, planContent.replace(re, "$1x] $2"), "utf-8");
461
- }
462
- else {
463
- // Regex didn't match — checkbox format differs from expected pattern.
464
- // Return false so callers know the plan was NOT updated and can
465
- // fall through to other recovery strategies instead of assuming success.
466
- return false;
467
- }
468
- }
469
- }
470
- return true;
471
- }
472
439
  // ─── Merge State Reconciliation ───────────────────────────────────────────────
473
440
  /**
474
441
  * Detect leftover merge state from a prior session and reconcile it.
@@ -590,39 +557,8 @@ export async function selfHealRuntimeRecords(base, ctx) {
590
557
  const now = Date.now();
591
558
  for (const record of records) {
592
559
  const { unitType, unitId } = record;
593
- // Case 0: complete-slice with SUMMARY + UAT but unchecked roadmap (#1350).
594
- // If a complete-slice was interrupted after writing artifacts but before
595
- // flipping the roadmap checkbox, the verification fails and the dispatch
596
- // loop relaunches the same unit forever. Auto-fix the checkbox.
597
- if (unitType === "complete-slice") {
598
- const { milestone: mid, slice: sid } = parseUnitId(unitId);
599
- if (mid && sid) {
600
- const dir = resolveSlicePath(base, mid, sid);
601
- if (dir) {
602
- const summaryPath = join(dir, buildSliceFileName(sid, "SUMMARY"));
603
- const uatPath = join(dir, buildSliceFileName(sid, "UAT"));
604
- if (existsSync(summaryPath) && existsSync(uatPath)) {
605
- const roadmapFile = resolveMilestoneFile(base, mid, "ROADMAP");
606
- if (roadmapFile && existsSync(roadmapFile)) {
607
- try {
608
- const roadmapContent = readFileSync(roadmapFile, "utf-8");
609
- const roadmap = parseRoadmap(roadmapContent);
610
- const slice = (roadmap.slices ?? []).find(s => s.id === sid);
611
- if (slice && !slice.done) {
612
- // Auto-fix: flip the checkbox using shared utility
613
- if (markSliceDoneInRoadmap(base, mid, sid)) {
614
- ctx.ui.notify(`Self-heal: marked ${sid} done in roadmap (SUMMARY + UAT exist but checkbox was stale).`, "info");
615
- }
616
- }
617
- }
618
- catch {
619
- // Roadmap parse failure — don't block self-heal
620
- }
621
- }
622
- }
623
- }
624
- }
625
- }
560
+ // Case 0 removed roadmap checkbox auto-fix is no longer needed.
561
+ // With DB-as-truth, stale checkboxes are fixed by repairStaleRenders().
626
562
  // Clear stale dispatched records (dispatched > 1h ago, process crashed)
627
563
  const age = now - (record.startedAt ?? 0);
628
564
  if (record.phase === "dispatched" && age > STALE_THRESHOLD_MS) {
@@ -654,13 +590,10 @@ export function buildLoopRemediationSteps(unitType, unitId, base) {
654
590
  case "execute-task": {
655
591
  if (!mid || !sid || !tid)
656
592
  break;
657
- const planRel = relSliceFile(base, mid, sid, "PLAN");
658
- const summaryRel = relTaskFile(base, mid, sid, tid, "SUMMARY");
659
593
  return [
660
- ` 1. Write ${summaryRel} (even a partial summary is sufficient to unblock the pipeline)`,
661
- ` 2. Mark ${tid} [x] in ${planRel}: change "- [ ] **${tid}:" → "- [x] **${tid}:"`,
662
- ` 3. Run \`gsd doctor\` to reconcile .gsd/ state`,
663
- ` 4. Resume auto-mode — it will pick up from the next task`,
594
+ ` 1. Run \`gsd undo-task ${tid}\` to reset the task state`,
595
+ ` 2. Resume auto-mode it will re-execute the task`,
596
+ ` 3. If the task keeps failing, run \`gsd recover\` to rebuild DB state from disk`,
664
597
  ].join("\n");
665
598
  }
666
599
  case "plan-slice":
@@ -672,7 +605,7 @@ export function buildLoopRemediationSteps(unitType, unitId, base) {
672
605
  : relSliceFile(base, mid, sid, "RESEARCH");
673
606
  return [
674
607
  ` 1. Write ${artifactRel} manually (or with the LLM in interactive mode)`,
675
- ` 2. Run \`gsd doctor\` to reconcile .gsd/ state`,
608
+ ` 2. Run \`gsd recover\` to rebuild DB state from disk`,
676
609
  ` 3. Resume auto-mode`,
677
610
  ].join("\n");
678
611
  }
@@ -680,10 +613,9 @@ export function buildLoopRemediationSteps(unitType, unitId, base) {
680
613
  if (!mid || !sid)
681
614
  break;
682
615
  return [
683
- ` 1. Write the slice summary and UAT file for ${sid} in ${relSlicePath(base, mid, sid)}`,
684
- ` 2. Mark ${sid} [x] in ${relMilestoneFile(base, mid, "ROADMAP")}`,
685
- ` 3. Run \`gsd doctor\` to reconcile .gsd/ state`,
686
- ` 4. Resume auto-mode`,
616
+ ` 1. Run \`gsd reset-slice ${sid}\` to reset the slice and all its tasks`,
617
+ ` 2. Resume auto-mode it will re-execute incomplete tasks and re-complete the slice`,
618
+ ` 3. If the slice keeps failing, run \`gsd recover\` to rebuild DB state from disk`,
687
619
  ].join("\n");
688
620
  }
689
621
  case "validate-milestone": {
@@ -692,7 +624,7 @@ export function buildLoopRemediationSteps(unitType, unitId, base) {
692
624
  const artifactRel = relMilestoneFile(base, mid, "VALIDATION");
693
625
  return [
694
626
  ` 1. Write ${artifactRel} with verdict: pass`,
695
- ` 2. Run \`gsd doctor\``,
627
+ ` 2. Run \`gsd recover\` to rebuild DB state from disk`,
696
628
  ` 3. Resume auto-mode`,
697
629
  ].join("\n");
698
630
  }
@@ -4,7 +4,7 @@
4
4
  * and blocker placeholder generation.
5
5
  */
6
6
  import { readUnitRuntimeRecord, writeUnitRuntimeRecord, formatExecuteTaskRecoveryStatus, inspectExecuteTaskDurability, } from "./unit-runtime.js";
7
- import { resolveExpectedArtifactPath, diagnoseExpectedArtifact, skipExecuteTask, writeBlockerPlaceholder, } from "./auto-recovery.js";
7
+ import { resolveExpectedArtifactPath, diagnoseExpectedArtifact, writeBlockerPlaceholder, } from "./auto-recovery.js";
8
8
  import { existsSync } from "node:fs";
9
9
  import { resolveAgentEnd } from "./auto-loop.js";
10
10
  export async function recoverTimedOutUnit(ctx, pi, unitType, unitId, reason, rctx) {
@@ -78,13 +78,10 @@ export async function recoverTimedOutUnit(ctx, pi, unitType, unitId, reason, rct
78
78
  ctx.ui.notify(`${reason === "idle" ? "Idle" : "Timeout"} recovery: steering ${unitType} ${unitId} to finish durable output (attempt ${attemptNumber}, session ${recoveryAttempts + 1}/${maxRecoveryAttempts}).`, "warning");
79
79
  return "recovered";
80
80
  }
81
- // Retries exhausted — write missing durable artifacts and advance.
81
+ // Retries exhausted — write a blocker placeholder and advance.
82
82
  const diagnostic = formatExecuteTaskRecoveryStatus(status);
83
- const [mid, sid, tid] = unitId.split("/");
84
- const skipped = mid && sid && tid
85
- ? skipExecuteTask(basePath, mid, sid, tid, status, reason, maxRecoveryAttempts)
86
- : false;
87
- if (skipped) {
83
+ const placeholder = writeBlockerPlaceholder(unitType, unitId, basePath, `${reason} recovery exhausted ${maxRecoveryAttempts} attempts. Status: ${diagnostic}`);
84
+ if (placeholder) {
88
85
  writeUnitRuntimeRecord(basePath, unitType, unitId, currentUnitStartedAt, {
89
86
  phase: "skipped",
90
87
  recovery: status,
@@ -8,7 +8,7 @@
8
8
  import { existsSync, cpSync, readFileSync, readdirSync, mkdirSync, realpathSync, rmSync, unlinkSync, lstatSync as lstatSyncFn, } from "node:fs";
9
9
  import { isAbsolute, join } from "node:path";
10
10
  import { GSDError, GSD_IO_ERROR, GSD_GIT_ERROR } from "./errors.js";
11
- import { copyWorktreeDb, reconcileWorktreeDb, isDbAvailable, } from "./gsd-db.js";
11
+ import { reconcileWorktreeDb, isDbAvailable, } from "./gsd-db.js";
12
12
  import { atomicWriteSync } from "./atomic-write.js";
13
13
  import { execFileSync } from "node:child_process";
14
14
  import { safeCopy, safeCopyRecursive } from "./safe-fs.js";
@@ -251,6 +251,22 @@ export function syncWorktreeStateBack(mainBasePath, worktreePath, milestoneId) {
251
251
  }
252
252
  if (!existsSync(wtGsd) || !existsSync(mainGsd))
253
253
  return { synced };
254
+ // ── 0. Pre-upgrade worktree DB reconciliation ────────────────────────
255
+ // If the worktree has its own gsd.db (copied before the WAL transition),
256
+ // reconcile its hierarchy data into the project root DB before syncing
257
+ // files. This handles in-flight worktrees that were created before the
258
+ // upgrade to shared WAL mode.
259
+ const wtLocalDb = join(wtGsd, "gsd.db");
260
+ const mainDb = join(mainGsd, "gsd.db");
261
+ if (existsSync(wtLocalDb) && existsSync(mainDb)) {
262
+ try {
263
+ reconcileWorktreeDb(mainDb, wtLocalDb);
264
+ synced.push("gsd.db (pre-upgrade reconcile)");
265
+ }
266
+ catch {
267
+ // Non-fatal — file sync below is the fallback
268
+ }
269
+ }
254
270
  // ── 1. Sync root-level .gsd/ files back ──────────────────────────────
255
271
  // The worktree is authoritative — complete-milestone updates REQUIREMENTS,
256
272
  // PROJECT, etc. These must overwrite main's copies so they survive teardown.
@@ -641,17 +657,11 @@ function copyPlanningArtifacts(srcBase, wtPath) {
641
657
  ]) {
642
658
  safeCopy(join(srcGsd, file), join(dstGsd, file), { force: true });
643
659
  }
644
- // Copy gsd.db if present in source
645
- const srcDb = join(srcGsd, "gsd.db");
646
- const destDb = join(dstGsd, "gsd.db");
647
- if (existsSync(srcDb)) {
648
- try {
649
- copyWorktreeDb(srcDb, destDb);
650
- }
651
- catch {
652
- /* non-fatal */
653
- }
654
- }
660
+ // Shared WAL (R012): worktrees use the project root's DB directly.
661
+ // No longer copy gsd.db into the worktree — the DB path resolver in
662
+ // ensureDbOpen() detects the worktree location and opens the root DB.
663
+ // Compat note: reconcileWorktreeDb() in mergeMilestoneToMain handles
664
+ // worktrees that already have a local gsd.db from before this change.
655
665
  }
656
666
  /**
657
667
  * Teardown an auto-worktree: chdir back to original base, then remove
@@ -1063,4 +1063,4 @@ export async function dispatchHookUnit(ctx, pi, hookName, triggerUnitType, trigg
1063
1063
  // Direct phase dispatch → auto-direct-dispatch.ts
1064
1064
  export { dispatchDirectPhase } from "./auto-direct-dispatch.js";
1065
1065
  // Re-export recovery functions for external consumers
1066
- export { resolveExpectedArtifactPath, verifyExpectedArtifact, writeBlockerPlaceholder, skipExecuteTask, buildLoopRemediationSteps, } from "./auto-recovery.js";
1066
+ export { resolveExpectedArtifactPath, verifyExpectedArtifact, writeBlockerPlaceholder, buildLoopRemediationSteps, } from "./auto-recovery.js";