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
@@ -0,0 +1,471 @@
1
+ /**
2
+ * Pre-Execution Checks — Validate task plans before execution begins.
3
+ *
4
+ * Runs these checks against a slice's task plan:
5
+ * 1. Package existence — npm view calls in parallel with timeout
6
+ * 2. File path consistency — verify files exist or are in prior expected_output
7
+ * 3. Task ordering — detect impossible ordering (task reads file created later)
8
+ * 4. Interface contracts — detect contradictory function signatures (warn only)
9
+ *
10
+ * Design principles:
11
+ * - Pure functions taking (tasks: TaskRow[], basePath: string) for testability
12
+ * - Network failures warn, don't fail (R012 conservative design)
13
+ * - Total execution <2s target (R013)
14
+ * - No AST parsers — interface parsing is heuristic (regex on code blocks)
15
+ */
16
+ import { existsSync } from "node:fs";
17
+ import { spawn } from "node:child_process";
18
+ import { resolve } from "node:path";
19
+ // ─── Package Existence Check ─────────────────────────────────────────────────
20
+ /**
21
+ * Extract npm package names from task descriptions.
22
+ * Looks for:
23
+ * - `npm install <pkg>` patterns
24
+ * - Code blocks with `require('<pkg>')` or `import ... from '<pkg>'`
25
+ * - Explicit mentions like "uses lodash" or "package: axios"
26
+ */
27
+ export function extractPackageReferences(description) {
28
+ const packages = new Set();
29
+ // Common words that aren't package names but might appear after install
30
+ const stopwords = new Set([
31
+ "then", "and", "the", "to", "a", "an", "in", "for", "with", "from", "or",
32
+ "npm", "yarn", "pnpm", "i", // Don't capture the command itself
33
+ ]);
34
+ // npm install <pkg> patterns (handles npm i, npm add, yarn add, pnpm add)
35
+ // Use a global pattern to find all install commands, then parse following tokens
36
+ const installCmdPattern = /(?:npm\s+(?:install|i|add)|yarn\s+add|pnpm\s+add)\s+/g;
37
+ let cmdMatch;
38
+ while ((cmdMatch = installCmdPattern.exec(description)) !== null) {
39
+ // Start after the install command
40
+ const afterCmd = description.slice(cmdMatch.index + cmdMatch[0].length);
41
+ // Match package-like tokens (alphanumeric, @, /, -, _) until we hit
42
+ // something that's not a package (non-token char after whitespace)
43
+ const tokenPattern = /^([@a-zA-Z][a-zA-Z0-9@/_-]*)(?:\s+|$)/;
44
+ let remaining = afterCmd;
45
+ while (remaining.length > 0) {
46
+ // Skip any flags like -D, --save-dev
47
+ const flagMatch = remaining.match(/^(-[a-zA-Z-]+)\s*/);
48
+ if (flagMatch) {
49
+ remaining = remaining.slice(flagMatch[0].length);
50
+ continue;
51
+ }
52
+ // Try to match a package name
53
+ const pkgMatch = remaining.match(tokenPattern);
54
+ if (pkgMatch) {
55
+ const token = pkgMatch[1];
56
+ // Skip stopwords - they indicate end of package list
57
+ if (stopwords.has(token.toLowerCase())) {
58
+ break;
59
+ }
60
+ packages.add(normalizePackageName(token));
61
+ remaining = remaining.slice(pkgMatch[0].length);
62
+ }
63
+ else {
64
+ // Not a package name, stop parsing this install command
65
+ break;
66
+ }
67
+ }
68
+ }
69
+ // require('pkg') or import from 'pkg' in code blocks
70
+ const importPattern = /(?:require\s*\(\s*['"]|from\s+['"])([a-zA-Z0-9@/_-]+)['"\)]/g;
71
+ let importMatch;
72
+ while ((importMatch = importPattern.exec(description)) !== null) {
73
+ // Skip relative imports and node builtins
74
+ const pkg = importMatch[1];
75
+ if (!pkg.startsWith(".") && !pkg.startsWith("node:")) {
76
+ packages.add(normalizePackageName(pkg));
77
+ }
78
+ }
79
+ return Array.from(packages);
80
+ }
81
+ /**
82
+ * Normalize package name to registry-checkable form.
83
+ * Handles scoped packages (@org/pkg) and subpaths (pkg/subpath → pkg).
84
+ */
85
+ function normalizePackageName(raw) {
86
+ // Scoped package: @org/pkg or @org/pkg/subpath
87
+ if (raw.startsWith("@")) {
88
+ const parts = raw.split("/");
89
+ return parts.length >= 2 ? `${parts[0]}/${parts[1]}` : raw;
90
+ }
91
+ // Regular package: pkg or pkg/subpath
92
+ return raw.split("/")[0];
93
+ }
94
+ /**
95
+ * Check if a package exists on npm registry.
96
+ * Returns null on success, error message on failure.
97
+ * Times out after timeoutMs (default 5000ms).
98
+ */
99
+ async function checkPackageOnNpm(packageName, timeoutMs = 5000) {
100
+ return new Promise((resolve) => {
101
+ const child = spawn("npm", ["view", packageName, "name"], {
102
+ stdio: ["ignore", "pipe", "pipe"],
103
+ timeout: timeoutMs,
104
+ });
105
+ let stdout = "";
106
+ let stderr = "";
107
+ child.stdout.on("data", (data) => {
108
+ stdout += data.toString();
109
+ });
110
+ child.stderr.on("data", (data) => {
111
+ stderr += data.toString();
112
+ });
113
+ const timer = setTimeout(() => {
114
+ child.kill("SIGTERM");
115
+ resolve({ exists: false, error: `Timeout after ${timeoutMs}ms` });
116
+ }, timeoutMs);
117
+ child.on("close", (code) => {
118
+ clearTimeout(timer);
119
+ if (code === 0 && stdout.trim()) {
120
+ resolve({ exists: true });
121
+ }
122
+ else if (stderr.includes("404") || stderr.includes("not found")) {
123
+ resolve({ exists: false, error: `Package not found: ${packageName}` });
124
+ }
125
+ else if (code !== 0) {
126
+ // Network error or other issue — warn, don't fail
127
+ resolve({ exists: true, error: `npm view failed (code ${code}): ${stderr.slice(0, 100)}` });
128
+ }
129
+ else {
130
+ resolve({ exists: true });
131
+ }
132
+ });
133
+ child.on("error", (err) => {
134
+ clearTimeout(timer);
135
+ resolve({ exists: true, error: `npm spawn error: ${err.message}` });
136
+ });
137
+ });
138
+ }
139
+ /**
140
+ * Check all package references in tasks for existence on npm.
141
+ * Runs checks in parallel with a 5s timeout per package.
142
+ * Network failures warn but don't fail (R012 conservative design).
143
+ */
144
+ export async function checkPackageExistence(tasks, _basePath) {
145
+ const results = [];
146
+ const packagesToCheck = new Set();
147
+ // Collect all package references from task descriptions
148
+ for (const task of tasks) {
149
+ const packages = extractPackageReferences(task.description);
150
+ for (const pkg of packages) {
151
+ packagesToCheck.add(pkg);
152
+ }
153
+ }
154
+ if (packagesToCheck.size === 0) {
155
+ return results;
156
+ }
157
+ // Check packages in parallel
158
+ const checkPromises = Array.from(packagesToCheck).map(async (pkg) => {
159
+ const result = await checkPackageOnNpm(pkg);
160
+ return { pkg, result };
161
+ });
162
+ const checkResults = await Promise.all(checkPromises);
163
+ for (const { pkg, result } of checkResults) {
164
+ if (!result.exists && !result.error?.includes("Timeout") && !result.error?.includes("spawn error")) {
165
+ // Package genuinely doesn't exist — blocking failure
166
+ results.push({
167
+ category: "package",
168
+ target: pkg,
169
+ passed: false,
170
+ message: result.error || `Package '${pkg}' not found on npm`,
171
+ blocking: true,
172
+ });
173
+ }
174
+ else if (result.error) {
175
+ // Network issue or timeout — warn but don't block
176
+ results.push({
177
+ category: "package",
178
+ target: pkg,
179
+ passed: true,
180
+ message: `Warning: ${result.error}`,
181
+ blocking: false,
182
+ });
183
+ }
184
+ // Silent success for existing packages — no need to report
185
+ }
186
+ return results;
187
+ }
188
+ // ─── File Path Consistency Check ─────────────────────────────────────────────
189
+ /**
190
+ * Normalize a file path for consistent comparison.
191
+ * - Strips leading ./
192
+ * - Normalizes path separators to forward slashes
193
+ * - Resolves redundant segments (e.g., foo/../bar → bar)
194
+ *
195
+ * This ensures that "./src/a.ts", "src/a.ts", and "src//a.ts" all compare equal.
196
+ */
197
+ export function normalizeFilePath(filePath) {
198
+ if (!filePath)
199
+ return filePath;
200
+ // Strip backtick wrapping from LLM-generated paths (#3649)
201
+ let normalized = filePath.replace(/`/g, "");
202
+ // Normalize path separators to forward slashes
203
+ normalized = normalized.replace(/\\/g, "/");
204
+ // Remove leading ./
205
+ while (normalized.startsWith("./")) {
206
+ normalized = normalized.slice(2);
207
+ }
208
+ // Remove duplicate slashes
209
+ normalized = normalized.replace(/\/+/g, "/");
210
+ // Remove trailing slash unless it's the root
211
+ if (normalized.length > 1 && normalized.endsWith("/")) {
212
+ normalized = normalized.slice(0, -1);
213
+ }
214
+ return normalized;
215
+ }
216
+ /**
217
+ * Build a set of files that will be created by tasks up to (but not including) taskIndex.
218
+ * All paths are normalized for consistent comparison.
219
+ */
220
+ function getExpectedOutputsUpTo(tasks, taskIndex) {
221
+ const outputs = new Set();
222
+ for (let i = 0; i < taskIndex; i++) {
223
+ for (const file of tasks[i].expected_output) {
224
+ outputs.add(normalizeFilePath(file));
225
+ }
226
+ }
227
+ return outputs;
228
+ }
229
+ /**
230
+ * Check that all files referenced in task.inputs either:
231
+ * 1. Exist on disk, OR
232
+ * 2. Are in a prior task's expected_output
233
+ *
234
+ * task.files ("files likely touched") is excluded — it intentionally includes
235
+ * files the task will create, so they don't need to pre-exist (#3626).
236
+ *
237
+ * All paths are normalized before comparison to ensure ./src/a.ts matches src/a.ts.
238
+ */
239
+ export function checkFilePathConsistency(tasks, basePath) {
240
+ const results = [];
241
+ for (let i = 0; i < tasks.length; i++) {
242
+ const task = tasks[i];
243
+ const priorOutputs = getExpectedOutputsUpTo(tasks, i);
244
+ const filesToCheck = [...task.inputs];
245
+ for (const file of filesToCheck) {
246
+ // Skip empty strings
247
+ if (!file.trim())
248
+ continue;
249
+ // Normalize path for consistent comparison
250
+ const normalizedFile = normalizeFilePath(file);
251
+ // Check if file exists on disk
252
+ const absolutePath = resolve(basePath, normalizedFile);
253
+ const existsOnDisk = existsSync(absolutePath);
254
+ // Check if file is in prior expected outputs (priorOutputs already normalized)
255
+ const inPriorOutputs = priorOutputs.has(normalizedFile);
256
+ if (!existsOnDisk && !inPriorOutputs) {
257
+ results.push({
258
+ category: "file",
259
+ target: file,
260
+ passed: false,
261
+ message: `Task ${task.id} references '${file}' which doesn't exist and isn't created by prior tasks`,
262
+ blocking: true,
263
+ });
264
+ }
265
+ }
266
+ }
267
+ return results;
268
+ }
269
+ // ─── Task Ordering Check ─────────────────────────────────────────────────────
270
+ /**
271
+ * Detect impossible task ordering: task N reads a file that task N+M creates.
272
+ * This is a fatal error — the plan has an impossible dependency.
273
+ *
274
+ * All paths are normalized before comparison to ensure ./src/a.ts matches src/a.ts.
275
+ */
276
+ export function checkTaskOrdering(tasks, _basePath) {
277
+ const results = [];
278
+ // Build map: normalized file → task index that creates it
279
+ const fileCreators = new Map();
280
+ for (let i = 0; i < tasks.length; i++) {
281
+ const task = tasks[i];
282
+ for (const file of task.expected_output) {
283
+ const normalizedFile = normalizeFilePath(file);
284
+ if (!fileCreators.has(normalizedFile)) {
285
+ fileCreators.set(normalizedFile, { taskId: task.id, index: i, originalPath: file });
286
+ }
287
+ }
288
+ }
289
+ // Check each task's inputs against file creators.
290
+ // Only check task.inputs — task.files ("files likely touched") intentionally
291
+ // includes files the task will create, so they don't indicate read-before-create (#3677).
292
+ for (let i = 0; i < tasks.length; i++) {
293
+ const task = tasks[i];
294
+ const filesToCheck = [...task.inputs];
295
+ for (const file of filesToCheck) {
296
+ const normalizedFile = normalizeFilePath(file);
297
+ const creator = fileCreators.get(normalizedFile);
298
+ if (creator && creator.index > i) {
299
+ // Task reads file that is created later — impossible ordering
300
+ results.push({
301
+ category: "file",
302
+ target: file,
303
+ passed: false,
304
+ message: `Task ${task.id} reads '${file}' but it's created by task ${creator.taskId} (sequence violation)`,
305
+ blocking: true,
306
+ });
307
+ }
308
+ }
309
+ }
310
+ return results;
311
+ }
312
+ /**
313
+ * Extract function signatures from code blocks in task description.
314
+ * Uses heuristic regex — not an AST parser.
315
+ */
316
+ function extractFunctionSignatures(description, taskId) {
317
+ const signatures = [];
318
+ // Match code blocks (```...```)
319
+ const codeBlockPattern = /```(?:typescript|ts|javascript|js)?\n([\s\S]*?)```/g;
320
+ let blockMatch;
321
+ while ((blockMatch = codeBlockPattern.exec(description)) !== null) {
322
+ const codeBlock = blockMatch[1];
323
+ // Match function declarations and exports
324
+ // Patterns:
325
+ // function name(params): ReturnType
326
+ // export function name(params): ReturnType
327
+ // export async function name(params): Promise<ReturnType>
328
+ // const name = (params): ReturnType =>
329
+ // export const name = (params): ReturnType =>
330
+ const funcPattern = /(?:export\s+)?(?:async\s+)?(?:function\s+|const\s+)(\w+)(?:\s*=\s*)?\s*\(([^)]*)\)(?:\s*:\s*([^{=>\n]+))?/g;
331
+ let funcMatch;
332
+ while ((funcMatch = funcPattern.exec(codeBlock)) !== null) {
333
+ const [raw, name, params, returnType] = funcMatch;
334
+ signatures.push({
335
+ name,
336
+ params: normalizeParams(params),
337
+ returnType: normalizeType(returnType || "void"),
338
+ taskId,
339
+ raw: raw.trim(),
340
+ });
341
+ }
342
+ // Match interface method signatures
343
+ // Pattern: methodName(params): ReturnType;
344
+ const methodPattern = /^\s*(\w+)\s*\(([^)]*)\)\s*:\s*([^;]+);/gm;
345
+ let methodMatch;
346
+ while ((methodMatch = methodPattern.exec(codeBlock)) !== null) {
347
+ const [raw, name, params, returnType] = methodMatch;
348
+ signatures.push({
349
+ name,
350
+ params: normalizeParams(params),
351
+ returnType: normalizeType(returnType),
352
+ taskId,
353
+ raw: raw.trim(),
354
+ });
355
+ }
356
+ }
357
+ return signatures;
358
+ }
359
+ /**
360
+ * Normalize parameter list for comparison.
361
+ * Removes whitespace, comments, and default values.
362
+ */
363
+ function normalizeParams(params) {
364
+ return params
365
+ .replace(/\/\*[\s\S]*?\*\//g, "") // Remove block comments
366
+ .replace(/\/\/[^\n]*/g, "") // Remove line comments
367
+ .replace(/\s*=\s*[^,)]+/g, "") // Remove default values
368
+ .replace(/\s+/g, " ") // Normalize whitespace
369
+ .trim();
370
+ }
371
+ /**
372
+ * Normalize type for comparison.
373
+ */
374
+ function normalizeType(type) {
375
+ return type
376
+ .replace(/\s+/g, " ")
377
+ .trim();
378
+ }
379
+ /**
380
+ * Check for contradictory function signatures across tasks.
381
+ * Same function name with different signatures is a warning (not blocking).
382
+ */
383
+ export function checkInterfaceContracts(tasks, _basePath) {
384
+ const results = [];
385
+ // Collect all signatures
386
+ const allSignatures = [];
387
+ for (const task of tasks) {
388
+ const sigs = extractFunctionSignatures(task.description, task.id);
389
+ allSignatures.push(...sigs);
390
+ }
391
+ // Group by function name
392
+ const byName = new Map();
393
+ for (const sig of allSignatures) {
394
+ const existing = byName.get(sig.name) || [];
395
+ existing.push(sig);
396
+ byName.set(sig.name, existing);
397
+ }
398
+ // Check for contradictions
399
+ for (const [name, sigs] of byName) {
400
+ if (sigs.length < 2)
401
+ continue;
402
+ // Compare signatures
403
+ const first = sigs[0];
404
+ for (let i = 1; i < sigs.length; i++) {
405
+ const current = sigs[i];
406
+ // Check parameter mismatch
407
+ if (first.params !== current.params) {
408
+ results.push({
409
+ category: "schema",
410
+ target: name,
411
+ passed: true, // Warning only, not blocking
412
+ message: `Function '${name}' has different parameters: '${first.params}' (${first.taskId}) vs '${current.params}' (${current.taskId})`,
413
+ blocking: false,
414
+ });
415
+ }
416
+ // Check return type mismatch
417
+ if (first.returnType !== current.returnType) {
418
+ results.push({
419
+ category: "schema",
420
+ target: name,
421
+ passed: true, // Warning only, not blocking
422
+ message: `Function '${name}' has different return types: '${first.returnType}' (${first.taskId}) vs '${current.returnType}' (${current.taskId})`,
423
+ blocking: false,
424
+ });
425
+ }
426
+ }
427
+ }
428
+ return results;
429
+ }
430
+ // ─── Main Entry Point ────────────────────────────────────────────────────────
431
+ /**
432
+ * Run all pre-execution checks against a slice's task plan.
433
+ *
434
+ * @param tasks - Array of TaskRow from the slice
435
+ * @param basePath - Base path for resolving file references
436
+ * @returns PreExecutionResult with status, checks, and duration
437
+ */
438
+ export async function runPreExecutionChecks(tasks, basePath) {
439
+ const startTime = Date.now();
440
+ const allChecks = [];
441
+ // Run sync checks first
442
+ const fileChecks = checkFilePathConsistency(tasks, basePath);
443
+ const orderingChecks = checkTaskOrdering(tasks, basePath);
444
+ const contractChecks = checkInterfaceContracts(tasks, basePath);
445
+ allChecks.push(...fileChecks, ...orderingChecks, ...contractChecks);
446
+ // Run async package checks
447
+ const packageChecks = await checkPackageExistence(tasks, basePath);
448
+ allChecks.push(...packageChecks);
449
+ const durationMs = Date.now() - startTime;
450
+ // Determine overall status
451
+ const hasBlockingFailure = allChecks.some((c) => !c.passed && c.blocking);
452
+ const hasNonBlockingFailure = allChecks.some((c) => !c.passed && !c.blocking);
453
+ // Interface contract checks pass but still report warnings via message
454
+ const hasInterfaceWarning = allChecks.some((c) => c.category === "schema" && c.message && !c.message.startsWith("Warning:"));
455
+ const hasNetworkWarning = allChecks.some((c) => c.passed && c.message?.startsWith("Warning:"));
456
+ let status;
457
+ if (hasBlockingFailure) {
458
+ status = "fail";
459
+ }
460
+ else if (hasNonBlockingFailure || hasInterfaceWarning || hasNetworkWarning) {
461
+ status = "warn";
462
+ }
463
+ else {
464
+ status = "pass";
465
+ }
466
+ return {
467
+ status,
468
+ checks: allChecks,
469
+ durationMs,
470
+ };
471
+ }
@@ -76,6 +76,13 @@ export const KNOWN_PREFERENCE_KEYS = new Set([
76
76
  "codebase",
77
77
  "slice_parallel",
78
78
  "safety_harness",
79
+ "enhanced_verification",
80
+ "enhanced_verification_pre",
81
+ "enhanced_verification_post",
82
+ "enhanced_verification_strict",
83
+ "discuss_preparation",
84
+ "discuss_web_research",
85
+ "discuss_depth",
79
86
  ]);
80
87
  /** Canonical list of all dispatch unit types. */
81
88
  export const KNOWN_UNIT_TYPES = [
@@ -542,6 +542,14 @@ export function validatePreferences(preferences) {
542
542
  errors.push("parallel.auto_merge must be one of: auto, confirm, manual");
543
543
  }
544
544
  }
545
+ if (p.worker_model !== undefined) {
546
+ if (typeof p.worker_model === "string" && p.worker_model.length > 0) {
547
+ parallel.worker_model = p.worker_model;
548
+ }
549
+ else {
550
+ errors.push("parallel.worker_model must be a non-empty string");
551
+ }
552
+ }
545
553
  if (Object.keys(parallel).length > 0) {
546
554
  validated.parallel = parallel;
547
555
  }
@@ -574,7 +582,15 @@ export function validatePreferences(preferences) {
574
582
  errors.push('reactive_execution.isolation_mode must be "same-tree"');
575
583
  }
576
584
  }
577
- const knownReKeys = new Set(["enabled", "max_parallel", "isolation_mode"]);
585
+ if (re.subagent_model !== undefined) {
586
+ if (typeof re.subagent_model === "string" && re.subagent_model.length > 0) {
587
+ validRe.subagent_model = re.subagent_model;
588
+ }
589
+ else {
590
+ errors.push("reactive_execution.subagent_model must be a non-empty string");
591
+ }
592
+ }
593
+ const knownReKeys = new Set(["enabled", "max_parallel", "isolation_mode", "subagent_model"]);
578
594
  for (const key of Object.keys(re)) {
579
595
  if (!knownReKeys.has(key)) {
580
596
  warnings.push(`unknown reactive_execution key "${key}" — ignored`);
@@ -939,5 +955,66 @@ export function validatePreferences(preferences) {
939
955
  errors.push("codebase must be an object");
940
956
  }
941
957
  }
958
+ // ─── Enhanced Verification ──────────────────────────────────────────────────
959
+ if (preferences.enhanced_verification !== undefined) {
960
+ if (typeof preferences.enhanced_verification === "boolean") {
961
+ validated.enhanced_verification = preferences.enhanced_verification;
962
+ }
963
+ else {
964
+ errors.push("enhanced_verification must be a boolean");
965
+ }
966
+ }
967
+ if (preferences.enhanced_verification_pre !== undefined) {
968
+ if (typeof preferences.enhanced_verification_pre === "boolean") {
969
+ validated.enhanced_verification_pre = preferences.enhanced_verification_pre;
970
+ }
971
+ else {
972
+ errors.push("enhanced_verification_pre must be a boolean");
973
+ }
974
+ }
975
+ if (preferences.enhanced_verification_post !== undefined) {
976
+ if (typeof preferences.enhanced_verification_post === "boolean") {
977
+ validated.enhanced_verification_post = preferences.enhanced_verification_post;
978
+ }
979
+ else {
980
+ errors.push("enhanced_verification_post must be a boolean");
981
+ }
982
+ }
983
+ if (preferences.enhanced_verification_strict !== undefined) {
984
+ if (typeof preferences.enhanced_verification_strict === "boolean") {
985
+ validated.enhanced_verification_strict = preferences.enhanced_verification_strict;
986
+ }
987
+ else {
988
+ errors.push("enhanced_verification_strict must be a boolean");
989
+ }
990
+ }
991
+ // ─── Discuss Preparation ────────────────────────────────────────────
992
+ if (preferences.discuss_preparation !== undefined) {
993
+ if (typeof preferences.discuss_preparation === "boolean") {
994
+ validated.discuss_preparation = preferences.discuss_preparation;
995
+ }
996
+ else {
997
+ errors.push("discuss_preparation must be a boolean");
998
+ }
999
+ }
1000
+ // ─── Discuss Web Research ───────────────────────────────────────────
1001
+ if (preferences.discuss_web_research !== undefined) {
1002
+ if (typeof preferences.discuss_web_research === "boolean") {
1003
+ validated.discuss_web_research = preferences.discuss_web_research;
1004
+ }
1005
+ else {
1006
+ errors.push("discuss_web_research must be a boolean");
1007
+ }
1008
+ }
1009
+ // ─── Discuss Depth ──────────────────────────────────────────────────
1010
+ if (preferences.discuss_depth !== undefined) {
1011
+ const validDepths = new Set(["quick", "standard", "thorough"]);
1012
+ if (typeof preferences.discuss_depth === "string" && validDepths.has(preferences.discuss_depth)) {
1013
+ validated.discuss_depth = preferences.discuss_depth;
1014
+ }
1015
+ else {
1016
+ errors.push(`discuss_depth must be one of: quick, standard, thorough`);
1017
+ }
1018
+ }
942
1019
  return { preferences: validated, errors, warnings };
943
1020
  }
@@ -127,9 +127,10 @@ function loadPreferencesFile(path, scope) {
127
127
  };
128
128
  }
129
129
  let _warnedUnrecognizedFormat = false;
130
- /** @internal Reset the warn-once flag — exported for testing only. */
130
+ /** @internal Reset the warn-once flags — exported for testing only. */
131
131
  export function _resetParseWarningFlag() {
132
132
  _warnedUnrecognizedFormat = false;
133
+ _warnedFrontmatterParse = false;
133
134
  }
134
135
  /** @internal Exported for testing only */
135
136
  export function parsePreferencesMarkdown(content) {
@@ -156,6 +157,7 @@ export function parsePreferencesMarkdown(content) {
156
157
  }
157
158
  return null;
158
159
  }
160
+ let _warnedFrontmatterParse = false;
159
161
  function parseFrontmatterBlock(frontmatter) {
160
162
  try {
161
163
  const parsed = parseYaml(frontmatter);
@@ -165,7 +167,11 @@ function parseFrontmatterBlock(frontmatter) {
165
167
  return parsed;
166
168
  }
167
169
  catch (e) {
168
- logWarning("guided", `YAML parse error in frontmatter block: ${e.message}`);
170
+ // Warn at most once per session to avoid flooding TUI (#3376)
171
+ if (!_warnedFrontmatterParse) {
172
+ _warnedFrontmatterParse = true;
173
+ logWarning("guided", `YAML parse error in preferences frontmatter (suppressing further): ${e.message}`);
174
+ }
169
175
  return {};
170
176
  }
171
177
  }
@@ -282,6 +288,10 @@ function mergePreferences(base, override) {
282
288
  verification_commands: mergeStringLists(base.verification_commands, override.verification_commands),
283
289
  verification_auto_fix: override.verification_auto_fix ?? base.verification_auto_fix,
284
290
  verification_max_retries: override.verification_max_retries ?? base.verification_max_retries,
291
+ enhanced_verification: override.enhanced_verification ?? base.enhanced_verification,
292
+ enhanced_verification_pre: override.enhanced_verification_pre ?? base.enhanced_verification_pre,
293
+ enhanced_verification_post: override.enhanced_verification_post ?? base.enhanced_verification_post,
294
+ enhanced_verification_strict: override.enhanced_verification_strict ?? base.enhanced_verification_strict,
285
295
  search_provider: override.search_provider ?? base.search_provider,
286
296
  context_selection: override.context_selection ?? base.context_selection,
287
297
  auto_visualize: override.auto_visualize ?? base.auto_visualize,
@@ -445,5 +455,6 @@ export function resolveParallelConfig(prefs) {
445
455
  budget_ceiling: prefs?.parallel?.budget_ceiling,
446
456
  merge_strategy: prefs?.parallel?.merge_strategy ?? "per-milestone",
447
457
  auto_merge: prefs?.parallel?.auto_merge ?? "confirm",
458
+ worker_model: prefs?.parallel?.worker_model,
448
459
  };
449
460
  }