gsd-pi 2.41.0 → 2.42.0-dev.eedc83f

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 (483) hide show
  1. package/README.md +92 -29
  2. package/dist/cli-web-branch.d.ts +6 -0
  3. package/dist/cli-web-branch.js +17 -0
  4. package/dist/cli.js +15 -1
  5. package/dist/onboarding.js +2 -1
  6. package/dist/resource-loader.js +39 -6
  7. package/dist/resources/extensions/async-jobs/async-bash-tool.js +52 -4
  8. package/dist/resources/extensions/gsd/auto/loop.js +89 -1
  9. package/dist/resources/extensions/gsd/auto/phases.js +28 -10
  10. package/dist/resources/extensions/gsd/auto/session.js +6 -0
  11. package/dist/resources/extensions/gsd/auto-dashboard.js +8 -2
  12. package/dist/resources/extensions/gsd/auto-dispatch.js +19 -2
  13. package/dist/resources/extensions/gsd/auto-post-unit.js +7 -0
  14. package/dist/resources/extensions/gsd/auto-prompts.js +1 -1
  15. package/dist/resources/extensions/gsd/auto-recovery.js +12 -4
  16. package/dist/resources/extensions/gsd/auto-start.js +8 -3
  17. package/dist/resources/extensions/gsd/auto-worktree.js +147 -13
  18. package/dist/resources/extensions/gsd/auto.js +64 -2
  19. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +199 -164
  20. package/dist/resources/extensions/gsd/bootstrap/journal-tools.js +62 -0
  21. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +2 -0
  22. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +25 -3
  23. package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +7 -2
  24. package/dist/resources/extensions/gsd/commands/catalog.js +40 -1
  25. package/dist/resources/extensions/gsd/commands/handlers/core.js +1 -0
  26. package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
  27. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +146 -0
  28. package/dist/resources/extensions/gsd/context-injector.js +74 -0
  29. package/dist/resources/extensions/gsd/context-store.js +4 -3
  30. package/dist/resources/extensions/gsd/custom-execution-policy.js +47 -0
  31. package/dist/resources/extensions/gsd/custom-verification.js +145 -0
  32. package/dist/resources/extensions/gsd/custom-workflow-engine.js +164 -0
  33. package/dist/resources/extensions/gsd/dashboard-overlay.js +1 -0
  34. package/dist/resources/extensions/gsd/db-writer.js +5 -2
  35. package/dist/resources/extensions/gsd/definition-loader.js +352 -0
  36. package/dist/resources/extensions/gsd/detection.js +20 -1
  37. package/dist/resources/extensions/gsd/dev-execution-policy.js +24 -0
  38. package/dist/resources/extensions/gsd/dev-workflow-engine.js +82 -0
  39. package/dist/resources/extensions/gsd/doctor-checks.js +31 -1
  40. package/dist/resources/extensions/gsd/doctor-providers.js +10 -0
  41. package/dist/resources/extensions/gsd/doctor.js +11 -1
  42. package/dist/resources/extensions/gsd/engine-resolver.js +40 -0
  43. package/dist/resources/extensions/gsd/engine-types.js +8 -0
  44. package/dist/resources/extensions/gsd/execution-policy.js +8 -0
  45. package/dist/resources/extensions/gsd/exit-command.js +12 -2
  46. package/dist/resources/extensions/gsd/export.js +9 -13
  47. package/dist/resources/extensions/gsd/extension-manifest.json +2 -2
  48. package/dist/resources/extensions/gsd/files.js +28 -11
  49. package/dist/resources/extensions/gsd/forensics.js +94 -3
  50. package/dist/resources/extensions/gsd/git-constants.js +1 -0
  51. package/dist/resources/extensions/gsd/git-service.js +73 -3
  52. package/dist/resources/extensions/gsd/graph.js +225 -0
  53. package/dist/resources/extensions/gsd/gsd-db.js +25 -8
  54. package/dist/resources/extensions/gsd/guided-flow-queue.js +1 -1
  55. package/dist/resources/extensions/gsd/guided-flow.js +7 -3
  56. package/dist/resources/extensions/gsd/journal.js +85 -0
  57. package/dist/resources/extensions/gsd/md-importer.js +5 -0
  58. package/dist/resources/extensions/gsd/milestone-ids.js +1 -1
  59. package/dist/resources/extensions/gsd/native-git-bridge.js +3 -2
  60. package/dist/resources/extensions/gsd/post-unit-hooks.js +24 -412
  61. package/dist/resources/extensions/gsd/preferences-types.js +2 -0
  62. package/dist/resources/extensions/gsd/preferences.js +60 -8
  63. package/dist/resources/extensions/gsd/prompt-loader.js +34 -4
  64. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +11 -10
  65. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +2 -2
  66. package/dist/resources/extensions/gsd/prompts/discuss.md +1 -1
  67. package/dist/resources/extensions/gsd/prompts/forensics.md +12 -5
  68. package/dist/resources/extensions/gsd/prompts/queue.md +1 -1
  69. package/dist/resources/extensions/gsd/repo-identity.js +92 -7
  70. package/dist/resources/extensions/gsd/rule-registry.js +489 -0
  71. package/dist/resources/extensions/gsd/rule-types.js +6 -0
  72. package/dist/resources/extensions/gsd/run-manager.js +134 -0
  73. package/dist/resources/extensions/gsd/service-tier.js +147 -0
  74. package/dist/resources/extensions/gsd/session-lock.js +2 -2
  75. package/dist/resources/extensions/gsd/structured-data-formatter.js +2 -1
  76. package/dist/resources/extensions/gsd/templates/decisions.md +2 -2
  77. package/dist/resources/extensions/gsd/workflow-engine.js +7 -0
  78. package/dist/resources/extensions/gsd/workflow-templates.js +13 -1
  79. package/dist/resources/extensions/gsd/worktree-manager.js +20 -6
  80. package/dist/resources/extensions/gsd/worktree-resolver.js +21 -4
  81. package/dist/resources/extensions/mcp-client/index.js +2 -1
  82. package/dist/resources/extensions/search-the-web/tool-search.js +3 -3
  83. package/dist/resources/extensions/subagent/index.js +7 -3
  84. package/dist/resources/extensions/voice/index.js +4 -4
  85. package/dist/resources/skills/create-workflow/SKILL.md +103 -0
  86. package/dist/resources/skills/create-workflow/references/feature-patterns.md +128 -0
  87. package/dist/resources/skills/create-workflow/references/verification-policies.md +76 -0
  88. package/dist/resources/skills/create-workflow/references/yaml-schema-v1.md +46 -0
  89. package/dist/resources/skills/create-workflow/templates/blog-post-pipeline.yaml +60 -0
  90. package/dist/resources/skills/create-workflow/templates/code-audit.yaml +60 -0
  91. package/dist/resources/skills/create-workflow/templates/release-checklist.yaml +66 -0
  92. package/dist/resources/skills/create-workflow/templates/workflow-definition.yaml +32 -0
  93. package/dist/resources/skills/create-workflow/workflows/create-from-scratch.md +104 -0
  94. package/dist/resources/skills/create-workflow/workflows/create-from-template.md +72 -0
  95. package/dist/web/standalone/.next/BUILD_ID +1 -1
  96. package/dist/web/standalone/.next/app-path-routes-manifest.json +13 -13
  97. package/dist/web/standalone/.next/build-manifest.json +4 -4
  98. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  99. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  100. package/dist/web/standalone/.next/required-server-files.json +3 -3
  101. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  102. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  103. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  104. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  112. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  113. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  114. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  115. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  116. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  118. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  128. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +5 -5
  166. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  172. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  186. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  188. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  190. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  195. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  196. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  197. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  199. package/dist/web/standalone/.next/server/app/index.html +1 -1
  200. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  201. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  202. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  203. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  204. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  205. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  206. package/dist/web/standalone/.next/server/app/page.js +2 -2
  207. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  208. package/dist/web/standalone/.next/server/app-paths-manifest.json +13 -13
  209. package/dist/web/standalone/.next/server/chunks/229.js +3 -3
  210. package/dist/web/standalone/.next/server/chunks/471.js +3 -3
  211. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  212. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  213. package/dist/web/standalone/.next/server/middleware.js +2 -2
  214. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  215. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  216. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  217. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  218. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  219. package/dist/web/standalone/.next/static/chunks/4024.c195dc1fdd2adbea.js +9 -0
  220. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-f2a7482d42a5614b.js +1 -0
  221. package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +1 -0
  222. package/dist/web/standalone/.next/static/chunks/app/page-b9367c5ae13b99c6.js +1 -0
  223. package/dist/web/standalone/.next/static/chunks/{main-app-2f2ee7b85712c2bd.js → main-app-fdab67f7802d7832.js} +1 -1
  224. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  225. package/dist/web/standalone/.next/static/chunks/{webpack-9afaaebf6042a1d7.js → webpack-fa307370fcf9fb2c.js} +1 -1
  226. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  227. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  228. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  229. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  230. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  231. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  232. package/dist/web/standalone/server.js +1 -1
  233. package/dist/web-mode.d.ts +4 -0
  234. package/dist/web-mode.js +69 -11
  235. package/package.json +1 -1
  236. package/packages/native/src/__tests__/text.test.mjs +33 -0
  237. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  238. package/packages/pi-agent-core/dist/agent.js +2 -0
  239. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  240. package/packages/pi-agent-core/dist/types.d.ts +6 -0
  241. package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
  242. package/packages/pi-agent-core/dist/types.js.map +1 -1
  243. package/packages/pi-agent-core/src/agent.test.ts +53 -0
  244. package/packages/pi-agent-core/src/agent.ts +3 -0
  245. package/packages/pi-agent-core/src/types.ts +6 -0
  246. package/packages/pi-agent-core/tsconfig.json +1 -1
  247. package/packages/pi-ai/dist/models.d.ts +5 -3
  248. package/packages/pi-ai/dist/models.d.ts.map +1 -1
  249. package/packages/pi-ai/dist/models.generated.d.ts +801 -1468
  250. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  251. package/packages/pi-ai/dist/models.generated.js +1135 -1588
  252. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  253. package/packages/pi-ai/dist/models.js.map +1 -1
  254. package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
  255. package/packages/pi-ai/dist/utils/oauth/github-copilot.js +60 -2
  256. package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
  257. package/packages/pi-ai/scripts/generate-models.ts +1543 -0
  258. package/packages/pi-ai/src/models.generated.ts +1140 -1593
  259. package/packages/pi-ai/src/models.ts +7 -4
  260. package/packages/pi-ai/src/utils/oauth/github-copilot.ts +74 -2
  261. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  262. package/packages/pi-coding-agent/dist/core/agent-session.js +8 -1
  263. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  264. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +7 -0
  265. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  266. package/packages/pi-coding-agent/dist/core/auth-storage.js +29 -2
  267. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  268. package/packages/pi-coding-agent/dist/core/auth-storage.test.js +60 -0
  269. package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
  270. package/packages/pi-coding-agent/dist/core/discovery-cache.test.js +3 -1
  271. package/packages/pi-coding-agent/dist/core/discovery-cache.test.js.map +1 -1
  272. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  273. package/packages/pi-coding-agent/dist/core/extensions/loader.js +18 -0
  274. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  275. package/packages/pi-coding-agent/dist/core/lsp/client.d.ts.map +1 -1
  276. package/packages/pi-coding-agent/dist/core/lsp/client.js +23 -0
  277. package/packages/pi-coding-agent/dist/core/lsp/client.js.map +1 -1
  278. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  279. package/packages/pi-coding-agent/dist/core/model-registry.js +2 -0
  280. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  281. package/packages/pi-coding-agent/dist/core/package-manager.d.ts +6 -0
  282. package/packages/pi-coding-agent/dist/core/package-manager.d.ts.map +1 -1
  283. package/packages/pi-coding-agent/dist/core/package-manager.js +63 -11
  284. package/packages/pi-coding-agent/dist/core/package-manager.js.map +1 -1
  285. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts +9 -0
  286. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
  287. package/packages/pi-coding-agent/dist/core/resource-loader.js +20 -6
  288. package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
  289. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  290. package/packages/pi-coding-agent/dist/core/system-prompt.js +6 -5
  291. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  292. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  293. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-editor.js +3 -0
  294. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-editor.js.map +1 -1
  295. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  296. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +9 -6
  297. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  298. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  299. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +10 -7
  300. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js.map +1 -1
  301. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  302. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +34 -10
  303. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  304. package/packages/pi-coding-agent/package.json +1 -1
  305. package/packages/pi-coding-agent/src/core/agent-session.ts +7 -1
  306. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +68 -0
  307. package/packages/pi-coding-agent/src/core/auth-storage.ts +30 -2
  308. package/packages/pi-coding-agent/src/core/discovery-cache.test.ts +4 -2
  309. package/packages/pi-coding-agent/src/core/extensions/loader.ts +18 -0
  310. package/packages/pi-coding-agent/src/core/lsp/client.ts +29 -0
  311. package/packages/pi-coding-agent/src/core/model-registry.ts +3 -0
  312. package/packages/pi-coding-agent/src/core/package-manager.ts +99 -58
  313. package/packages/pi-coding-agent/src/core/resource-loader.ts +24 -6
  314. package/packages/pi-coding-agent/src/core/system-prompt.ts +6 -5
  315. package/packages/pi-coding-agent/src/modes/interactive/components/extension-editor.ts +3 -0
  316. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +10 -6
  317. package/packages/pi-coding-agent/src/modes/interactive/components/login-dialog.ts +11 -7
  318. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +36 -11
  319. package/pkg/package.json +1 -1
  320. package/src/resources/extensions/async-jobs/async-bash-timeout.test.ts +122 -0
  321. package/src/resources/extensions/async-jobs/async-bash-tool.ts +40 -4
  322. package/src/resources/extensions/gsd/auto/loop-deps.ts +5 -1
  323. package/src/resources/extensions/gsd/auto/loop.ts +101 -1
  324. package/src/resources/extensions/gsd/auto/phases.ts +30 -10
  325. package/src/resources/extensions/gsd/auto/session.ts +6 -0
  326. package/src/resources/extensions/gsd/auto/types.ts +4 -0
  327. package/src/resources/extensions/gsd/auto-dashboard.ts +9 -2
  328. package/src/resources/extensions/gsd/auto-dispatch.ts +25 -5
  329. package/src/resources/extensions/gsd/auto-post-unit.ts +8 -0
  330. package/src/resources/extensions/gsd/auto-prompts.ts +1 -1
  331. package/src/resources/extensions/gsd/auto-recovery.ts +12 -4
  332. package/src/resources/extensions/gsd/auto-start.ts +8 -3
  333. package/src/resources/extensions/gsd/auto-worktree.ts +162 -18
  334. package/src/resources/extensions/gsd/auto.ts +71 -2
  335. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +209 -162
  336. package/src/resources/extensions/gsd/bootstrap/journal-tools.ts +62 -0
  337. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +2 -0
  338. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +25 -4
  339. package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +9 -2
  340. package/src/resources/extensions/gsd/commands/catalog.ts +40 -1
  341. package/src/resources/extensions/gsd/commands/handlers/core.ts +1 -0
  342. package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
  343. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +164 -0
  344. package/src/resources/extensions/gsd/context-injector.ts +100 -0
  345. package/src/resources/extensions/gsd/context-store.ts +4 -3
  346. package/src/resources/extensions/gsd/custom-execution-policy.ts +73 -0
  347. package/src/resources/extensions/gsd/custom-verification.ts +180 -0
  348. package/src/resources/extensions/gsd/custom-workflow-engine.ts +216 -0
  349. package/src/resources/extensions/gsd/dashboard-overlay.ts +1 -0
  350. package/src/resources/extensions/gsd/db-writer.ts +6 -2
  351. package/src/resources/extensions/gsd/definition-loader.ts +462 -0
  352. package/src/resources/extensions/gsd/detection.ts +20 -1
  353. package/src/resources/extensions/gsd/dev-execution-policy.ts +51 -0
  354. package/src/resources/extensions/gsd/dev-workflow-engine.ts +110 -0
  355. package/src/resources/extensions/gsd/doctor-checks.ts +32 -1
  356. package/src/resources/extensions/gsd/doctor-providers.ts +13 -0
  357. package/src/resources/extensions/gsd/doctor-types.ts +1 -0
  358. package/src/resources/extensions/gsd/doctor.ts +12 -1
  359. package/src/resources/extensions/gsd/engine-resolver.ts +57 -0
  360. package/src/resources/extensions/gsd/engine-types.ts +71 -0
  361. package/src/resources/extensions/gsd/execution-policy.ts +43 -0
  362. package/src/resources/extensions/gsd/exit-command.ts +14 -2
  363. package/src/resources/extensions/gsd/export.ts +8 -15
  364. package/src/resources/extensions/gsd/extension-manifest.json +2 -2
  365. package/src/resources/extensions/gsd/files.ts +29 -12
  366. package/src/resources/extensions/gsd/forensics.ts +101 -3
  367. package/src/resources/extensions/gsd/git-constants.ts +1 -0
  368. package/src/resources/extensions/gsd/git-service.ts +76 -6
  369. package/src/resources/extensions/gsd/graph.ts +312 -0
  370. package/src/resources/extensions/gsd/gsd-db.ts +37 -8
  371. package/src/resources/extensions/gsd/guided-flow-queue.ts +1 -1
  372. package/src/resources/extensions/gsd/guided-flow.ts +7 -3
  373. package/src/resources/extensions/gsd/journal.ts +134 -0
  374. package/src/resources/extensions/gsd/md-importer.ts +6 -0
  375. package/src/resources/extensions/gsd/milestone-ids.ts +1 -1
  376. package/src/resources/extensions/gsd/native-git-bridge.ts +3 -2
  377. package/src/resources/extensions/gsd/post-unit-hooks.ts +24 -462
  378. package/src/resources/extensions/gsd/preferences-types.ts +6 -0
  379. package/src/resources/extensions/gsd/preferences.ts +63 -6
  380. package/src/resources/extensions/gsd/prompt-loader.ts +35 -4
  381. package/src/resources/extensions/gsd/prompts/complete-milestone.md +11 -10
  382. package/src/resources/extensions/gsd/prompts/discuss-headless.md +2 -2
  383. package/src/resources/extensions/gsd/prompts/discuss.md +1 -1
  384. package/src/resources/extensions/gsd/prompts/forensics.md +12 -5
  385. package/src/resources/extensions/gsd/prompts/queue.md +1 -1
  386. package/src/resources/extensions/gsd/repo-identity.ts +95 -7
  387. package/src/resources/extensions/gsd/rule-registry.ts +599 -0
  388. package/src/resources/extensions/gsd/rule-types.ts +68 -0
  389. package/src/resources/extensions/gsd/run-manager.ts +180 -0
  390. package/src/resources/extensions/gsd/service-tier.ts +184 -0
  391. package/src/resources/extensions/gsd/session-lock.ts +2 -2
  392. package/src/resources/extensions/gsd/structured-data-formatter.ts +3 -1
  393. package/src/resources/extensions/gsd/templates/decisions.md +2 -2
  394. package/src/resources/extensions/gsd/tests/activity-log.test.ts +31 -69
  395. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +103 -120
  396. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +85 -0
  397. package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +2 -2
  398. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +202 -0
  399. package/src/resources/extensions/gsd/tests/bundled-workflow-defs.test.ts +180 -0
  400. package/src/resources/extensions/gsd/tests/captures.test.ts +12 -1
  401. package/src/resources/extensions/gsd/tests/commands-workflow-custom.test.ts +283 -0
  402. package/src/resources/extensions/gsd/tests/context-injector.test.ts +313 -0
  403. package/src/resources/extensions/gsd/tests/context-store.test.ts +10 -5
  404. package/src/resources/extensions/gsd/tests/continue-here.test.ts +20 -20
  405. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +540 -0
  406. package/src/resources/extensions/gsd/tests/custom-verification.test.ts +382 -0
  407. package/src/resources/extensions/gsd/tests/custom-workflow-engine.test.ts +339 -0
  408. package/src/resources/extensions/gsd/tests/dashboard-custom-engine.test.ts +87 -0
  409. package/src/resources/extensions/gsd/tests/db-writer.test.ts +10 -0
  410. package/src/resources/extensions/gsd/tests/definition-loader.test.ts +778 -0
  411. package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +318 -0
  412. package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +15 -10
  413. package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +5 -4
  414. package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +167 -0
  415. package/src/resources/extensions/gsd/tests/doctor-task-done-missing-summary-slice-loop.test.ts +174 -0
  416. package/src/resources/extensions/gsd/tests/e2e-workflow-pipeline-integration.test.ts +476 -0
  417. package/src/resources/extensions/gsd/tests/engine-interfaces-contract.test.ts +271 -0
  418. package/src/resources/extensions/gsd/tests/exit-command.test.ts +55 -0
  419. package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +48 -0
  420. package/src/resources/extensions/gsd/tests/forensics-issue-routing.test.ts +43 -0
  421. package/src/resources/extensions/gsd/tests/git-locale.test.ts +133 -0
  422. package/src/resources/extensions/gsd/tests/git-service.test.ts +49 -0
  423. package/src/resources/extensions/gsd/tests/graph-operations.test.ts +599 -0
  424. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +8 -1
  425. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +7 -7
  426. package/src/resources/extensions/gsd/tests/iterate-engine-integration.test.ts +429 -0
  427. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +513 -0
  428. package/src/resources/extensions/gsd/tests/journal-query-tool.test.ts +147 -0
  429. package/src/resources/extensions/gsd/tests/journal.test.ts +341 -0
  430. package/src/resources/extensions/gsd/tests/manifest-status.test.ts +73 -82
  431. package/src/resources/extensions/gsd/tests/md-importer.test.ts +31 -1
  432. package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
  433. package/src/resources/extensions/gsd/tests/milestone-id-reservation.test.ts +1 -1
  434. package/src/resources/extensions/gsd/tests/parsers.test.ts +110 -0
  435. package/src/resources/extensions/gsd/tests/preferences.test.ts +47 -25
  436. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +3 -1
  437. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +61 -1
  438. package/src/resources/extensions/gsd/tests/routing-history.test.ts +11 -22
  439. package/src/resources/extensions/gsd/tests/rule-registry.test.ts +413 -0
  440. package/src/resources/extensions/gsd/tests/run-manager.test.ts +229 -0
  441. package/src/resources/extensions/gsd/tests/service-tier.test.ts +127 -0
  442. package/src/resources/extensions/gsd/tests/skill-lifecycle.test.ts +2 -2
  443. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +102 -0
  444. package/src/resources/extensions/gsd/tests/structured-data-formatter.test.ts +4 -3
  445. package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +151 -0
  446. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +45 -0
  447. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +117 -0
  448. package/src/resources/extensions/gsd/tests/triage-dispatch.test.ts +6 -1
  449. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +156 -263
  450. package/src/resources/extensions/gsd/tests/windows-path-normalization.test.ts +99 -0
  451. package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +1 -0
  452. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +4 -0
  453. package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +135 -0
  454. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +203 -106
  455. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +78 -3
  456. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +140 -0
  457. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +74 -0
  458. package/src/resources/extensions/gsd/types.ts +3 -0
  459. package/src/resources/extensions/gsd/workflow-engine.ts +38 -0
  460. package/src/resources/extensions/gsd/workflow-templates.ts +12 -1
  461. package/src/resources/extensions/gsd/worktree-manager.ts +21 -6
  462. package/src/resources/extensions/gsd/worktree-resolver.ts +32 -11
  463. package/src/resources/extensions/mcp-client/index.ts +5 -1
  464. package/src/resources/extensions/search-the-web/tool-search.ts +3 -3
  465. package/src/resources/extensions/subagent/index.ts +7 -3
  466. package/src/resources/extensions/voice/index.ts +4 -4
  467. package/src/resources/skills/create-workflow/SKILL.md +103 -0
  468. package/src/resources/skills/create-workflow/references/feature-patterns.md +128 -0
  469. package/src/resources/skills/create-workflow/references/verification-policies.md +76 -0
  470. package/src/resources/skills/create-workflow/references/yaml-schema-v1.md +46 -0
  471. package/src/resources/skills/create-workflow/templates/blog-post-pipeline.yaml +60 -0
  472. package/src/resources/skills/create-workflow/templates/code-audit.yaml +60 -0
  473. package/src/resources/skills/create-workflow/templates/release-checklist.yaml +66 -0
  474. package/src/resources/skills/create-workflow/templates/workflow-definition.yaml +32 -0
  475. package/src/resources/skills/create-workflow/workflows/create-from-scratch.md +104 -0
  476. package/src/resources/skills/create-workflow/workflows/create-from-template.md +72 -0
  477. package/dist/web/standalone/.next/static/chunks/4024.279c423e4661ece1.js +0 -9
  478. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-e07acdb7dd069836.js +0 -1
  479. package/dist/web/standalone/.next/static/chunks/app/layout-745c6ed5fea5fb06.js +0 -1
  480. package/dist/web/standalone/.next/static/chunks/app/page-801b53eff6e83579.js +0 -1
  481. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-e6255954dccfcf0a.js +0 -1
  482. /package/dist/web/standalone/.next/static/{Ute3pMouVczQyT15qrBBO → JUBX5FUR73jiViQU5a-Cx}/_buildManifest.js +0 -0
  483. /package/dist/web/standalone/.next/static/{Ute3pMouVczQyT15qrBBO → JUBX5FUR73jiViQU5a-Cx}/_ssgManifest.js +0 -0
package/README.md CHANGED
@@ -24,35 +24,98 @@ One command. Walk away. Come back to a built project with clean git history.
24
24
 
25
25
  ---
26
26
 
27
- ## What's New in v2.39–v2.40
28
-
29
- - **GitHub sync extension** — auto-sync milestones, slices, and tasks to GitHub Issues, PRs, and Milestones. Opt in with `github.enabled: true` in preferences. Requires `gh` CLI.
30
- - **Skill tool resolution** — skills are now resolved and activated automatically in dispatched prompts based on `always_use_skills`, `prefer_skills`, and `skill_rules` preferences. Skills are matched to dispatch context at build time.
31
- - **Health check phase 2** — `/gsd doctor` issues now surface in real time across the dashboard widget, workflow visualizer, and HTML reports with severity levels (error/warning/info).
32
- - **Forensics upgrade** `/gsd forensics` is now a full-access GSD debugger with structured anomaly detection (stuck loops, cost spikes, timeouts, missing artifacts), unit traces, and LLM-guided root-cause analysis.
33
- - **Auto PR on milestone completion** — set `git.auto_pr: true` to automatically create a draft PR when a milestone completes. Requires `auto_push: true` and `gh` CLI.
34
- - **RUNTIME.md template**declare project-level runtime context (API endpoints, env vars, deployment info) in `.gsd/RUNTIME.md`. Inlined into task execution prompts to prevent hallucination.
35
- - **Welcome screen** — branded startup UI showing version, active model, available tool keys, and quick-start commands.
36
- - **`GSD_HOME` and `GSD_PROJECT_ID` env vars** — override the global `~/.gsd` directory and per-project identity hash for CI/CD and multi-clone environments.
37
- - **Browser and runtime UAT types** — new `browser-executable` and `runtime-executable` UAT types control when auto-mode pauses for validation.
38
- - **Pipeline decomposition** — auto-loop rewritten from recursive dispatch to a linear phase pipeline (pre-dispatch → dispatch → post-unit → verification → stuck detection) for better debuggability.
39
- - **Sliding-window stuck detection** — replaces the simple counter with a pattern-aware sliding window, reducing false positives on legitimate retries.
40
- - **Data-loss recovery** — automatic detection and recovery of `.gsd/` data loss from v2.30.0–v2.38.0 migration issues, with atomic migration and rollback on failure.
41
- - **Model preferences in guided flow** — per-phase model selection now applies in step mode, not just auto mode.
42
-
43
- See the full [Changelog](./CHANGELOG.md) for details.
44
-
45
- ### Previous highlights (v2.34–v2.38)
46
-
47
- - **Reactive task execution (ADR-004)** — graph-derived parallel task dispatch within slices
48
- - **Anthropic Vertex AI provider** — Claude on Google Vertex AI
49
- - **cmux integration** — sidebar status, progress bars, and notifications for cmux terminal multiplexer users
50
- - **Redesigned dashboard** two-column layout with 4 widget modes (full → small → min → off)
51
- - **AGENTS.md support** — deprecated `agent-instructions.md` in favor of standard `AGENTS.md` / `CLAUDE.md`
52
- - **AI-powered triage** — automated issue and PR triage via Claude Haiku
53
- - **Auto-generated OpenRouter registry** — model registry built from OpenRouter API
54
- - **`/gsd changelog`**LLM-summarized release notes for any version
55
- - **Search budget enforcement** — session-level cap prevents unbounded web search
27
+ ## What's New in v2.42.0
28
+
29
+ ### New Features
30
+
31
+ - **Declarative workflow engine** — define YAML workflows that execute through auto-loop, enabling repeatable multi-step automations without code. (#2024)
32
+ - **Unified rule registry & event journal** centralized rule registry, event journal with query tool, and standardized tool naming convention. (#1928)
33
+ - **PR risk checker** — CI classifies changed files by system area and surfaces risk level on pull requests. (#1930)
34
+ - **`/gsd fast`**toggle service tier for supported models, enabling prioritized API routing for faster responses. (#1862)
35
+ - **Web mode CLI flags** — `--host`, `--port`, and `--allowed-origins` flags give full control over the web server bind address and CORS policy. (#1873)
36
+ - **ADR attribution** — architecture decision records now distinguish human, agent, and collaborative authorship. (#1830)
37
+
38
+ ### Key Fixes
39
+
40
+ - **Node v24 web boot** — resolved `ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING` that prevented `gsd --web` from starting on Node v24. (#1864)
41
+ - **Worktree health check for all ecosystems** — broadened from JS-only to 17+ ecosystems (Rust, Go, Python, Java, etc.). (#1860)
42
+ - **Doctor roadmap atomicity** — roadmap checkbox gating now checks summary on disk, not issue detection, preventing false unchecks. (#1915)
43
+ - **Windows path handling** — 8.3 short path resolution, backslash normalization in bash commands, PowerShell browser launch, and parenthesis escaping. (#1960, #1863, #1870, #1872)
44
+ - **Auth token persistence** — web UI auth token survives page refreshes via sessionStorage. (#1877)
45
+ - **German/non-English locale git errors** — git commands now force `LC_ALL=C` to prevent locale-dependent parse failures.
46
+ - **Orphan web server process** — stale web server processes on port 3000 are now cleaned up automatically.
47
+
48
+ ---
49
+
50
+ ## What's New in v2.41.0
51
+
52
+ ### New Features
53
+
54
+ - **Browser-based web interface** run GSD from the browser with `gsd --web`. Full project management, real-time progress, and multi-project support via server-sent events. (#1717)
55
+ - **Doctor: worktree lifecycle checks** — `/gsd doctor` now validates worktree health, detects orphaned worktrees, consolidates cleanup, and enhances `/worktree list` with lifecycle status. (#1814)
56
+ - **CI: docs-only PR detection** — PRs that only change documentation skip build and test steps, with a new prompt injection scan for security. (#1699)
57
+ - **Custom Models guide** — new documentation for adding custom providers (Ollama, vLLM, LM Studio, proxies) via `models.json`. (#1670)
58
+
59
+ ### Data Loss Prevention (Critical Fixes)
60
+
61
+ This release includes 7 fixes preventing silent data loss in auto-mode:
62
+
63
+ - **Hallucination guard** — execute-task agents that complete with zero tool calls are now rejected as hallucinated. Previously, agents could produce detailed but fabricated summaries without writing any code, wasting ~$25/milestone. (#1838)
64
+ - **Merge anchor verification** — before deleting a milestone worktree/branch, GSD now verifies the code is actually on the integration branch. Prevents orphaning commits when squash-merge produces an empty diff. (#1829)
65
+ - **Dirty working tree detection** — `nativeMergeSquash` now distinguishes dirty-tree rejections from content conflicts, preventing silent commit loss when synced `.gsd/` files block the merge. (#1752)
66
+ - **Doctor cleanup safety** — the `orphaned_completed_units` check no longer auto-fixes during post-task health checks. Previously, timing races could cause the doctor to remove valid completion keys, reverting users to earlier tasks. (#1825)
67
+ - **Root file reverse-sync** — worktree teardown now syncs root-level `.gsd/` files (PROJECT.md, REQUIREMENTS.md, completed-units.json) back to the project root. Previously these were lost on milestone closeout. (#1831)
68
+ - **Empty merge guard** — milestone branches with unanchored code changes are preserved instead of deleted when squash-merge produces nothing to commit. (#1755)
69
+ - **Crash-safe task closeout** — orphaned checkboxes in PLAN.md are unchecked on retry, preventing phantom task completion. (#1759)
70
+
71
+ ### Auto-Mode Stability
72
+
73
+ - **Terminal hang fix** — `stopAuto()` now resolves pending promises, preventing the terminal from freezing permanently after stopping auto-mode. (#1818)
74
+ - **Signal handler coverage** — SIGHUP and SIGINT now clean up lock files, not just SIGTERM. Prevents stranded locks on VS-Code crash. (#1821)
75
+ - **Needs-discussion routing** — milestones in `needs-discussion` phase now route to the smart entry UI instead of hard-stopping, breaking the infinite loop. (#1820)
76
+ - **Infrastructure error handling** — auto-mode stops immediately on ENOSPC, ENOMEM, and similar unrecoverable errors instead of retrying. (#1780)
77
+ - **Dependency-aware dispatch** — slice dispatch now uses declared `depends_on` instead of positional ordering. (#1770)
78
+ - **Queue mode depth verification** — the write gate now processes depth verification in queue mode, fixing a deadlock where CONTEXT.md writes were permanently blocked. (#1823)
79
+
80
+ ### Roadmap Parser Improvements
81
+
82
+ - **Table format support** — roadmaps using markdown tables (`| S01 | Title | Risk | Status |`) are now parsed correctly. (#1741)
83
+ - **Prose header fallback** — when `## Slices` contains H3 headers instead of checkboxes, the prose parser is invoked as a fallback. (#1744)
84
+ - **Completion marker detection** — prose headers with `✓` or `(Complete)` markers are correctly identified as done. (#1816)
85
+ - **Zero-slice stub handling** — stub roadmaps from `/gsd queue` return `pre-planning` instead of `blocked`. (#1826)
86
+ - **Immediate roadmap fix** — roadmap checkbox and UAT stub are fixed immediately after last task instead of deferring to `complete-slice`. (#1819)
87
+
88
+ ### State & Git Improvements
89
+
90
+ - **CONTEXT-DRAFT.md fallback** — `depends_on` is read from CONTEXT-DRAFT.md when CONTEXT.md doesn't exist, preventing draft milestones from being promoted past dependency constraints. (#1743)
91
+ - **Unborn branch support** — `nativeBranchExists` handles repos with zero commits, preventing dispatch deadlock on new repos. (#1815)
92
+ - **Ghost milestone detection** — empty `.gsd/milestones/` directories are skipped instead of crashing `deriveState()`. (#1817)
93
+ - **Default branch detection** — milestone merge detects `master` vs `main` instead of hardcoding. (#1669)
94
+ - **Milestone title extraction** — titles are pulled from CONTEXT.md headings when no ROADMAP exists. (#1729)
95
+
96
+ ### Windows & Platform
97
+
98
+ - **Windows path handling** — 8.3 short paths, `pathToFileURL` for ESM imports, and `realpathSync.native` fixes across the test suite and verification gate. (#1804)
99
+ - **DEP0190 fix** — `spawnSync` deprecation warning eliminated by passing commands to shell explicitly. (#1827)
100
+ - **Web build skip on Windows** — Next.js webpack EPERM errors on system directories are handled gracefully.
101
+
102
+ ### Developer Experience
103
+
104
+ - **@ file finder fix** — typing `@` no longer freezes the TUI. The fix adds debounce, dedup, and empty-query short-circuit. (#1832)
105
+ - **Tool-call loop guard** — detects and breaks infinite tool-call loops within a single unit, preventing stack overflow. (#1801)
106
+ - **Completion deferral fix** — roadmap checkbox and UAT stub are fixed at task level, closing the fragile handoff window between last task and `complete-slice`. (#1819)
107
+
108
+ See the full [Changelog](./CHANGELOG.md) for all 70+ fixes in this release.
109
+
110
+ ### Previous highlights (v2.39–v2.40)
111
+
112
+ - **GitHub sync extension** — auto-sync milestones to GitHub Issues, PRs, and Milestones
113
+ - **Skill tool resolution** — skills auto-activate in dispatched prompts
114
+ - **Health check phase 2** — real-time doctor issues in dashboard and visualizer
115
+ - **Forensics upgrade** — full-access GSD debugger with anomaly detection
116
+ - **Pipeline decomposition** — auto-loop rewritten as linear phase pipeline
117
+ - **Sliding-window stuck detection** — pattern-aware, fewer false positives
118
+ - **Data-loss recovery** — automatic detection and recovery from v2.30–v2.38 migration issues
56
119
 
57
120
  ---
58
121
 
@@ -13,6 +13,12 @@ export interface CliFlags {
13
13
  web?: boolean;
14
14
  /** Optional project path for web mode: `gsd --web <path>` or `gsd web start <path>` */
15
15
  webPath?: string;
16
+ /** Custom host to bind web server to: `--host 0.0.0.0` */
17
+ webHost?: string;
18
+ /** Custom port for web server: `--port 8080` */
19
+ webPort?: number;
20
+ /** Additional allowed origins for CORS: `--allowed-origins http://192.168.1.10:8080` */
21
+ webAllowedOrigins?: string[];
16
22
  help?: boolean;
17
23
  version?: boolean;
18
24
  }
@@ -29,6 +29,20 @@ export function parseCliArgs(argv) {
29
29
  flags.webPath = args[++i];
30
30
  }
31
31
  }
32
+ else if (arg === '--host' && i + 1 < args.length) {
33
+ flags.webHost = args[++i];
34
+ }
35
+ else if (arg === '--port' && i + 1 < args.length) {
36
+ const portStr = args[++i];
37
+ const port = parseInt(portStr, 10);
38
+ if (Number.isFinite(port) && port > 0 && port < 65536) {
39
+ flags.webPort = port;
40
+ }
41
+ }
42
+ else if (arg === '--allowed-origins' && i + 1 < args.length) {
43
+ const origins = args[++i].split(',').map(o => o.trim()).filter(Boolean);
44
+ flags.webAllowedOrigins = (flags.webAllowedOrigins ?? []).concat(origins);
45
+ }
32
46
  else if (arg === '--model' && i + 1 < args.length) {
33
47
  flags.model = args[++i];
34
48
  }
@@ -216,6 +230,9 @@ export async function runWebCliBranch(flags, deps = {}) {
216
230
  cwd: currentCwd,
217
231
  projectSessionsDir,
218
232
  agentDir,
233
+ host: flags.webHost,
234
+ port: flags.webPort,
235
+ allowedOrigins: flags.webAllowedOrigins,
219
236
  });
220
237
  if (!status.ok) {
221
238
  emitWebModeFailure(stderr, status);
package/dist/cli.js CHANGED
@@ -14,6 +14,14 @@ import { parseCliArgs as parseWebCliArgs, runWebCliBranch, migrateLegacyFlatSess
14
14
  import { stopWebMode } from './web-mode.js';
15
15
  import { getProjectSessionsDir } from './project-sessions.js';
16
16
  import { markStartup, printStartupTimings } from './startup-timings.js';
17
+ // ---------------------------------------------------------------------------
18
+ // V8 compile cache — Node 22+ can cache compiled bytecode across runs,
19
+ // eliminating repeated parse/compile overhead for unchanged modules.
20
+ // Must be set early so dynamic imports (extensions, lazy subcommands) benefit.
21
+ // ---------------------------------------------------------------------------
22
+ if (parseInt(process.versions.node) >= 22) {
23
+ process.env.NODE_COMPILE_CACHE ??= join(agentDir, '.compile-cache');
24
+ }
17
25
  function exitIfManagedResourcesAreNewer(currentAgentDir) {
18
26
  const currentVersion = process.env.GSD_VERSION || '0.0.0';
19
27
  const managedVersion = getNewerManagedResourceVersion(currentAgentDir, currentVersion);
@@ -461,8 +469,14 @@ const sessionManager = cliFlags._selectedSessionPath
461
469
  exitIfManagedResourcesAreNewer(agentDir);
462
470
  initResources(agentDir);
463
471
  markStartup('initResources');
472
+ // Overlap resource loading with session manager setup — both are independent.
473
+ // resourceLoader.reload() is the most expensive step (jiti compilation), so
474
+ // starting it early shaves ~50-200ms off interactive startup.
464
475
  const resourceLoader = buildResourceLoader(agentDir);
465
- await resourceLoader.reload();
476
+ const resourceLoadPromise = resourceLoader.reload();
477
+ // While resources load, let session manager finish any async I/O it needs.
478
+ // Then await the resource promise before creating the agent session.
479
+ await resourceLoadPromise;
466
480
  markStartup('resourceLoader.reload');
467
481
  const { session, extensionsResult } = await createAgentSession({
468
482
  authStorage,
@@ -94,7 +94,8 @@ async function loadPico() {
94
94
  /** Open a URL in the system browser (best-effort, non-blocking) */
95
95
  function openBrowser(url) {
96
96
  if (process.platform === 'win32') {
97
- execFile('cmd', ['/c', 'start', '', url], () => { });
97
+ // PowerShell's Start-Process handles URLs with '&' safely; cmd /c start does not.
98
+ execFile('powershell', ['-c', `Start-Process '${url.replace(/'/g, "''")}'`], () => { });
98
99
  }
99
100
  else {
100
101
  const cmd = process.platform === 'darwin' ? 'open' : 'xdg-open';
@@ -48,14 +48,25 @@ function getBundledGsdVersion() {
48
48
  }
49
49
  }
50
50
  function writeManagedResourceManifest(agentDir) {
51
- // Record root-level files currently in the bundled extensions source so that
52
- // future upgrades can detect and prune any that get removed or moved.
51
+ // Record root-level files and subdirectory extension names currently in the
52
+ // bundled extensions source so that future upgrades can detect and prune any
53
+ // that get removed or moved.
53
54
  let installedExtensionRootFiles = [];
55
+ let installedExtensionDirs = [];
54
56
  try {
55
57
  if (existsSync(bundledExtensionsDir)) {
56
- installedExtensionRootFiles = readdirSync(bundledExtensionsDir, { withFileTypes: true })
58
+ const entries = readdirSync(bundledExtensionsDir, { withFileTypes: true });
59
+ installedExtensionRootFiles = entries
57
60
  .filter(e => e.isFile())
58
61
  .map(e => e.name);
62
+ installedExtensionDirs = entries
63
+ .filter(e => e.isDirectory())
64
+ .filter(e => {
65
+ // Only track directories that are actual extensions (contain index.js or index.ts)
66
+ const dirPath = join(bundledExtensionsDir, e.name);
67
+ return existsSync(join(dirPath, 'index.js')) || existsSync(join(dirPath, 'index.ts'));
68
+ })
69
+ .map(e => e.name);
59
70
  }
60
71
  }
61
72
  catch { /* non-fatal */ }
@@ -64,6 +75,7 @@ function writeManagedResourceManifest(agentDir) {
64
75
  syncedAt: Date.now(),
65
76
  contentHash: computeResourceFingerprint(),
66
77
  installedExtensionRootFiles,
78
+ installedExtensionDirs,
67
79
  };
68
80
  writeFileSync(getManagedResourceManifestPath(agentDir), JSON.stringify(manifest));
69
81
  }
@@ -284,16 +296,20 @@ function pruneRemovedBundledExtensions(manifest, agentDir) {
284
296
  return;
285
297
  // Current bundled root-level files (what the new version provides)
286
298
  const currentSourceFiles = new Set();
299
+ // Current bundled subdirectory extensions
300
+ const currentSourceDirs = new Set();
287
301
  try {
288
302
  if (existsSync(bundledExtensionsDir)) {
289
303
  for (const e of readdirSync(bundledExtensionsDir, { withFileTypes: true })) {
290
304
  if (e.isFile())
291
305
  currentSourceFiles.add(e.name);
306
+ if (e.isDirectory())
307
+ currentSourceDirs.add(e.name);
292
308
  }
293
309
  }
294
310
  }
295
311
  catch { /* non-fatal */ }
296
- const removeIfStale = (fileName) => {
312
+ const removeFileIfStale = (fileName) => {
297
313
  if (currentSourceFiles.has(fileName))
298
314
  return; // still in bundle, not stale
299
315
  const stale = join(extensionsDir, fileName);
@@ -303,17 +319,33 @@ function pruneRemovedBundledExtensions(manifest, agentDir) {
303
319
  }
304
320
  catch { /* non-fatal */ }
305
321
  };
322
+ const removeDirIfStale = (dirName) => {
323
+ if (currentSourceDirs.has(dirName))
324
+ return; // still in bundle, not stale
325
+ const stale = join(extensionsDir, dirName);
326
+ try {
327
+ if (existsSync(stale))
328
+ rmSync(stale, { recursive: true, force: true });
329
+ }
330
+ catch { /* non-fatal */ }
331
+ };
306
332
  if (manifest?.installedExtensionRootFiles) {
307
333
  // Manifest-based: remove previously-installed root files that are no longer bundled
308
334
  for (const prevFile of manifest.installedExtensionRootFiles) {
309
- removeIfStale(prevFile);
335
+ removeFileIfStale(prevFile);
336
+ }
337
+ }
338
+ if (manifest?.installedExtensionDirs) {
339
+ // Manifest-based: remove previously-installed subdirectory extensions that are no longer bundled
340
+ for (const prevDir of manifest.installedExtensionDirs) {
341
+ removeDirIfStale(prevDir);
310
342
  }
311
343
  }
312
344
  // Always remove known stale files regardless of manifest state.
313
345
  // These were installed by pre-manifest versions so they may not appear in
314
346
  // installedExtensionRootFiles even when a manifest exists.
315
347
  // env-utils.js was moved from extensions/ root → gsd/ in v2.39.x (#1634)
316
- removeIfStale('env-utils.js');
348
+ removeFileIfStale('env-utils.js');
317
349
  }
318
350
  /**
319
351
  * Syncs all bundled resources to agentDir (~/.gsd/agent/) on every launch.
@@ -416,5 +448,6 @@ export function buildResourceLoader(agentDir) {
416
448
  return new DefaultResourceLoader({
417
449
  agentDir,
418
450
  additionalExtensionPaths: piExtensionPaths,
451
+ bundledExtensionNames: bundledKeys,
419
452
  });
420
453
  }
@@ -83,6 +83,15 @@ export function createAsyncBashTool(getManager, getCwd) {
83
83
  */
84
84
  function executeBashInBackground(command, cwd, signal, timeout) {
85
85
  return new Promise((resolve, reject) => {
86
+ let settled = false;
87
+ const safeResolve = (value) => { if (!settled) {
88
+ settled = true;
89
+ resolve(value);
90
+ } };
91
+ const safeReject = (err) => { if (!settled) {
92
+ settled = true;
93
+ reject(err);
94
+ } };
86
95
  const { shell, args } = getShellConfig();
87
96
  const resolvedCommand = sanitizeCommand(command);
88
97
  const child = spawn(shell, [...args, resolvedCommand], {
@@ -93,11 +102,42 @@ function executeBashInBackground(command, cwd, signal, timeout) {
93
102
  });
94
103
  let timedOut = false;
95
104
  let timeoutHandle;
105
+ let sigkillHandle;
106
+ let hardDeadlineHandle;
107
+ /** Grace period (ms) between SIGTERM and SIGKILL. */
108
+ const SIGKILL_GRACE_MS = 5_000;
109
+ /** Hard deadline (ms) after SIGKILL to force-resolve the promise. */
110
+ const HARD_DEADLINE_MS = 3_000;
96
111
  if (timeout !== undefined && timeout > 0) {
97
112
  timeoutHandle = setTimeout(() => {
98
113
  timedOut = true;
99
114
  if (child.pid)
100
115
  killTree(child.pid);
116
+ // If the process ignores SIGTERM, escalate to SIGKILL
117
+ sigkillHandle = setTimeout(() => {
118
+ if (child.pid) {
119
+ try {
120
+ process.kill(-child.pid, "SIGKILL");
121
+ }
122
+ catch { /* ignore */ }
123
+ try {
124
+ process.kill(child.pid, "SIGKILL");
125
+ }
126
+ catch { /* ignore */ }
127
+ }
128
+ // Hard deadline: if even SIGKILL doesn't trigger 'close',
129
+ // force-resolve so the job doesn't hang forever (#2186).
130
+ hardDeadlineHandle = setTimeout(() => {
131
+ const output = Buffer.concat(chunks).toString("utf-8");
132
+ safeResolve(output
133
+ ? `${output}\n\nCommand timed out after ${timeout} seconds (force-killed)`
134
+ : `Command timed out after ${timeout} seconds (force-killed)`);
135
+ }, HARD_DEADLINE_MS);
136
+ if (typeof hardDeadlineHandle === "object" && "unref" in hardDeadlineHandle)
137
+ hardDeadlineHandle.unref();
138
+ }, SIGKILL_GRACE_MS);
139
+ if (typeof sigkillHandle === "object" && "unref" in sigkillHandle)
140
+ sigkillHandle.unref();
101
141
  }, timeout * 1000);
102
142
  }
103
143
  const chunks = [];
@@ -139,23 +179,31 @@ function executeBashInBackground(command, cwd, signal, timeout) {
139
179
  child.on("error", (err) => {
140
180
  if (timeoutHandle)
141
181
  clearTimeout(timeoutHandle);
182
+ if (sigkillHandle)
183
+ clearTimeout(sigkillHandle);
184
+ if (hardDeadlineHandle)
185
+ clearTimeout(hardDeadlineHandle);
142
186
  signal.removeEventListener("abort", onAbort);
143
- reject(err);
187
+ safeReject(err);
144
188
  });
145
189
  child.on("close", (code) => {
146
190
  if (timeoutHandle)
147
191
  clearTimeout(timeoutHandle);
192
+ if (sigkillHandle)
193
+ clearTimeout(sigkillHandle);
194
+ if (hardDeadlineHandle)
195
+ clearTimeout(hardDeadlineHandle);
148
196
  signal.removeEventListener("abort", onAbort);
149
197
  if (spillStream)
150
198
  spillStream.end();
151
199
  if (signal.aborted) {
152
200
  const output = Buffer.concat(chunks).toString("utf-8");
153
- resolve(output ? `${output}\n\nCommand aborted` : "Command aborted");
201
+ safeResolve(output ? `${output}\n\nCommand aborted` : "Command aborted");
154
202
  return;
155
203
  }
156
204
  if (timedOut) {
157
205
  const output = Buffer.concat(chunks).toString("utf-8");
158
- resolve(output ? `${output}\n\nCommand timed out after ${timeout} seconds` : `Command timed out after ${timeout} seconds`);
206
+ safeResolve(output ? `${output}\n\nCommand timed out after ${timeout} seconds` : `Command timed out after ${timeout} seconds`);
159
207
  return;
160
208
  }
161
209
  const fullOutput = Buffer.concat(chunks).toString("utf-8");
@@ -176,7 +224,7 @@ function executeBashInBackground(command, cwd, signal, timeout) {
176
224
  if (code !== 0 && code !== null) {
177
225
  text += `\n\nCommand exited with code ${code}`;
178
226
  }
179
- resolve(text);
227
+ safeResolve(text);
180
228
  });
181
229
  });
182
230
  }
@@ -6,11 +6,13 @@
6
6
  *
7
7
  * Imports from: auto/types, auto/resolve, auto/phases
8
8
  */
9
+ import { randomUUID } from "node:crypto";
9
10
  import { MAX_LOOP_ITERATIONS, } from "./types.js";
10
11
  import { _clearCurrentResolve } from "./resolve.js";
11
12
  import { runPreDispatch, runDispatch, runGuards, runUnitPhase, runFinalize, } from "./phases.js";
12
13
  import { debugLog } from "../debug-logger.js";
13
14
  import { isInfrastructureError } from "./infra-errors.js";
15
+ import { resolveEngine } from "../engine-resolver.js";
14
16
  /**
15
17
  * Main auto-mode execution loop. Iterates: derive → dispatch → guards →
16
18
  * runUnit → finalize → repeat. Exits when s.active becomes false or a
@@ -27,6 +29,10 @@ export async function autoLoop(ctx, pi, s, deps) {
27
29
  while (s.active) {
28
30
  iteration++;
29
31
  debugLog("autoLoop", { phase: "loop-top", iteration });
32
+ // ── Journal: per-iteration flow grouping ──
33
+ const flowId = randomUUID();
34
+ let seqCounter = 0;
35
+ const nextSeq = () => ++seqCounter;
30
36
  if (iteration > MAX_LOOP_ITERATIONS) {
31
37
  debugLog("autoLoop", {
32
38
  phase: "exit",
@@ -53,6 +59,7 @@ export async function autoLoop(ctx, pi, s, deps) {
53
59
  unitType: sidecarItem.unitType,
54
60
  unitId: sidecarItem.unitId,
55
61
  });
62
+ deps.emitJournalEvent({ ts: new Date().toISOString(), flowId, seq: nextSeq(), eventType: "sidecar-dequeue", data: { kind: sidecarItem.kind, unitType: sidecarItem.unitType, unitId: sidecarItem.unitId } });
56
63
  }
57
64
  const sessionLockBase = deps.lockBase();
58
65
  if (sessionLockBase) {
@@ -73,8 +80,88 @@ export async function autoLoop(ctx, pi, s, deps) {
73
80
  break;
74
81
  }
75
82
  }
76
- const ic = { ctx, pi, s, deps, prefs, iteration };
83
+ const ic = { ctx, pi, s, deps, prefs, iteration, flowId, nextSeq };
84
+ deps.emitJournalEvent({ ts: new Date().toISOString(), flowId, seq: nextSeq(), eventType: "iteration-start", data: { iteration } });
77
85
  let iterData;
86
+ // ── Custom engine path ──────────────────────────────────────────────
87
+ // When activeEngineId is a non-dev value, bypass runPreDispatch and
88
+ // runDispatch entirely — the custom engine drives its own state via
89
+ // GRAPH.yaml. Shares runGuards and runUnitPhase with the dev path.
90
+ // After unit execution, verifies then reconciles via the engine layer.
91
+ //
92
+ // GSD_ENGINE_BYPASS=1 skips the engine layer entirely — falls through
93
+ // to the dev path below.
94
+ if (s.activeEngineId != null && s.activeEngineId !== "dev" && !sidecarItem && process.env.GSD_ENGINE_BYPASS !== "1") {
95
+ debugLog("autoLoop", { phase: "custom-engine-derive", iteration, engineId: s.activeEngineId });
96
+ const { engine, policy } = resolveEngine({
97
+ activeEngineId: s.activeEngineId,
98
+ activeRunDir: s.activeRunDir,
99
+ });
100
+ const engineState = await engine.deriveState(s.basePath);
101
+ if (engineState.isComplete) {
102
+ await deps.stopAuto(ctx, pi, "Workflow complete");
103
+ break;
104
+ }
105
+ debugLog("autoLoop", { phase: "custom-engine-dispatch", iteration });
106
+ const dispatch = await engine.resolveDispatch(engineState, { basePath: s.basePath });
107
+ if (dispatch.action === "stop") {
108
+ await deps.stopAuto(ctx, pi, dispatch.reason ?? "Engine stopped");
109
+ break;
110
+ }
111
+ if (dispatch.action === "skip") {
112
+ continue;
113
+ }
114
+ // dispatch.action === "dispatch"
115
+ const step = dispatch.step;
116
+ const gsdState = await deps.deriveState(s.basePath);
117
+ iterData = {
118
+ unitType: step.unitType,
119
+ unitId: step.unitId,
120
+ prompt: step.prompt,
121
+ finalPrompt: step.prompt,
122
+ pauseAfterUatDispatch: false,
123
+ observabilityIssues: [],
124
+ state: gsdState,
125
+ mid: s.currentMilestoneId ?? "workflow",
126
+ midTitle: "Workflow",
127
+ isRetry: false,
128
+ previousTier: undefined,
129
+ };
130
+ // ── Progress widget (mirrors dev path in runDispatch) ──
131
+ deps.updateProgressWidget(ctx, iterData.unitType, iterData.unitId, iterData.state);
132
+ // ── Guards (shared with dev path) ──
133
+ const guardsResult = await runGuards(ic, s.currentMilestoneId ?? "workflow");
134
+ if (guardsResult.action === "break")
135
+ break;
136
+ // ── Unit execution (shared with dev path) ──
137
+ const unitPhaseResult = await runUnitPhase(ic, iterData, loopState);
138
+ if (unitPhaseResult.action === "break")
139
+ break;
140
+ // ── Verify first, then reconcile (only mark complete on pass) ──
141
+ debugLog("autoLoop", { phase: "custom-engine-verify", iteration, unitId: iterData.unitId });
142
+ const verifyResult = await policy.verify(iterData.unitType, iterData.unitId, { basePath: s.basePath });
143
+ if (verifyResult === "pause") {
144
+ await deps.pauseAuto(ctx, pi);
145
+ break;
146
+ }
147
+ if (verifyResult === "retry") {
148
+ debugLog("autoLoop", { phase: "custom-engine-verify-retry", iteration, unitId: iterData.unitId });
149
+ continue;
150
+ }
151
+ // Verification passed — mark step complete
152
+ debugLog("autoLoop", { phase: "custom-engine-reconcile", iteration, unitId: iterData.unitId });
153
+ await engine.reconcile(engineState, {
154
+ unitType: iterData.unitType,
155
+ unitId: iterData.unitId,
156
+ startedAt: s.currentUnit?.startedAt ?? Date.now(),
157
+ finishedAt: Date.now(),
158
+ });
159
+ deps.clearUnitTimeout();
160
+ consecutiveErrors = 0;
161
+ deps.emitJournalEvent({ ts: new Date().toISOString(), flowId, seq: nextSeq(), eventType: "iteration-end", data: { iteration } });
162
+ debugLog("autoLoop", { phase: "iteration-complete", iteration });
163
+ continue;
164
+ }
78
165
  if (!sidecarItem) {
79
166
  // ── Phase 1: Pre-dispatch ─────────────────────────────────────────
80
167
  const preDispatchResult = await runPreDispatch(ic, loopState);
@@ -121,6 +208,7 @@ export async function autoLoop(ctx, pi, s, deps) {
121
208
  if (finalizeResult.action === "continue")
122
209
  continue;
123
210
  consecutiveErrors = 0; // Iteration completed successfully
211
+ deps.emitJournalEvent({ ts: new Date().toISOString(), flowId, seq: nextSeq(), eventType: "iteration-end", data: { iteration } });
124
212
  debugLog("autoLoop", { phase: "iteration-complete", iteration });
125
213
  }
126
214
  catch (loopErr) {