gsd-pi 2.65.0-dev.5c8557b → 2.65.0-dev.6cc5110

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 (305) hide show
  1. package/dist/mcp-server.js +6 -2
  2. package/dist/resources/extensions/browser-tools/capture.js +20 -1
  3. package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +93 -0
  4. package/dist/resources/extensions/gsd/auto/run-unit.js +13 -2
  5. package/dist/resources/extensions/gsd/auto/session.js +4 -0
  6. package/dist/resources/extensions/gsd/auto-dispatch.js +99 -9
  7. package/dist/resources/extensions/gsd/auto-model-selection.js +7 -5
  8. package/dist/resources/extensions/gsd/auto-post-unit.js +17 -6
  9. package/dist/resources/extensions/gsd/auto-prompts.js +24 -0
  10. package/dist/resources/extensions/gsd/auto-recovery.js +40 -22
  11. package/dist/resources/extensions/gsd/auto-start.js +42 -11
  12. package/dist/resources/extensions/gsd/auto-tool-tracking.js +10 -0
  13. package/dist/resources/extensions/gsd/auto-worktree.js +29 -7
  14. package/dist/resources/extensions/gsd/auto.js +21 -15
  15. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +17 -4
  16. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +10 -0
  17. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +6 -4
  18. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +5 -1
  19. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +4 -1
  20. package/dist/resources/extensions/gsd/commands/context.js +8 -1
  21. package/dist/resources/extensions/gsd/commands/handlers/core.js +20 -0
  22. package/dist/resources/extensions/gsd/commands-extensions.js +1 -1
  23. package/dist/resources/extensions/gsd/config-overlay.js +312 -0
  24. package/dist/resources/extensions/gsd/db-writer.js +13 -3
  25. package/dist/resources/extensions/gsd/detection.js +1 -1
  26. package/dist/resources/extensions/gsd/dispatch-guard.js +2 -1
  27. package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -0
  28. package/dist/resources/extensions/gsd/doctor.js +2 -1
  29. package/dist/resources/extensions/gsd/gitignore.js +1 -0
  30. package/dist/resources/extensions/gsd/gsd-db.js +11 -2
  31. package/dist/resources/extensions/gsd/guided-flow.js +220 -29
  32. package/dist/resources/extensions/gsd/json-persistence.js +5 -2
  33. package/dist/resources/extensions/gsd/md-importer.js +14 -7
  34. package/dist/resources/extensions/gsd/parallel-orchestrator.js +17 -11
  35. package/dist/resources/extensions/gsd/pre-execution-checks.js +12 -5
  36. package/dist/resources/extensions/gsd/preferences-types.js +3 -0
  37. package/dist/resources/extensions/gsd/preferences-validation.js +45 -1
  38. package/dist/resources/extensions/gsd/preferences.js +9 -2
  39. package/dist/resources/extensions/gsd/preparation.js +1092 -0
  40. package/dist/resources/extensions/gsd/prompt-validation.js +67 -0
  41. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +3 -3
  42. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  43. package/dist/resources/extensions/gsd/prompts/discuss-prepared.md +424 -0
  44. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +4 -1
  45. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +5 -4
  46. package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +23 -0
  47. package/dist/resources/extensions/gsd/prompts/rethink.md +2 -1
  48. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +56 -23
  49. package/dist/resources/extensions/gsd/quick.js +19 -15
  50. package/dist/resources/extensions/gsd/reactive-graph.js +12 -0
  51. package/dist/resources/extensions/gsd/roadmap-slices.js +24 -5
  52. package/dist/resources/extensions/gsd/safety/content-validator.js +3 -3
  53. package/dist/resources/extensions/gsd/session-lock.js +23 -1
  54. package/dist/resources/extensions/gsd/state.js +112 -22
  55. package/dist/resources/extensions/gsd/templates/context-enhanced.md +138 -0
  56. package/dist/resources/extensions/gsd/tools/complete-milestone.js +15 -3
  57. package/dist/resources/extensions/gsd/tools/complete-slice.js +27 -6
  58. package/dist/resources/extensions/gsd/tools/complete-task.js +31 -7
  59. package/dist/resources/extensions/gsd/tools/plan-milestone.js +7 -5
  60. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +5 -2
  61. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +119 -0
  62. package/dist/resources/extensions/gsd/tools/reopen-slice.js +30 -0
  63. package/dist/resources/extensions/gsd/tools/reopen-task.js +18 -0
  64. package/dist/resources/extensions/gsd/triage-resolution.js +33 -16
  65. package/dist/resources/extensions/gsd/undo.js +3 -2
  66. package/dist/resources/extensions/gsd/workflow-logger.js +1 -1
  67. package/dist/resources/extensions/gsd/workflow-projections.js +4 -7
  68. package/dist/resources/extensions/gsd/workflow-reconcile.js +100 -9
  69. package/dist/resources/extensions/gsd/workflow-templates.js +11 -2
  70. package/dist/resources/extensions/gsd/worktree-manager.js +5 -2
  71. package/dist/resources/extensions/gsd/worktree.js +9 -0
  72. package/dist/resources/extensions/shared/interview-ui.js +1 -1
  73. package/dist/web/standalone/.next/BUILD_ID +1 -1
  74. package/dist/web/standalone/.next/app-path-routes-manifest.json +18 -18
  75. package/dist/web/standalone/.next/build-manifest.json +3 -3
  76. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  77. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  78. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  79. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  80. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  81. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  82. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  83. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  84. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  85. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  86. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  87. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  88. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  89. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  90. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  91. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/index.html +1 -1
  95. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  101. package/dist/web/standalone/.next/server/app-paths-manifest.json +18 -18
  102. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  103. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  104. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  105. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  106. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  107. package/dist/web/standalone/.next/static/chunks/6502.8874bcae249c02e1.js +9 -0
  108. package/dist/web/standalone/.next/static/chunks/{webpack-a1c1e452c6b32d04.js → webpack-9fed74684e1c5bb1.js} +1 -1
  109. package/package.json +1 -1
  110. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
  111. package/packages/pi-coding-agent/dist/core/retry-handler.js +30 -19
  112. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  113. package/packages/pi-coding-agent/dist/core/retry-handler.test.js +51 -0
  114. package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
  115. package/packages/pi-coding-agent/dist/core/sdk.js +9 -9
  116. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  117. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts +2 -1
  118. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts.map +1 -1
  119. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js +10 -1
  120. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js.map +1 -1
  121. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +1 -0
  122. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  123. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +20 -5
  124. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  125. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +15 -1
  126. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  127. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +18 -0
  128. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  129. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  130. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +4 -0
  131. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  132. package/packages/pi-coding-agent/src/core/retry-handler.test.ts +80 -0
  133. package/packages/pi-coding-agent/src/core/retry-handler.ts +37 -25
  134. package/packages/pi-coding-agent/src/core/sdk.ts +9 -9
  135. package/packages/pi-coding-agent/src/modes/interactive/components/provider-manager.ts +10 -0
  136. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +20 -4
  137. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +27 -0
  138. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +16 -1
  139. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +5 -0
  140. package/packages/pi-tui/dist/components/image.d.ts +2 -0
  141. package/packages/pi-tui/dist/components/image.d.ts.map +1 -1
  142. package/packages/pi-tui/dist/components/image.js +4 -0
  143. package/packages/pi-tui/dist/components/image.js.map +1 -1
  144. package/packages/pi-tui/dist/components/image.test.d.ts +6 -0
  145. package/packages/pi-tui/dist/components/image.test.d.ts.map +1 -0
  146. package/packages/pi-tui/dist/components/image.test.js +32 -0
  147. package/packages/pi-tui/dist/components/image.test.js.map +1 -0
  148. package/packages/pi-tui/src/components/image.test.ts +36 -0
  149. package/packages/pi-tui/src/components/image.ts +5 -0
  150. package/src/resources/extensions/browser-tools/capture.ts +19 -1
  151. package/src/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +93 -0
  152. package/src/resources/extensions/gsd/auto/run-unit.ts +12 -2
  153. package/src/resources/extensions/gsd/auto/session.ts +4 -0
  154. package/src/resources/extensions/gsd/auto-dispatch.ts +110 -9
  155. package/src/resources/extensions/gsd/auto-model-selection.ts +7 -5
  156. package/src/resources/extensions/gsd/auto-post-unit.ts +16 -6
  157. package/src/resources/extensions/gsd/auto-prompts.ts +31 -0
  158. package/src/resources/extensions/gsd/auto-recovery.ts +29 -23
  159. package/src/resources/extensions/gsd/auto-start.ts +45 -10
  160. package/src/resources/extensions/gsd/auto-tool-tracking.ts +10 -0
  161. package/src/resources/extensions/gsd/auto-worktree.ts +28 -7
  162. package/src/resources/extensions/gsd/auto.ts +19 -8
  163. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +16 -4
  164. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +10 -0
  165. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +5 -4
  166. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +4 -1
  167. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +4 -1
  168. package/src/resources/extensions/gsd/commands/context.ts +7 -1
  169. package/src/resources/extensions/gsd/commands/handlers/core.ts +23 -0
  170. package/src/resources/extensions/gsd/commands-extensions.ts +1 -1
  171. package/src/resources/extensions/gsd/config-overlay.ts +331 -0
  172. package/src/resources/extensions/gsd/db-writer.ts +11 -3
  173. package/src/resources/extensions/gsd/detection.ts +1 -1
  174. package/src/resources/extensions/gsd/dispatch-guard.ts +2 -1
  175. package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -0
  176. package/src/resources/extensions/gsd/doctor.ts +2 -1
  177. package/src/resources/extensions/gsd/gitignore.ts +1 -0
  178. package/src/resources/extensions/gsd/gsd-db.ts +13 -2
  179. package/src/resources/extensions/gsd/guided-flow.ts +254 -30
  180. package/src/resources/extensions/gsd/json-persistence.ts +6 -3
  181. package/src/resources/extensions/gsd/md-importer.ts +13 -6
  182. package/src/resources/extensions/gsd/parallel-orchestrator.ts +19 -11
  183. package/src/resources/extensions/gsd/pre-execution-checks.ts +15 -7
  184. package/src/resources/extensions/gsd/preferences-types.ts +25 -0
  185. package/src/resources/extensions/gsd/preferences-validation.ts +45 -1
  186. package/src/resources/extensions/gsd/preferences.ts +9 -2
  187. package/src/resources/extensions/gsd/preparation.ts +1419 -0
  188. package/src/resources/extensions/gsd/prompt-validation.ts +88 -0
  189. package/src/resources/extensions/gsd/prompts/complete-milestone.md +3 -3
  190. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  191. package/src/resources/extensions/gsd/prompts/discuss-prepared.md +424 -0
  192. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +4 -1
  193. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +5 -4
  194. package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +23 -0
  195. package/src/resources/extensions/gsd/prompts/rethink.md +2 -1
  196. package/src/resources/extensions/gsd/prompts/validate-milestone.md +56 -23
  197. package/src/resources/extensions/gsd/quick.ts +20 -15
  198. package/src/resources/extensions/gsd/reactive-graph.ts +18 -0
  199. package/src/resources/extensions/gsd/roadmap-slices.ts +21 -5
  200. package/src/resources/extensions/gsd/safety/content-validator.ts +3 -3
  201. package/src/resources/extensions/gsd/session-lock.ts +17 -1
  202. package/src/resources/extensions/gsd/state.ts +112 -20
  203. package/src/resources/extensions/gsd/templates/context-enhanced.md +138 -0
  204. package/src/resources/extensions/gsd/tests/adversarial-review-fixes.test.ts +223 -0
  205. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +33 -2
  206. package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +56 -0
  207. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +41 -0
  208. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +72 -0
  209. package/src/resources/extensions/gsd/tests/complete-task-normalize-lists.test.ts +54 -0
  210. package/src/resources/extensions/gsd/tests/defer-milestone-stamp.test.ts +30 -0
  211. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +4 -3
  212. package/src/resources/extensions/gsd/tests/discuss-incremental-persistence.test.ts +36 -0
  213. package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +46 -0
  214. package/src/resources/extensions/gsd/tests/dispatch-guard-closed-status.test.ts +33 -0
  215. package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +37 -0
  216. package/src/resources/extensions/gsd/tests/error-success-mask.test.ts +37 -0
  217. package/src/resources/extensions/gsd/tests/find-missing-summaries-closed.test.ts +48 -0
  218. package/src/resources/extensions/gsd/tests/frontmatter-parse-noise.test.ts +42 -0
  219. package/src/resources/extensions/gsd/tests/gitignore-bg-shell.test.ts +38 -0
  220. package/src/resources/extensions/gsd/tests/guided-flow-state-rebuild.test.ts +103 -0
  221. package/src/resources/extensions/gsd/tests/import-done-milestones.test.ts +42 -0
  222. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +11 -9
  223. package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +4 -2
  224. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +28 -30
  225. package/src/resources/extensions/gsd/tests/integration/test-isolation.ts +53 -0
  226. package/src/resources/extensions/gsd/tests/integration-prepared-discussion.test.ts +525 -0
  227. package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +62 -0
  228. package/src/resources/extensions/gsd/tests/needs-remediation-revalidation.test.ts +48 -0
  229. package/src/resources/extensions/gsd/tests/note-captures-executed.test.ts +46 -0
  230. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +77 -0
  231. package/src/resources/extensions/gsd/tests/phantom-ghost-detection.test.ts +55 -0
  232. package/src/resources/extensions/gsd/tests/phantom-milestone-default-queued.test.ts +39 -0
  233. package/src/resources/extensions/gsd/tests/pre-exec-backtick-strip.test.ts +68 -0
  234. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +218 -20
  235. package/src/resources/extensions/gsd/tests/pre-execution-fail-closed.test.ts +2 -2
  236. package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +2 -2
  237. package/src/resources/extensions/gsd/tests/preparation.test.ts +1211 -0
  238. package/src/resources/extensions/gsd/tests/project-root-cwd-crash.test.ts +53 -0
  239. package/src/resources/extensions/gsd/tests/projection-no-plan-overwrite.test.ts +83 -0
  240. package/src/resources/extensions/gsd/tests/prompt-builder.test.ts +669 -0
  241. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +7 -4
  242. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +85 -0
  243. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +2 -1
  244. package/src/resources/extensions/gsd/tests/query-tools-db-open.test.ts +47 -0
  245. package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +107 -0
  246. package/src/resources/extensions/gsd/tests/reactive-graph.test.ts +45 -0
  247. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +63 -0
  248. package/src/resources/extensions/gsd/tests/rogue-file-detection.test.ts +4 -5
  249. package/src/resources/extensions/gsd/tests/run-uat-replay-cap.test.ts +51 -0
  250. package/src/resources/extensions/gsd/tests/show-config-command.test.ts +56 -0
  251. package/src/resources/extensions/gsd/tests/skip-slice-state-rebuild.test.ts +31 -0
  252. package/src/resources/extensions/gsd/tests/skipped-validation-completion.test.ts +39 -0
  253. package/src/resources/extensions/gsd/tests/slice-sequence-insert.test.ts +51 -0
  254. package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +1 -1
  255. package/src/resources/extensions/gsd/tests/stale-lockfile-recovery.test.ts +36 -0
  256. package/src/resources/extensions/gsd/tests/stale-queued-milestone.test.ts +147 -0
  257. package/src/resources/extensions/gsd/tests/stale-worktree-cwd.test.ts +13 -0
  258. package/src/resources/extensions/gsd/tests/stash-pop-gsd-conflict.test.ts +21 -0
  259. package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +21 -0
  260. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +6 -7
  261. package/src/resources/extensions/gsd/tests/status-db-open.test.ts +47 -0
  262. package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +1 -0
  263. package/src/resources/extensions/gsd/tests/symlink-extension-discovery.test.ts +125 -0
  264. package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +65 -0
  265. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +29 -1
  266. package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +2 -1
  267. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +3 -4
  268. package/src/resources/extensions/gsd/tests/verification-operational-gate.test.ts +15 -0
  269. package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +89 -0
  270. package/src/resources/extensions/gsd/tests/wave1-critical-regressions.test.ts +49 -0
  271. package/src/resources/extensions/gsd/tests/wave2-events-regressions.test.ts +48 -0
  272. package/src/resources/extensions/gsd/tests/wave3-session-regressions.test.ts +47 -0
  273. package/src/resources/extensions/gsd/tests/wave4-write-safety-regressions.test.ts +70 -0
  274. package/src/resources/extensions/gsd/tests/worker-model-override.test.ts +48 -0
  275. package/src/resources/extensions/gsd/tests/workflow-logger-audit.test.ts +6 -3
  276. package/src/resources/extensions/gsd/tests/worktree-expected-warnings.test.ts +38 -0
  277. package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +16 -0
  278. package/src/resources/extensions/gsd/tests/worktree-main-branch.test.ts +20 -0
  279. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +16 -17
  280. package/src/resources/extensions/gsd/tests/worktree-sync-tasks.test.ts +13 -9
  281. package/src/resources/extensions/gsd/tests/worktree.test.ts +26 -9
  282. package/src/resources/extensions/gsd/tests/zero-slice-roadmap-guided.test.ts +19 -0
  283. package/src/resources/extensions/gsd/tools/complete-milestone.ts +13 -3
  284. package/src/resources/extensions/gsd/tools/complete-slice.ts +26 -6
  285. package/src/resources/extensions/gsd/tools/complete-task.ts +29 -7
  286. package/src/resources/extensions/gsd/tools/plan-milestone.ts +11 -9
  287. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +5 -2
  288. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +152 -0
  289. package/src/resources/extensions/gsd/tools/reopen-slice.ts +27 -0
  290. package/src/resources/extensions/gsd/tools/reopen-task.ts +17 -0
  291. package/src/resources/extensions/gsd/triage-resolution.ts +37 -17
  292. package/src/resources/extensions/gsd/types.ts +4 -0
  293. package/src/resources/extensions/gsd/undo.ts +3 -2
  294. package/src/resources/extensions/gsd/workflow-events.ts +1 -1
  295. package/src/resources/extensions/gsd/workflow-logger.ts +1 -1
  296. package/src/resources/extensions/gsd/workflow-projections.ts +4 -6
  297. package/src/resources/extensions/gsd/workflow-reconcile.ts +109 -8
  298. package/src/resources/extensions/gsd/workflow-templates.ts +11 -2
  299. package/src/resources/extensions/gsd/worktree-manager.ts +4 -2
  300. package/src/resources/extensions/gsd/worktree.ts +10 -0
  301. package/src/resources/extensions/shared/interview-ui.ts +1 -1
  302. package/src/resources/extensions/shared/tests/interview-notes-loop.test.ts +8 -10
  303. package/dist/web/standalone/.next/static/chunks/6502.7593d7797a4b3999.js +0 -9
  304. /package/dist/web/standalone/.next/static/{qq3YfHPfyqvh3DIMVmsRH → iueakR5x5bQbax2sGz8Yr}/_buildManifest.js +0 -0
  305. /package/dist/web/standalone/.next/static/{qq3YfHPfyqvh3DIMVmsRH → iueakR5x5bQbax2sGz8Yr}/_ssgManifest.js +0 -0
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Parallel research slices dispatch — structural tests.
3
+ *
4
+ * Verifies the dispatch rule and prompt builder exist with correct structure.
5
+ */
6
+
7
+ import test from "node:test";
8
+ import assert from "node:assert/strict";
9
+ import { readFileSync } from "node:fs";
10
+ import { join, dirname } from "node:path";
11
+ import { fileURLToPath } from "node:url";
12
+
13
+ const __dirname = dirname(fileURLToPath(import.meta.url));
14
+
15
+ const dispatchSrc = readFileSync(join(__dirname, "..", "auto-dispatch.ts"), "utf-8");
16
+ const promptsSrc = readFileSync(join(__dirname, "..", "auto-prompts.ts"), "utf-8");
17
+ const templatePath = join(__dirname, "..", "prompts", "parallel-research-slices.md");
18
+ const templateSrc = readFileSync(templatePath, "utf-8");
19
+
20
+ // ─── Dispatch rule ────────────────────────────────────────────────────────
21
+
22
+ test("dispatch: parallel-research-slices rule exists", () => {
23
+ assert.ok(
24
+ dispatchSrc.includes("parallel-research-slices"),
25
+ "dispatch table should have parallel-research-slices rule",
26
+ );
27
+ });
28
+
29
+ test("dispatch: parallel-research-slices requires 2+ slices", () => {
30
+ assert.ok(
31
+ dispatchSrc.includes("researchReadySlices.length < 2"),
32
+ "rule should require at least 2 slices for parallel dispatch",
33
+ );
34
+ });
35
+
36
+ test("dispatch: parallel-research-slices respects skip_research", () => {
37
+ const ruleIdx = dispatchSrc.indexOf("parallel-research-slices");
38
+ const ruleBlock = dispatchSrc.slice(ruleIdx, ruleIdx + 500);
39
+ assert.ok(
40
+ ruleBlock.includes("skip_research") || dispatchSrc.slice(ruleIdx - 300, ruleIdx).includes("skip_research"),
41
+ "rule should check skip_research preference",
42
+ );
43
+ });
44
+
45
+ // ─── Prompt builder ───────────────────────────────────────────────────────
46
+
47
+ test("prompt: buildParallelResearchSlicesPrompt exported", () => {
48
+ assert.ok(
49
+ promptsSrc.includes("export async function buildParallelResearchSlicesPrompt"),
50
+ "buildParallelResearchSlicesPrompt should be exported",
51
+ );
52
+ });
53
+
54
+ test("prompt: builds per-slice subagent prompts", () => {
55
+ assert.ok(
56
+ promptsSrc.includes("buildResearchSlicePrompt"),
57
+ "parallel prompt builder should delegate to per-slice research prompts",
58
+ );
59
+ });
60
+
61
+ // ─── Template ─────────────────────────────────────────────────────────────
62
+
63
+ test("template: parallel-research-slices.md has required variables", () => {
64
+ assert.ok(templateSrc.includes("{{sliceCount}}"), "template should use sliceCount");
65
+ assert.ok(templateSrc.includes("{{mid}}"), "template should use mid");
66
+ assert.ok(templateSrc.includes("{{subagentPrompts}}"), "template should use subagentPrompts");
67
+ });
68
+
69
+ // ─── Validate milestone prompt ────────────────────────────────────────────
70
+
71
+ test("template: validate-milestone uses parallel reviewers", () => {
72
+ const validateSrc = readFileSync(join(__dirname, "..", "prompts", "validate-milestone.md"), "utf-8");
73
+ assert.ok(
74
+ validateSrc.includes("Reviewer A") && validateSrc.includes("Reviewer B") && validateSrc.includes("Reviewer C"),
75
+ "validate-milestone should dispatch 3 parallel reviewers",
76
+ );
77
+ });
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Regression test for #3671 — isGhostMilestone detects phantom queued rows
3
+ *
4
+ * gsd_milestone_generate_id inserts a DB row with status "queued" as a side
5
+ * effect. If the milestone is never planned, isGhostMilestone previously
6
+ * returned false for any milestone with a DB row, blocking the state machine.
7
+ *
8
+ * The fix makes isGhostMilestone treat a "queued" DB row with no disk
9
+ * artifacts (CONTEXT, ROADMAP, SUMMARY) as a ghost.
10
+ *
11
+ * This structural test verifies the dbRow.status === 'queued' guard exists.
12
+ */
13
+
14
+ import { describe, test } from 'node:test';
15
+ import assert from 'node:assert/strict';
16
+ import { readFileSync } from 'node:fs';
17
+ import { fileURLToPath } from 'node:url';
18
+ import { dirname, join } from 'node:path';
19
+
20
+ const __filename = fileURLToPath(import.meta.url);
21
+ const __dirname = dirname(__filename);
22
+
23
+ const source = readFileSync(join(__dirname, '..', 'state.ts'), 'utf-8');
24
+
25
+ describe('isGhostMilestone phantom queued detection (#3671)', () => {
26
+ test('isGhostMilestone function exists', () => {
27
+ assert.match(source, /export function isGhostMilestone\(/,
28
+ 'isGhostMilestone should be exported');
29
+ });
30
+
31
+ test('checks dbRow.status === queued', () => {
32
+ assert.match(source, /dbRow\.status\s*===\s*['"]queued['"]/,
33
+ 'isGhostMilestone should check dbRow.status === "queued"');
34
+ });
35
+
36
+ test('checks for CONTEXT disk artifact', () => {
37
+ assert.match(source, /resolveMilestoneFile\(basePath,\s*mid,\s*["']CONTEXT["']\)/,
38
+ 'should check for CONTEXT file');
39
+ });
40
+
41
+ test('checks for ROADMAP disk artifact', () => {
42
+ assert.match(source, /resolveMilestoneFile\(basePath,\s*mid,\s*["']ROADMAP["']\)/,
43
+ 'should check for ROADMAP file');
44
+ });
45
+
46
+ test('checks for SUMMARY disk artifact', () => {
47
+ assert.match(source, /resolveMilestoneFile\(basePath,\s*mid,\s*["']SUMMARY["']\)/,
48
+ 'should check for SUMMARY file');
49
+ });
50
+
51
+ test('returns !hasContent for queued rows (ghost if no artifacts)', () => {
52
+ assert.match(source, /return !hasContent/,
53
+ 'should return !hasContent for queued phantom milestones');
54
+ });
55
+ });
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Regression test for #3695 — insertMilestone defaults status to "queued"
3
+ *
4
+ * Milestones were being auto-created with status "active", causing phantom
5
+ * milestones to appear as active work. The fix defaults to "queued" so
6
+ * new milestones must be explicitly activated.
7
+ */
8
+
9
+ import { describe, test } from 'node:test';
10
+ import assert from 'node:assert/strict';
11
+ import { readFileSync } from 'node:fs';
12
+ import { fileURLToPath } from 'node:url';
13
+ import { dirname, join } from 'node:path';
14
+
15
+ const __filename = fileURLToPath(import.meta.url);
16
+ const __dirname = dirname(__filename);
17
+
18
+ const dbSrc = readFileSync(
19
+ join(__dirname, '..', 'gsd-db.ts'),
20
+ 'utf-8',
21
+ );
22
+
23
+ describe('insertMilestone defaults status to queued (#3695)', () => {
24
+ test('insertMilestone function exists', () => {
25
+ assert.match(dbSrc, /export function insertMilestone\(/,
26
+ 'insertMilestone should be exported from gsd-db.ts');
27
+ });
28
+
29
+ test('default status is "queued" not "active"', () => {
30
+ // The status parameter should default to "queued" via nullish coalescing
31
+ assert.match(dbSrc, /m\.status\s*\?\?\s*"queued"/,
32
+ 'insertMilestone should default status to "queued"');
33
+ });
34
+
35
+ test('comment explains the rationale', () => {
36
+ assert.match(dbSrc, /never auto-create milestones as "active"/i,
37
+ 'should have a comment explaining why default is queued');
38
+ });
39
+ });
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Regression test for #3626 / #3649 — pre-execution-checks false positives
3
+ *
4
+ * Two sources of false positives were fixed:
5
+ * 1. normalizeFilePath did not strip backtick wrapping from LLM-generated
6
+ * paths like `src/foo.ts`, causing file-existence checks to fail (#3649).
7
+ * 2. checkFilePathConsistency checked both task.files and task.inputs, but
8
+ * task.files ("files likely touched") intentionally includes files that
9
+ * will be created by the task, so they don't need to pre-exist (#3626).
10
+ */
11
+
12
+ import { describe, it } from 'node:test'
13
+ import assert from 'node:assert/strict'
14
+ import { normalizeFilePath, checkFilePathConsistency } from '../pre-execution-checks.ts'
15
+ import { readFileSync } from 'node:fs'
16
+ import { resolve } from 'node:path'
17
+
18
+ const src = readFileSync(
19
+ resolve(process.cwd(), 'src', 'resources', 'extensions', 'gsd', 'pre-execution-checks.ts'),
20
+ 'utf-8',
21
+ )
22
+
23
+ describe('normalizeFilePath backtick stripping (#3649)', () => {
24
+ it('strips backticks from file paths', () => {
25
+ assert.equal(normalizeFilePath('`src/foo.ts`'), 'src/foo.ts')
26
+ })
27
+
28
+ it('strips backticks even when mixed with other normalization', () => {
29
+ assert.equal(normalizeFilePath('`./src//bar.ts`'), 'src/bar.ts')
30
+ })
31
+
32
+ it('leaves normal paths unchanged', () => {
33
+ assert.equal(normalizeFilePath('src/foo.ts'), 'src/foo.ts')
34
+ })
35
+
36
+ it('handles empty string', () => {
37
+ assert.equal(normalizeFilePath(''), '')
38
+ })
39
+ })
40
+
41
+ describe('checkFilePathConsistency checks task.inputs not task.files (#3626)', () => {
42
+ it('source uses only task.inputs in filesToCheck', () => {
43
+ // Verify the fix structurally: the spread should be [...task.inputs] only
44
+ const fnStart = src.indexOf('export function checkFilePathConsistency(')
45
+ assert.ok(fnStart !== -1, 'checkFilePathConsistency function must exist')
46
+
47
+ // Find the filesToCheck assignment
48
+ const filesToCheckLine = src.indexOf('filesToCheck', fnStart)
49
+ assert.ok(filesToCheckLine !== -1, 'filesToCheck assignment must exist')
50
+
51
+ // Extract the line
52
+ const lineEnd = src.indexOf('\n', filesToCheckLine)
53
+ const line = src.slice(filesToCheckLine, lineEnd)
54
+
55
+ // Must include task.inputs
56
+ assert.ok(
57
+ line.includes('task.inputs'),
58
+ 'filesToCheck must reference task.inputs',
59
+ )
60
+
61
+ // Must NOT include task.files
62
+ assert.ok(
63
+ !line.includes('task.files'),
64
+ 'filesToCheck must NOT reference task.files — files likely touched include ' +
65
+ 'files the task will create, so they do not need to pre-exist',
66
+ )
67
+ })
68
+ })
@@ -193,7 +193,7 @@ describe("checkFilePathConsistency", () => {
193
193
  }
194
194
  });
195
195
 
196
- test("fails when files don't exist and not in prior outputs", () => {
196
+ test("fails when inputs don't exist and not in prior outputs", () => {
197
197
  tempDir = join(tmpdir(), `pre-exec-test-${Date.now()}`);
198
198
  mkdirSync(tempDir, { recursive: true });
199
199
 
@@ -201,8 +201,8 @@ describe("checkFilePathConsistency", () => {
201
201
  const tasks = [
202
202
  createTask({
203
203
  id: "T01",
204
- files: ["nonexistent.ts"],
205
- inputs: [],
204
+ files: [],
205
+ inputs: ["nonexistent.ts"],
206
206
  expected_output: [],
207
207
  }),
208
208
  ];
@@ -218,7 +218,7 @@ describe("checkFilePathConsistency", () => {
218
218
  }
219
219
  });
220
220
 
221
- test("checks both files and inputs arrays", () => {
221
+ test("checks only inputs array, not files array", () => {
222
222
  tempDir = join(tmpdir(), `pre-exec-test-${Date.now()}`);
223
223
  mkdirSync(tempDir, { recursive: true });
224
224
 
@@ -232,10 +232,13 @@ describe("checkFilePathConsistency", () => {
232
232
  }),
233
233
  ];
234
234
 
235
+ // Only inputs are checked — files ("files likely touched") are excluded
236
+ // because they may include files the task will create (#3626)
235
237
  const results = checkFilePathConsistency(tasks, tempDir);
236
- assert.equal(results.length, 2);
237
- assert.ok(results.some((r) => r.target === "missing-file.ts"));
238
+ assert.equal(results.length, 1);
238
239
  assert.ok(results.some((r) => r.target === "missing-input.ts"));
240
+ // missing-file.ts should NOT produce a failure
241
+ assert.ok(!results.some((r) => r.target === "missing-file.ts"));
239
242
  } finally {
240
243
  rmSync(tempDir, { recursive: true, force: true });
241
244
  }
@@ -388,13 +391,13 @@ describe("checkFilePathConsistency with path normalization", () => {
388
391
  });
389
392
 
390
393
  describe("checkTaskOrdering with path normalization", () => {
391
- test("./path triggers ordering check for path in expected_output", () => {
394
+ test("./path in inputs triggers ordering check for path in expected_output", () => {
392
395
  const tasks = [
393
396
  createTask({
394
397
  id: "T01",
395
398
  sequence: 0,
396
- files: ["./generated.ts"], // Reads with ./
397
- inputs: [],
399
+ files: [],
400
+ inputs: ["./generated.ts"], // Reads with ./
398
401
  expected_output: [],
399
402
  }),
400
403
  createTask({
@@ -412,13 +415,13 @@ describe("checkTaskOrdering with path normalization", () => {
412
415
  assert.ok(results[0].message.includes("T02"));
413
416
  });
414
417
 
415
- test("path triggers ordering check for ./path in expected_output", () => {
418
+ test("path in inputs triggers ordering check for ./path in expected_output", () => {
416
419
  const tasks = [
417
420
  createTask({
418
421
  id: "T01",
419
422
  sequence: 0,
420
- files: ["generated.ts"], // Reads without ./
421
- inputs: [],
423
+ files: [],
424
+ inputs: ["generated.ts"], // Reads without ./
422
425
  expected_output: [],
423
426
  }),
424
427
  createTask({
@@ -483,13 +486,13 @@ describe("checkTaskOrdering", () => {
483
486
  assert.deepEqual(results, []);
484
487
  });
485
488
 
486
- test("fails when task reads file created by later task", () => {
489
+ test("fails when task inputs reference file created by later task", () => {
487
490
  const tasks = [
488
491
  createTask({
489
492
  id: "T01",
490
493
  sequence: 0,
491
- files: ["generated.ts"], // Reads file that doesn't exist yet
492
- inputs: [],
494
+ files: [],
495
+ inputs: ["generated.ts"], // Reads file that doesn't exist yet
493
496
  expected_output: [],
494
497
  }),
495
498
  createTask({
@@ -534,13 +537,13 @@ describe("checkTaskOrdering", () => {
534
537
  assert.ok(results[0].message.includes("schema.json"));
535
538
  });
536
539
 
537
- test("handles multiple ordering violations", () => {
540
+ test("handles multiple ordering violations via inputs", () => {
538
541
  const tasks = [
539
542
  createTask({
540
543
  id: "T01",
541
544
  sequence: 0,
542
- files: ["a.ts", "b.ts"],
543
- inputs: [],
545
+ files: [],
546
+ inputs: ["a.ts", "b.ts"],
544
547
  expected_output: [],
545
548
  }),
546
549
  createTask({
@@ -825,8 +828,8 @@ describe("runPreExecutionChecks", () => {
825
828
  const tasks = [
826
829
  createTask({
827
830
  id: "T01",
828
- files: ["nonexistent.ts"],
829
- inputs: [],
831
+ files: [],
832
+ inputs: ["nonexistent.ts"],
830
833
  expected_output: [],
831
834
  }),
832
835
  ];
@@ -952,6 +955,201 @@ function check(a: number): void
952
955
  });
953
956
  });
954
957
 
958
+ // ─── Regression Tests: checkTaskOrdering false positive (#3677) ──────────────
959
+
960
+ describe("checkTaskOrdering false positive regression (#3677)", () => {
961
+ test("task.files should not trigger ordering violation when file is in later expected_output", () => {
962
+ // T01 has files: ["component.tsx"] — this is a file the task will CREATE,
963
+ // not read. Including task.files in the ordering check causes a false positive.
964
+ // After fix (check only task.inputs), this should return 0 results.
965
+ const tasks = [
966
+ createTask({
967
+ id: "T01",
968
+ sequence: 0,
969
+ files: ["component.tsx"],
970
+ inputs: [],
971
+ expected_output: [],
972
+ }),
973
+ createTask({
974
+ id: "T02",
975
+ sequence: 1,
976
+ files: [],
977
+ inputs: [],
978
+ expected_output: ["component.tsx"],
979
+ }),
980
+ ];
981
+
982
+ const results = checkTaskOrdering(tasks, "/tmp");
983
+ assert.equal(results.length, 0, "task.files should not be checked for ordering violations");
984
+ });
985
+
986
+ test("task.files with multiple files should not trigger false positives", () => {
987
+ // T01 lists several files it will touch/create — none should trigger ordering
988
+ // violations just because T02 declares one of them as expected_output.
989
+ const tasks = [
990
+ createTask({
991
+ id: "T01",
992
+ sequence: 0,
993
+ files: ["a.ts", "b.ts", "c.ts"],
994
+ inputs: [],
995
+ expected_output: [],
996
+ }),
997
+ createTask({
998
+ id: "T02",
999
+ sequence: 1,
1000
+ files: [],
1001
+ inputs: [],
1002
+ expected_output: ["b.ts"],
1003
+ }),
1004
+ ];
1005
+
1006
+ const results = checkTaskOrdering(tasks, "/tmp");
1007
+ assert.equal(results.length, 0, "Multiple task.files should not generate false positive violations");
1008
+ });
1009
+
1010
+ test("task.inputs SHOULD still trigger ordering violation", () => {
1011
+ // task.inputs represents files a task genuinely needs to READ, so a sequence
1012
+ // violation here is a real error and must still be detected.
1013
+ const tasks = [
1014
+ createTask({
1015
+ id: "T01",
1016
+ sequence: 0,
1017
+ files: [],
1018
+ inputs: ["config.json"],
1019
+ expected_output: [],
1020
+ }),
1021
+ createTask({
1022
+ id: "T02",
1023
+ sequence: 1,
1024
+ files: [],
1025
+ inputs: [],
1026
+ expected_output: ["config.json"],
1027
+ }),
1028
+ ];
1029
+
1030
+ const results = checkTaskOrdering(tasks, "/tmp");
1031
+ assert.equal(results.length, 1, "task.inputs ordering violation must still be detected");
1032
+ assert.equal(results[0].blocking, true);
1033
+ assert.ok(results[0].message.includes("T01"));
1034
+ assert.ok(results[0].message.includes("T02"));
1035
+ assert.ok(results[0].message.includes("sequence violation"));
1036
+ });
1037
+
1038
+ test("mixed files and inputs — only inputs trigger ordering violation", () => {
1039
+ // T01 will create "created.ts" (files) and also needs to READ "needed.json" (inputs).
1040
+ // T02 creates both. Only the inputs dependency is a real violation.
1041
+ const tasks = [
1042
+ createTask({
1043
+ id: "T01",
1044
+ sequence: 0,
1045
+ files: ["created.ts"],
1046
+ inputs: ["needed.json"],
1047
+ expected_output: [],
1048
+ }),
1049
+ createTask({
1050
+ id: "T02",
1051
+ sequence: 1,
1052
+ files: [],
1053
+ inputs: [],
1054
+ expected_output: ["created.ts", "needed.json"],
1055
+ }),
1056
+ ];
1057
+
1058
+ const results = checkTaskOrdering(tasks, "/tmp");
1059
+ assert.equal(results.length, 1, "Only the inputs entry should produce a violation, not files");
1060
+ assert.ok(results[0].target === "needed.json", "Violation target should be the input, not the file");
1061
+ });
1062
+
1063
+ test("task.files with normalized paths should not false-positive", () => {
1064
+ // Path normalization (./src/new-file.ts → src/new-file.ts) should not cause
1065
+ // task.files to match against expected_output and produce a false positive.
1066
+ const tasks = [
1067
+ createTask({
1068
+ id: "T01",
1069
+ sequence: 0,
1070
+ files: ["./src/new-file.ts"],
1071
+ inputs: [],
1072
+ expected_output: [],
1073
+ }),
1074
+ createTask({
1075
+ id: "T02",
1076
+ sequence: 1,
1077
+ files: [],
1078
+ inputs: [],
1079
+ expected_output: ["src/new-file.ts"],
1080
+ }),
1081
+ ];
1082
+
1083
+ const results = checkTaskOrdering(tasks, "/tmp");
1084
+ assert.equal(results.length, 0, "Normalized task.files path should not trigger a false positive");
1085
+ });
1086
+ });
1087
+
1088
+ // ─── checkFilePathConsistency additional edge cases ──────────────────────────
1089
+
1090
+ describe("checkFilePathConsistency additional edge cases", () => {
1091
+ test("inputs referencing glob-like patterns should not crash", () => {
1092
+ // A glob pattern in inputs is unusual but should be handled gracefully.
1093
+ // The file won't exist on disk, so it should produce a blocking result.
1094
+ const tasks = [
1095
+ createTask({
1096
+ id: "T01",
1097
+ files: [],
1098
+ inputs: ["src/**/*.ts"],
1099
+ expected_output: [],
1100
+ }),
1101
+ ];
1102
+
1103
+ // Should not throw
1104
+ let results: ReturnType<typeof checkFilePathConsistency>;
1105
+ assert.doesNotThrow(() => {
1106
+ results = checkFilePathConsistency(tasks, "/tmp");
1107
+ });
1108
+ assert.equal(results!.length, 1, "Glob-pattern input that doesn't exist should produce a blocking result");
1109
+ assert.equal(results![0].blocking, true);
1110
+ });
1111
+
1112
+ test("empty inputs array produces no results", () => {
1113
+ // A task with no inputs and only files should produce zero results from
1114
+ // consistency check — files are not checked (#3626).
1115
+ const tasks = [
1116
+ createTask({
1117
+ id: "T01",
1118
+ files: ["anything.ts"],
1119
+ inputs: [],
1120
+ expected_output: [],
1121
+ }),
1122
+ ];
1123
+
1124
+ const results = checkFilePathConsistency(tasks, "/tmp");
1125
+ assert.equal(results.length, 0, "Empty inputs should produce no consistency check results");
1126
+ });
1127
+
1128
+ test("inputs with absolute paths are checked correctly", () => {
1129
+ // An absolute path in inputs should resolve to itself and pass when the file exists.
1130
+ const tempDir = join(tmpdir(), `pre-exec-test-abs-${Date.now()}`);
1131
+ mkdirSync(tempDir, { recursive: true });
1132
+ const absFilePath = join(tempDir, "real-file.ts");
1133
+ writeFileSync(absFilePath, "// content");
1134
+
1135
+ try {
1136
+ const tasks = [
1137
+ createTask({
1138
+ id: "T01",
1139
+ files: [],
1140
+ inputs: [absFilePath],
1141
+ expected_output: [],
1142
+ }),
1143
+ ];
1144
+
1145
+ const results = checkFilePathConsistency(tasks, tempDir);
1146
+ assert.equal(results.length, 0, "Absolute path to an existing file should pass consistency check");
1147
+ } finally {
1148
+ rmSync(tempDir, { recursive: true, force: true });
1149
+ }
1150
+ });
1151
+ });
1152
+
955
1153
  // ─── PreExecutionResult Type Tests ───────────────────────────────────────────
956
1154
 
957
1155
  describe("PreExecutionResult type", () => {
@@ -225,9 +225,9 @@ describe("Pre-execution fail-closed behavior", () => {
225
225
  planning: {
226
226
  description: "References missing file",
227
227
  estimate: "1h",
228
- files: ["nonexistent-file.ts"],
228
+ files: [],
229
229
  verify: "npm test",
230
- inputs: [],
230
+ inputs: ["nonexistent-file.ts"],
231
231
  expectedOutput: [],
232
232
  observabilityImpact: "",
233
233
  },
@@ -189,9 +189,9 @@ function createFailingTasks(): void {
189
189
  planning: {
190
190
  description: "This task references a non-existent file",
191
191
  estimate: "1h",
192
- files: ["nonexistent-file-that-does-not-exist.ts"],
192
+ files: [],
193
193
  verify: "npm test",
194
- inputs: [],
194
+ inputs: ["nonexistent-file-that-does-not-exist.ts"],
195
195
  expectedOutput: [],
196
196
  observabilityImpact: "",
197
197
  },