gsd-pi 2.81.0-dev.72a81bdf3 → 2.82.0-dev.20138ae42

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 (463) hide show
  1. package/README.md +50 -31
  2. package/dist/resources/.managed-resources-content-hash +1 -1
  3. package/dist/resources/GSD-WORKFLOW.md +10 -1
  4. package/dist/resources/extensions/browser-tools/tools/screenshot.js +1 -0
  5. package/dist/resources/extensions/browser-tools/tools/zoom.js +1 -0
  6. package/dist/resources/extensions/claude-code-cli/partial-builder.js +2 -1
  7. package/dist/resources/extensions/cmux/index.js +5 -0
  8. package/dist/resources/extensions/gsd/auto/infra-errors.js +9 -3
  9. package/dist/resources/extensions/gsd/auto/loop.js +5 -5
  10. package/dist/resources/extensions/gsd/auto/orchestrator.js +124 -6
  11. package/dist/resources/extensions/gsd/auto/phases.js +30 -1
  12. package/dist/resources/extensions/gsd/auto/workflow-memory-pressure.js +12 -0
  13. package/dist/resources/extensions/gsd/auto-dashboard.js +66 -1
  14. package/dist/resources/extensions/gsd/auto-dispatch.js +13 -6
  15. package/dist/resources/extensions/gsd/auto-model-selection.js +2 -0
  16. package/dist/resources/extensions/gsd/auto-post-unit.js +233 -127
  17. package/dist/resources/extensions/gsd/auto-prompts.js +13 -5
  18. package/dist/resources/extensions/gsd/auto-recovery.js +31 -1
  19. package/dist/resources/extensions/gsd/auto-start.js +85 -12
  20. package/dist/resources/extensions/gsd/auto-verification.js +28 -22
  21. package/dist/resources/extensions/gsd/auto-worktree.js +111 -1
  22. package/dist/resources/extensions/gsd/auto.js +158 -55
  23. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +25 -6
  24. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +9 -8
  25. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +9 -2
  26. package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +21 -9
  27. package/dist/resources/extensions/gsd/bootstrap/system-context.js +55 -12
  28. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +16 -2
  29. package/dist/resources/extensions/gsd/clean-root-preflight.js +170 -8
  30. package/dist/resources/extensions/gsd/commands/catalog.js +4 -1
  31. package/dist/resources/extensions/gsd/commands/handlers/core.js +38 -1
  32. package/dist/resources/extensions/gsd/commands-bootstrap.js +5 -0
  33. package/dist/resources/extensions/gsd/commands-handlers.js +15 -2
  34. package/dist/resources/extensions/gsd/context-store.js +112 -0
  35. package/dist/resources/extensions/gsd/crash-recovery.js +31 -5
  36. package/dist/resources/extensions/gsd/db/unit-dispatches.js +3 -2
  37. package/dist/resources/extensions/gsd/db-writer.js +150 -84
  38. package/dist/resources/extensions/gsd/dispatch-guard.js +2 -2
  39. package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  40. package/dist/resources/extensions/gsd/doctor-git-checks.js +41 -6
  41. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +28 -11
  42. package/dist/resources/extensions/gsd/doctor.js +2 -28
  43. package/dist/resources/extensions/gsd/export-html.js +27 -425
  44. package/dist/resources/extensions/gsd/git-service.js +39 -1
  45. package/dist/resources/extensions/gsd/gsd-db.js +1 -0
  46. package/dist/resources/extensions/gsd/guided-flow.js +93 -111
  47. package/dist/resources/extensions/gsd/guided-unit-context.js +23 -0
  48. package/dist/resources/extensions/gsd/knowledge-backfill.js +144 -0
  49. package/dist/resources/extensions/gsd/knowledge-capture.js +136 -0
  50. package/dist/resources/extensions/gsd/knowledge-parser.js +154 -0
  51. package/dist/resources/extensions/gsd/knowledge-projection.js +210 -0
  52. package/dist/resources/extensions/gsd/markdown-renderer.js +6 -1
  53. package/dist/resources/extensions/gsd/md-importer.js +1 -1
  54. package/dist/resources/extensions/gsd/memory-backfill.js +73 -17
  55. package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +222 -0
  56. package/dist/resources/extensions/gsd/migrate/command.js +5 -0
  57. package/dist/resources/extensions/gsd/migrate/parsers.js +10 -0
  58. package/dist/resources/extensions/gsd/migrate/preview.js +9 -0
  59. package/dist/resources/extensions/gsd/migrate/transformer.js +51 -4
  60. package/dist/resources/extensions/gsd/migrate/writer.js +11 -1
  61. package/dist/resources/extensions/gsd/migration-auto-check.js +12 -17
  62. package/dist/resources/extensions/gsd/milestone-actions.js +11 -4
  63. package/dist/resources/extensions/gsd/native-git-bridge.js +48 -12
  64. package/dist/resources/extensions/gsd/pending-auto-start.js +52 -0
  65. package/dist/resources/extensions/gsd/post-execution-checks.js +73 -2
  66. package/dist/resources/extensions/gsd/pre-execution-checks.js +28 -1
  67. package/dist/resources/extensions/gsd/prompt-loader.js +1 -1
  68. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  69. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  70. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
  71. package/dist/resources/extensions/gsd/prompts/discuss.md +9 -9
  72. package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
  73. package/dist/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
  74. package/dist/resources/extensions/gsd/prompts/plan-slice.md +4 -4
  75. package/dist/resources/extensions/gsd/prompts/queue.md +4 -4
  76. package/dist/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  77. package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  78. package/dist/resources/extensions/gsd/prompts/system.md +2 -2
  79. package/dist/resources/extensions/gsd/provider-switch-observer.js +146 -0
  80. package/dist/resources/extensions/gsd/smart-entry-routing.js +36 -0
  81. package/dist/resources/extensions/gsd/state-reconciliation/drift/merge-state.js +6 -1
  82. package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +9 -14
  83. package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +19 -24
  84. package/dist/resources/extensions/gsd/status-guards.js +4 -0
  85. package/dist/resources/extensions/gsd/templates/knowledge.md +2 -2
  86. package/dist/resources/extensions/gsd/templates/plan.md +8 -5
  87. package/dist/resources/extensions/gsd/templates/task-plan.md +4 -2
  88. package/dist/resources/extensions/gsd/tools/complete-milestone.js +6 -8
  89. package/dist/resources/extensions/gsd/tools/complete-slice.js +6 -8
  90. package/dist/resources/extensions/gsd/tools/plan-milestone.js +7 -1
  91. package/dist/resources/extensions/gsd/tools/plan-slice.js +89 -14
  92. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +119 -0
  93. package/dist/resources/extensions/gsd/unit-context-manifest.js +32 -10
  94. package/dist/resources/extensions/gsd/validation.js +23 -1
  95. package/dist/resources/extensions/gsd/verification-gate.js +68 -7
  96. package/dist/resources/extensions/gsd/verification-verdict.js +26 -0
  97. package/dist/resources/extensions/gsd/workflow-projections.js +6 -8
  98. package/dist/resources/extensions/gsd/worktree-lifecycle.js +54 -10
  99. package/dist/resources/extensions/shared/html-shell.js +388 -0
  100. package/dist/resources/extensions/subagent/index.js +448 -78
  101. package/dist/resources/extensions/subagent/launch.js +77 -0
  102. package/dist/resources/extensions/subagent/run-store.js +148 -0
  103. package/dist/resources/extensions/visual-brief/artifact-policy.js +29 -0
  104. package/dist/resources/extensions/visual-brief/extension-manifest.json +8 -0
  105. package/dist/resources/extensions/visual-brief/index.js +5 -0
  106. package/dist/resources/extensions/visual-brief/page-contract.js +124 -0
  107. package/dist/resources/extensions/visual-brief/prompts.js +140 -0
  108. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  109. package/dist/web/standalone/.next/BUILD_ID +1 -1
  110. package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -12
  111. package/dist/web/standalone/.next/build-manifest.json +3 -3
  112. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  113. package/dist/web/standalone/.next/react-loadable-manifest.json +3 -3
  114. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  115. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  116. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  122. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  124. package/dist/web/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  125. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  126. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  127. package/dist/web/standalone/.next/server/app/_not-found.rsc +4 -7
  128. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -7
  129. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  130. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -5
  131. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  132. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  133. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -5
  134. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  135. package/dist/web/standalone/.next/server/app/index.html +1 -1
  136. package/dist/web/standalone/.next/server/app/index.rsc +4 -7
  137. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  138. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -7
  139. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  140. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -5
  141. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -5
  142. package/dist/web/standalone/.next/server/app/page.js +2 -2
  143. package/dist/web/standalone/.next/server/app/page.js.nft.json +1 -1
  144. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
  146. package/dist/web/standalone/.next/server/chunks/4266.js +2 -0
  147. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  148. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  150. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  151. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  152. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  153. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  154. package/dist/web/standalone/.next/static/chunks/2973.33f26573894b6153.js +2 -0
  155. package/dist/web/standalone/.next/static/chunks/{8359.e059d86b255fce1c.js → 8359.7eb3bb8f8ecf4c01.js} +2 -2
  156. package/dist/web/standalone/.next/static/chunks/app/layout-8c10ec293ae0f1d5.js +1 -0
  157. package/dist/web/standalone/.next/static/chunks/{webpack-de742b64187e13fe.js → webpack-9a4db269f9ed63ad.js} +1 -1
  158. package/dist/web/standalone/.next/static/css/746ee28c929d1880.css +1 -0
  159. package/package.json +6 -5
  160. package/packages/contracts/dist/rpc.test.js +7 -0
  161. package/packages/contracts/dist/rpc.test.js.map +1 -1
  162. package/packages/contracts/dist/workflow.d.ts +21 -0
  163. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  164. package/packages/contracts/dist/workflow.js +24 -0
  165. package/packages/contracts/dist/workflow.js.map +1 -1
  166. package/packages/contracts/src/rpc.test.ts +8 -0
  167. package/packages/contracts/src/workflow.ts +24 -0
  168. package/packages/daemon/package.json +2 -2
  169. package/packages/mcp-server/README.md +14 -3
  170. package/packages/mcp-server/dist/workflow-tools.d.ts +0 -3
  171. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  172. package/packages/mcp-server/dist/workflow-tools.js +80 -0
  173. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  174. package/packages/mcp-server/package.json +2 -2
  175. package/packages/mcp-server/src/workflow-tools-parity.test.ts +244 -0
  176. package/packages/mcp-server/src/workflow-tools.test.ts +23 -1
  177. package/packages/mcp-server/src/workflow-tools.ts +168 -0
  178. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  179. package/packages/native/package.json +1 -1
  180. package/packages/native/tsconfig.json +2 -1
  181. package/packages/native/tsconfig.tsbuildinfo +1 -1
  182. package/packages/pi-agent-core/package.json +1 -1
  183. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  184. package/packages/pi-ai/dist/index.d.ts +2 -2
  185. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  186. package/packages/pi-ai/dist/index.js +1 -1
  187. package/packages/pi-ai/dist/index.js.map +1 -1
  188. package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts.map +1 -1
  189. package/packages/pi-ai/dist/providers/openai-codex-responses.js +82 -1
  190. package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
  191. package/packages/pi-ai/dist/providers/openai-codex-responses.test.d.ts +2 -0
  192. package/packages/pi-ai/dist/providers/openai-codex-responses.test.d.ts.map +1 -0
  193. package/packages/pi-ai/dist/providers/openai-codex-responses.test.js +52 -0
  194. package/packages/pi-ai/dist/providers/openai-codex-responses.test.js.map +1 -0
  195. package/packages/pi-ai/dist/providers/simple-options.d.ts +2 -4
  196. package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
  197. package/packages/pi-ai/dist/providers/simple-options.js +5 -6
  198. package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
  199. package/packages/pi-ai/dist/providers/simple-options.test.d.ts +2 -0
  200. package/packages/pi-ai/dist/providers/simple-options.test.d.ts.map +1 -0
  201. package/packages/pi-ai/dist/providers/simple-options.test.js +50 -0
  202. package/packages/pi-ai/dist/providers/simple-options.test.js.map +1 -0
  203. package/packages/pi-ai/dist/providers/transform-messages.d.ts +11 -0
  204. package/packages/pi-ai/dist/providers/transform-messages.d.ts.map +1 -1
  205. package/packages/pi-ai/dist/providers/transform-messages.js +20 -0
  206. package/packages/pi-ai/dist/providers/transform-messages.js.map +1 -1
  207. package/packages/pi-ai/package.json +1 -1
  208. package/packages/pi-ai/src/index.ts +7 -2
  209. package/packages/pi-ai/src/providers/openai-codex-responses.test.ts +63 -0
  210. package/packages/pi-ai/src/providers/openai-codex-responses.ts +91 -1
  211. package/packages/pi-ai/src/providers/simple-options.test.ts +60 -0
  212. package/packages/pi-ai/src/providers/simple-options.ts +5 -6
  213. package/packages/pi-ai/src/providers/transform-messages.ts +24 -0
  214. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  215. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts +2 -0
  216. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts.map +1 -0
  217. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js +66 -0
  218. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js.map +1 -0
  219. package/packages/pi-coding-agent/dist/core/agent-session.js +1 -1
  220. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  221. package/packages/pi-coding-agent/dist/core/system-prompt.js +4 -4
  222. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  223. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  224. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +24 -6
  225. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  226. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.d.ts +2 -0
  227. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.d.ts.map +1 -0
  228. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.js +17 -0
  229. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.js.map +1 -0
  230. package/packages/pi-coding-agent/package.json +1 -1
  231. package/packages/pi-coding-agent/src/core/agent-session-thinking-level.test.ts +79 -0
  232. package/packages/pi-coding-agent/src/core/agent-session.ts +1 -1
  233. package/packages/pi-coding-agent/src/core/system-prompt.ts +4 -4
  234. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +23 -7
  235. package/packages/pi-coding-agent/src/tests/system-prompt-file-safety.test.ts +22 -0
  236. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  237. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  238. package/packages/pi-tui/dist/tui.js +5 -0
  239. package/packages/pi-tui/dist/tui.js.map +1 -1
  240. package/packages/pi-tui/package.json +1 -1
  241. package/packages/pi-tui/src/tui.ts +6 -0
  242. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  243. package/packages/rpc-client/package.json +1 -1
  244. package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
  245. package/pkg/package.json +1 -1
  246. package/src/resources/GSD-WORKFLOW.md +10 -1
  247. package/src/resources/extensions/browser-tools/tools/screenshot.ts +1 -0
  248. package/src/resources/extensions/browser-tools/tools/zoom.ts +1 -0
  249. package/src/resources/extensions/claude-code-cli/partial-builder.ts +2 -1
  250. package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +19 -2
  251. package/src/resources/extensions/cmux/index.ts +6 -0
  252. package/src/resources/extensions/gsd/auto/contracts.ts +59 -16
  253. package/src/resources/extensions/gsd/auto/infra-errors.ts +9 -3
  254. package/src/resources/extensions/gsd/auto/loop.ts +8 -5
  255. package/src/resources/extensions/gsd/auto/orchestrator.ts +129 -6
  256. package/src/resources/extensions/gsd/auto/phases.ts +36 -1
  257. package/src/resources/extensions/gsd/auto/workflow-memory-pressure.ts +13 -0
  258. package/src/resources/extensions/gsd/auto-dashboard.ts +72 -1
  259. package/src/resources/extensions/gsd/auto-dispatch.ts +14 -6
  260. package/src/resources/extensions/gsd/auto-model-selection.ts +2 -1
  261. package/src/resources/extensions/gsd/auto-post-unit.ts +266 -139
  262. package/src/resources/extensions/gsd/auto-prompts.ts +13 -5
  263. package/src/resources/extensions/gsd/auto-recovery.ts +29 -0
  264. package/src/resources/extensions/gsd/auto-start.ts +92 -9
  265. package/src/resources/extensions/gsd/auto-verification.ts +36 -34
  266. package/src/resources/extensions/gsd/auto-worktree.ts +119 -1
  267. package/src/resources/extensions/gsd/auto.ts +167 -53
  268. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +33 -6
  269. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +9 -8
  270. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +10 -2
  271. package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +19 -7
  272. package/src/resources/extensions/gsd/bootstrap/system-context.ts +58 -15
  273. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +19 -3
  274. package/src/resources/extensions/gsd/clean-root-preflight.ts +174 -8
  275. package/src/resources/extensions/gsd/commands/catalog.ts +4 -1
  276. package/src/resources/extensions/gsd/commands/handlers/core.ts +41 -1
  277. package/src/resources/extensions/gsd/commands-bootstrap.ts +10 -0
  278. package/src/resources/extensions/gsd/commands-handlers.ts +19 -2
  279. package/src/resources/extensions/gsd/context-store.ts +120 -1
  280. package/src/resources/extensions/gsd/crash-recovery.ts +30 -4
  281. package/src/resources/extensions/gsd/db/unit-dispatches.ts +4 -3
  282. package/src/resources/extensions/gsd/db-writer.ts +167 -84
  283. package/src/resources/extensions/gsd/dispatch-guard.ts +2 -2
  284. package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  285. package/src/resources/extensions/gsd/doctor-git-checks.ts +44 -6
  286. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +25 -13
  287. package/src/resources/extensions/gsd/doctor-types.ts +2 -0
  288. package/src/resources/extensions/gsd/doctor.ts +2 -27
  289. package/src/resources/extensions/gsd/export-html.ts +27 -427
  290. package/src/resources/extensions/gsd/git-service.ts +45 -1
  291. package/src/resources/extensions/gsd/gsd-db.ts +3 -0
  292. package/src/resources/extensions/gsd/guided-flow.ts +126 -128
  293. package/src/resources/extensions/gsd/guided-unit-context.ts +30 -0
  294. package/src/resources/extensions/gsd/knowledge-backfill.ts +164 -0
  295. package/src/resources/extensions/gsd/knowledge-capture.ts +160 -0
  296. package/src/resources/extensions/gsd/knowledge-parser.ts +174 -0
  297. package/src/resources/extensions/gsd/knowledge-projection.ts +241 -0
  298. package/src/resources/extensions/gsd/markdown-renderer.ts +6 -1
  299. package/src/resources/extensions/gsd/md-importer.ts +1 -1
  300. package/src/resources/extensions/gsd/memory-backfill.ts +89 -17
  301. package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +277 -0
  302. package/src/resources/extensions/gsd/migrate/command.ts +5 -0
  303. package/src/resources/extensions/gsd/migrate/parsers.ts +11 -0
  304. package/src/resources/extensions/gsd/migrate/preview.ts +10 -0
  305. package/src/resources/extensions/gsd/migrate/transformer.ts +58 -4
  306. package/src/resources/extensions/gsd/migrate/writer.ts +14 -1
  307. package/src/resources/extensions/gsd/migration-auto-check.ts +15 -23
  308. package/src/resources/extensions/gsd/milestone-actions.ts +10 -4
  309. package/src/resources/extensions/gsd/native-git-bridge.ts +54 -12
  310. package/src/resources/extensions/gsd/pending-auto-start.ts +79 -0
  311. package/src/resources/extensions/gsd/post-execution-checks.ts +87 -2
  312. package/src/resources/extensions/gsd/pre-execution-checks.ts +32 -1
  313. package/src/resources/extensions/gsd/prompt-loader.ts +1 -1
  314. package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  315. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  316. package/src/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
  317. package/src/resources/extensions/gsd/prompts/discuss.md +9 -9
  318. package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
  319. package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
  320. package/src/resources/extensions/gsd/prompts/plan-slice.md +4 -4
  321. package/src/resources/extensions/gsd/prompts/queue.md +4 -4
  322. package/src/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  323. package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  324. package/src/resources/extensions/gsd/prompts/system.md +2 -2
  325. package/src/resources/extensions/gsd/provider-switch-observer.ts +185 -0
  326. package/src/resources/extensions/gsd/smart-entry-routing.ts +77 -0
  327. package/src/resources/extensions/gsd/state-reconciliation/drift/merge-state.ts +8 -1
  328. package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +12 -15
  329. package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +17 -25
  330. package/src/resources/extensions/gsd/status-guards.ts +5 -0
  331. package/src/resources/extensions/gsd/templates/knowledge.md +2 -2
  332. package/src/resources/extensions/gsd/templates/plan.md +8 -5
  333. package/src/resources/extensions/gsd/templates/task-plan.md +4 -2
  334. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +71 -0
  335. package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +116 -0
  336. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +129 -0
  337. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +487 -4
  338. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +12 -11
  339. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +53 -2
  340. package/src/resources/extensions/gsd/tests/auto-post-unit-step-message.test.ts +12 -1
  341. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +15 -1
  342. package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +4 -4
  343. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +1 -0
  344. package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +69 -1
  345. package/src/resources/extensions/gsd/tests/brief-command.test.ts +89 -0
  346. package/src/resources/extensions/gsd/tests/browser-tools-compatibility-declarations.test.ts +62 -0
  347. package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +107 -2
  348. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +11 -2
  349. package/src/resources/extensions/gsd/tests/closeout-git-deferral.test.ts +16 -0
  350. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +4 -1
  351. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +5 -9
  352. package/src/resources/extensions/gsd/tests/complete-task.test.ts +3 -1
  353. package/src/resources/extensions/gsd/tests/context-store-decisions-from-memories.test.ts +312 -0
  354. package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +43 -2
  355. package/src/resources/extensions/gsd/tests/db-authority-regression.test.ts +208 -0
  356. package/src/resources/extensions/gsd/tests/db-writer.test.ts +13 -8
  357. package/src/resources/extensions/gsd/tests/decisions-projection-from-memories.test.ts +453 -0
  358. package/src/resources/extensions/gsd/tests/decisions-stop-table-writes.test.ts +348 -0
  359. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +59 -2
  360. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +39 -0
  361. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +27 -0
  362. package/src/resources/extensions/gsd/tests/evidence-cross-ref.test.ts +38 -0
  363. package/src/resources/extensions/gsd/tests/export-html-enhancements.test.ts +8 -0
  364. package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +8 -4
  365. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +11 -7
  366. package/src/resources/extensions/gsd/tests/guided-discuss-project-prompt-rendering.test.ts +2 -0
  367. package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +106 -0
  368. package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +59 -11
  369. package/src/resources/extensions/gsd/tests/guided-flow.test.ts +21 -0
  370. package/src/resources/extensions/gsd/tests/guided-tool-contract.test.ts +65 -0
  371. package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +7 -7
  372. package/src/resources/extensions/gsd/tests/hook-model-resolution.test.ts +5 -0
  373. package/src/resources/extensions/gsd/tests/infra-error.test.ts +2 -2
  374. package/src/resources/extensions/gsd/tests/infra-errors-cooldown.test.ts +9 -0
  375. package/src/resources/extensions/gsd/tests/integration/doctor-git.test.ts +44 -0
  376. package/src/resources/extensions/gsd/tests/integration/doctor-runtime.test.ts +20 -0
  377. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +103 -1
  378. package/src/resources/extensions/gsd/tests/integration/integration-lifecycle.test.ts +13 -5
  379. package/src/resources/extensions/gsd/tests/integration/migrate-command.test.ts +48 -3
  380. package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +6 -1
  381. package/src/resources/extensions/gsd/tests/knowledge-backfill-projection.test.ts +323 -0
  382. package/src/resources/extensions/gsd/tests/knowledge-capture.test.ts +242 -0
  383. package/src/resources/extensions/gsd/tests/knowledge.test.ts +47 -2
  384. package/src/resources/extensions/gsd/tests/load-knowledge-block-rules-only.test.ts +209 -0
  385. package/src/resources/extensions/gsd/tests/memory-consolidation-scanner.test.ts +316 -0
  386. package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +5 -1
  387. package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +24 -1
  388. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +6 -1
  389. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +26 -18
  390. package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +63 -2
  391. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +121 -1
  392. package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +55 -1
  393. package/src/resources/extensions/gsd/tests/pending-autostart-scope.test.ts +29 -5
  394. package/src/resources/extensions/gsd/tests/plan-milestone-sketch-render.test.ts +157 -0
  395. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +26 -0
  396. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +2 -0
  397. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +225 -1
  398. package/src/resources/extensions/gsd/tests/plan-task.test.ts +17 -0
  399. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +79 -1
  400. package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +86 -0
  401. package/src/resources/extensions/gsd/tests/post-unit-git-failure.test.ts +1 -1
  402. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +53 -0
  403. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +8 -0
  404. package/src/resources/extensions/gsd/tests/prompt-loader.test.ts +23 -0
  405. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +20 -1
  406. package/src/resources/extensions/gsd/tests/provider-switch-observer.test.ts +252 -0
  407. package/src/resources/extensions/gsd/tests/remediation-completion-guard.test.ts +46 -2
  408. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +16 -4
  409. package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +10 -0
  410. package/src/resources/extensions/gsd/tests/smart-entry-routing.test.ts +113 -0
  411. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +53 -2
  412. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +6 -0
  413. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +119 -23
  414. package/src/resources/extensions/gsd/tests/stuck-state-via-db.test.ts +64 -1
  415. package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +7 -3
  416. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +86 -7
  417. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +110 -1
  418. package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +78 -0
  419. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +1 -1
  420. package/src/resources/extensions/gsd/tests/workflow-memory-pressure.test.ts +21 -1
  421. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +1 -1
  422. package/src/resources/extensions/gsd/tests/worktree-git-pathspec.test.ts +39 -0
  423. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +64 -12
  424. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +25 -0
  425. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +54 -0
  426. package/src/resources/extensions/gsd/tools/complete-milestone.ts +8 -10
  427. package/src/resources/extensions/gsd/tools/complete-slice.ts +6 -8
  428. package/src/resources/extensions/gsd/tools/plan-milestone.ts +5 -1
  429. package/src/resources/extensions/gsd/tools/plan-slice.ts +98 -12
  430. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +135 -0
  431. package/src/resources/extensions/gsd/types.ts +1 -1
  432. package/src/resources/extensions/gsd/unit-context-manifest.ts +47 -11
  433. package/src/resources/extensions/gsd/validation.ts +23 -1
  434. package/src/resources/extensions/gsd/verification-gate.ts +78 -6
  435. package/src/resources/extensions/gsd/verification-verdict.ts +47 -0
  436. package/src/resources/extensions/gsd/workflow-logger.ts +4 -0
  437. package/src/resources/extensions/gsd/workflow-projections.ts +6 -8
  438. package/src/resources/extensions/gsd/worktree-lifecycle.ts +61 -10
  439. package/src/resources/extensions/shared/html-shell.ts +412 -0
  440. package/src/resources/extensions/subagent/index.ts +567 -103
  441. package/src/resources/extensions/subagent/launch.ts +131 -0
  442. package/src/resources/extensions/subagent/run-store.ts +218 -0
  443. package/src/resources/extensions/subagent/tests/launch.test.ts +115 -0
  444. package/src/resources/extensions/subagent/tests/run-store.test.ts +111 -0
  445. package/src/resources/extensions/visual-brief/artifact-policy.ts +41 -0
  446. package/src/resources/extensions/visual-brief/extension-manifest.json +8 -0
  447. package/src/resources/extensions/visual-brief/index.ts +8 -0
  448. package/src/resources/extensions/visual-brief/page-contract.ts +136 -0
  449. package/src/resources/extensions/visual-brief/prompts.ts +183 -0
  450. package/src/resources/extensions/visual-brief/tests/visual-brief.test.ts +212 -0
  451. package/dist/web/standalone/.next/server/chunks/5822.js +0 -2
  452. package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +0 -1
  453. package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +0 -1
  454. package/dist/web/standalone/.next/static/css/54ec2745c1da488b.css +0 -1
  455. package/dist/web/standalone/.next/static/css/de70bee13400563f.css +0 -1
  456. package/dist/web/standalone/.next/static/media/4cf2300e9c8272f7-s.p.woff2 +0 -0
  457. package/dist/web/standalone/.next/static/media/747892c23ea88013-s.woff2 +0 -0
  458. package/dist/web/standalone/.next/static/media/8d697b304b401681-s.woff2 +0 -0
  459. package/dist/web/standalone/.next/static/media/93f479601ee12b01-s.p.woff2 +0 -0
  460. package/dist/web/standalone/.next/static/media/9610d9e46709d722-s.woff2 +0 -0
  461. package/dist/web/standalone/.next/static/media/ba015fad6dcf6784-s.woff2 +0 -0
  462. /package/dist/web/standalone/.next/static/{rIkMv4YSNlfSeqmGqWVns → xRy4LqKSNKdT7y6ATYyEl}/_buildManifest.js +0 -0
  463. /package/dist/web/standalone/.next/static/{rIkMv4YSNlfSeqmGqWVns → xRy4LqKSNKdT7y6ATYyEl}/_ssgManifest.js +0 -0
@@ -4,6 +4,18 @@ import { createRequire } from "node:module";
4
4
  const require = createRequire(import.meta.url);
5
5
  const DEFAULT_MEMORY_PRESSURE_THRESHOLD = 0.85;
6
6
  const DEFAULT_HEAP_LIMIT_MB = 4096;
7
+ /**
8
+ * Returns true on auto-mode startup, then every configured interval.
9
+ *
10
+ * Iteration 1 is checked explicitly so early session memory pressure cannot
11
+ * bypass the periodic interval guard.
12
+ */
13
+ export function shouldCheckMemoryPressure(iteration, interval) {
14
+ if (!Number.isInteger(interval) || interval <= 0) {
15
+ throw new Error("Memory pressure check interval must be a positive integer");
16
+ }
17
+ return iteration === 1 || iteration % interval === 0;
18
+ }
7
19
  function defaultHeapLimitBytes() {
8
20
  const v8 = require("node:v8");
9
21
  const limit = v8.getHeapStatistics?.().heap_size_limit;
@@ -27,6 +27,19 @@ export function extractUatSliceId(unitId) {
27
27
  return slice;
28
28
  return null;
29
29
  }
30
+ export function buildPhaseHandoffOutcome(input) {
31
+ const phase = unitPhaseLabel(input.unitType);
32
+ const detail = extractLastAssistantSummary(input.agentEndMessages) ??
33
+ `Completed ${unitVerb(input.unitType)} ${input.unitId}.`;
34
+ return {
35
+ status: "complete",
36
+ title: `${phase} complete`,
37
+ detail,
38
+ unitLabel: `${unitVerb(input.unitType)} ${input.unitId}`,
39
+ nextAction: "Preparing the next phase. Review this handoff while the next session starts.",
40
+ commands: ["/gsd status for overview", "/gsd visualize to inspect", "/gsd notifications for history"],
41
+ };
42
+ }
30
43
  // ─── Unit Description Helpers ─────────────────────────────────────────────────
31
44
  export function unitVerb(unitType) {
32
45
  if (unitType.startsWith("hook/"))
@@ -464,7 +477,6 @@ export function _resetWidgetModeForTests() {
464
477
  export function updateProgressWidget(ctx, unitType, unitId, state, accessors, tierBadge) {
465
478
  if (!ctx.hasUI)
466
479
  return;
467
- ctx.ui.setWidget("gsd-outcome", undefined);
468
480
  // Welcome header is a startup-only banner — permanently suppress it once
469
481
  // auto-mode activates. The dashboard widget owns all status from here.
470
482
  // Note: setHeader(undefined) restores the built-in header (logo +
@@ -927,3 +939,56 @@ function normalizeRollupText(value) {
927
939
  return null;
928
940
  return clean;
929
941
  }
942
+ function isAssistantMessage(value) {
943
+ if (!value || typeof value !== "object")
944
+ return false;
945
+ const record = value;
946
+ if (record.role === "assistant")
947
+ return true;
948
+ const message = record.message;
949
+ if (message && typeof message === "object") {
950
+ return message.role === "assistant";
951
+ }
952
+ return false;
953
+ }
954
+ function extractLastAssistantSummary(messages) {
955
+ if (!messages || messages.length === 0)
956
+ return null;
957
+ for (let i = messages.length - 1; i >= 0; i--) {
958
+ if (!isAssistantMessage(messages[i]))
959
+ continue;
960
+ const text = extractMessageText(messages[i]);
961
+ const clean = normalizeRollupText(text);
962
+ if (clean)
963
+ return truncateToWidth(clean, 220, "…");
964
+ }
965
+ return null;
966
+ }
967
+ function extractMessageText(value) {
968
+ if (typeof value === "string")
969
+ return value;
970
+ if (!value || typeof value !== "object")
971
+ return null;
972
+ const record = value;
973
+ if (typeof record.content === "string")
974
+ return record.content;
975
+ const message = record.message;
976
+ if (message && typeof message === "object") {
977
+ return extractMessageText(message);
978
+ }
979
+ const content = record.content;
980
+ if (Array.isArray(content)) {
981
+ const parts = content
982
+ .map((part) => {
983
+ if (typeof part === "string")
984
+ return part;
985
+ if (!part || typeof part !== "object")
986
+ return "";
987
+ const partRecord = part;
988
+ return typeof partRecord.text === "string" ? partRecord.text : "";
989
+ })
990
+ .filter(Boolean);
991
+ return parts.length > 0 ? parts.join(" ") : null;
992
+ }
993
+ return null;
994
+ }
@@ -102,6 +102,9 @@ function missingSliceStop(mid, phase) {
102
102
  level: "error",
103
103
  };
104
104
  }
105
+ function isRegistryMilestoneComplete(state, mid) {
106
+ return state.registry.some((milestone) => milestone.id === mid && milestone.status === "complete");
107
+ }
105
108
  /**
106
109
  * Check for milestone slices missing SUMMARY files.
107
110
  * Returns array of missing slice IDs, or empty array if all present or DB unavailable.
@@ -247,6 +250,8 @@ export const DISPATCH_RULES = [
247
250
  return null;
248
251
  if (!MILESTONE_ID_RE.test(mid))
249
252
  return null;
253
+ if (isRegistryMilestoneComplete(state, mid))
254
+ return null;
250
255
  // Align with the plan-v2 gate's lookup semantics: whitespace-only counts
251
256
  // as missing, and an auto worktree may fall back to GSD_PROJECT_ROOT.
252
257
  if (hasFinalizedMilestoneContext(basePath, mid))
@@ -557,6 +562,8 @@ export const DISPATCH_RULES = [
557
562
  match: async ({ state, mid, midTitle, basePath, prefs, structuredQuestionsAvailable }) => {
558
563
  if (state.phase !== "pre-planning")
559
564
  return null;
565
+ if (isRegistryMilestoneComplete(state, mid))
566
+ return null;
560
567
  const contextFile = resolveMilestoneFile(basePath, mid, "CONTEXT");
561
568
  const hasContext = !!(contextFile && (await loadFile(contextFile)));
562
569
  if (hasContext)
@@ -1091,19 +1098,19 @@ export const DISPATCH_RULES = [
1091
1098
  return { action: "skip" };
1092
1099
  }
1093
1100
  }
1094
- // Safety guard (#2675): block completion when VALIDATION verdict is
1095
- // needs-remediation. The state machine treats needs-remediation as
1096
- // terminal (to prevent validate-milestone loops per #832), but
1097
- // completing-milestone should NOT proceed — remediation work is needed.
1101
+ // Safety guard (#2675, #5747): block completion when VALIDATION
1102
+ // verdict is non-passing. The state machine treats these verdicts as
1103
+ // terminal, but completing-milestone should NOT proceed — remediation
1104
+ // or human attention is needed.
1098
1105
  const validationFile = resolveMilestoneFile(basePath, mid, "VALIDATION");
1099
1106
  if (validationFile) {
1100
1107
  const validationContent = await loadFile(validationFile);
1101
1108
  if (validationContent) {
1102
1109
  const verdict = extractVerdict(validationContent);
1103
- if (verdict === "needs-remediation") {
1110
+ if (verdict === "needs-remediation" || verdict === "needs-attention") {
1104
1111
  return {
1105
1112
  action: "stop",
1106
- reason: `Cannot complete milestone ${mid}: VALIDATION verdict is "needs-remediation". Address the remediation findings and re-run validation, or update the verdict manually.`,
1113
+ reason: `Cannot complete milestone ${mid}: VALIDATION verdict is "${verdict}". Address the validation findings and re-run validation, or update the verdict manually.`,
1107
1114
  level: "warning",
1108
1115
  };
1109
1116
  }
@@ -494,6 +494,8 @@ autoModeStartThinkingLevel) {
494
494
  * Handles formats: "provider/model", "bare-id", "org/model-name" (OpenRouter).
495
495
  */
496
496
  export function resolveModelId(modelId, availableModels, currentProvider) {
497
+ if (!modelId)
498
+ return undefined;
497
499
  const slashIdx = modelId.indexOf("/");
498
500
  if (slashIdx !== -1) {
499
501
  const maybeProvider = modelId.substring(0, slashIdx);
@@ -7,8 +7,8 @@
7
7
  *
8
8
  * Split into two functions called sequentially by auto-loop with
9
9
  * the verification gate between them:
10
- * 1. postUnitPreVerification() — commit, doctor, state rebuild, worktree sync, artifact verification
11
- * 2. postUnitPostVerification() — DB dual-write, hooks, triage, quick-tasks
10
+ * 1. postUnitPreVerification() — closeout git for non-task units, doctor, state rebuild, worktree sync, artifact verification
11
+ * 2. postUnitPostVerification() — post-verified task git, DB dual-write, hooks, triage, quick-tasks
12
12
  *
13
13
  * Extracted from the pre-loop agent_end handler in auto.ts.
14
14
  */
@@ -23,7 +23,7 @@ import { rebuildState } from "./doctor.js";
23
23
  import { parseUnitId } from "./unit-id.js";
24
24
  import { closeoutUnit } from "./auto-unit-closeout.js";
25
25
  import { runTurnGitAction, } from "./git-service.js";
26
- import { verifyExpectedArtifact, resolveExpectedArtifactPath, writeBlockerPlaceholder, diagnoseExpectedArtifact, } from "./auto-recovery.js";
26
+ import { verifyExpectedArtifact, resolveExpectedArtifactPath, writeBlockerPlaceholder, diagnoseExpectedArtifact, diagnoseWorktreeIntegrityFailure, } from "./auto-recovery.js";
27
27
  import { regenerateIfMissing } from "./workflow-projections.js";
28
28
  import { WorktreeStateProjection } from "./worktree-state-projection.js";
29
29
  import { createWorkspace, scopeMilestone } from "./workspace.js";
@@ -37,8 +37,7 @@ import { debugLog } from "./debug-logger.js";
37
37
  import { runSafely } from "./auto-utils.js";
38
38
  import { getEvidence, clearEvidenceFromDisk } from "./safety/evidence-collector.js";
39
39
  import { validateFileChanges } from "./safety/file-change-validator.js";
40
- // crossReferenceEvidence available for future use when verification_evidence is stored in DB
41
- // import { crossReferenceEvidence, type ClaimedEvidence } from "./safety/evidence-cross-ref.js";
40
+ import { crossReferenceEvidence } from "./safety/evidence-cross-ref.js";
42
41
  import { validateContent } from "./safety/content-validator.js";
43
42
  import { resolveSafetyHarnessConfig } from "./safety/safety-harness.js";
44
43
  import { resolveExpectedArtifactPath as resolveArtifactForContent } from "./auto-artifact-paths.js";
@@ -126,7 +125,7 @@ async function buildTaskCommitContextForUnit(basePath, unitId) {
126
125
  sliceId: sid,
127
126
  sliceTitle: stripKnownIdPrefix(slice?.title, sid),
128
127
  oneLiner: summary?.oneLiner || task?.one_liner || undefined,
129
- keyFiles: summary?.frontmatter.key_files?.filter(f => !f.includes("{{")) ??
128
+ keyFiles: summary?.frontmatter.key_files?.filter(f => !f.includes("{{") && f.trim() !== "(none)") ??
130
129
  task?.key_files ??
131
130
  undefined,
132
131
  issueNumber: ghIssueNumber,
@@ -171,6 +170,9 @@ export function _shouldDispatchQuickTaskForTest(state) {
171
170
  !!state.currentUnit &&
172
171
  state.currentUnit.type !== "quick-task";
173
172
  }
173
+ export function shouldDeferCloseoutGitAction(unitType) {
174
+ return unitType === "execute-task";
175
+ }
174
176
  /** Unit types that only touch `.gsd/` internal state files (no code changes).
175
177
  * Auto-commit is skipped for these — their state files are picked up by the
176
178
  * next actual task commit via `smartStage()`. */
@@ -301,6 +303,19 @@ export function buildStepCompleteMessage(nextState) {
301
303
  return `Step complete. Next: ${next.label}\n`
302
304
  + `Run /clear, then /gsd to continue (or /gsd auto to run continuously).`;
303
305
  }
306
+ /**
307
+ * Decide whether step mode should stop at the step wizard after a unit finishes.
308
+ *
309
+ * @param currentUnitType The just-finished unit type, such as "execute-task" or
310
+ * "complete-milestone"; may be null/undefined when no current unit is known.
311
+ * @param phaseAfterUnit The freshly derived next phase, such as "executing" or
312
+ * "complete"; may be null/undefined if state derivation failed.
313
+ * @returns true to show the step wizard; false to keep the loop running so
314
+ * terminal milestone completion can reach the merge/finalization path.
315
+ */
316
+ export function shouldReturnStepWizardAfterUnit(currentUnitType, phaseAfterUnit) {
317
+ return currentUnitType !== "complete-milestone" && phaseAfterUnit !== "complete";
318
+ }
304
319
  export const USER_DRIVEN_DEEP_UNITS = new Set([
305
320
  "discuss-project",
306
321
  "discuss-requirements",
@@ -316,6 +331,10 @@ function artifactValidationKind(unitType) {
316
331
  return null;
317
332
  }
318
333
  function describeArtifactVerificationFailure(unitType, unitId, basePath) {
334
+ const worktreeFailure = diagnoseWorktreeIntegrityFailure(basePath);
335
+ if (worktreeFailure) {
336
+ return `${worktreeFailure} Unit: ${unitType} ${unitId}.`;
337
+ }
319
338
  const artifactPath = resolveExpectedArtifactPath(unitType, unitId, basePath);
320
339
  if (!artifactPath) {
321
340
  return `Artifact verification failed: ${unitType} "${unitId}" has no resolvable artifact path.`;
@@ -360,6 +379,148 @@ export async function autoCommitUnit(basePath, unitType, unitId, ctx) {
360
379
  return null;
361
380
  }
362
381
  }
382
+ /**
383
+ * Execute the turn-level git action (commit, snapshot, or status-only).
384
+ *
385
+ * @param opts.softFailure - Defaults to false. When true, retry git failures,
386
+ * warn, and continue without pausing auto-mode; use for best-effort deferred
387
+ * closeout work where a git failure should not block the run.
388
+ */
389
+ async function runCloseoutGitAction(pctx, unit, opts) {
390
+ const { s, ctx, pi, pauseAuto } = pctx;
391
+ const prefs = loadEffectiveGSDPreferences()?.preferences;
392
+ const uokFlags = resolveUokFlags(prefs);
393
+ const turnAction = uokFlags.gitops ? uokFlags.gitopsTurnAction : "commit";
394
+ const traceId = s.currentTraceId ?? `turn:${unit.startedAt}`;
395
+ const turnId = s.currentTurnId ?? `${unit.type}/${unit.id}/${unit.startedAt}`;
396
+ s.lastGitActionFailure = null;
397
+ s.lastGitActionStatus = null;
398
+ try {
399
+ let taskContext;
400
+ if (turnAction === "commit" && unit.type === "execute-task") {
401
+ taskContext = await buildTaskCommitContextForUnit(s.basePath, unit.id);
402
+ }
403
+ // Invalidate the nativeHasChanges cache before auto-commit (#1853).
404
+ // The cache has a 10-second TTL and is keyed by basePath. A stale
405
+ // `false` result causes autoCommit to skip staging entirely.
406
+ _resetHasChangesCache();
407
+ const skipLifecycleCommit = turnAction === "commit" && LIFECYCLE_ONLY_UNITS.has(unit.type);
408
+ if (skipLifecycleCommit) {
409
+ debugLog("postUnit", {
410
+ phase: "git-action-skipped",
411
+ reason: "lifecycle-only-unit",
412
+ unitType: unit.type,
413
+ unitId: unit.id,
414
+ });
415
+ }
416
+ else {
417
+ const maxAttempts = opts?.softFailure ? 3 : 1;
418
+ let gitResult = runTurnGitAction({
419
+ basePath: s.basePath,
420
+ action: turnAction,
421
+ unitType: unit.type,
422
+ unitId: unit.id,
423
+ taskContext,
424
+ });
425
+ for (let attempt = 1; gitResult.status === "failed" && attempt < maxAttempts; attempt++) {
426
+ await new Promise((resolve) => setTimeout(resolve, 250 * attempt));
427
+ gitResult = runTurnGitAction({
428
+ basePath: s.basePath,
429
+ action: turnAction,
430
+ unitType: unit.type,
431
+ unitId: unit.id,
432
+ taskContext,
433
+ });
434
+ }
435
+ if (uokFlags.gitops) {
436
+ writeTurnGitTransaction({
437
+ basePath: s.basePath,
438
+ traceId,
439
+ turnId,
440
+ unitType: unit.type,
441
+ unitId: unit.id,
442
+ stage: "publish",
443
+ action: turnAction,
444
+ push: uokFlags.gitopsTurnPush,
445
+ status: gitResult.status,
446
+ error: gitResult.error,
447
+ metadata: {
448
+ dirty: gitResult.dirty,
449
+ commitMessage: gitResult.commitMessage,
450
+ snapshotLabel: gitResult.snapshotLabel,
451
+ },
452
+ });
453
+ }
454
+ if (gitResult.status === "failed") {
455
+ s.lastGitActionFailure = gitResult.error ?? `git ${turnAction} failed`;
456
+ s.lastGitActionStatus = "failed";
457
+ if (uokFlags.gitops && uokFlags.gates) {
458
+ const parsed = parseUnitId(unit.id);
459
+ const gateRunner = new UokGateRunner();
460
+ gateRunner.register({
461
+ id: "closeout-git-action",
462
+ type: "closeout",
463
+ execute: async () => ({
464
+ outcome: "fail",
465
+ failureClass: "git",
466
+ rationale: `turn git action "${turnAction}" failed`,
467
+ findings: gitResult.error ?? "unknown git failure",
468
+ }),
469
+ });
470
+ await gateRunner.run("closeout-git-action", {
471
+ basePath: s.basePath,
472
+ traceId,
473
+ turnId,
474
+ milestoneId: parsed.milestone ?? undefined,
475
+ sliceId: parsed.slice ?? undefined,
476
+ taskId: parsed.task ?? undefined,
477
+ unitType: unit.type,
478
+ unitId: unit.id,
479
+ });
480
+ }
481
+ const failureMsg = `Git ${turnAction} failed: ${(gitResult.error ?? "unknown error").split("\n")[0]}`;
482
+ ctx.ui.notify(failureMsg, opts?.softFailure ? "warning" : "error");
483
+ debugLog("postUnit", {
484
+ phase: opts?.softFailure ? "git-action-failed-soft" : "git-action-failed-blocking",
485
+ action: turnAction,
486
+ error: gitResult.error ?? "unknown error",
487
+ });
488
+ if (opts?.softFailure) {
489
+ return "continue";
490
+ }
491
+ await pauseAuto(ctx, pi);
492
+ return "dispatched";
493
+ }
494
+ s.lastGitActionStatus = "ok";
495
+ if (turnAction === "commit" && gitResult.commitMessage) {
496
+ ctx.ui.notify(`Committed: ${gitResult.commitMessage.split("\n")[0]}`, "info");
497
+ }
498
+ else if (turnAction === "snapshot" && gitResult.snapshotLabel) {
499
+ ctx.ui.notify(`Snapshot recorded: ${gitResult.snapshotLabel}`, "info");
500
+ }
501
+ }
502
+ }
503
+ catch (e) {
504
+ const message = e instanceof Error ? e.message : String(e);
505
+ s.lastGitActionFailure = message;
506
+ s.lastGitActionStatus = "failed";
507
+ debugLog("postUnit", { phase: "git-action", error: message, action: turnAction });
508
+ ctx.ui.notify(`Git ${turnAction} failed: ${message.split("\n")[0]}`, opts?.softFailure ? "warning" : "error");
509
+ if (opts?.softFailure) {
510
+ return "continue";
511
+ }
512
+ if (uokFlags.gitops) {
513
+ await pauseAuto(ctx, pi);
514
+ return "dispatched";
515
+ }
516
+ }
517
+ // GitHub sync (non-blocking, opt-in)
518
+ await runSafely("postUnit", "github-sync", async () => {
519
+ const { runGitHubSync } = await import("../github-sync/sync.js");
520
+ await runGitHubSync(s.basePath, unit.type, unit.id);
521
+ });
522
+ return "continue";
523
+ }
363
524
  /**
364
525
  * Pre-verification processing: parallel worker signal check, cache invalidation,
365
526
  * auto-commit, doctor run, state rebuild, worktree sync, artifact verification.
@@ -370,7 +531,7 @@ export async function autoCommitUnit(basePath, unitType, unitId, ctx) {
370
531
  * - "retry" — artifact verification failed, s.pendingVerificationRetry set for loop re-iteration
371
532
  */
372
533
  export async function postUnitPreVerification(pctx, opts) {
373
- const { s, ctx, pi, buildSnapshotOpts, stopAuto, pauseAuto } = pctx;
534
+ const { s, ctx, pi, stopAuto, pauseAuto } = pctx;
374
535
  // ── Parallel worker signal check ──
375
536
  const milestoneLock = process.env.GSD_MILESTONE_LOCK;
376
537
  if (milestoneLock) {
@@ -392,125 +553,22 @@ export async function postUnitPreVerification(pctx, opts) {
392
553
  if (!opts?.skipSettleDelay) {
393
554
  await new Promise(r => setTimeout(r, 100));
394
555
  }
395
- const prefs = loadEffectiveGSDPreferences()?.preferences;
396
- const uokFlags = resolveUokFlags(prefs);
397
556
  // Turn-level git action (commit | snapshot | status-only)
398
557
  if (s.currentUnit) {
399
558
  const unit = s.currentUnit;
400
- const turnAction = uokFlags.gitops ? uokFlags.gitopsTurnAction : "commit";
401
- const traceId = s.currentTraceId ?? `turn:${unit.startedAt}`;
402
- const turnId = s.currentTurnId ?? `${unit.type}/${unit.id}/${unit.startedAt}`;
403
- s.lastGitActionFailure = null;
404
- s.lastGitActionStatus = null;
405
- try {
406
- let taskContext;
407
- if (turnAction === "commit" && s.currentUnit.type === "execute-task") {
408
- taskContext = await buildTaskCommitContextForUnit(s.basePath, s.currentUnit.id);
409
- }
410
- // Invalidate the nativeHasChanges cache before auto-commit (#1853).
411
- // The cache has a 10-second TTL and is keyed by basePath. A stale
412
- // `false` result causes autoCommit to skip staging entirely, leaving
413
- // code files only in the working tree where they are destroyed by
414
- // `git worktree remove --force` during teardown.
415
- _resetHasChangesCache();
416
- const skipLifecycleCommit = turnAction === "commit" && LIFECYCLE_ONLY_UNITS.has(s.currentUnit.type);
417
- if (skipLifecycleCommit) {
418
- debugLog("postUnit", {
419
- phase: "git-action-skipped",
420
- reason: "lifecycle-only-unit",
421
- unitType: s.currentUnit.type,
422
- unitId: s.currentUnit.id,
423
- });
424
- }
425
- else {
426
- const gitResult = runTurnGitAction({
427
- basePath: s.basePath,
428
- action: turnAction,
429
- unitType: s.currentUnit.type,
430
- unitId: s.currentUnit.id,
431
- taskContext,
432
- });
433
- if (uokFlags.gitops) {
434
- writeTurnGitTransaction({
435
- basePath: s.basePath,
436
- traceId,
437
- turnId,
438
- unitType: unit.type,
439
- unitId: unit.id,
440
- stage: "publish",
441
- action: turnAction,
442
- push: uokFlags.gitopsTurnPush,
443
- status: gitResult.status,
444
- error: gitResult.error,
445
- metadata: {
446
- dirty: gitResult.dirty,
447
- commitMessage: gitResult.commitMessage,
448
- snapshotLabel: gitResult.snapshotLabel,
449
- },
450
- });
451
- }
452
- if (gitResult.status === "failed") {
453
- s.lastGitActionFailure = gitResult.error ?? `git ${turnAction} failed`;
454
- s.lastGitActionStatus = "failed";
455
- if (uokFlags.gitops && uokFlags.gates) {
456
- const parsed = parseUnitId(unit.id);
457
- const gateRunner = new UokGateRunner();
458
- gateRunner.register({
459
- id: "closeout-git-action",
460
- type: "closeout",
461
- execute: async () => ({
462
- outcome: "fail",
463
- failureClass: "git",
464
- rationale: `turn git action "${turnAction}" failed`,
465
- findings: gitResult.error ?? "unknown git failure",
466
- }),
467
- });
468
- await gateRunner.run("closeout-git-action", {
469
- basePath: s.basePath,
470
- traceId,
471
- turnId,
472
- milestoneId: parsed.milestone ?? undefined,
473
- sliceId: parsed.slice ?? undefined,
474
- taskId: parsed.task ?? undefined,
475
- unitType: unit.type,
476
- unitId: unit.id,
477
- });
478
- }
479
- const failureMsg = `Git ${turnAction} failed: ${(gitResult.error ?? "unknown error").split("\n")[0]}`;
480
- ctx.ui.notify(failureMsg, "error");
481
- debugLog("postUnit", {
482
- phase: "git-action-failed-blocking",
483
- action: turnAction,
484
- error: gitResult.error ?? "unknown error",
485
- });
486
- await pauseAuto(ctx, pi);
487
- return "dispatched";
488
- }
489
- s.lastGitActionStatus = "ok";
490
- if (turnAction === "commit" && gitResult.commitMessage) {
491
- ctx.ui.notify(`Committed: ${gitResult.commitMessage.split("\n")[0]}`, "info");
492
- }
493
- else if (turnAction === "snapshot" && gitResult.snapshotLabel) {
494
- ctx.ui.notify(`Snapshot recorded: ${gitResult.snapshotLabel}`, "info");
495
- }
496
- }
559
+ if (shouldDeferCloseoutGitAction(unit.type)) {
560
+ debugLog("postUnit", {
561
+ phase: "git-action-deferred-until-verification",
562
+ unitType: unit.type,
563
+ unitId: unit.id,
564
+ });
497
565
  }
498
- catch (e) {
499
- const message = e instanceof Error ? e.message : String(e);
500
- s.lastGitActionFailure = message;
501
- s.lastGitActionStatus = "failed";
502
- debugLog("postUnit", { phase: "git-action", error: message, action: turnAction });
503
- ctx.ui.notify(`Git ${turnAction} failed: ${message.split("\n")[0]}`, uokFlags.gitops ? "error" : "warning");
504
- if (uokFlags.gitops) {
505
- await pauseAuto(ctx, pi);
566
+ else {
567
+ const gitActionResult = await runCloseoutGitAction(pctx, unit);
568
+ if (gitActionResult === "dispatched") {
506
569
  return "dispatched";
507
570
  }
508
571
  }
509
- // GitHub sync (non-blocking, opt-in)
510
- await runSafely("postUnit", "github-sync", async () => {
511
- const { runGitHubSync } = await import("../github-sync/sync.js");
512
- await runGitHubSync(s.basePath, unit.type, unit.id);
513
- });
514
572
  // Prune dead bg-shell processes
515
573
  await runSafely("postUnit", "prune-bg-shell", async () => {
516
574
  const { pruneDeadProcesses } = await import("../bg-shell/process-manager.js");
@@ -723,7 +781,7 @@ export async function postUnitPreVerification(pctx, opts) {
723
781
  const safetyConfig = resolveSafetyHarnessConfig(prefs?.safety_harness);
724
782
  if (safetyConfig.enabled) {
725
783
  const { milestone: sMid, slice: sSid, task: sTid } = parseUnitId(s.currentUnit.id);
726
- // File change validation (execute-task only, after auto-commit)
784
+ // File change validation (execute-task only, after unit execution)
727
785
  if (safetyConfig.file_change_validation && s.currentUnit.type === "execute-task" && sMid && sSid && sTid && isDbAvailable()) {
728
786
  try {
729
787
  const taskRow = getTask(sMid, sSid, sTid);
@@ -756,12 +814,34 @@ export async function postUnitPreVerification(pctx, opts) {
756
814
  const bashCalls = actual.filter(e => e.kind === "bash");
757
815
  if (sMid && sSid && sTid && isDbAvailable()) {
758
816
  const taskRow = getTask(sMid, sSid, sTid);
759
- const claimedCommands = getVerificationEvidence(sMid, sSid, sTid)
760
- .map((row) => row.command)
761
- .filter((command) => typeof command === "string" && command.trim().length > 0);
762
- if (taskRow?.status === "complete" && claimedCommands.length > 0 && bashCalls.length === 0) {
763
- logWarning("safety", "task claimed verification command evidence but no execution tool calls were recorded");
764
- ctx.ui.notify(`Safety: task ${sTid} claimed command evidence but no execution tool calls were recorded`, "warning");
817
+ if (taskRow?.status === "complete") {
818
+ const claimedEvidence = getVerificationEvidence(sMid, sSid, sTid)
819
+ .map((row) => ({
820
+ command: row.command,
821
+ exitCode: row.exit_code,
822
+ verdict: row.verdict,
823
+ }))
824
+ .filter((row) => typeof row.command === "string" && row.command.trim().length > 0);
825
+ const mismatches = crossReferenceEvidence(claimedEvidence, actual);
826
+ for (const mismatch of mismatches) {
827
+ const logMessage = `evidence-xref: ${mismatch.reason}`;
828
+ if (mismatch.severity === "error") {
829
+ logError("safety", logMessage);
830
+ }
831
+ else {
832
+ logWarning("safety", logMessage);
833
+ }
834
+ }
835
+ if (claimedEvidence.length > 0 && bashCalls.length === 0) {
836
+ logWarning("safety", "task claimed verification command evidence but no execution tool calls were recorded");
837
+ ctx.ui.notify(`Safety: task ${sTid} claimed command evidence but no execution tool calls were recorded`, "warning");
838
+ }
839
+ const blockingMismatch = mismatches.find((mismatch) => mismatch.severity === "error");
840
+ if (blockingMismatch) {
841
+ ctx.ui.notify(`Safety: task ${sTid} claimed passing verification that failed in recorded execution`, "error");
842
+ await pauseAuto(ctx, pi);
843
+ return "dispatched";
844
+ }
765
845
  }
766
846
  }
767
847
  }
@@ -922,6 +1002,22 @@ export async function postUnitPreVerification(pctx, opts) {
922
1002
  ctx.ui.notify(`${s.currentUnit.type} ${s.currentUnit.id} — deterministic policy rejection, wrote blocker placeholder (no retries) (#4973)`, "warning");
923
1003
  // Fall through to "continue" — do NOT enter the retry or db-unavailable paths.
924
1004
  }
1005
+ else if (!triggerArtifactVerified && diagnoseWorktreeIntegrityFailure(s.basePath)) {
1006
+ const retryKey = `${s.currentUnit.type}:${s.currentUnit.id}`;
1007
+ const worktreeFailure = diagnoseWorktreeIntegrityFailure(s.basePath);
1008
+ s.pendingVerificationRetry = null;
1009
+ s.verificationRetryCount.delete(retryKey);
1010
+ s.verificationRetryFailureHashes.delete(retryKey);
1011
+ debugLog("postUnit", {
1012
+ phase: "worktree-integrity-failure",
1013
+ unitType: s.currentUnit.type,
1014
+ unitId: s.currentUnit.id,
1015
+ basePath: s.basePath,
1016
+ });
1017
+ ctx.ui.notify(`${worktreeFailure} Retry ${s.currentUnit.id} after repair.`, "error");
1018
+ await pauseAuto(ctx, pi);
1019
+ return "dispatched";
1020
+ }
925
1021
  else if (!triggerArtifactVerified && !isDbAvailable()) {
926
1022
  debugLog("postUnit", { phase: "artifact-verify-skip-db-unavailable", unitType: s.currentUnit.type, unitId: s.currentUnit.id });
927
1023
  const dbSkipDiag = diagnoseExpectedArtifact(s.currentUnit.type, s.currentUnit.id, s.basePath);
@@ -992,6 +1088,12 @@ export async function postUnitPreVerification(pctx, opts) {
992
1088
  export async function postUnitPostVerification(pctx) {
993
1089
  const { s, ctx, pi, buildSnapshotOpts, lockBase, stopAuto, pauseAuto, updateProgressWidget } = pctx;
994
1090
  if (s.currentUnit) {
1091
+ if (shouldDeferCloseoutGitAction(s.currentUnit.type)) {
1092
+ const gitActionResult = await runCloseoutGitAction(pctx, s.currentUnit, { softFailure: true });
1093
+ if (gitActionResult === "dispatched") {
1094
+ return "stopped";
1095
+ }
1096
+ }
995
1097
  try {
996
1098
  const codebasePrefs = loadEffectiveGSDPreferences()?.preferences?.codebase;
997
1099
  const refresh = ensureCodebaseMapFresh(s.basePath, codebasePrefs
@@ -1359,15 +1461,19 @@ export async function postUnitPostVerification(pctx) {
1359
1461
  // Without this notify(), /gsd in step mode finishes a unit and silently
1360
1462
  // exits the loop, leaving the user with no hint to /clear and /gsd again.
1361
1463
  if (s.stepMode) {
1464
+ let phaseAfterUnit = null;
1362
1465
  try {
1363
1466
  const nextState = await deriveState(s.canonicalProjectRoot);
1467
+ phaseAfterUnit = nextState.phase;
1364
1468
  ctx.ui.notify(buildStepCompleteMessage(nextState), "info");
1365
1469
  }
1366
1470
  catch (e) {
1367
1471
  debugLog("postUnit", { phase: "step-wizard-notify", error: String(e) });
1368
1472
  ctx.ui.notify(STEP_COMPLETE_FALLBACK_MESSAGE, "info");
1369
1473
  }
1370
- return "step-wizard";
1474
+ return shouldReturnStepWizardAfterUnit(s.currentUnit?.type, phaseAfterUnit)
1475
+ ? "step-wizard"
1476
+ : "continue";
1371
1477
  }
1372
1478
  return "continue";
1373
1479
  }