gsd-pi 2.65.0 → 2.66.0-dev.6c91c1f

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 (458) hide show
  1. package/dist/mcp-server.js +6 -2
  2. package/dist/resources/extensions/browser-tools/capture.js +20 -1
  3. package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +93 -0
  4. package/dist/resources/extensions/gsd/auto/finalize-timeout.js +2 -0
  5. package/dist/resources/extensions/gsd/auto/loop.js +2 -2
  6. package/dist/resources/extensions/gsd/auto/phases.js +48 -5
  7. package/dist/resources/extensions/gsd/auto/run-unit.js +13 -2
  8. package/dist/resources/extensions/gsd/auto/session.js +4 -0
  9. package/dist/resources/extensions/gsd/auto/types.js +2 -0
  10. package/dist/resources/extensions/gsd/auto-dashboard.js +2 -1
  11. package/dist/resources/extensions/gsd/auto-dispatch.js +99 -9
  12. package/dist/resources/extensions/gsd/auto-model-selection.js +7 -5
  13. package/dist/resources/extensions/gsd/auto-post-unit.js +17 -6
  14. package/dist/resources/extensions/gsd/auto-prompts.js +24 -0
  15. package/dist/resources/extensions/gsd/auto-recovery.js +40 -22
  16. package/dist/resources/extensions/gsd/auto-start.js +175 -12
  17. package/dist/resources/extensions/gsd/auto-tool-tracking.js +10 -0
  18. package/dist/resources/extensions/gsd/auto-worktree.js +29 -7
  19. package/dist/resources/extensions/gsd/auto.js +21 -15
  20. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +17 -4
  21. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +10 -0
  22. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +6 -4
  23. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +5 -1
  24. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +11 -3
  25. package/dist/resources/extensions/gsd/bootstrap/system-context.js +3 -1
  26. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +31 -1
  27. package/dist/resources/extensions/gsd/commands/context.js +8 -1
  28. package/dist/resources/extensions/gsd/commands/handlers/core.js +23 -2
  29. package/dist/resources/extensions/gsd/commands-extensions.js +1 -1
  30. package/dist/resources/extensions/gsd/config-overlay.js +312 -0
  31. package/dist/resources/extensions/gsd/db-writer.js +13 -3
  32. package/dist/resources/extensions/gsd/detection.js +1 -1
  33. package/dist/resources/extensions/gsd/dispatch-guard.js +2 -1
  34. package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -0
  35. package/dist/resources/extensions/gsd/doctor.js +2 -1
  36. package/dist/resources/extensions/gsd/files.js +17 -0
  37. package/dist/resources/extensions/gsd/gitignore.js +1 -0
  38. package/dist/resources/extensions/gsd/gsd-db.js +47 -4
  39. package/dist/resources/extensions/gsd/guided-flow.js +220 -29
  40. package/dist/resources/extensions/gsd/index.js +1 -1
  41. package/dist/resources/extensions/gsd/json-persistence.js +5 -2
  42. package/dist/resources/extensions/gsd/md-importer.js +14 -7
  43. package/dist/resources/extensions/gsd/notification-overlay.js +1 -1
  44. package/dist/resources/extensions/gsd/notification-widget.js +2 -1
  45. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +1 -1
  46. package/dist/resources/extensions/gsd/parallel-orchestrator.js +17 -11
  47. package/dist/resources/extensions/gsd/pre-execution-checks.js +26 -5
  48. package/dist/resources/extensions/gsd/preferences-types.js +3 -0
  49. package/dist/resources/extensions/gsd/preferences-validation.js +45 -1
  50. package/dist/resources/extensions/gsd/preferences.js +9 -2
  51. package/dist/resources/extensions/gsd/preparation.js +1092 -0
  52. package/dist/resources/extensions/gsd/prompt-validation.js +67 -0
  53. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +3 -3
  54. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  55. package/dist/resources/extensions/gsd/prompts/discuss-prepared.md +424 -0
  56. package/dist/resources/extensions/gsd/prompts/discuss.md +2 -0
  57. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +6 -1
  58. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +5 -4
  59. package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +23 -0
  60. package/dist/resources/extensions/gsd/prompts/queue.md +2 -0
  61. package/dist/resources/extensions/gsd/prompts/rethink.md +2 -1
  62. package/dist/resources/extensions/gsd/prompts/system.md +2 -2
  63. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +56 -23
  64. package/dist/resources/extensions/gsd/quick.js +19 -15
  65. package/dist/resources/extensions/gsd/reactive-graph.js +12 -0
  66. package/dist/resources/extensions/gsd/roadmap-slices.js +24 -5
  67. package/dist/resources/extensions/gsd/safety/content-validator.js +3 -3
  68. package/dist/resources/extensions/gsd/session-lock.js +23 -1
  69. package/dist/resources/extensions/gsd/state.js +115 -28
  70. package/dist/resources/extensions/gsd/templates/context-enhanced.md +138 -0
  71. package/dist/resources/extensions/gsd/tools/complete-milestone.js +15 -3
  72. package/dist/resources/extensions/gsd/tools/complete-slice.js +27 -6
  73. package/dist/resources/extensions/gsd/tools/complete-task.js +31 -7
  74. package/dist/resources/extensions/gsd/tools/plan-milestone.js +7 -5
  75. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +5 -2
  76. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +119 -0
  77. package/dist/resources/extensions/gsd/tools/reopen-slice.js +30 -0
  78. package/dist/resources/extensions/gsd/tools/reopen-task.js +18 -0
  79. package/dist/resources/extensions/gsd/triage-resolution.js +33 -16
  80. package/dist/resources/extensions/gsd/undo.js +3 -2
  81. package/dist/resources/extensions/gsd/workflow-events.js +1 -0
  82. package/dist/resources/extensions/gsd/workflow-logger.js +1 -1
  83. package/dist/resources/extensions/gsd/workflow-projections.js +7 -9
  84. package/dist/resources/extensions/gsd/workflow-reconcile.js +100 -9
  85. package/dist/resources/extensions/gsd/workflow-templates.js +11 -2
  86. package/dist/resources/extensions/gsd/worktree-manager.js +5 -2
  87. package/dist/resources/extensions/gsd/worktree.js +9 -0
  88. package/dist/resources/extensions/shared/interview-ui.js +1 -1
  89. package/dist/resources/extensions/subagent/agents.js +19 -5
  90. package/dist/web/standalone/.next/BUILD_ID +1 -1
  91. package/dist/web/standalone/.next/app-path-routes-manifest.json +11 -11
  92. package/dist/web/standalone/.next/build-manifest.json +4 -4
  93. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  94. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  95. package/dist/web/standalone/.next/required-server-files.json +3 -3
  96. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  97. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  98. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  99. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  101. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  102. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  103. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  104. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  107. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  108. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  109. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  110. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  111. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  113. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  123. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  135. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  155. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  165. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  171. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  185. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  187. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  189. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  191. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  195. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  196. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  197. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  199. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  200. package/dist/web/standalone/.next/server/app/index.html +1 -1
  201. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  202. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  203. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  204. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  205. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  206. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  207. package/dist/web/standalone/.next/server/app/page.js +2 -2
  208. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  209. package/dist/web/standalone/.next/server/app-paths-manifest.json +11 -11
  210. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  211. package/dist/web/standalone/.next/server/chunks/7471.js +3 -3
  212. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  213. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  214. package/dist/web/standalone/.next/server/middleware.js +2 -2
  215. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  216. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  217. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  218. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  219. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  220. package/dist/web/standalone/.next/static/chunks/6502.8874bcae249c02e1.js +9 -0
  221. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  222. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  223. package/dist/web/standalone/.next/static/chunks/app/page-0c485498795110d6.js +1 -0
  224. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  225. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  226. package/dist/web/standalone/.next/static/chunks/{webpack-a1c1e452c6b32d04.js → webpack-9fed74684e1c5bb1.js} +1 -1
  227. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  228. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  229. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  230. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  231. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  232. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  233. package/dist/web/standalone/server.js +1 -1
  234. package/package.json +1 -1
  235. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
  236. package/packages/pi-coding-agent/dist/core/retry-handler.js +30 -19
  237. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  238. package/packages/pi-coding-agent/dist/core/retry-handler.test.js +51 -0
  239. package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
  240. package/packages/pi-coding-agent/dist/core/sdk.js +9 -9
  241. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  242. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts +2 -1
  243. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts.map +1 -1
  244. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js +10 -1
  245. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js.map +1 -1
  246. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +1 -0
  247. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  248. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +20 -5
  249. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  250. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +15 -1
  251. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  252. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +18 -0
  253. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  254. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  255. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +4 -0
  256. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  257. package/packages/pi-coding-agent/package.json +1 -1
  258. package/packages/pi-coding-agent/src/core/retry-handler.test.ts +80 -0
  259. package/packages/pi-coding-agent/src/core/retry-handler.ts +37 -25
  260. package/packages/pi-coding-agent/src/core/sdk.ts +9 -9
  261. package/packages/pi-coding-agent/src/modes/interactive/components/provider-manager.ts +10 -0
  262. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +20 -4
  263. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +27 -0
  264. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +16 -1
  265. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +5 -0
  266. package/packages/pi-tui/dist/components/image.d.ts +2 -0
  267. package/packages/pi-tui/dist/components/image.d.ts.map +1 -1
  268. package/packages/pi-tui/dist/components/image.js +4 -0
  269. package/packages/pi-tui/dist/components/image.js.map +1 -1
  270. package/packages/pi-tui/dist/components/image.test.d.ts +6 -0
  271. package/packages/pi-tui/dist/components/image.test.d.ts.map +1 -0
  272. package/packages/pi-tui/dist/components/image.test.js +32 -0
  273. package/packages/pi-tui/dist/components/image.test.js.map +1 -0
  274. package/packages/pi-tui/src/components/image.test.ts +36 -0
  275. package/packages/pi-tui/src/components/image.ts +5 -0
  276. package/pkg/package.json +1 -1
  277. package/src/resources/extensions/browser-tools/capture.ts +19 -1
  278. package/src/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +93 -0
  279. package/src/resources/extensions/gsd/auto/finalize-timeout.ts +3 -0
  280. package/src/resources/extensions/gsd/auto/loop.ts +2 -2
  281. package/src/resources/extensions/gsd/auto/phases.ts +68 -3
  282. package/src/resources/extensions/gsd/auto/run-unit.ts +12 -2
  283. package/src/resources/extensions/gsd/auto/session.ts +4 -0
  284. package/src/resources/extensions/gsd/auto/types.ts +5 -0
  285. package/src/resources/extensions/gsd/auto-dashboard.ts +2 -1
  286. package/src/resources/extensions/gsd/auto-dispatch.ts +110 -9
  287. package/src/resources/extensions/gsd/auto-model-selection.ts +7 -5
  288. package/src/resources/extensions/gsd/auto-post-unit.ts +16 -6
  289. package/src/resources/extensions/gsd/auto-prompts.ts +31 -0
  290. package/src/resources/extensions/gsd/auto-recovery.ts +29 -23
  291. package/src/resources/extensions/gsd/auto-start.ts +188 -10
  292. package/src/resources/extensions/gsd/auto-tool-tracking.ts +10 -0
  293. package/src/resources/extensions/gsd/auto-worktree.ts +28 -7
  294. package/src/resources/extensions/gsd/auto.ts +19 -8
  295. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +16 -4
  296. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +10 -0
  297. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +5 -4
  298. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +4 -1
  299. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +11 -3
  300. package/src/resources/extensions/gsd/bootstrap/system-context.ts +3 -1
  301. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +36 -1
  302. package/src/resources/extensions/gsd/commands/context.ts +7 -1
  303. package/src/resources/extensions/gsd/commands/handlers/core.ts +26 -2
  304. package/src/resources/extensions/gsd/commands-extensions.ts +1 -1
  305. package/src/resources/extensions/gsd/config-overlay.ts +331 -0
  306. package/src/resources/extensions/gsd/db-writer.ts +11 -3
  307. package/src/resources/extensions/gsd/detection.ts +1 -1
  308. package/src/resources/extensions/gsd/dispatch-guard.ts +2 -1
  309. package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -0
  310. package/src/resources/extensions/gsd/doctor.ts +2 -1
  311. package/src/resources/extensions/gsd/files.ts +19 -0
  312. package/src/resources/extensions/gsd/gitignore.ts +1 -0
  313. package/src/resources/extensions/gsd/gsd-db.ts +46 -4
  314. package/src/resources/extensions/gsd/guided-flow.ts +254 -30
  315. package/src/resources/extensions/gsd/index.ts +1 -0
  316. package/src/resources/extensions/gsd/json-persistence.ts +6 -3
  317. package/src/resources/extensions/gsd/md-importer.ts +13 -6
  318. package/src/resources/extensions/gsd/notification-overlay.ts +1 -1
  319. package/src/resources/extensions/gsd/notification-widget.ts +2 -1
  320. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +1 -1
  321. package/src/resources/extensions/gsd/parallel-orchestrator.ts +19 -11
  322. package/src/resources/extensions/gsd/pre-execution-checks.ts +32 -7
  323. package/src/resources/extensions/gsd/preferences-types.ts +25 -0
  324. package/src/resources/extensions/gsd/preferences-validation.ts +45 -1
  325. package/src/resources/extensions/gsd/preferences.ts +9 -2
  326. package/src/resources/extensions/gsd/preparation.ts +1419 -0
  327. package/src/resources/extensions/gsd/prompt-validation.ts +88 -0
  328. package/src/resources/extensions/gsd/prompts/complete-milestone.md +3 -3
  329. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  330. package/src/resources/extensions/gsd/prompts/discuss-prepared.md +424 -0
  331. package/src/resources/extensions/gsd/prompts/discuss.md +2 -0
  332. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +6 -1
  333. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +5 -4
  334. package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +23 -0
  335. package/src/resources/extensions/gsd/prompts/queue.md +2 -0
  336. package/src/resources/extensions/gsd/prompts/rethink.md +2 -1
  337. package/src/resources/extensions/gsd/prompts/system.md +2 -2
  338. package/src/resources/extensions/gsd/prompts/validate-milestone.md +56 -23
  339. package/src/resources/extensions/gsd/quick.ts +20 -15
  340. package/src/resources/extensions/gsd/reactive-graph.ts +18 -0
  341. package/src/resources/extensions/gsd/roadmap-slices.ts +21 -5
  342. package/src/resources/extensions/gsd/safety/content-validator.ts +3 -3
  343. package/src/resources/extensions/gsd/session-lock.ts +17 -1
  344. package/src/resources/extensions/gsd/state.ts +115 -26
  345. package/src/resources/extensions/gsd/templates/context-enhanced.md +138 -0
  346. package/src/resources/extensions/gsd/tests/adversarial-review-fixes.test.ts +223 -0
  347. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +33 -2
  348. package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +56 -0
  349. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +41 -0
  350. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +72 -0
  351. package/src/resources/extensions/gsd/tests/complete-task-normalize-lists.test.ts +54 -0
  352. package/src/resources/extensions/gsd/tests/defer-milestone-stamp.test.ts +30 -0
  353. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +4 -3
  354. package/src/resources/extensions/gsd/tests/discuss-incremental-persistence.test.ts +36 -0
  355. package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +46 -0
  356. package/src/resources/extensions/gsd/tests/dispatch-guard-closed-status.test.ts +33 -0
  357. package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +37 -0
  358. package/src/resources/extensions/gsd/tests/error-success-mask.test.ts +37 -0
  359. package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +125 -0
  360. package/src/resources/extensions/gsd/tests/find-missing-summaries-closed.test.ts +48 -0
  361. package/src/resources/extensions/gsd/tests/format-shortcut.test.ts +69 -0
  362. package/src/resources/extensions/gsd/tests/frontmatter-parse-noise.test.ts +42 -0
  363. package/src/resources/extensions/gsd/tests/gitignore-bg-shell.test.ts +38 -0
  364. package/src/resources/extensions/gsd/tests/guided-flow-state-rebuild.test.ts +103 -0
  365. package/src/resources/extensions/gsd/tests/import-done-milestones.test.ts +42 -0
  366. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +11 -9
  367. package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +4 -2
  368. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +28 -30
  369. package/src/resources/extensions/gsd/tests/integration/test-isolation.ts +53 -0
  370. package/src/resources/extensions/gsd/tests/integration-prepared-discussion.test.ts +525 -0
  371. package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +62 -0
  372. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +11 -10
  373. package/src/resources/extensions/gsd/tests/needs-remediation-revalidation.test.ts +48 -0
  374. package/src/resources/extensions/gsd/tests/note-captures-executed.test.ts +46 -0
  375. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +189 -0
  376. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +77 -0
  377. package/src/resources/extensions/gsd/tests/phantom-ghost-detection.test.ts +55 -0
  378. package/src/resources/extensions/gsd/tests/phantom-milestone-default-queued.test.ts +39 -0
  379. package/src/resources/extensions/gsd/tests/pre-exec-backtick-strip.test.ts +68 -0
  380. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +284 -20
  381. package/src/resources/extensions/gsd/tests/pre-execution-fail-closed.test.ts +2 -2
  382. package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +2 -2
  383. package/src/resources/extensions/gsd/tests/preparation.test.ts +1211 -0
  384. package/src/resources/extensions/gsd/tests/project-root-cwd-crash.test.ts +53 -0
  385. package/src/resources/extensions/gsd/tests/projection-no-plan-overwrite.test.ts +83 -0
  386. package/src/resources/extensions/gsd/tests/prompt-builder.test.ts +669 -0
  387. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +7 -4
  388. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +85 -0
  389. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +2 -1
  390. package/src/resources/extensions/gsd/tests/query-tools-db-open.test.ts +47 -0
  391. package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +107 -0
  392. package/src/resources/extensions/gsd/tests/reactive-graph.test.ts +45 -0
  393. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +63 -0
  394. package/src/resources/extensions/gsd/tests/rogue-file-detection.test.ts +4 -5
  395. package/src/resources/extensions/gsd/tests/run-uat-replay-cap.test.ts +51 -0
  396. package/src/resources/extensions/gsd/tests/show-config-command.test.ts +56 -0
  397. package/src/resources/extensions/gsd/tests/skip-slice-state-rebuild.test.ts +31 -0
  398. package/src/resources/extensions/gsd/tests/skipped-validation-completion.test.ts +39 -0
  399. package/src/resources/extensions/gsd/tests/slice-sequence-insert.test.ts +51 -0
  400. package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +1 -1
  401. package/src/resources/extensions/gsd/tests/stale-lockfile-recovery.test.ts +36 -0
  402. package/src/resources/extensions/gsd/tests/stale-queued-milestone.test.ts +147 -0
  403. package/src/resources/extensions/gsd/tests/stale-worktree-cwd.test.ts +13 -0
  404. package/src/resources/extensions/gsd/tests/stash-pop-gsd-conflict.test.ts +21 -0
  405. package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +21 -0
  406. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +6 -7
  407. package/src/resources/extensions/gsd/tests/status-db-open.test.ts +47 -0
  408. package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +1 -0
  409. package/src/resources/extensions/gsd/tests/subagent-agent-discovery.test.ts +47 -0
  410. package/src/resources/extensions/gsd/tests/symlink-extension-discovery.test.ts +125 -0
  411. package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +65 -0
  412. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +29 -1
  413. package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +2 -1
  414. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +3 -4
  415. package/src/resources/extensions/gsd/tests/verification-operational-gate.test.ts +15 -0
  416. package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +89 -0
  417. package/src/resources/extensions/gsd/tests/wave1-critical-regressions.test.ts +49 -0
  418. package/src/resources/extensions/gsd/tests/wave2-events-regressions.test.ts +48 -0
  419. package/src/resources/extensions/gsd/tests/wave3-session-regressions.test.ts +47 -0
  420. package/src/resources/extensions/gsd/tests/wave4-write-safety-regressions.test.ts +70 -0
  421. package/src/resources/extensions/gsd/tests/wave5-consistency-regressions.test.ts +165 -0
  422. package/src/resources/extensions/gsd/tests/worker-model-override.test.ts +48 -0
  423. package/src/resources/extensions/gsd/tests/workflow-logger-audit.test.ts +6 -3
  424. package/src/resources/extensions/gsd/tests/worktree-expected-warnings.test.ts +38 -0
  425. package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +16 -0
  426. package/src/resources/extensions/gsd/tests/worktree-main-branch.test.ts +20 -0
  427. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +16 -17
  428. package/src/resources/extensions/gsd/tests/worktree-sync-tasks.test.ts +13 -9
  429. package/src/resources/extensions/gsd/tests/worktree.test.ts +26 -9
  430. package/src/resources/extensions/gsd/tests/write-gate.test.ts +127 -2
  431. package/src/resources/extensions/gsd/tests/zero-slice-roadmap-guided.test.ts +19 -0
  432. package/src/resources/extensions/gsd/tools/complete-milestone.ts +13 -3
  433. package/src/resources/extensions/gsd/tools/complete-slice.ts +26 -6
  434. package/src/resources/extensions/gsd/tools/complete-task.ts +29 -7
  435. package/src/resources/extensions/gsd/tools/plan-milestone.ts +11 -9
  436. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +5 -2
  437. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +152 -0
  438. package/src/resources/extensions/gsd/tools/reopen-slice.ts +27 -0
  439. package/src/resources/extensions/gsd/tools/reopen-task.ts +17 -0
  440. package/src/resources/extensions/gsd/triage-resolution.ts +37 -17
  441. package/src/resources/extensions/gsd/types.ts +4 -0
  442. package/src/resources/extensions/gsd/undo.ts +3 -2
  443. package/src/resources/extensions/gsd/workflow-events.ts +5 -3
  444. package/src/resources/extensions/gsd/workflow-logger.ts +1 -1
  445. package/src/resources/extensions/gsd/workflow-projections.ts +7 -8
  446. package/src/resources/extensions/gsd/workflow-reconcile.ts +109 -8
  447. package/src/resources/extensions/gsd/workflow-templates.ts +11 -2
  448. package/src/resources/extensions/gsd/worktree-manager.ts +4 -2
  449. package/src/resources/extensions/gsd/worktree.ts +10 -0
  450. package/src/resources/extensions/shared/interview-ui.ts +1 -1
  451. package/src/resources/extensions/shared/tests/interview-notes-loop.test.ts +8 -10
  452. package/src/resources/extensions/subagent/agents.ts +30 -6
  453. package/dist/web/standalone/.next/static/chunks/6502.7593d7797a4b3999.js +0 -9
  454. package/dist/web/standalone/.next/static/chunks/app/page-62be3b5fa91e4c8f.js +0 -1
  455. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  456. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  457. /package/dist/web/standalone/.next/static/{MRM3OSYIAa4HMDqVGQ9nt → _X1i-S7l1jZfb7lmIZozb}/_buildManifest.js +0 -0
  458. /package/dist/web/standalone/.next/static/{MRM3OSYIAa4HMDqVGQ9nt → _X1i-S7l1jZfb7lmIZozb}/_ssgManifest.js +0 -0
@@ -7,12 +7,20 @@ import {
7
7
  transaction,
8
8
  updateTaskStatus,
9
9
  updateSliceStatus,
10
+ updateMilestoneStatus,
10
11
  getSliceTasks,
12
+ insertMilestone,
13
+ _getAdapter,
14
+ getMilestoneSlices,
11
15
  insertVerificationEvidence,
12
16
  upsertDecision,
13
17
  openDatabase,
18
+ setTaskBlockerDiscovered,
14
19
  } from "./gsd-db.js";
15
20
  import { isClosedStatus } from "./status-guards.js";
21
+ import { invalidateStateCache } from "./state.js";
22
+ import { clearPathCache } from "./paths.js";
23
+ import { clearParseCache } from "./files.js";
16
24
  import { writeManifest } from "./workflow-manifest.js";
17
25
  import { atomicWriteSync } from "./atomic-write.js";
18
26
  import { acquireSyncLock, releaseSyncLock } from "./sync-lock.js";
@@ -73,7 +81,15 @@ function replayEvents(events: WorkflowEvent[]): void {
73
81
  transaction(() => {
74
82
  for (const event of events) {
75
83
  const p = event.params;
76
- switch (event.cmd) {
84
+ // Normalize cmd format: completion tools write hyphens ("complete-task"),
85
+ // legacy logs use underscores ("complete_task"). Accept both formats.
86
+ // Type guard: malformed event lines with non-string cmd are skipped.
87
+ if (typeof event.cmd !== "string") {
88
+ logWarning("reconcile", `Event with non-string cmd skipped: ${JSON.stringify(event.cmd)}`);
89
+ continue;
90
+ }
91
+ const cmd = event.cmd.replace(/-/g, "_");
92
+ switch (cmd) {
77
93
  case "complete_task": {
78
94
  const milestoneId = p["milestoneId"] as string;
79
95
  const sliceId = p["sliceId"] as string;
@@ -89,13 +105,11 @@ function replayEvents(events: WorkflowEvent[]): void {
89
105
  break;
90
106
  }
91
107
  case "report_blocker": {
92
- // report_blocker marks the task with blocker_discovered = 1
93
- // The DB helper updateTaskStatus doesn't handle blockers,
94
- // so we just update status to "blocked" as a best-effort replay.
95
108
  const milestoneId = p["milestoneId"] as string;
96
109
  const sliceId = p["sliceId"] as string;
97
110
  const taskId = p["taskId"] as string;
98
111
  updateTaskStatus(milestoneId, sliceId, taskId, "blocked");
112
+ setTaskBlockerDiscovered(milestoneId, sliceId, taskId, true);
99
113
  break;
100
114
  }
101
115
  case "record_verification": {
@@ -120,9 +134,66 @@ function replayEvents(events: WorkflowEvent[]): void {
120
134
  replaySliceComplete(milestoneId, sliceId, event.ts);
121
135
  break;
122
136
  }
137
+ case "complete_milestone": {
138
+ const milestoneId = p["milestoneId"] as string;
139
+ if (!milestoneId) break;
140
+ // Invariant check: only mark complete if all slices are closed.
141
+ // Without this guard, a reordered/partial event stream could close
142
+ // a milestone while work is still incomplete.
143
+ const mSlices = getMilestoneSlices(milestoneId);
144
+ const allClosed = mSlices.length === 0 || mSlices.every(s => isClosedStatus(s.status));
145
+ if (allClosed) {
146
+ updateMilestoneStatus(milestoneId, "complete", event.ts);
147
+ } else {
148
+ logWarning("reconcile", `Skipping complete_milestone replay for ${milestoneId}: not all slices are closed`);
149
+ }
150
+ break;
151
+ }
152
+ case "plan_milestone": {
153
+ // Replay milestone creation — uses INSERT OR IGNORE (gsd-db's insertMilestone is safe)
154
+ const mId = p["milestoneId"] as string;
155
+ if (mId) {
156
+ insertMilestone({ id: mId, title: (p["title"] as string) ?? mId });
157
+ }
158
+ break;
159
+ }
123
160
  case "plan_slice": {
124
- // plan_slice events are informational slice should already exist.
125
- // No DB mutation needed during replay (the slice was inserted at plan time).
161
+ // Replay slice creationstrict INSERT OR IGNORE to avoid overwriting
162
+ // progressed status. insertSlice() uses ON CONFLICT DO UPDATE which
163
+ // could downgrade a completed slice back to pending.
164
+ const milestoneId = p["milestoneId"] as string;
165
+ const sliceId = p["sliceId"] as string;
166
+ 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
+ }
174
+ }
175
+ break;
176
+ }
177
+ case "plan_task": {
178
+ // Replay task creation — strict INSERT OR IGNORE to avoid overwriting
179
+ // progressed status. insertTask() uses ON CONFLICT DO UPDATE which
180
+ // could downgrade a done/in-progress task back to pending.
181
+ const milestoneId = p["milestoneId"] as string;
182
+ const sliceId = p["sliceId"] as string;
183
+ const taskId = p["taskId"] as string;
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
+ }
192
+ }
193
+ break;
194
+ }
195
+ case "replan_slice": {
196
+ // Informational — replan events don't mutate DB during replay
126
197
  break;
127
198
  }
128
199
  case "save_decision": {
@@ -140,7 +211,7 @@ function replayEvents(events: WorkflowEvent[]): void {
140
211
  break;
141
212
  }
142
213
  default:
143
- // Unknown commands are silently skipped during replay
214
+ logWarning("reconcile", `Unknown event cmd during replay: "${event.cmd}" — skipped`);
144
215
  break;
145
216
  }
146
217
  }
@@ -158,26 +229,42 @@ export function extractEntityKey(
158
229
  event: WorkflowEvent,
159
230
  ): { type: string; id: string } | null {
160
231
  const p = event.params;
232
+ // Normalize cmd format: accept both hyphens and underscores
233
+ if (typeof event.cmd !== "string") return null;
234
+ const cmd = event.cmd.replace(/-/g, "_");
161
235
 
162
- switch (event.cmd) {
236
+ switch (cmd) {
163
237
  case "complete_task":
164
238
  case "start_task":
165
239
  case "report_blocker":
166
240
  case "record_verification":
241
+ case "plan_task":
167
242
  return typeof p["taskId"] === "string"
168
243
  ? { type: "task", id: p["taskId"] }
169
244
  : null;
170
245
 
171
246
  case "complete_slice":
247
+ case "replan_slice":
172
248
  return typeof p["sliceId"] === "string"
173
249
  ? { type: "slice", id: p["sliceId"] }
174
250
  : null;
175
251
 
252
+ case "complete_milestone":
253
+ return typeof p["milestoneId"] === "string"
254
+ ? { type: "milestone", id: p["milestoneId"] }
255
+ : null;
256
+
176
257
  case "plan_slice":
177
258
  return typeof p["sliceId"] === "string"
178
259
  ? { type: "slice_plan", id: p["sliceId"] }
179
260
  : null;
180
261
 
262
+ case "complete_milestone":
263
+ case "plan_milestone":
264
+ return typeof p["milestoneId"] === "string"
265
+ ? { type: "milestone", id: p["milestoneId"] }
266
+ : null;
267
+
181
268
  case "save_decision":
182
269
  if (typeof p["scope"] === "string" && typeof p["decision"] === "string") {
183
270
  return { type: "decision", id: `${p["scope"]}:${p["decision"]}` };
@@ -360,6 +447,14 @@ function _reconcileWorktreeLogsInner(
360
447
  const merged = indexed.map(({ e }) => e);
361
448
 
362
449
  // Step 7: Write merged event log FIRST (so crash recovery can re-derive DB state)
450
+ // Guard: detect concurrent appendEvent calls between our read (step 1) and
451
+ // this rewrite. If the log grew, re-read and retry to avoid dropping events.
452
+ const preWriteEvents = readEvents(mainLogPath);
453
+ if (preWriteEvents.length > mainEvents.length) {
454
+ logWarning("reconcile", `Event log grew during reconcile (${mainEvents.length} → ${preWriteEvents.length}), retrying with fresh read`);
455
+ return _reconcileWorktreeLogsInner(mainBasePath, worktreeBasePath);
456
+ }
457
+
363
458
  const baseEvents = mainEvents.slice(0, forkPoint + 1);
364
459
  const mergedLog = baseEvents.concat(merged);
365
460
  const logContent = mergedLog.map((e) => JSON.stringify(e)).join("\n") + (mergedLog.length > 0 ? "\n" : "");
@@ -377,6 +472,12 @@ function _reconcileWorktreeLogsInner(
377
472
  logWarning("reconcile", "manifest write failed (non-fatal)", { error: (err as Error).message });
378
473
  }
379
474
 
475
+ // Step 10: Invalidate caches so deriveState() sees post-reconcile DB state.
476
+ // Use targeted invalidation (not invalidateAllCaches) to avoid wiping artifacts table.
477
+ invalidateStateCache();
478
+ clearPathCache();
479
+ clearParseCache();
480
+
380
481
  return { autoMerged: merged.length, conflicts: [] };
381
482
  }
382
483
 
@@ -58,8 +58,17 @@ let cachedRegistry: TemplateRegistry | null = null;
58
58
  export function loadRegistry(): TemplateRegistry {
59
59
  if (cachedRegistry) return cachedRegistry;
60
60
 
61
- const content = readFileSync(registryPath, "utf-8");
62
- cachedRegistry = JSON.parse(content) as TemplateRegistry;
61
+ if (!existsSync(registryPath)) {
62
+ cachedRegistry = { version: 1, templates: {} };
63
+ return cachedRegistry;
64
+ }
65
+
66
+ try {
67
+ const content = readFileSync(registryPath, "utf-8");
68
+ cachedRegistry = JSON.parse(content) as TemplateRegistry;
69
+ } catch {
70
+ cachedRegistry = { version: 1, templates: {} };
71
+ }
63
72
  return cachedRegistry;
64
73
  }
65
74
 
@@ -89,7 +89,9 @@ function normalizePathForComparison(path: string): string {
89
89
  */
90
90
  export function resolveGitDir(basePath: string): string {
91
91
  const gitPath = join(basePath, ".git");
92
- if (!existsSync(gitPath)) return join(basePath, ".git");
92
+ if (!existsSync(gitPath)) return gitPath;
93
+ // In a normal repo .git is a directory — skip the file read (#3597)
94
+ if (lstatSync(gitPath).isDirectory()) return gitPath;
93
95
  try {
94
96
  const content = readFileSync(gitPath, "utf-8").trim();
95
97
  if (content.startsWith("gitdir: ")) {
@@ -98,7 +100,7 @@ export function resolveGitDir(basePath: string): string {
98
100
  } catch (e) {
99
101
  logWarning("worktree", `.git file read failed: ${(e as Error).message}`);
100
102
  }
101
- return join(basePath, ".git");
103
+ return gitPath;
102
104
  }
103
105
 
104
106
  export function worktreesDir(basePath: string): string {
@@ -42,6 +42,16 @@ function getService(basePath: string): GitServiceImpl {
42
42
  return cachedService;
43
43
  }
44
44
 
45
+ /**
46
+ * Clear the cached GitServiceImpl. For testing only — forces the next
47
+ * getService() call to re-read preferences and create a fresh instance.
48
+ * @internal
49
+ */
50
+ export function _resetServiceCache(): void {
51
+ cachedService = null;
52
+ cachedBasePath = null;
53
+ }
54
+
45
55
  /**
46
56
  * Set the active milestone ID on the cached GitServiceImpl.
47
57
  * This enables integration branch resolution in getMainBranch().
@@ -300,7 +300,7 @@ export async function showInterviewRound(
300
300
  // instead of being trapped in a re-asking loop (bug #2715).
301
301
  // Only auto-open if the user hasn't already provided notes —
302
302
  // otherwise Enter from notes mode loops back here endlessly.
303
- if (!isMultiSelect(currentIdx) && states[currentIdx].cursorIndex === noneOrDoneIdx(currentIdx) && !states[currentIdx].notes) {
303
+ if (!isMultiSelect(currentIdx) && states[currentIdx].cursorIndex === noneOrDoneIdx(currentIdx) && !states[currentIdx].notes && !states[currentIdx].notesVisible) {
304
304
  states[currentIdx].notesVisible = true;
305
305
  focusNotes = true;
306
306
  loadStateToEditor();
@@ -109,25 +109,23 @@ describe("interview-ui notes loop regression (#3502)", () => {
109
109
  assert.equal(answer.selected, "None of the above");
110
110
  });
111
111
 
112
- it("still auto-opens notes when selecting 'None of the above' with no prior notes", async () => {
112
+ it("Enter on empty notes advances instead of re-opening (notesVisible guard)", async () => {
113
113
  // Press Down twice to "None of the above", Enter to select
114
- // Then immediately Enter again (empty notes) — this should re-open notes
115
- // because the guard only skips when notes are non-empty.
116
- // Type something on second open, then Enter to proceed.
114
+ // Then immediately Enter again (empty notes) — notesVisible is already
115
+ // true from auto-open, so the guard prevents re-opening and Enter
116
+ // advances to review. The notes remain empty.
117
117
  const result = await runWithInputs(questions, [
118
118
  DOWN, // cursor → 1
119
119
  DOWN, // cursor → 2 (None of the above)
120
- ENTER, // commit → auto-opens notes
121
- ENTER, // empty notes → goNextOrSubmit should re-open notes (empty guard)
122
- "o", "k", // type "ok"
123
- ENTER, // now notes = "ok" → should advance to review
124
- ENTER, // submit
120
+ ENTER, // commit → auto-opens notes (notesVisible = true)
121
+ ENTER, // empty notes → notesVisible prevents re-open advances to review
122
+ ENTER, // submit from review screen
125
123
  ]);
126
124
 
127
125
  assert.ok(result, "should return a result");
128
126
  const answer = result.answers.q1;
129
127
  assert.ok(answer, "answer for q1 should exist");
130
- assert.equal(answer.notes, "ok");
128
+ assert.equal(answer.notes, "");
131
129
  });
132
130
 
133
131
  it("normal option selection is unaffected", async () => {
@@ -25,6 +25,33 @@ export interface AgentDiscoveryResult {
25
25
  projectAgentsDir: string | null;
26
26
  }
27
27
 
28
+ interface AgentFrontmatter extends Record<string, unknown> {
29
+ name?: string;
30
+ description?: string;
31
+ tools?: string | string[];
32
+ model?: string;
33
+ }
34
+
35
+ function parseAgentTools(value: string | string[] | undefined): string[] | undefined {
36
+ if (typeof value === "string") {
37
+ const tools = value
38
+ .split(",")
39
+ .map((tool) => tool.trim())
40
+ .filter(Boolean);
41
+ return tools.length > 0 ? tools : undefined;
42
+ }
43
+
44
+ if (Array.isArray(value)) {
45
+ const tools = value
46
+ .flatMap((tool) => typeof tool === "string" ? tool.split(",") : [])
47
+ .map((tool) => tool.trim())
48
+ .filter(Boolean);
49
+ return tools.length > 0 ? tools : undefined;
50
+ }
51
+
52
+ return undefined;
53
+ }
54
+
28
55
  function loadAgentsFromDir(dir: string, source: "user" | "project"): AgentConfig[] {
29
56
  const agents: AgentConfig[] = [];
30
57
 
@@ -51,16 +78,13 @@ function loadAgentsFromDir(dir: string, source: "user" | "project"): AgentConfig
51
78
  continue;
52
79
  }
53
80
 
54
- const { frontmatter, body } = parseFrontmatter<Record<string, string>>(content);
81
+ const { frontmatter, body } = parseFrontmatter<AgentFrontmatter>(content);
55
82
 
56
- if (!frontmatter.name || !frontmatter.description) {
83
+ if (typeof frontmatter.name !== "string" || typeof frontmatter.description !== "string") {
57
84
  continue;
58
85
  }
59
86
 
60
- const tools = frontmatter.tools
61
- ?.split(",")
62
- .map((t: string) => t.trim())
63
- .filter(Boolean);
87
+ const tools = parseAgentTools(frontmatter.tools);
64
88
 
65
89
  agents.push({
66
90
  name: frontmatter.name,