gsd-pi 2.64.0-dev.f8aad9b → 2.65.0-dev.16e10d7

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 (473) hide show
  1. package/dist/headless.js +3 -1
  2. package/dist/mcp-server.js +6 -2
  3. package/dist/resources/extensions/bg-shell/bg-shell-lifecycle.js +22 -7
  4. package/dist/resources/extensions/bg-shell/process-manager.js +6 -1
  5. package/dist/resources/extensions/browser-tools/capture.js +20 -1
  6. package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +93 -0
  7. package/dist/resources/extensions/gsd/auto/run-unit.js +13 -2
  8. package/dist/resources/extensions/gsd/auto-dispatch.js +94 -8
  9. package/dist/resources/extensions/gsd/auto-model-selection.js +7 -5
  10. package/dist/resources/extensions/gsd/auto-post-unit.js +115 -7
  11. package/dist/resources/extensions/gsd/auto-prompts.js +24 -0
  12. package/dist/resources/extensions/gsd/auto-recovery.js +12 -8
  13. package/dist/resources/extensions/gsd/auto-start.js +35 -1
  14. package/dist/resources/extensions/gsd/auto-tool-tracking.js +10 -0
  15. package/dist/resources/extensions/gsd/auto-verification.js +138 -1
  16. package/dist/resources/extensions/gsd/auto-worktree.js +29 -7
  17. package/dist/resources/extensions/gsd/auto.js +2 -2
  18. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +17 -4
  19. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +34 -13
  20. package/dist/resources/extensions/gsd/bootstrap/notify-interceptor.js +28 -0
  21. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +6 -4
  22. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +5 -1
  23. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +12 -1
  24. package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +16 -0
  25. package/dist/resources/extensions/gsd/bootstrap/system-context.js +20 -0
  26. package/dist/resources/extensions/gsd/commands/catalog.js +7 -1
  27. package/dist/resources/extensions/gsd/commands/context.js +8 -1
  28. package/dist/resources/extensions/gsd/commands/handlers/core.js +21 -0
  29. package/dist/resources/extensions/gsd/commands/handlers/notifications-handler.js +104 -0
  30. package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
  31. package/dist/resources/extensions/gsd/commands-extensions.js +1 -1
  32. package/dist/resources/extensions/gsd/config-overlay.js +312 -0
  33. package/dist/resources/extensions/gsd/detection.js +1 -1
  34. package/dist/resources/extensions/gsd/dispatch-guard.js +2 -1
  35. package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -0
  36. package/dist/resources/extensions/gsd/doctor.js +2 -1
  37. package/dist/resources/extensions/gsd/gitignore.js +1 -0
  38. package/dist/resources/extensions/gsd/gsd-db.js +11 -2
  39. package/dist/resources/extensions/gsd/guided-flow.js +220 -29
  40. package/dist/resources/extensions/gsd/md-importer.js +14 -7
  41. package/dist/resources/extensions/gsd/notification-overlay.js +256 -0
  42. package/dist/resources/extensions/gsd/notification-store.js +273 -0
  43. package/dist/resources/extensions/gsd/notification-widget.js +56 -0
  44. package/dist/resources/extensions/gsd/parallel-orchestrator.js +17 -11
  45. package/dist/resources/extensions/gsd/post-execution-checks.js +407 -0
  46. package/dist/resources/extensions/gsd/pre-execution-checks.js +471 -0
  47. package/dist/resources/extensions/gsd/preferences-types.js +7 -0
  48. package/dist/resources/extensions/gsd/preferences-validation.js +78 -1
  49. package/dist/resources/extensions/gsd/preferences.js +13 -2
  50. package/dist/resources/extensions/gsd/preparation.js +1092 -0
  51. package/dist/resources/extensions/gsd/prompt-validation.js +67 -0
  52. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +3 -3
  53. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  54. package/dist/resources/extensions/gsd/prompts/discuss-prepared.md +424 -0
  55. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +4 -1
  56. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +5 -4
  57. package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +23 -0
  58. package/dist/resources/extensions/gsd/prompts/rethink.md +2 -1
  59. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +56 -23
  60. package/dist/resources/extensions/gsd/quick.js +19 -15
  61. package/dist/resources/extensions/gsd/reactive-graph.js +12 -0
  62. package/dist/resources/extensions/gsd/roadmap-slices.js +24 -5
  63. package/dist/resources/extensions/gsd/safety/content-validator.js +3 -3
  64. package/dist/resources/extensions/gsd/session-lock.js +23 -1
  65. package/dist/resources/extensions/gsd/state.js +100 -12
  66. package/dist/resources/extensions/gsd/templates/context-enhanced.md +138 -0
  67. package/dist/resources/extensions/gsd/tools/complete-slice.js +12 -3
  68. package/dist/resources/extensions/gsd/tools/complete-task.js +16 -4
  69. package/dist/resources/extensions/gsd/tools/plan-milestone.js +7 -5
  70. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +5 -2
  71. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +119 -0
  72. package/dist/resources/extensions/gsd/tools/reopen-slice.js +30 -0
  73. package/dist/resources/extensions/gsd/tools/reopen-task.js +18 -0
  74. package/dist/resources/extensions/gsd/triage-resolution.js +25 -9
  75. package/dist/resources/extensions/gsd/verification-evidence.js +18 -0
  76. package/dist/resources/extensions/gsd/workflow-logger.js +8 -0
  77. package/dist/resources/extensions/gsd/workflow-projections.js +4 -7
  78. package/dist/resources/extensions/gsd/workflow-reconcile.js +2 -4
  79. package/dist/resources/extensions/gsd/workflow-templates.js +11 -2
  80. package/dist/resources/extensions/gsd/worktree-manager.js +5 -2
  81. package/dist/resources/extensions/gsd/worktree.js +9 -0
  82. package/dist/resources/extensions/shared/interview-ui.js +1 -1
  83. package/dist/web/standalone/.next/BUILD_ID +1 -1
  84. package/dist/web/standalone/.next/app-path-routes-manifest.json +18 -17
  85. package/dist/web/standalone/.next/build-manifest.json +3 -3
  86. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  87. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  88. package/dist/web/standalone/.next/routes-manifest.json +6 -0
  89. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  90. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  91. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  98. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  101. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  102. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  103. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  104. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/api/notifications/route.js +3 -0
  106. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -0
  107. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -0
  108. package/dist/web/standalone/.next/server/app/index.html +1 -1
  109. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app-paths-manifest.json +18 -17
  116. package/dist/web/standalone/.next/server/functions-config-manifest.json +1 -0
  117. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  118. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  120. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  121. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  122. package/dist/web/standalone/.next/static/Z3TgDP0c7kG9j8CVQVGcl/_buildManifest.js +1 -0
  123. package/dist/web/standalone/.next/static/chunks/6502.8874bcae249c02e1.js +9 -0
  124. package/dist/web/standalone/.next/static/chunks/app/_global-error/page-8805a20e15762c3c.js +1 -0
  125. package/dist/web/standalone/.next/static/chunks/app/api/boot/route-8805a20e15762c3c.js +1 -0
  126. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/input/route-8805a20e15762c3c.js +1 -0
  127. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/resize/route-8805a20e15762c3c.js +1 -0
  128. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/stream/route-8805a20e15762c3c.js +1 -0
  129. package/dist/web/standalone/.next/static/chunks/app/api/browse-directories/route-8805a20e15762c3c.js +1 -0
  130. package/dist/web/standalone/.next/static/chunks/app/api/captures/route-8805a20e15762c3c.js +1 -0
  131. package/dist/web/standalone/.next/static/chunks/app/api/cleanup/route-8805a20e15762c3c.js +1 -0
  132. package/dist/web/standalone/.next/static/chunks/app/api/dev-mode/route-8805a20e15762c3c.js +1 -0
  133. package/dist/web/standalone/.next/static/chunks/app/api/doctor/route-8805a20e15762c3c.js +1 -0
  134. package/dist/web/standalone/.next/static/chunks/app/api/experimental/route-8805a20e15762c3c.js +1 -0
  135. package/dist/web/standalone/.next/static/chunks/app/api/export-data/route-8805a20e15762c3c.js +1 -0
  136. package/dist/web/standalone/.next/static/chunks/app/api/files/route-8805a20e15762c3c.js +1 -0
  137. package/dist/web/standalone/.next/static/chunks/app/api/forensics/route-8805a20e15762c3c.js +1 -0
  138. package/dist/web/standalone/.next/static/chunks/app/api/git/route-8805a20e15762c3c.js +1 -0
  139. package/dist/web/standalone/.next/static/chunks/app/api/history/route-8805a20e15762c3c.js +1 -0
  140. package/dist/web/standalone/.next/static/chunks/app/api/hooks/route-8805a20e15762c3c.js +1 -0
  141. package/dist/web/standalone/.next/static/chunks/app/api/inspect/route-8805a20e15762c3c.js +1 -0
  142. package/dist/web/standalone/.next/static/chunks/app/api/knowledge/route-8805a20e15762c3c.js +1 -0
  143. package/dist/web/standalone/.next/static/chunks/app/api/live-state/route-8805a20e15762c3c.js +1 -0
  144. package/dist/web/standalone/.next/static/chunks/app/api/notifications/route-8805a20e15762c3c.js +1 -0
  145. package/dist/web/standalone/.next/static/chunks/app/api/onboarding/route-8805a20e15762c3c.js +1 -0
  146. package/dist/web/standalone/.next/static/chunks/app/api/preferences/route-8805a20e15762c3c.js +1 -0
  147. package/dist/web/standalone/.next/static/chunks/app/api/projects/route-8805a20e15762c3c.js +1 -0
  148. package/dist/web/standalone/.next/static/chunks/app/api/recovery/route-8805a20e15762c3c.js +1 -0
  149. package/dist/web/standalone/.next/static/chunks/app/api/remote-questions/route-8805a20e15762c3c.js +1 -0
  150. package/dist/web/standalone/.next/static/chunks/app/api/session/browser/route-8805a20e15762c3c.js +1 -0
  151. package/dist/web/standalone/.next/static/chunks/app/api/session/command/route-8805a20e15762c3c.js +1 -0
  152. package/dist/web/standalone/.next/static/chunks/app/api/session/events/route-8805a20e15762c3c.js +1 -0
  153. package/dist/web/standalone/.next/static/chunks/app/api/session/manage/route-8805a20e15762c3c.js +1 -0
  154. package/dist/web/standalone/.next/static/chunks/app/api/settings-data/route-8805a20e15762c3c.js +1 -0
  155. package/dist/web/standalone/.next/static/chunks/app/api/shutdown/route-8805a20e15762c3c.js +1 -0
  156. package/dist/web/standalone/.next/static/chunks/app/api/skill-health/route-8805a20e15762c3c.js +1 -0
  157. package/dist/web/standalone/.next/static/chunks/app/api/steer/route-8805a20e15762c3c.js +1 -0
  158. package/dist/web/standalone/.next/static/chunks/app/api/switch-root/route-8805a20e15762c3c.js +1 -0
  159. package/dist/web/standalone/.next/static/chunks/app/api/terminal/input/route-8805a20e15762c3c.js +1 -0
  160. package/dist/web/standalone/.next/static/chunks/app/api/terminal/resize/route-8805a20e15762c3c.js +1 -0
  161. package/dist/web/standalone/.next/static/chunks/app/api/terminal/sessions/route-8805a20e15762c3c.js +1 -0
  162. package/dist/web/standalone/.next/static/chunks/app/api/terminal/stream/route-8805a20e15762c3c.js +1 -0
  163. package/dist/web/standalone/.next/static/chunks/app/api/terminal/upload/route-8805a20e15762c3c.js +1 -0
  164. package/dist/web/standalone/.next/static/chunks/app/api/undo/route-8805a20e15762c3c.js +1 -0
  165. package/dist/web/standalone/.next/static/chunks/app/api/update/route-8805a20e15762c3c.js +1 -0
  166. package/dist/web/standalone/.next/static/chunks/app/api/visualizer/route-8805a20e15762c3c.js +1 -0
  167. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-8805a20e15762c3c.js +1 -0
  168. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-8805a20e15762c3c.js +1 -0
  169. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-8805a20e15762c3c.js +1 -0
  170. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-8805a20e15762c3c.js +1 -0
  171. package/dist/web/standalone/.next/static/chunks/{webpack-a1c1e452c6b32d04.js → webpack-9fed74684e1c5bb1.js} +1 -1
  172. package/package.json +1 -1
  173. package/packages/pi-agent-core/dist/agent-loop.js +26 -9
  174. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  175. package/packages/pi-agent-core/src/agent-loop.test.ts +100 -4
  176. package/packages/pi-agent-core/src/agent-loop.ts +43 -12
  177. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.d.ts +2 -0
  178. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.d.ts.map +1 -0
  179. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +38 -0
  180. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -0
  181. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  182. package/packages/pi-coding-agent/dist/core/agent-session.js +11 -0
  183. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  184. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.d.ts +2 -0
  185. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.d.ts.map +1 -0
  186. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js +24 -0
  187. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js.map +1 -0
  188. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
  189. package/packages/pi-coding-agent/dist/core/resource-loader.js +4 -1
  190. package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
  191. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
  192. package/packages/pi-coding-agent/dist/core/retry-handler.js +30 -19
  193. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  194. package/packages/pi-coding-agent/dist/core/retry-handler.test.js +51 -0
  195. package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
  196. package/packages/pi-coding-agent/dist/core/sdk.js +9 -9
  197. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  198. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts +2 -1
  199. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts.map +1 -1
  200. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js +10 -1
  201. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js.map +1 -1
  202. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +2 -0
  203. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  204. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +28 -5
  205. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  206. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +15 -1
  207. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  208. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +18 -0
  209. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  210. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +6 -0
  211. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  212. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +40 -0
  213. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  214. package/packages/pi-coding-agent/package.json +1 -1
  215. package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +64 -0
  216. package/packages/pi-coding-agent/src/core/agent-session.ts +10 -0
  217. package/packages/pi-coding-agent/src/core/resource-loader-cache-reset.test.ts +42 -0
  218. package/packages/pi-coding-agent/src/core/resource-loader.ts +5 -1
  219. package/packages/pi-coding-agent/src/core/retry-handler.test.ts +80 -0
  220. package/packages/pi-coding-agent/src/core/retry-handler.ts +37 -25
  221. package/packages/pi-coding-agent/src/core/sdk.ts +9 -9
  222. package/packages/pi-coding-agent/src/modes/interactive/components/provider-manager.ts +10 -0
  223. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +29 -4
  224. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +27 -0
  225. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +16 -1
  226. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +38 -0
  227. package/packages/pi-tui/dist/__tests__/overlay-layout.test.d.ts +2 -0
  228. package/packages/pi-tui/dist/__tests__/overlay-layout.test.d.ts.map +1 -0
  229. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js +66 -0
  230. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js.map +1 -0
  231. package/packages/pi-tui/dist/components/image.d.ts +2 -0
  232. package/packages/pi-tui/dist/components/image.d.ts.map +1 -1
  233. package/packages/pi-tui/dist/components/image.js +4 -0
  234. package/packages/pi-tui/dist/components/image.js.map +1 -1
  235. package/packages/pi-tui/dist/components/image.test.d.ts +6 -0
  236. package/packages/pi-tui/dist/components/image.test.d.ts.map +1 -0
  237. package/packages/pi-tui/dist/components/image.test.js +32 -0
  238. package/packages/pi-tui/dist/components/image.test.js.map +1 -0
  239. package/packages/pi-tui/dist/components/loader.d.ts +4 -2
  240. package/packages/pi-tui/dist/components/loader.d.ts.map +1 -1
  241. package/packages/pi-tui/dist/components/loader.js +27 -9
  242. package/packages/pi-tui/dist/components/loader.js.map +1 -1
  243. package/packages/pi-tui/dist/components/text.d.ts.map +1 -1
  244. package/packages/pi-tui/dist/components/text.js +2 -0
  245. package/packages/pi-tui/dist/components/text.js.map +1 -1
  246. package/packages/pi-tui/dist/overlay-layout.d.ts.map +1 -1
  247. package/packages/pi-tui/dist/overlay-layout.js +12 -1
  248. package/packages/pi-tui/dist/overlay-layout.js.map +1 -1
  249. package/packages/pi-tui/dist/tui.d.ts +4 -0
  250. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  251. package/packages/pi-tui/dist/tui.js +35 -0
  252. package/packages/pi-tui/dist/tui.js.map +1 -1
  253. package/packages/pi-tui/src/__tests__/overlay-layout.test.ts +82 -0
  254. package/packages/pi-tui/src/components/image.test.ts +36 -0
  255. package/packages/pi-tui/src/components/image.ts +5 -0
  256. package/packages/pi-tui/src/components/loader.ts +27 -10
  257. package/packages/pi-tui/src/components/text.ts +1 -0
  258. package/packages/pi-tui/src/overlay-layout.ts +13 -1
  259. package/packages/pi-tui/src/tui.ts +34 -0
  260. package/pkg/package.json +1 -1
  261. package/src/resources/extensions/bg-shell/bg-shell-lifecycle.ts +19 -7
  262. package/src/resources/extensions/bg-shell/process-manager.ts +8 -2
  263. package/src/resources/extensions/browser-tools/capture.ts +19 -1
  264. package/src/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +93 -0
  265. package/src/resources/extensions/gsd/auto/run-unit.ts +12 -2
  266. package/src/resources/extensions/gsd/auto-dispatch.ts +105 -8
  267. package/src/resources/extensions/gsd/auto-model-selection.ts +7 -5
  268. package/src/resources/extensions/gsd/auto-post-unit.ts +138 -6
  269. package/src/resources/extensions/gsd/auto-prompts.ts +31 -0
  270. package/src/resources/extensions/gsd/auto-recovery.ts +10 -8
  271. package/src/resources/extensions/gsd/auto-start.ts +38 -0
  272. package/src/resources/extensions/gsd/auto-tool-tracking.ts +10 -0
  273. package/src/resources/extensions/gsd/auto-verification.ts +190 -2
  274. package/src/resources/extensions/gsd/auto-worktree.ts +28 -7
  275. package/src/resources/extensions/gsd/auto.ts +2 -1
  276. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +16 -4
  277. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +35 -13
  278. package/src/resources/extensions/gsd/bootstrap/notify-interceptor.ts +34 -0
  279. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +5 -4
  280. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +4 -1
  281. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +12 -1
  282. package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +20 -0
  283. package/src/resources/extensions/gsd/bootstrap/system-context.ts +28 -0
  284. package/src/resources/extensions/gsd/commands/catalog.ts +7 -1
  285. package/src/resources/extensions/gsd/commands/context.ts +7 -1
  286. package/src/resources/extensions/gsd/commands/handlers/core.ts +24 -0
  287. package/src/resources/extensions/gsd/commands/handlers/notifications-handler.ts +140 -0
  288. package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
  289. package/src/resources/extensions/gsd/commands-extensions.ts +1 -1
  290. package/src/resources/extensions/gsd/config-overlay.ts +331 -0
  291. package/src/resources/extensions/gsd/detection.ts +1 -1
  292. package/src/resources/extensions/gsd/dispatch-guard.ts +2 -1
  293. package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -0
  294. package/src/resources/extensions/gsd/doctor.ts +2 -1
  295. package/src/resources/extensions/gsd/gitignore.ts +1 -0
  296. package/src/resources/extensions/gsd/gsd-db.ts +13 -2
  297. package/src/resources/extensions/gsd/guided-flow.ts +254 -30
  298. package/src/resources/extensions/gsd/md-importer.ts +13 -6
  299. package/src/resources/extensions/gsd/notification-overlay.ts +295 -0
  300. package/src/resources/extensions/gsd/notification-store.ts +293 -0
  301. package/src/resources/extensions/gsd/notification-widget.ts +68 -0
  302. package/src/resources/extensions/gsd/parallel-orchestrator.ts +19 -11
  303. package/src/resources/extensions/gsd/post-execution-checks.ts +539 -0
  304. package/src/resources/extensions/gsd/pre-execution-checks.ts +581 -0
  305. package/src/resources/extensions/gsd/preferences-types.ts +53 -0
  306. package/src/resources/extensions/gsd/preferences-validation.ts +78 -1
  307. package/src/resources/extensions/gsd/preferences.ts +13 -2
  308. package/src/resources/extensions/gsd/preparation.ts +1419 -0
  309. package/src/resources/extensions/gsd/prompt-validation.ts +88 -0
  310. package/src/resources/extensions/gsd/prompts/complete-milestone.md +3 -3
  311. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  312. package/src/resources/extensions/gsd/prompts/discuss-prepared.md +424 -0
  313. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +4 -1
  314. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +5 -4
  315. package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +23 -0
  316. package/src/resources/extensions/gsd/prompts/rethink.md +2 -1
  317. package/src/resources/extensions/gsd/prompts/validate-milestone.md +56 -23
  318. package/src/resources/extensions/gsd/quick.ts +20 -15
  319. package/src/resources/extensions/gsd/reactive-graph.ts +18 -0
  320. package/src/resources/extensions/gsd/roadmap-slices.ts +21 -5
  321. package/src/resources/extensions/gsd/safety/content-validator.ts +3 -3
  322. package/src/resources/extensions/gsd/session-lock.ts +17 -1
  323. package/src/resources/extensions/gsd/state.ts +101 -11
  324. package/src/resources/extensions/gsd/templates/context-enhanced.md +138 -0
  325. package/src/resources/extensions/gsd/tests/adversarial-review-fixes.test.ts +223 -0
  326. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +33 -2
  327. package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +56 -0
  328. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +41 -0
  329. package/src/resources/extensions/gsd/tests/complete-slice-string-coercion.test.ts +36 -0
  330. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +72 -0
  331. package/src/resources/extensions/gsd/tests/complete-task-normalize-lists.test.ts +54 -0
  332. package/src/resources/extensions/gsd/tests/defer-milestone-stamp.test.ts +30 -0
  333. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +4 -3
  334. package/src/resources/extensions/gsd/tests/discuss-incremental-persistence.test.ts +36 -0
  335. package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +46 -0
  336. package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +76 -0
  337. package/src/resources/extensions/gsd/tests/dispatch-guard-closed-status.test.ts +33 -0
  338. package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +37 -0
  339. package/src/resources/extensions/gsd/tests/enhanced-verification-integration.test.ts +526 -0
  340. package/src/resources/extensions/gsd/tests/error-success-mask.test.ts +37 -0
  341. package/src/resources/extensions/gsd/tests/find-missing-summaries-closed.test.ts +48 -0
  342. package/src/resources/extensions/gsd/tests/frontmatter-parse-noise.test.ts +42 -0
  343. package/src/resources/extensions/gsd/tests/gitignore-bg-shell.test.ts +38 -0
  344. package/src/resources/extensions/gsd/tests/guided-flow-state-rebuild.test.ts +103 -0
  345. package/src/resources/extensions/gsd/tests/import-done-milestones.test.ts +42 -0
  346. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +5 -3
  347. package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +4 -2
  348. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +28 -30
  349. package/src/resources/extensions/gsd/tests/integration/test-isolation.ts +53 -0
  350. package/src/resources/extensions/gsd/tests/integration-prepared-discussion.test.ts +525 -0
  351. package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +62 -0
  352. package/src/resources/extensions/gsd/tests/needs-remediation-revalidation.test.ts +48 -0
  353. package/src/resources/extensions/gsd/tests/note-captures-executed.test.ts +46 -0
  354. package/src/resources/extensions/gsd/tests/notification-overlay.test.ts +73 -0
  355. package/src/resources/extensions/gsd/tests/notification-store.test.ts +282 -0
  356. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +77 -0
  357. package/src/resources/extensions/gsd/tests/phantom-ghost-detection.test.ts +55 -0
  358. package/src/resources/extensions/gsd/tests/phantom-milestone-default-queued.test.ts +39 -0
  359. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +312 -0
  360. package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +813 -0
  361. package/src/resources/extensions/gsd/tests/pre-exec-backtick-strip.test.ts +68 -0
  362. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +1197 -0
  363. package/src/resources/extensions/gsd/tests/pre-execution-fail-closed.test.ts +266 -0
  364. package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +457 -0
  365. package/src/resources/extensions/gsd/tests/preparation.test.ts +1211 -0
  366. package/src/resources/extensions/gsd/tests/project-root-cwd-crash.test.ts +53 -0
  367. package/src/resources/extensions/gsd/tests/projection-no-plan-overwrite.test.ts +83 -0
  368. package/src/resources/extensions/gsd/tests/prompt-builder.test.ts +669 -0
  369. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +7 -4
  370. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +85 -0
  371. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +2 -1
  372. package/src/resources/extensions/gsd/tests/query-tools-db-open.test.ts +47 -0
  373. package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +107 -0
  374. package/src/resources/extensions/gsd/tests/reactive-graph.test.ts +45 -0
  375. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +63 -0
  376. package/src/resources/extensions/gsd/tests/rogue-file-detection.test.ts +4 -5
  377. package/src/resources/extensions/gsd/tests/run-uat-replay-cap.test.ts +51 -0
  378. package/src/resources/extensions/gsd/tests/show-config-command.test.ts +56 -0
  379. package/src/resources/extensions/gsd/tests/skip-slice-state-rebuild.test.ts +31 -0
  380. package/src/resources/extensions/gsd/tests/skipped-validation-completion.test.ts +39 -0
  381. package/src/resources/extensions/gsd/tests/slice-sequence-insert.test.ts +51 -0
  382. package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +1 -1
  383. package/src/resources/extensions/gsd/tests/stale-lockfile-recovery.test.ts +36 -0
  384. package/src/resources/extensions/gsd/tests/stale-queued-milestone.test.ts +147 -0
  385. package/src/resources/extensions/gsd/tests/stale-worktree-cwd.test.ts +13 -0
  386. package/src/resources/extensions/gsd/tests/stash-pop-gsd-conflict.test.ts +21 -0
  387. package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +21 -0
  388. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +6 -7
  389. package/src/resources/extensions/gsd/tests/status-db-open.test.ts +47 -0
  390. package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +1 -0
  391. package/src/resources/extensions/gsd/tests/symlink-extension-discovery.test.ts +125 -0
  392. package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +65 -0
  393. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +29 -1
  394. package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +2 -1
  395. package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +163 -0
  396. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +3 -4
  397. package/src/resources/extensions/gsd/tests/verification-operational-gate.test.ts +15 -0
  398. package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +89 -0
  399. package/src/resources/extensions/gsd/tests/worker-model-override.test.ts +48 -0
  400. package/src/resources/extensions/gsd/tests/worktree-expected-warnings.test.ts +38 -0
  401. package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +16 -0
  402. package/src/resources/extensions/gsd/tests/worktree-main-branch.test.ts +20 -0
  403. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +16 -17
  404. package/src/resources/extensions/gsd/tests/worktree-sync-tasks.test.ts +13 -9
  405. package/src/resources/extensions/gsd/tests/worktree.test.ts +26 -9
  406. package/src/resources/extensions/gsd/tests/zero-slice-roadmap-guided.test.ts +19 -0
  407. package/src/resources/extensions/gsd/tools/complete-slice.ts +13 -3
  408. package/src/resources/extensions/gsd/tools/complete-task.ts +16 -4
  409. package/src/resources/extensions/gsd/tools/plan-milestone.ts +11 -9
  410. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +5 -2
  411. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +152 -0
  412. package/src/resources/extensions/gsd/tools/reopen-slice.ts +27 -0
  413. package/src/resources/extensions/gsd/tools/reopen-task.ts +17 -0
  414. package/src/resources/extensions/gsd/triage-resolution.ts +29 -10
  415. package/src/resources/extensions/gsd/types.ts +4 -0
  416. package/src/resources/extensions/gsd/verification-evidence.ts +68 -0
  417. package/src/resources/extensions/gsd/workflow-logger.ts +13 -0
  418. package/src/resources/extensions/gsd/workflow-projections.ts +4 -6
  419. package/src/resources/extensions/gsd/workflow-reconcile.ts +2 -3
  420. package/src/resources/extensions/gsd/workflow-templates.ts +11 -2
  421. package/src/resources/extensions/gsd/worktree-manager.ts +4 -2
  422. package/src/resources/extensions/gsd/worktree.ts +10 -0
  423. package/src/resources/extensions/shared/interview-ui.ts +1 -1
  424. package/src/resources/extensions/shared/tests/interview-notes-loop.test.ts +8 -10
  425. package/dist/web/standalone/.next/static/F1mOwzgCW9R8N3Pt1Et87/_buildManifest.js +0 -1
  426. package/dist/web/standalone/.next/static/chunks/6502.7593d7797a4b3999.js +0 -9
  427. package/dist/web/standalone/.next/static/chunks/app/_global-error/page-c4cc189e7b117ea2.js +0 -1
  428. package/dist/web/standalone/.next/static/chunks/app/api/boot/route-c4cc189e7b117ea2.js +0 -1
  429. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/input/route-c4cc189e7b117ea2.js +0 -1
  430. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/resize/route-c4cc189e7b117ea2.js +0 -1
  431. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/stream/route-c4cc189e7b117ea2.js +0 -1
  432. package/dist/web/standalone/.next/static/chunks/app/api/browse-directories/route-c4cc189e7b117ea2.js +0 -1
  433. package/dist/web/standalone/.next/static/chunks/app/api/captures/route-c4cc189e7b117ea2.js +0 -1
  434. package/dist/web/standalone/.next/static/chunks/app/api/cleanup/route-c4cc189e7b117ea2.js +0 -1
  435. package/dist/web/standalone/.next/static/chunks/app/api/dev-mode/route-c4cc189e7b117ea2.js +0 -1
  436. package/dist/web/standalone/.next/static/chunks/app/api/doctor/route-c4cc189e7b117ea2.js +0 -1
  437. package/dist/web/standalone/.next/static/chunks/app/api/experimental/route-c4cc189e7b117ea2.js +0 -1
  438. package/dist/web/standalone/.next/static/chunks/app/api/export-data/route-c4cc189e7b117ea2.js +0 -1
  439. package/dist/web/standalone/.next/static/chunks/app/api/files/route-c4cc189e7b117ea2.js +0 -1
  440. package/dist/web/standalone/.next/static/chunks/app/api/forensics/route-c4cc189e7b117ea2.js +0 -1
  441. package/dist/web/standalone/.next/static/chunks/app/api/git/route-c4cc189e7b117ea2.js +0 -1
  442. package/dist/web/standalone/.next/static/chunks/app/api/history/route-c4cc189e7b117ea2.js +0 -1
  443. package/dist/web/standalone/.next/static/chunks/app/api/hooks/route-c4cc189e7b117ea2.js +0 -1
  444. package/dist/web/standalone/.next/static/chunks/app/api/inspect/route-c4cc189e7b117ea2.js +0 -1
  445. package/dist/web/standalone/.next/static/chunks/app/api/knowledge/route-c4cc189e7b117ea2.js +0 -1
  446. package/dist/web/standalone/.next/static/chunks/app/api/live-state/route-c4cc189e7b117ea2.js +0 -1
  447. package/dist/web/standalone/.next/static/chunks/app/api/onboarding/route-c4cc189e7b117ea2.js +0 -1
  448. package/dist/web/standalone/.next/static/chunks/app/api/preferences/route-c4cc189e7b117ea2.js +0 -1
  449. package/dist/web/standalone/.next/static/chunks/app/api/projects/route-c4cc189e7b117ea2.js +0 -1
  450. package/dist/web/standalone/.next/static/chunks/app/api/recovery/route-c4cc189e7b117ea2.js +0 -1
  451. package/dist/web/standalone/.next/static/chunks/app/api/remote-questions/route-c4cc189e7b117ea2.js +0 -1
  452. package/dist/web/standalone/.next/static/chunks/app/api/session/browser/route-c4cc189e7b117ea2.js +0 -1
  453. package/dist/web/standalone/.next/static/chunks/app/api/session/command/route-c4cc189e7b117ea2.js +0 -1
  454. package/dist/web/standalone/.next/static/chunks/app/api/session/events/route-c4cc189e7b117ea2.js +0 -1
  455. package/dist/web/standalone/.next/static/chunks/app/api/session/manage/route-c4cc189e7b117ea2.js +0 -1
  456. package/dist/web/standalone/.next/static/chunks/app/api/settings-data/route-c4cc189e7b117ea2.js +0 -1
  457. package/dist/web/standalone/.next/static/chunks/app/api/shutdown/route-c4cc189e7b117ea2.js +0 -1
  458. package/dist/web/standalone/.next/static/chunks/app/api/skill-health/route-c4cc189e7b117ea2.js +0 -1
  459. package/dist/web/standalone/.next/static/chunks/app/api/steer/route-c4cc189e7b117ea2.js +0 -1
  460. package/dist/web/standalone/.next/static/chunks/app/api/switch-root/route-c4cc189e7b117ea2.js +0 -1
  461. package/dist/web/standalone/.next/static/chunks/app/api/terminal/input/route-c4cc189e7b117ea2.js +0 -1
  462. package/dist/web/standalone/.next/static/chunks/app/api/terminal/resize/route-c4cc189e7b117ea2.js +0 -1
  463. package/dist/web/standalone/.next/static/chunks/app/api/terminal/sessions/route-c4cc189e7b117ea2.js +0 -1
  464. package/dist/web/standalone/.next/static/chunks/app/api/terminal/stream/route-c4cc189e7b117ea2.js +0 -1
  465. package/dist/web/standalone/.next/static/chunks/app/api/terminal/upload/route-c4cc189e7b117ea2.js +0 -1
  466. package/dist/web/standalone/.next/static/chunks/app/api/undo/route-c4cc189e7b117ea2.js +0 -1
  467. package/dist/web/standalone/.next/static/chunks/app/api/update/route-c4cc189e7b117ea2.js +0 -1
  468. package/dist/web/standalone/.next/static/chunks/app/api/visualizer/route-c4cc189e7b117ea2.js +0 -1
  469. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-c4cc189e7b117ea2.js +0 -1
  470. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-c4cc189e7b117ea2.js +0 -1
  471. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-c4cc189e7b117ea2.js +0 -1
  472. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-c4cc189e7b117ea2.js +0 -1
  473. /package/dist/web/standalone/.next/static/{F1mOwzgCW9R8N3Pt1Et87 → Z3TgDP0c7kG9j8CVQVGcl}/_ssgManifest.js +0 -0
@@ -187,8 +187,17 @@ export async function handleCompleteSlice(params, basePath) {
187
187
  if (ownershipErr) {
188
188
  return { error: ownershipErr };
189
189
  }
190
+ // ── Verification content gate (#3580) ──────────────────────────────────
191
+ // Reject completion when the provided verification/UAT clearly indicates
192
+ // the slice is blocked or failed. Prevents prompt regressions from
193
+ // silently advancing blocked slices.
194
+ const BLOCKED_SIGNALS = /\b(status:\s*blocked|verification_result:\s*failed|slice is blocked|cannot complete|verification failed)\b/i;
195
+ if (BLOCKED_SIGNALS.test(params.verification || "") || BLOCKED_SIGNALS.test(params.uatContent || "")) {
196
+ return { error: `slice verification indicates blocked/failed state — do not complete a slice that has not passed verification. Address the blockers and re-verify first.` };
197
+ }
190
198
  // ── Guards + DB writes inside a single transaction (prevents TOCTOU) ───
191
199
  const completedAt = new Date().toISOString();
200
+ const originalSliceStatus = getSlice(params.milestoneId, params.sliceId)?.status ?? "pending";
192
201
  let guardError = null;
193
202
  transaction(() => {
194
203
  // State machine preconditions (inside txn for atomicity).
@@ -217,8 +226,8 @@ export async function handleCompleteSlice(params, basePath) {
217
226
  return;
218
227
  }
219
228
  // All guards passed — perform writes
220
- insertMilestone({ id: params.milestoneId });
221
- insertSlice({ id: params.sliceId, milestoneId: params.milestoneId });
229
+ insertMilestone({ id: params.milestoneId, title: params.milestoneId });
230
+ insertSlice({ id: params.sliceId, milestoneId: params.milestoneId, title: params.sliceId });
222
231
  updateSliceStatus(params.milestoneId, params.sliceId, "complete", completedAt);
223
232
  });
224
233
  if (guardError) {
@@ -256,7 +265,7 @@ export async function handleCompleteSlice(params, basePath) {
256
265
  catch (renderErr) {
257
266
  // Disk render failed — roll back DB status so state stays consistent
258
267
  logWarning("tool", `complete_slice — disk render failed for ${params.milestoneId}/${params.sliceId}, rolling back DB status`, { error: renderErr.message });
259
- updateSliceStatus(params.milestoneId, params.sliceId, 'pending');
268
+ updateSliceStatus(params.milestoneId, params.sliceId, originalSliceStatus);
260
269
  invalidateStateCache();
261
270
  return { error: `disk render failed: ${renderErr.message}` };
262
271
  }
@@ -19,6 +19,18 @@ import { renderAllProjections, renderSummaryContent } from "../workflow-projecti
19
19
  import { writeManifest } from "../workflow-manifest.js";
20
20
  import { appendEvent } from "../workflow-events.js";
21
21
  import { logWarning } from "../workflow-logger.js";
22
+ /**
23
+ * Normalize a list parameter that may arrive as a string (newline-delimited
24
+ * bullet list from the LLM) into a string array (#3361).
25
+ */
26
+ function normalizeListParam(value) {
27
+ if (Array.isArray(value))
28
+ return value.map(String);
29
+ if (typeof value === "string" && value.trim()) {
30
+ return value.split(/\n/).map(s => s.replace(/^[\s\-*•]+/, "").trim()).filter(Boolean);
31
+ }
32
+ return [];
33
+ }
22
34
  /**
23
35
  * Build a TaskRow-shaped object from CompleteTaskParams so the unified
24
36
  * renderSummaryContent() can be used at completion time (#2720).
@@ -38,8 +50,8 @@ function paramsToTaskRow(params, completedAt) {
38
50
  blocker_discovered: params.blockerDiscovered ?? false,
39
51
  deviations: params.deviations ?? "",
40
52
  known_issues: params.knownIssues ?? "",
41
- key_files: params.keyFiles ?? [],
42
- key_decisions: params.keyDecisions ?? [],
53
+ key_files: normalizeListParam(params.keyFiles),
54
+ key_decisions: normalizeListParam(params.keyDecisions),
43
55
  full_summary_md: "",
44
56
  description: "",
45
57
  estimate: "",
@@ -101,8 +113,8 @@ export async function handleCompleteTask(params, basePath) {
101
113
  return;
102
114
  }
103
115
  // All guards passed — perform writes
104
- insertMilestone({ id: params.milestoneId });
105
- insertSlice({ id: params.sliceId, milestoneId: params.milestoneId });
116
+ insertMilestone({ id: params.milestoneId, title: params.milestoneId });
117
+ insertSlice({ id: params.sliceId, milestoneId: params.milestoneId, title: params.sliceId });
106
118
  insertTask({
107
119
  id: params.taskId,
108
120
  sliceId: params.sliceId,
@@ -113,10 +113,10 @@ function validateParams(params) {
113
113
  successCriteria: params.successCriteria ? validateStringArray(params.successCriteria, "successCriteria") : [],
114
114
  keyRisks: params.keyRisks ? validateRiskEntries(params.keyRisks) : [],
115
115
  proofStrategy: params.proofStrategy ? validateProofStrategy(params.proofStrategy) : [],
116
- verificationContract: params.verificationContract ?? "Not provided.",
117
- verificationIntegration: params.verificationIntegration ?? "Not provided.",
118
- verificationOperational: params.verificationOperational ?? "Not provided.",
119
- verificationUat: params.verificationUat ?? "Not provided.",
116
+ verificationContract: params.verificationContract ?? "",
117
+ verificationIntegration: params.verificationIntegration ?? "",
118
+ verificationOperational: params.verificationOperational ?? "",
119
+ verificationUat: params.verificationUat ?? "",
120
120
  definitionOfDone: params.definitionOfDone ? validateStringArray(params.definitionOfDone, "definitionOfDone") : [],
121
121
  requirementCoverage: params.requirementCoverage ?? "Not provided.",
122
122
  boundaryMapMarkdown: params.boundaryMapMarkdown ?? "Not provided.",
@@ -191,7 +191,8 @@ export async function handlePlanMilestone(rawParams, basePath) {
191
191
  requirementCoverage: params.requirementCoverage,
192
192
  boundaryMapMarkdown: params.boundaryMapMarkdown,
193
193
  });
194
- for (const slice of params.slices) {
194
+ for (let i = 0; i < params.slices.length; i++) {
195
+ const slice = params.slices[i];
195
196
  // Preserve completed/done status on re-plan (#2558).
196
197
  // Without this, a re-plan after milestone transition would reset
197
198
  // already-completed slices back to "pending".
@@ -207,6 +208,7 @@ export async function handlePlanMilestone(rawParams, basePath) {
207
208
  risk: slice.risk,
208
209
  depends: slice.depends,
209
210
  demo: slice.demo,
211
+ sequence: i + 1, // Preserve agent-ordered sequence (#3356)
210
212
  });
211
213
  upsertSlicePlanning(params.milestoneId, slice.sliceId, {
212
214
  goal: slice.goal,
@@ -129,8 +129,10 @@ export async function handleReassessRoadmap(rawParams, basePath) {
129
129
  demo: mod.demo,
130
130
  });
131
131
  }
132
- // Insert new slices
133
- for (const added of params.sliceChanges.added) {
132
+ // Insert new slices — assign sequence after existing slices (#3356)
133
+ const existingCount = getMilestoneSlices(params.milestoneId).length;
134
+ for (let i = 0; i < params.sliceChanges.added.length; i++) {
135
+ const added = params.sliceChanges.added[i];
134
136
  insertSlice({
135
137
  id: added.sliceId,
136
138
  milestoneId: params.milestoneId,
@@ -139,6 +141,7 @@ export async function handleReassessRoadmap(rawParams, basePath) {
139
141
  risk: added.risk,
140
142
  depends: added.depends,
141
143
  demo: added.demo ?? "",
144
+ sequence: existingCount + i + 1,
142
145
  });
143
146
  }
144
147
  // Delete removed slices
@@ -0,0 +1,119 @@
1
+ // GSD — reopen-milestone tool handler
2
+ /**
3
+ * reopen-milestone handler — the core operation behind gsd_milestone_reopen.
4
+ *
5
+ * Resets a closed milestone back to "active", all of its slices to
6
+ * "in_progress", and all tasks to "pending". Cleans up stale filesystem
7
+ * artifacts so the DB-filesystem reconciler does not auto-correct
8
+ * entities back to "complete".
9
+ */
10
+ import { getMilestone, getMilestoneSlices, getSliceTasks, updateMilestoneStatus, updateSliceStatus, updateTaskStatus, transaction, } from "../gsd-db.js";
11
+ import { invalidateStateCache } from "../state.js";
12
+ import { isClosedStatus } from "../status-guards.js";
13
+ import { renderAllProjections } from "../workflow-projections.js";
14
+ import { writeManifest } from "../workflow-manifest.js";
15
+ import { appendEvent } from "../workflow-events.js";
16
+ import { logWarning } from "../workflow-logger.js";
17
+ import { debugLog } from "../debug-logger.js";
18
+ import { existsSync, unlinkSync } from "node:fs";
19
+ import { join } from "node:path";
20
+ import { resolveMilestonePath, resolveSlicePath, resolveTasksDir, clearPathCache } from "../paths.js";
21
+ export async function handleReopenMilestone(params, basePath) {
22
+ // ── Validate required fields ────────────────────────────────────────────
23
+ if (!params.milestoneId || typeof params.milestoneId !== "string" || params.milestoneId.trim() === "") {
24
+ return { error: "milestoneId is required and must be a non-empty string" };
25
+ }
26
+ // ── Guards + DB writes inside a single transaction (prevents TOCTOU) ───
27
+ let guardError = null;
28
+ let slicesResetCount = 0;
29
+ let tasksResetCount = 0;
30
+ transaction(() => {
31
+ const milestone = getMilestone(params.milestoneId);
32
+ if (!milestone) {
33
+ guardError = `milestone not found: ${params.milestoneId}`;
34
+ return;
35
+ }
36
+ if (!isClosedStatus(milestone.status)) {
37
+ guardError = `milestone ${params.milestoneId} is not closed (status: ${milestone.status}) — nothing to reopen`;
38
+ return;
39
+ }
40
+ updateMilestoneStatus(params.milestoneId, "active", null);
41
+ const slices = getMilestoneSlices(params.milestoneId);
42
+ slicesResetCount = slices.length;
43
+ for (const slice of slices) {
44
+ updateSliceStatus(params.milestoneId, slice.id, "in_progress");
45
+ const tasks = getSliceTasks(params.milestoneId, slice.id);
46
+ tasksResetCount += tasks.length;
47
+ for (const task of tasks) {
48
+ updateTaskStatus(params.milestoneId, slice.id, task.id, "pending");
49
+ }
50
+ }
51
+ });
52
+ if (guardError) {
53
+ return { error: guardError };
54
+ }
55
+ // ── Invalidate caches ────────────────────────────────────────────────────
56
+ invalidateStateCache();
57
+ // ── Clean up stale filesystem artifacts (M12 fix) ────────────────────────
58
+ // Without this, the DB-filesystem reconciler sees SUMMARY.md files and
59
+ // auto-corrects entities back to "complete", making reopen a no-op (#3161).
60
+ try {
61
+ const milestoneDir = resolveMilestonePath(basePath, params.milestoneId);
62
+ if (milestoneDir) {
63
+ const milestoneSummary = join(milestoneDir, `${params.milestoneId}-SUMMARY.md`);
64
+ if (existsSync(milestoneSummary))
65
+ unlinkSync(milestoneSummary);
66
+ }
67
+ const slices = getMilestoneSlices(params.milestoneId);
68
+ for (const slice of slices) {
69
+ const sliceDir = resolveSlicePath(basePath, params.milestoneId, slice.id);
70
+ if (sliceDir) {
71
+ const sliceSummary = join(sliceDir, `${slice.id}-SUMMARY.md`);
72
+ if (existsSync(sliceSummary))
73
+ unlinkSync(sliceSummary);
74
+ const sliceUat = join(sliceDir, `${slice.id}-UAT.md`);
75
+ if (existsSync(sliceUat))
76
+ unlinkSync(sliceUat);
77
+ }
78
+ const tasksDir = resolveTasksDir(basePath, params.milestoneId, slice.id);
79
+ if (tasksDir) {
80
+ const tasks = getSliceTasks(params.milestoneId, slice.id);
81
+ for (const task of tasks) {
82
+ const taskSummary = join(tasksDir, `${task.id}-SUMMARY.md`);
83
+ if (existsSync(taskSummary))
84
+ unlinkSync(taskSummary);
85
+ }
86
+ }
87
+ }
88
+ }
89
+ catch (err) {
90
+ debugLog("reopen-milestone-cleanup-failed", { milestoneId: params.milestoneId, error: String(err) });
91
+ }
92
+ clearPathCache();
93
+ // ── Post-mutation hook ───────────────────────────────────────────────────
94
+ try {
95
+ await renderAllProjections(basePath, params.milestoneId);
96
+ writeManifest(basePath);
97
+ appendEvent(basePath, {
98
+ cmd: "reopen-milestone",
99
+ params: {
100
+ milestoneId: params.milestoneId,
101
+ reason: params.reason ?? null,
102
+ slicesReset: slicesResetCount,
103
+ tasksReset: tasksResetCount,
104
+ },
105
+ ts: new Date().toISOString(),
106
+ actor: "agent",
107
+ actor_name: params.actorName,
108
+ trigger_reason: params.triggerReason,
109
+ });
110
+ }
111
+ catch (hookErr) {
112
+ logWarning("tool", `reopen-milestone post-mutation hook warning: ${hookErr.message}`);
113
+ }
114
+ return {
115
+ milestoneId: params.milestoneId,
116
+ slicesReset: slicesResetCount,
117
+ tasksReset: tasksResetCount,
118
+ };
119
+ }
@@ -16,6 +16,9 @@ import { renderAllProjections } from "../workflow-projections.js";
16
16
  import { writeManifest } from "../workflow-manifest.js";
17
17
  import { appendEvent } from "../workflow-events.js";
18
18
  import { logWarning } from "../workflow-logger.js";
19
+ import { existsSync, unlinkSync } from "node:fs";
20
+ import { join } from "node:path";
21
+ import { resolveTasksDir, resolveSlicePath, clearPathCache } from "../paths.js";
19
22
  export async function handleReopenSlice(params, basePath) {
20
23
  // ── Validate required fields ────────────────────────────────────────────
21
24
  if (!params.sliceId || typeof params.sliceId !== "string" || params.sliceId.trim() === "") {
@@ -59,6 +62,33 @@ export async function handleReopenSlice(params, basePath) {
59
62
  }
60
63
  // ── Invalidate caches ────────────────────────────────────────────────────
61
64
  invalidateStateCache();
65
+ // ── Clean up stale filesystem artifacts (M12 fix) ────────────────────────
66
+ // Without this, the DB-filesystem reconciler sees SUMMARY.md files and
67
+ // auto-corrects tasks back to "complete", making reopen a no-op (#3161).
68
+ try {
69
+ const tasksDir = resolveTasksDir(basePath, params.milestoneId, params.sliceId);
70
+ if (tasksDir) {
71
+ const tasks = getSliceTasks(params.milestoneId, params.sliceId);
72
+ for (const task of tasks) {
73
+ const summaryPath = join(tasksDir, `${task.id}-SUMMARY.md`);
74
+ if (existsSync(summaryPath))
75
+ unlinkSync(summaryPath);
76
+ }
77
+ }
78
+ const sliceDir = resolveSlicePath(basePath, params.milestoneId, params.sliceId);
79
+ if (sliceDir) {
80
+ const sliceSummary = join(sliceDir, `${params.sliceId}-SUMMARY.md`);
81
+ if (existsSync(sliceSummary))
82
+ unlinkSync(sliceSummary);
83
+ const sliceUat = join(sliceDir, `${params.sliceId}-UAT.md`);
84
+ if (existsSync(sliceUat))
85
+ unlinkSync(sliceUat);
86
+ }
87
+ }
88
+ catch (cleanupErr) {
89
+ logWarning("tool", `reopen-slice artifact cleanup warning: ${cleanupErr.message}`);
90
+ }
91
+ clearPathCache();
62
92
  // ── Post-mutation hook ───────────────────────────────────────────────────
63
93
  try {
64
94
  await renderAllProjections(basePath, params.milestoneId);
@@ -15,6 +15,9 @@ import { renderAllProjections } from "../workflow-projections.js";
15
15
  import { writeManifest } from "../workflow-manifest.js";
16
16
  import { appendEvent } from "../workflow-events.js";
17
17
  import { logWarning } from "../workflow-logger.js";
18
+ import { existsSync, unlinkSync } from "node:fs";
19
+ import { join } from "node:path";
20
+ import { resolveTasksDir, clearPathCache } from "../paths.js";
18
21
  export async function handleReopenTask(params, basePath) {
19
22
  // ── Validate required fields ────────────────────────────────────────────
20
23
  if (!params.taskId || typeof params.taskId !== "string" || params.taskId.trim() === "") {
@@ -63,6 +66,21 @@ export async function handleReopenTask(params, basePath) {
63
66
  }
64
67
  // ── Invalidate caches ────────────────────────────────────────────────────
65
68
  invalidateStateCache();
69
+ // ── Clean up stale filesystem artifacts (M12 fix) ────────────────────────
70
+ // Without this, the DB-filesystem reconciler sees the SUMMARY.md and
71
+ // auto-corrects the task back to "complete", making reopen a no-op (#3161).
72
+ try {
73
+ const tasksDir = resolveTasksDir(basePath, params.milestoneId, params.sliceId);
74
+ if (tasksDir) {
75
+ const summaryPath = join(tasksDir, `${params.taskId}-SUMMARY.md`);
76
+ if (existsSync(summaryPath))
77
+ unlinkSync(summaryPath);
78
+ }
79
+ }
80
+ catch (cleanupErr) {
81
+ logWarning("tool", `reopen-task artifact cleanup warning: ${cleanupErr.message}`);
82
+ }
83
+ clearPathCache();
66
84
  // ── Post-mutation hook ───────────────────────────────────────────────────
67
85
  try {
68
86
  await renderAllProjections(basePath, params.milestoneId);
@@ -373,13 +373,16 @@ export function executeTriageResolutions(basePath, mid, sid) {
373
373
  }
374
374
  }
375
375
  }
376
- // Also process deferred captures that target milestone IDs — create
377
- // milestone directories so deriveState() discovers them.
378
- const deferred = loadAllCaptures(basePath).filter(c => c.status === "resolved" && !c.executed && c.classification === "defer");
379
- if (deferred.length > 0) {
380
- // Group deferred captures by target milestone
376
+ // Also process deferred and milestone-class captures (#3542).
377
+ // A defer/milestone capture's "action" is the triage decision itself —
378
+ // once classified and resolved, the capture is done. The target milestone
379
+ // picks up the work naturally from its planning context.
380
+ const deferrable = loadAllCaptures(basePath).filter(c => c.status === "resolved" && !c.executed &&
381
+ (c.classification === "defer" || c.classification === "milestone"));
382
+ if (deferrable.length > 0) {
383
+ // Group captures that reference a specific milestone — create dirs as needed.
381
384
  const byMilestone = new Map();
382
- for (const cap of deferred) {
385
+ for (const cap of deferrable) {
383
386
  const target = cap.resolution?.match(/\b(M\d{3}(?:-[a-z0-9]{6})?)\b/)?.[1];
384
387
  if (target) {
385
388
  const list = byMilestone.get(target) ?? [];
@@ -394,12 +397,25 @@ export function executeTriageResolutions(basePath, mid, sid) {
394
397
  if (created) {
395
398
  result.deferredMilestones++;
396
399
  result.actions.push(`Created milestone ${milestoneId} for ${captures.length} deferred capture(s)`);
397
- for (const cap of captures) {
398
- markCaptureExecuted(basePath, cap.id);
399
- }
400
400
  }
401
401
  }
402
402
  }
403
+ // Stamp ALL defer/milestone captures as executed (#3542 gaps 1-3).
404
+ // Previously only captures that triggered dir creation were stamped.
405
+ // Captures without a milestone ID in resolution text, or targeting an
406
+ // existing directory, were silently dropped — never stamped.
407
+ for (const cap of deferrable) {
408
+ if (!cap.executed) {
409
+ markCaptureExecuted(basePath, cap.id);
410
+ }
411
+ }
412
+ }
413
+ // Mark note captures as executed — they're informational only, no action
414
+ // needed. Without this they stay in "resolved but not executed" limbo (#3578).
415
+ const notes = loadAllCaptures(basePath).filter(c => c.status === "resolved" && !c.executed && c.classification === "note");
416
+ for (const cap of notes) {
417
+ markCaptureExecuted(basePath, cap.id);
418
+ result.actions.push(`Note acknowledged: ${cap.id} — "${cap.text}"`);
403
419
  }
404
420
  if (actionable.length === 0)
405
421
  return result;
@@ -55,6 +55,24 @@ export function writeVerificationJSON(result, tasksDir, taskId, unitId, retryAtt
55
55
  const filePath = join(tasksDir, `${taskId}-VERIFY.json`);
56
56
  writeFileSync(filePath, JSON.stringify(evidence, null, 2) + "\n", "utf-8");
57
57
  }
58
+ /**
59
+ * Write pre-execution check results to a PRE-EXEC-VERIFY.json artifact
60
+ * in the slice directory.
61
+ */
62
+ export function writePreExecutionEvidence(result, sliceDir, milestoneId, sliceId) {
63
+ mkdirSync(sliceDir, { recursive: true });
64
+ const evidence = {
65
+ schemaVersion: 1,
66
+ milestoneId,
67
+ sliceId,
68
+ timestamp: Date.now(),
69
+ status: result.status,
70
+ durationMs: result.durationMs,
71
+ checks: result.checks,
72
+ };
73
+ const filePath = join(sliceDir, `${sliceId}-PRE-EXEC-VERIFY.json`);
74
+ writeFileSync(filePath, JSON.stringify(evidence, null, 2) + "\n", "utf-8");
75
+ }
58
76
  // ─── Markdown Evidence Table ─────────────────────────────────────────────────
59
77
  /**
60
78
  * Format duration in milliseconds as seconds with 1 decimal place.
@@ -17,6 +17,7 @@
17
17
  // Node process.
18
18
  import { appendFileSync, readFileSync, existsSync, mkdirSync } from "node:fs";
19
19
  import { join } from "node:path";
20
+ import { appendNotification } from "./notification-store.js";
20
21
  // ─── Buffer & Persistent Audit ──────────────────────────────────────────
21
22
  const MAX_BUFFER = 100;
22
23
  let _buffer = [];
@@ -179,6 +180,13 @@ function _push(severity, component, message, context) {
179
180
  const prefix = severity === "error" ? "ERROR" : "WARN";
180
181
  const ctxStr = context ? ` ${JSON.stringify(context)}` : "";
181
182
  process.stderr.write(`[gsd:${component}] ${prefix}: ${message}${ctxStr}\n`);
183
+ // Persist to notification store (both warnings and errors)
184
+ try {
185
+ appendNotification(`[${component}] ${message}`, severity === "error" ? "error" : "warning", "workflow-logger");
186
+ }
187
+ catch (notifErr) {
188
+ process.stderr.write(`[gsd:workflow-logger] notification-store append failed: ${notifErr.message}\n`);
189
+ }
182
190
  // Buffer for auto-loop to drain
183
191
  _buffer.push(entry);
184
192
  if (_buffer.length > MAX_BUFFER) {
@@ -324,13 +324,10 @@ export async function renderAllProjections(basePath, milestoneId) {
324
324
  // Query all slices for this milestone
325
325
  const sliceRows = getMilestoneSlices(milestoneId);
326
326
  for (const slice of sliceRows) {
327
- // Render PLAN.md for each slice
328
- try {
329
- renderPlanProjection(basePath, milestoneId, slice.id);
330
- }
331
- catch (err) {
332
- logWarning("projection", `renderPlanProjection failed for ${milestoneId}/${slice.id}: ${err.message}`);
333
- }
327
+ // PLAN.md is rendered by the authoritative markdown-renderer.js in
328
+ // plan-slice/replan-slice tools. Do NOT overwrite it here — the simplified
329
+ // projection is missing key sections (Must-Haves, Verification, Files
330
+ // Likely Touched) and corrupts multi-line task descriptions (#3651).
334
331
  // Render SUMMARY.md for each completed task
335
332
  const taskRows = getSliceTasks(milestoneId, slice.id);
336
333
  const doneTasks = taskRows.filter(t => t.status === "done" || t.status === "complete");
@@ -2,7 +2,7 @@ import { join } from "node:path";
2
2
  import { mkdirSync, existsSync, readFileSync, unlinkSync } from "node:fs";
3
3
  import { logWarning, logError } from "./workflow-logger.js";
4
4
  import { readEvents, findForkPoint, appendEvent, getSessionId } from "./workflow-events.js";
5
- import { transaction, updateTaskStatus, updateSliceStatus, getSliceTasks, insertVerificationEvidence, upsertDecision, openDatabase, } from "./gsd-db.js";
5
+ import { transaction, updateTaskStatus, updateSliceStatus, getSliceTasks, insertVerificationEvidence, upsertDecision, openDatabase, setTaskBlockerDiscovered, } from "./gsd-db.js";
6
6
  import { isClosedStatus } from "./status-guards.js";
7
7
  import { writeManifest } from "./workflow-manifest.js";
8
8
  import { atomicWriteSync } from "./atomic-write.js";
@@ -60,13 +60,11 @@ function replayEvents(events) {
60
60
  break;
61
61
  }
62
62
  case "report_blocker": {
63
- // report_blocker marks the task with blocker_discovered = 1
64
- // The DB helper updateTaskStatus doesn't handle blockers,
65
- // so we just update status to "blocked" as a best-effort replay.
66
63
  const milestoneId = p["milestoneId"];
67
64
  const sliceId = p["sliceId"];
68
65
  const taskId = p["taskId"];
69
66
  updateTaskStatus(milestoneId, sliceId, taskId, "blocked");
67
+ setTaskBlockerDiscovered(milestoneId, sliceId, taskId, true);
70
68
  break;
71
69
  }
72
70
  case "record_verification": {
@@ -29,8 +29,17 @@ let cachedRegistry = null;
29
29
  export function loadRegistry() {
30
30
  if (cachedRegistry)
31
31
  return cachedRegistry;
32
- const content = readFileSync(registryPath, "utf-8");
33
- cachedRegistry = JSON.parse(content);
32
+ if (!existsSync(registryPath)) {
33
+ cachedRegistry = { version: 1, templates: {} };
34
+ return cachedRegistry;
35
+ }
36
+ try {
37
+ const content = readFileSync(registryPath, "utf-8");
38
+ cachedRegistry = JSON.parse(content);
39
+ }
40
+ catch {
41
+ cachedRegistry = { version: 1, templates: {} };
42
+ }
34
43
  return cachedRegistry;
35
44
  }
36
45
  /**
@@ -44,7 +44,10 @@ function normalizePathForComparison(path) {
44
44
  export function resolveGitDir(basePath) {
45
45
  const gitPath = join(basePath, ".git");
46
46
  if (!existsSync(gitPath))
47
- return join(basePath, ".git");
47
+ return gitPath;
48
+ // In a normal repo .git is a directory — skip the file read (#3597)
49
+ if (lstatSync(gitPath).isDirectory())
50
+ return gitPath;
48
51
  try {
49
52
  const content = readFileSync(gitPath, "utf-8").trim();
50
53
  if (content.startsWith("gitdir: ")) {
@@ -54,7 +57,7 @@ export function resolveGitDir(basePath) {
54
57
  catch (e) {
55
58
  logWarning("worktree", `.git file read failed: ${e.message}`);
56
59
  }
57
- return join(basePath, ".git");
60
+ return gitPath;
58
61
  }
59
62
  export function worktreesDir(basePath) {
60
63
  return join(basePath, ".gsd", "worktrees");
@@ -34,6 +34,15 @@ function getService(basePath) {
34
34
  }
35
35
  return cachedService;
36
36
  }
37
+ /**
38
+ * Clear the cached GitServiceImpl. For testing only — forces the next
39
+ * getService() call to re-read preferences and create a fresh instance.
40
+ * @internal
41
+ */
42
+ export function _resetServiceCache() {
43
+ cachedService = null;
44
+ cachedBasePath = null;
45
+ }
37
46
  /**
38
47
  * Set the active milestone ID on the cached GitServiceImpl.
39
48
  * This enables integration branch resolution in getMainBranch().
@@ -204,7 +204,7 @@ export async function showInterviewRound(questions, opts, ctx) {
204
204
  // instead of being trapped in a re-asking loop (bug #2715).
205
205
  // Only auto-open if the user hasn't already provided notes —
206
206
  // otherwise Enter from notes mode loops back here endlessly.
207
- if (!isMultiSelect(currentIdx) && states[currentIdx].cursorIndex === noneOrDoneIdx(currentIdx) && !states[currentIdx].notes) {
207
+ if (!isMultiSelect(currentIdx) && states[currentIdx].cursorIndex === noneOrDoneIdx(currentIdx) && !states[currentIdx].notes && !states[currentIdx].notesVisible) {
208
208
  states[currentIdx].notesVisible = true;
209
209
  focusNotes = true;
210
210
  loadStateToEditor();
@@ -1 +1 @@
1
- F1mOwzgCW9R8N3Pt1Et87
1
+ Z3TgDP0c7kG9j8CVQVGcl
@@ -1,46 +1,47 @@
1
1
  {
2
2
  "/_global-error/page": "/_global-error",
3
3
  "/_not-found/page": "/_not-found",
4
+ "/api/bridge-terminal/input/route": "/api/bridge-terminal/input",
4
5
  "/api/boot/route": "/api/boot",
5
6
  "/api/bridge-terminal/resize/route": "/api/bridge-terminal/resize",
6
- "/api/bridge-terminal/input/route": "/api/bridge-terminal/input",
7
7
  "/api/bridge-terminal/stream/route": "/api/bridge-terminal/stream",
8
8
  "/api/cleanup/route": "/api/cleanup",
9
9
  "/api/dev-mode/route": "/api/dev-mode",
10
- "/api/doctor/route": "/api/doctor",
11
- "/api/captures/route": "/api/captures",
10
+ "/api/browse-directories/route": "/api/browse-directories",
12
11
  "/api/export-data/route": "/api/export-data",
12
+ "/api/captures/route": "/api/captures",
13
+ "/api/doctor/route": "/api/doctor",
13
14
  "/api/forensics/route": "/api/forensics",
14
15
  "/api/history/route": "/api/history",
15
- "/api/experimental/route": "/api/experimental",
16
16
  "/api/git/route": "/api/git",
17
- "/api/hooks/route": "/api/hooks",
18
17
  "/api/inspect/route": "/api/inspect",
19
- "/api/browse-directories/route": "/api/browse-directories",
18
+ "/api/hooks/route": "/api/hooks",
19
+ "/api/experimental/route": "/api/experimental",
20
+ "/api/notifications/route": "/api/notifications",
21
+ "/api/live-state/route": "/api/live-state",
20
22
  "/api/knowledge/route": "/api/knowledge",
23
+ "/api/recovery/route": "/api/recovery",
21
24
  "/api/preferences/route": "/api/preferences",
22
- "/api/live-state/route": "/api/live-state",
25
+ "/api/session/browser/route": "/api/session/browser",
23
26
  "/api/onboarding/route": "/api/onboarding",
27
+ "/api/session/command/route": "/api/session/command",
24
28
  "/api/projects/route": "/api/projects",
25
- "/api/recovery/route": "/api/recovery",
26
- "/api/session/browser/route": "/api/session/browser",
27
29
  "/api/session/events/route": "/api/session/events",
28
- "/api/session/command/route": "/api/session/command",
29
- "/api/session/manage/route": "/api/session/manage",
30
+ "/api/shutdown/route": "/api/shutdown",
30
31
  "/api/settings-data/route": "/api/settings-data",
31
- "/api/files/route": "/api/files",
32
32
  "/api/skill-health/route": "/api/skill-health",
33
- "/api/shutdown/route": "/api/shutdown",
34
33
  "/api/steer/route": "/api/steer",
35
- "/api/terminal/resize/route": "/api/terminal/resize",
34
+ "/api/session/manage/route": "/api/session/manage",
36
35
  "/api/terminal/input/route": "/api/terminal/input",
36
+ "/api/terminal/resize/route": "/api/terminal/resize",
37
37
  "/api/switch-root/route": "/api/switch-root",
38
- "/api/visualizer/route": "/api/visualizer",
38
+ "/api/terminal/sessions/route": "/api/terminal/sessions",
39
39
  "/api/terminal/stream/route": "/api/terminal/stream",
40
40
  "/api/undo/route": "/api/undo",
41
- "/api/terminal/sessions/route": "/api/terminal/sessions",
41
+ "/api/update/route": "/api/update",
42
+ "/api/files/route": "/api/files",
42
43
  "/api/terminal/upload/route": "/api/terminal/upload",
44
+ "/api/visualizer/route": "/api/visualizer",
43
45
  "/api/remote-questions/route": "/api/remote-questions",
44
- "/api/update/route": "/api/update",
45
46
  "/page": "/"
46
47
  }
@@ -4,11 +4,11 @@
4
4
  ],
5
5
  "devFiles": [],
6
6
  "lowPriorityFiles": [
7
- "static/F1mOwzgCW9R8N3Pt1Et87/_buildManifest.js",
8
- "static/F1mOwzgCW9R8N3Pt1Et87/_ssgManifest.js"
7
+ "static/Z3TgDP0c7kG9j8CVQVGcl/_buildManifest.js",
8
+ "static/Z3TgDP0c7kG9j8CVQVGcl/_ssgManifest.js"
9
9
  ],
10
10
  "rootMainFiles": [
11
- "static/chunks/webpack-a1c1e452c6b32d04.js",
11
+ "static/chunks/webpack-9fed74684e1c5bb1.js",
12
12
  "static/chunks/4bd1b696-e5d7c65570c947b7.js",
13
13
  "static/chunks/3794-337d1ca25ad99a89.js",
14
14
  "static/chunks/main-app-fdab67f7802d7832.js"