gsd-pi 2.41.0 → 2.42.0-dev.1df898f

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 (494) 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 +18 -3
  5. package/dist/loader.js +3 -1
  6. package/dist/onboarding.js +2 -1
  7. package/dist/resource-loader.js +39 -6
  8. package/dist/resources/extensions/async-jobs/async-bash-tool.js +52 -4
  9. package/dist/resources/extensions/async-jobs/await-tool.js +5 -0
  10. package/dist/resources/extensions/async-jobs/index.js +2 -0
  11. package/dist/resources/extensions/gsd/auto/loop.js +89 -1
  12. package/dist/resources/extensions/gsd/auto/phases.js +29 -13
  13. package/dist/resources/extensions/gsd/auto/session.js +6 -0
  14. package/dist/resources/extensions/gsd/auto-dashboard.js +8 -2
  15. package/dist/resources/extensions/gsd/auto-dispatch.js +19 -2
  16. package/dist/resources/extensions/gsd/auto-post-unit.js +7 -0
  17. package/dist/resources/extensions/gsd/auto-prompts.js +3 -16
  18. package/dist/resources/extensions/gsd/auto-recovery.js +12 -4
  19. package/dist/resources/extensions/gsd/auto-start.js +16 -14
  20. package/dist/resources/extensions/gsd/auto-worktree.js +147 -13
  21. package/dist/resources/extensions/gsd/auto.js +64 -2
  22. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +199 -164
  23. package/dist/resources/extensions/gsd/bootstrap/journal-tools.js +62 -0
  24. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +2 -0
  25. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +25 -3
  26. package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +7 -2
  27. package/dist/resources/extensions/gsd/commands/catalog.js +40 -1
  28. package/dist/resources/extensions/gsd/commands/handlers/core.js +1 -0
  29. package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
  30. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +146 -0
  31. package/dist/resources/extensions/gsd/context-injector.js +74 -0
  32. package/dist/resources/extensions/gsd/context-store.js +4 -3
  33. package/dist/resources/extensions/gsd/custom-execution-policy.js +47 -0
  34. package/dist/resources/extensions/gsd/custom-verification.js +145 -0
  35. package/dist/resources/extensions/gsd/custom-workflow-engine.js +164 -0
  36. package/dist/resources/extensions/gsd/dashboard-overlay.js +1 -0
  37. package/dist/resources/extensions/gsd/db-writer.js +5 -2
  38. package/dist/resources/extensions/gsd/definition-loader.js +352 -0
  39. package/dist/resources/extensions/gsd/detection.js +20 -1
  40. package/dist/resources/extensions/gsd/dev-execution-policy.js +24 -0
  41. package/dist/resources/extensions/gsd/dev-workflow-engine.js +82 -0
  42. package/dist/resources/extensions/gsd/doctor-checks.js +31 -1
  43. package/dist/resources/extensions/gsd/doctor-providers.js +10 -0
  44. package/dist/resources/extensions/gsd/doctor.js +11 -1
  45. package/dist/resources/extensions/gsd/engine-resolver.js +40 -0
  46. package/dist/resources/extensions/gsd/engine-types.js +8 -0
  47. package/dist/resources/extensions/gsd/execution-policy.js +8 -0
  48. package/dist/resources/extensions/gsd/exit-command.js +12 -2
  49. package/dist/resources/extensions/gsd/export.js +9 -13
  50. package/dist/resources/extensions/gsd/extension-manifest.json +2 -2
  51. package/dist/resources/extensions/gsd/files.js +28 -11
  52. package/dist/resources/extensions/gsd/forensics.js +94 -3
  53. package/dist/resources/extensions/gsd/git-constants.js +1 -0
  54. package/dist/resources/extensions/gsd/git-service.js +6 -2
  55. package/dist/resources/extensions/gsd/graph.js +225 -0
  56. package/dist/resources/extensions/gsd/gsd-db.js +25 -8
  57. package/dist/resources/extensions/gsd/guided-flow-queue.js +1 -1
  58. package/dist/resources/extensions/gsd/guided-flow.js +7 -3
  59. package/dist/resources/extensions/gsd/journal.js +85 -0
  60. package/dist/resources/extensions/gsd/md-importer.js +5 -0
  61. package/dist/resources/extensions/gsd/milestone-ids.js +1 -1
  62. package/dist/resources/extensions/gsd/native-git-bridge.js +3 -2
  63. package/dist/resources/extensions/gsd/post-unit-hooks.js +24 -412
  64. package/dist/resources/extensions/gsd/preferences-types.js +2 -0
  65. package/dist/resources/extensions/gsd/preferences.js +60 -8
  66. package/dist/resources/extensions/gsd/prompt-loader.js +34 -4
  67. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +11 -10
  68. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +2 -2
  69. package/dist/resources/extensions/gsd/prompts/discuss.md +1 -1
  70. package/dist/resources/extensions/gsd/prompts/forensics.md +12 -5
  71. package/dist/resources/extensions/gsd/prompts/queue.md +1 -1
  72. package/dist/resources/extensions/gsd/repo-identity.js +92 -7
  73. package/dist/resources/extensions/gsd/rule-registry.js +489 -0
  74. package/dist/resources/extensions/gsd/rule-types.js +6 -0
  75. package/dist/resources/extensions/gsd/run-manager.js +134 -0
  76. package/dist/resources/extensions/gsd/service-tier.js +147 -0
  77. package/dist/resources/extensions/gsd/session-lock.js +2 -2
  78. package/dist/resources/extensions/gsd/structured-data-formatter.js +2 -1
  79. package/dist/resources/extensions/gsd/templates/decisions.md +2 -2
  80. package/dist/resources/extensions/gsd/workflow-engine.js +7 -0
  81. package/dist/resources/extensions/gsd/workflow-templates.js +13 -1
  82. package/dist/resources/extensions/gsd/worktree-manager.js +20 -6
  83. package/dist/resources/extensions/gsd/worktree-resolver.js +21 -4
  84. package/dist/resources/extensions/gsd/worktree.js +2 -2
  85. package/dist/resources/extensions/mcp-client/index.js +2 -1
  86. package/dist/resources/extensions/search-the-web/tool-search.js +3 -3
  87. package/dist/resources/extensions/subagent/index.js +7 -3
  88. package/dist/resources/extensions/voice/index.js +4 -4
  89. package/dist/resources/skills/create-workflow/SKILL.md +103 -0
  90. package/dist/resources/skills/create-workflow/references/feature-patterns.md +128 -0
  91. package/dist/resources/skills/create-workflow/references/verification-policies.md +76 -0
  92. package/dist/resources/skills/create-workflow/references/yaml-schema-v1.md +46 -0
  93. package/dist/resources/skills/create-workflow/templates/blog-post-pipeline.yaml +60 -0
  94. package/dist/resources/skills/create-workflow/templates/code-audit.yaml +60 -0
  95. package/dist/resources/skills/create-workflow/templates/release-checklist.yaml +66 -0
  96. package/dist/resources/skills/create-workflow/templates/workflow-definition.yaml +32 -0
  97. package/dist/resources/skills/create-workflow/workflows/create-from-scratch.md +104 -0
  98. package/dist/resources/skills/create-workflow/workflows/create-from-template.md +72 -0
  99. package/dist/web/standalone/.next/BUILD_ID +1 -1
  100. package/dist/web/standalone/.next/app-path-routes-manifest.json +9 -9
  101. package/dist/web/standalone/.next/build-manifest.json +4 -4
  102. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  103. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  104. package/dist/web/standalone/.next/required-server-files.json +3 -3
  105. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  106. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  107. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  108. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  116. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  118. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  119. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  120. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  122. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  132. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +5 -5
  170. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  176. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  190. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  192. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  194. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  195. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  196. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  197. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  199. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  200. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  201. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  202. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  203. package/dist/web/standalone/.next/server/app/index.html +1 -1
  204. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  205. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  206. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  207. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  208. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  209. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  210. package/dist/web/standalone/.next/server/app/page.js +2 -2
  211. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  212. package/dist/web/standalone/.next/server/app-paths-manifest.json +9 -9
  213. package/dist/web/standalone/.next/server/chunks/229.js +3 -3
  214. package/dist/web/standalone/.next/server/chunks/471.js +3 -3
  215. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  216. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  217. package/dist/web/standalone/.next/server/middleware.js +2 -2
  218. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  219. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  220. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  221. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  222. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  223. package/dist/web/standalone/.next/static/chunks/4024.c195dc1fdd2adbea.js +9 -0
  224. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-f2a7482d42a5614b.js +1 -0
  225. package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +1 -0
  226. package/dist/web/standalone/.next/static/chunks/app/page-b9367c5ae13b99c6.js +1 -0
  227. package/dist/web/standalone/.next/static/chunks/{main-app-2f2ee7b85712c2bd.js → main-app-fdab67f7802d7832.js} +1 -1
  228. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  229. package/dist/web/standalone/.next/static/chunks/{webpack-9afaaebf6042a1d7.js → webpack-fa307370fcf9fb2c.js} +1 -1
  230. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  231. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  232. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  233. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  234. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  235. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  236. package/dist/web/standalone/server.js +1 -1
  237. package/dist/web-mode.d.ts +4 -0
  238. package/dist/web-mode.js +69 -11
  239. package/package.json +1 -1
  240. package/packages/native/src/__tests__/text.test.mjs +33 -0
  241. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  242. package/packages/pi-agent-core/dist/agent.js +2 -0
  243. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  244. package/packages/pi-agent-core/dist/types.d.ts +6 -0
  245. package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
  246. package/packages/pi-agent-core/dist/types.js.map +1 -1
  247. package/packages/pi-agent-core/src/agent.test.ts +53 -0
  248. package/packages/pi-agent-core/src/agent.ts +3 -0
  249. package/packages/pi-agent-core/src/types.ts +6 -0
  250. package/packages/pi-agent-core/tsconfig.json +1 -1
  251. package/packages/pi-ai/dist/models.d.ts +5 -3
  252. package/packages/pi-ai/dist/models.d.ts.map +1 -1
  253. package/packages/pi-ai/dist/models.generated.d.ts +801 -1468
  254. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  255. package/packages/pi-ai/dist/models.generated.js +1135 -1588
  256. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  257. package/packages/pi-ai/dist/models.js.map +1 -1
  258. package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
  259. package/packages/pi-ai/dist/utils/oauth/github-copilot.js +60 -2
  260. package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
  261. package/packages/pi-ai/scripts/generate-models.ts +1543 -0
  262. package/packages/pi-ai/src/models.generated.ts +1140 -1593
  263. package/packages/pi-ai/src/models.ts +7 -4
  264. package/packages/pi-ai/src/utils/oauth/github-copilot.ts +74 -2
  265. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  266. package/packages/pi-coding-agent/dist/core/agent-session.js +8 -1
  267. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  268. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +7 -0
  269. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  270. package/packages/pi-coding-agent/dist/core/auth-storage.js +29 -2
  271. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  272. package/packages/pi-coding-agent/dist/core/auth-storage.test.js +60 -0
  273. package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
  274. package/packages/pi-coding-agent/dist/core/discovery-cache.test.js +3 -1
  275. package/packages/pi-coding-agent/dist/core/discovery-cache.test.js.map +1 -1
  276. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  277. package/packages/pi-coding-agent/dist/core/extensions/loader.js +18 -0
  278. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  279. package/packages/pi-coding-agent/dist/core/lsp/client.d.ts.map +1 -1
  280. package/packages/pi-coding-agent/dist/core/lsp/client.js +23 -0
  281. package/packages/pi-coding-agent/dist/core/lsp/client.js.map +1 -1
  282. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  283. package/packages/pi-coding-agent/dist/core/model-registry.js +2 -0
  284. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  285. package/packages/pi-coding-agent/dist/core/package-manager.d.ts +6 -0
  286. package/packages/pi-coding-agent/dist/core/package-manager.d.ts.map +1 -1
  287. package/packages/pi-coding-agent/dist/core/package-manager.js +63 -11
  288. package/packages/pi-coding-agent/dist/core/package-manager.js.map +1 -1
  289. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts +9 -0
  290. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
  291. package/packages/pi-coding-agent/dist/core/resource-loader.js +20 -6
  292. package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
  293. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  294. package/packages/pi-coding-agent/dist/core/system-prompt.js +6 -5
  295. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  296. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  297. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-editor.js +3 -0
  298. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-editor.js.map +1 -1
  299. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  300. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +9 -6
  301. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  302. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  303. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +10 -7
  304. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js.map +1 -1
  305. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  306. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +34 -10
  307. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  308. package/packages/pi-coding-agent/package.json +1 -1
  309. package/packages/pi-coding-agent/src/core/agent-session.ts +7 -1
  310. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +68 -0
  311. package/packages/pi-coding-agent/src/core/auth-storage.ts +30 -2
  312. package/packages/pi-coding-agent/src/core/discovery-cache.test.ts +4 -2
  313. package/packages/pi-coding-agent/src/core/extensions/loader.ts +18 -0
  314. package/packages/pi-coding-agent/src/core/lsp/client.ts +29 -0
  315. package/packages/pi-coding-agent/src/core/model-registry.ts +3 -0
  316. package/packages/pi-coding-agent/src/core/package-manager.ts +99 -58
  317. package/packages/pi-coding-agent/src/core/resource-loader.ts +24 -6
  318. package/packages/pi-coding-agent/src/core/system-prompt.ts +6 -5
  319. package/packages/pi-coding-agent/src/modes/interactive/components/extension-editor.ts +3 -0
  320. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +10 -6
  321. package/packages/pi-coding-agent/src/modes/interactive/components/login-dialog.ts +11 -7
  322. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +36 -11
  323. package/pkg/package.json +1 -1
  324. package/src/resources/extensions/async-jobs/async-bash-timeout.test.ts +122 -0
  325. package/src/resources/extensions/async-jobs/async-bash-tool.ts +40 -4
  326. package/src/resources/extensions/async-jobs/await-tool.test.ts +47 -0
  327. package/src/resources/extensions/async-jobs/await-tool.ts +5 -0
  328. package/src/resources/extensions/async-jobs/index.ts +1 -0
  329. package/src/resources/extensions/async-jobs/job-manager.ts +2 -0
  330. package/src/resources/extensions/gsd/auto/loop-deps.ts +5 -2
  331. package/src/resources/extensions/gsd/auto/loop.ts +101 -1
  332. package/src/resources/extensions/gsd/auto/phases.ts +31 -13
  333. package/src/resources/extensions/gsd/auto/session.ts +6 -0
  334. package/src/resources/extensions/gsd/auto/types.ts +4 -0
  335. package/src/resources/extensions/gsd/auto-dashboard.ts +9 -2
  336. package/src/resources/extensions/gsd/auto-dispatch.ts +25 -5
  337. package/src/resources/extensions/gsd/auto-post-unit.ts +8 -0
  338. package/src/resources/extensions/gsd/auto-prompts.ts +2 -18
  339. package/src/resources/extensions/gsd/auto-recovery.ts +12 -4
  340. package/src/resources/extensions/gsd/auto-start.ts +15 -13
  341. package/src/resources/extensions/gsd/auto-worktree.ts +162 -18
  342. package/src/resources/extensions/gsd/auto.ts +71 -2
  343. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +209 -162
  344. package/src/resources/extensions/gsd/bootstrap/journal-tools.ts +62 -0
  345. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +2 -0
  346. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +25 -4
  347. package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +9 -2
  348. package/src/resources/extensions/gsd/commands/catalog.ts +40 -1
  349. package/src/resources/extensions/gsd/commands/handlers/core.ts +1 -0
  350. package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
  351. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +164 -0
  352. package/src/resources/extensions/gsd/context-injector.ts +100 -0
  353. package/src/resources/extensions/gsd/context-store.ts +4 -3
  354. package/src/resources/extensions/gsd/custom-execution-policy.ts +73 -0
  355. package/src/resources/extensions/gsd/custom-verification.ts +180 -0
  356. package/src/resources/extensions/gsd/custom-workflow-engine.ts +216 -0
  357. package/src/resources/extensions/gsd/dashboard-overlay.ts +1 -0
  358. package/src/resources/extensions/gsd/db-writer.ts +6 -2
  359. package/src/resources/extensions/gsd/definition-loader.ts +462 -0
  360. package/src/resources/extensions/gsd/detection.ts +20 -1
  361. package/src/resources/extensions/gsd/dev-execution-policy.ts +51 -0
  362. package/src/resources/extensions/gsd/dev-workflow-engine.ts +110 -0
  363. package/src/resources/extensions/gsd/doctor-checks.ts +32 -1
  364. package/src/resources/extensions/gsd/doctor-providers.ts +13 -0
  365. package/src/resources/extensions/gsd/doctor-types.ts +1 -0
  366. package/src/resources/extensions/gsd/doctor.ts +12 -1
  367. package/src/resources/extensions/gsd/engine-resolver.ts +57 -0
  368. package/src/resources/extensions/gsd/engine-types.ts +71 -0
  369. package/src/resources/extensions/gsd/execution-policy.ts +43 -0
  370. package/src/resources/extensions/gsd/exit-command.ts +14 -2
  371. package/src/resources/extensions/gsd/export.ts +8 -15
  372. package/src/resources/extensions/gsd/extension-manifest.json +2 -2
  373. package/src/resources/extensions/gsd/files.ts +29 -12
  374. package/src/resources/extensions/gsd/forensics.ts +101 -3
  375. package/src/resources/extensions/gsd/git-constants.ts +1 -0
  376. package/src/resources/extensions/gsd/git-service.ts +5 -5
  377. package/src/resources/extensions/gsd/gitignore.ts +1 -1
  378. package/src/resources/extensions/gsd/graph.ts +312 -0
  379. package/src/resources/extensions/gsd/gsd-db.ts +37 -8
  380. package/src/resources/extensions/gsd/guided-flow-queue.ts +1 -1
  381. package/src/resources/extensions/gsd/guided-flow.ts +7 -3
  382. package/src/resources/extensions/gsd/journal.ts +134 -0
  383. package/src/resources/extensions/gsd/md-importer.ts +6 -0
  384. package/src/resources/extensions/gsd/milestone-ids.ts +1 -1
  385. package/src/resources/extensions/gsd/native-git-bridge.ts +3 -2
  386. package/src/resources/extensions/gsd/post-unit-hooks.ts +24 -462
  387. package/src/resources/extensions/gsd/preferences-types.ts +6 -0
  388. package/src/resources/extensions/gsd/preferences.ts +63 -6
  389. package/src/resources/extensions/gsd/prompt-loader.ts +35 -4
  390. package/src/resources/extensions/gsd/prompts/complete-milestone.md +11 -10
  391. package/src/resources/extensions/gsd/prompts/discuss-headless.md +2 -2
  392. package/src/resources/extensions/gsd/prompts/discuss.md +1 -1
  393. package/src/resources/extensions/gsd/prompts/forensics.md +12 -5
  394. package/src/resources/extensions/gsd/prompts/queue.md +1 -1
  395. package/src/resources/extensions/gsd/repo-identity.ts +95 -7
  396. package/src/resources/extensions/gsd/rule-registry.ts +599 -0
  397. package/src/resources/extensions/gsd/rule-types.ts +68 -0
  398. package/src/resources/extensions/gsd/run-manager.ts +180 -0
  399. package/src/resources/extensions/gsd/service-tier.ts +184 -0
  400. package/src/resources/extensions/gsd/session-lock.ts +2 -2
  401. package/src/resources/extensions/gsd/structured-data-formatter.ts +3 -1
  402. package/src/resources/extensions/gsd/templates/decisions.md +2 -2
  403. package/src/resources/extensions/gsd/tests/activity-log.test.ts +31 -69
  404. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +103 -120
  405. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +85 -0
  406. package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +2 -2
  407. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +202 -0
  408. package/src/resources/extensions/gsd/tests/bundled-workflow-defs.test.ts +180 -0
  409. package/src/resources/extensions/gsd/tests/captures.test.ts +12 -1
  410. package/src/resources/extensions/gsd/tests/commands-workflow-custom.test.ts +283 -0
  411. package/src/resources/extensions/gsd/tests/context-injector.test.ts +313 -0
  412. package/src/resources/extensions/gsd/tests/context-store.test.ts +10 -5
  413. package/src/resources/extensions/gsd/tests/continue-here.test.ts +20 -20
  414. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +540 -0
  415. package/src/resources/extensions/gsd/tests/custom-verification.test.ts +382 -0
  416. package/src/resources/extensions/gsd/tests/custom-workflow-engine.test.ts +339 -0
  417. package/src/resources/extensions/gsd/tests/dashboard-custom-engine.test.ts +87 -0
  418. package/src/resources/extensions/gsd/tests/db-writer.test.ts +10 -0
  419. package/src/resources/extensions/gsd/tests/definition-loader.test.ts +778 -0
  420. package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +318 -0
  421. package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +15 -10
  422. package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +5 -4
  423. package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +167 -0
  424. package/src/resources/extensions/gsd/tests/doctor-task-done-missing-summary-slice-loop.test.ts +174 -0
  425. package/src/resources/extensions/gsd/tests/e2e-workflow-pipeline-integration.test.ts +476 -0
  426. package/src/resources/extensions/gsd/tests/engine-interfaces-contract.test.ts +271 -0
  427. package/src/resources/extensions/gsd/tests/exit-command.test.ts +55 -0
  428. package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +48 -0
  429. package/src/resources/extensions/gsd/tests/forensics-issue-routing.test.ts +43 -0
  430. package/src/resources/extensions/gsd/tests/git-locale.test.ts +133 -0
  431. package/src/resources/extensions/gsd/tests/git-service.test.ts +44 -0
  432. package/src/resources/extensions/gsd/tests/graph-operations.test.ts +599 -0
  433. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +8 -1
  434. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +7 -7
  435. package/src/resources/extensions/gsd/tests/iterate-engine-integration.test.ts +429 -0
  436. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +513 -0
  437. package/src/resources/extensions/gsd/tests/journal-query-tool.test.ts +147 -0
  438. package/src/resources/extensions/gsd/tests/journal.test.ts +341 -0
  439. package/src/resources/extensions/gsd/tests/manifest-status.test.ts +73 -82
  440. package/src/resources/extensions/gsd/tests/md-importer.test.ts +31 -1
  441. package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
  442. package/src/resources/extensions/gsd/tests/milestone-id-reservation.test.ts +1 -1
  443. package/src/resources/extensions/gsd/tests/parsers.test.ts +110 -0
  444. package/src/resources/extensions/gsd/tests/preferences.test.ts +47 -25
  445. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +3 -1
  446. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +61 -1
  447. package/src/resources/extensions/gsd/tests/routing-history.test.ts +11 -22
  448. package/src/resources/extensions/gsd/tests/rule-registry.test.ts +413 -0
  449. package/src/resources/extensions/gsd/tests/run-manager.test.ts +229 -0
  450. package/src/resources/extensions/gsd/tests/service-tier.test.ts +127 -0
  451. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +56 -3
  452. package/src/resources/extensions/gsd/tests/skill-lifecycle.test.ts +2 -2
  453. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +102 -0
  454. package/src/resources/extensions/gsd/tests/structured-data-formatter.test.ts +4 -3
  455. package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +151 -0
  456. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +45 -0
  457. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +117 -0
  458. package/src/resources/extensions/gsd/tests/triage-dispatch.test.ts +6 -1
  459. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +156 -263
  460. package/src/resources/extensions/gsd/tests/windows-path-normalization.test.ts +99 -0
  461. package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +1 -0
  462. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +4 -0
  463. package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +135 -0
  464. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +203 -106
  465. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +79 -5
  466. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +140 -0
  467. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +74 -0
  468. package/src/resources/extensions/gsd/types.ts +3 -0
  469. package/src/resources/extensions/gsd/workflow-engine.ts +38 -0
  470. package/src/resources/extensions/gsd/workflow-templates.ts +12 -1
  471. package/src/resources/extensions/gsd/worktree-manager.ts +21 -6
  472. package/src/resources/extensions/gsd/worktree-resolver.ts +32 -12
  473. package/src/resources/extensions/gsd/worktree.ts +2 -2
  474. package/src/resources/extensions/mcp-client/index.ts +5 -1
  475. package/src/resources/extensions/search-the-web/tool-search.ts +3 -3
  476. package/src/resources/extensions/subagent/index.ts +7 -3
  477. package/src/resources/extensions/voice/index.ts +4 -4
  478. package/src/resources/skills/create-workflow/SKILL.md +103 -0
  479. package/src/resources/skills/create-workflow/references/feature-patterns.md +128 -0
  480. package/src/resources/skills/create-workflow/references/verification-policies.md +76 -0
  481. package/src/resources/skills/create-workflow/references/yaml-schema-v1.md +46 -0
  482. package/src/resources/skills/create-workflow/templates/blog-post-pipeline.yaml +60 -0
  483. package/src/resources/skills/create-workflow/templates/code-audit.yaml +60 -0
  484. package/src/resources/skills/create-workflow/templates/release-checklist.yaml +66 -0
  485. package/src/resources/skills/create-workflow/templates/workflow-definition.yaml +32 -0
  486. package/src/resources/skills/create-workflow/workflows/create-from-scratch.md +104 -0
  487. package/src/resources/skills/create-workflow/workflows/create-from-template.md +72 -0
  488. package/dist/web/standalone/.next/static/chunks/4024.279c423e4661ece1.js +0 -9
  489. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-e07acdb7dd069836.js +0 -1
  490. package/dist/web/standalone/.next/static/chunks/app/layout-745c6ed5fea5fb06.js +0 -1
  491. package/dist/web/standalone/.next/static/chunks/app/page-801b53eff6e83579.js +0 -1
  492. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-e6255954dccfcf0a.js +0 -1
  493. /package/dist/web/standalone/.next/static/{Ute3pMouVczQyT15qrBBO → qw8qDHXOTLUXBq1vEknSz}/_buildManifest.js +0 -0
  494. /package/dist/web/standalone/.next/static/{Ute3pMouVczQyT15qrBBO → qw8qDHXOTLUXBq1vEknSz}/_ssgManifest.js +0 -0
@@ -337,7 +337,7 @@ function makeMockDeps(
337
337
  pruneQueueOrder: () => {},
338
338
  isInAutoWorktree: () => false,
339
339
  shouldUseWorktreeIsolation: () => false,
340
- mergeMilestoneToMain: () => ({ pushed: false }),
340
+ mergeMilestoneToMain: () => ({ pushed: false, codeFilesChanged: true }),
341
341
  teardownAutoWorktree: () => {},
342
342
  createAutoWorktree: () => "/tmp/wt",
343
343
  captureIntegrationBranch: () => {},
@@ -416,6 +416,7 @@ function makeMockDeps(
416
416
  getSessionFile: () => "/tmp/session.json",
417
417
  rebuildState: async () => {},
418
418
  resolveModelId: (id: string, models: any[]) => models.find((m: any) => m.id === id),
419
+ emitJournalEvent: () => {},
419
420
  };
420
421
 
421
422
  const merged = { ...baseDeps, ...overrides, callLog };
@@ -594,7 +595,6 @@ test("autoLoop calls deriveState → resolveDispatch → runUnit in sequence", a
594
595
  ctx.sessionManager = { getSessionFile: () => "/tmp/session.json" };
595
596
  const pi = makeMockPi();
596
597
 
597
- let loopCount = 0;
598
598
  const s = makeLoopSession();
599
599
 
600
600
  const deps = makeMockDeps({
@@ -620,11 +620,8 @@ test("autoLoop calls deriveState → resolveDispatch → runUnit in sequence", a
620
620
  },
621
621
  postUnitPostVerification: async () => {
622
622
  deps.callLog.push("postUnitPostVerification");
623
- loopCount++;
624
- // After first iteration, deactivate to exit the loop
625
- if (loopCount >= 1) {
626
- s.active = false;
627
- }
623
+ // Deactivate after first iteration to exit the loop
624
+ s.active = false;
628
625
  return "continue" as const;
629
626
  },
630
627
  });
@@ -682,7 +679,6 @@ test("crash lock records session file from AFTER newSession, not before (#1710)"
682
679
  };
683
680
  const pi = makeMockPi();
684
681
 
685
- let loopCount = 0;
686
682
  const s = makeLoopSession({
687
683
  cmdCtx: {
688
684
  newSession: () => {
@@ -730,10 +726,8 @@ test("crash lock records session file from AFTER newSession, not before (#1710)"
730
726
  },
731
727
  postUnitPostVerification: async () => {
732
728
  deps.callLog.push("postUnitPostVerification");
733
- loopCount++;
734
- if (loopCount >= 1) {
735
- s.active = false;
736
- }
729
+ // Deactivate after first iteration to exit the loop
730
+ s.active = false;
737
731
  return "continue" as const;
738
732
  },
739
733
  });
@@ -790,6 +784,23 @@ test("autoLoop handles verification retry by continuing loop", async (t) => {
790
784
  let deriveCallCount = 0;
791
785
  const s = makeLoopSession();
792
786
 
787
+ // Pre-queued verification actions: each entry provides a side-effect + return value
788
+ type VerifyAction = { sideEffect?: () => void; response: "retry" | "continue" };
789
+ const verificationActions: VerifyAction[] = [
790
+ {
791
+ sideEffect: () => {
792
+ // Simulate retry — set pendingVerificationRetry on session
793
+ s.pendingVerificationRetry = {
794
+ unitId: "M001/S01/T01",
795
+ failureContext: "test failed: expected X got Y",
796
+ attempt: 1,
797
+ };
798
+ },
799
+ response: "retry",
800
+ },
801
+ { response: "continue" },
802
+ ];
803
+
793
804
  const deps = makeMockDeps({
794
805
  deriveState: async () => {
795
806
  deriveCallCount++;
@@ -804,19 +815,11 @@ test("autoLoop handles verification retry by continuing loop", async (t) => {
804
815
  } as any;
805
816
  },
806
817
  runPostUnitVerification: async () => {
818
+ const action = verificationActions[verifyCallCount] ?? { response: "continue" as const };
807
819
  verifyCallCount++;
808
820
  deps.callLog.push("runPostUnitVerification");
809
- if (verifyCallCount === 1) {
810
- // First call: simulate retry — set pendingVerificationRetry on session
811
- s.pendingVerificationRetry = {
812
- unitId: "M001/S01/T01",
813
- failureContext: "test failed: expected X got Y",
814
- attempt: 1,
815
- };
816
- return "retry" as const;
817
- }
818
- // Second call: pass
819
- return "continue" as const;
821
+ action.sideEffect?.();
822
+ return action.response;
820
823
  },
821
824
  postUnitPostVerification: async () => {
822
825
  deps.callLog.push("postUnitPostVerification");
@@ -893,19 +896,17 @@ test("autoLoop handles dispatch skip action by continuing", async (t) => {
893
896
  const s = makeLoopSession();
894
897
 
895
898
  let dispatchCallCount = 0;
899
+ // Pre-queued dispatch responses: first call returns "skip", second returns "stop"
900
+ const dispatchResponses = [
901
+ { action: "skip" as const },
902
+ { action: "stop" as const, reason: "done", level: "info" as const },
903
+ ];
896
904
  const deps = makeMockDeps({
897
905
  resolveDispatch: async () => {
906
+ const response = dispatchResponses[dispatchCallCount] ?? dispatchResponses[dispatchResponses.length - 1];
898
907
  dispatchCallCount++;
899
908
  deps.callLog.push("resolveDispatch");
900
- if (dispatchCallCount === 1) {
901
- return { action: "skip" as const };
902
- }
903
- // Second time: stop to exit the loop
904
- return {
905
- action: "stop" as const,
906
- reason: "done",
907
- level: "info" as const,
908
- };
909
+ return response;
909
910
  },
910
911
  });
911
912
 
@@ -935,22 +936,26 @@ test("autoLoop drains sidecar queue after postUnitPostVerification enqueues item
935
936
  const s = makeLoopSession();
936
937
 
937
938
  let postVerCallCount = 0;
939
+ const postVerActions: Array<() => void> = [
940
+ () => {
941
+ // First call (main unit): enqueue a sidecar item
942
+ s.sidecarQueue.push({
943
+ kind: "hook" as const,
944
+ unitType: "hook/review",
945
+ unitId: "M001/S01/T01/review",
946
+ prompt: "review the code",
947
+ });
948
+ },
949
+ () => {
950
+ // Second call (sidecar unit completed): deactivate
951
+ s.active = false;
952
+ },
953
+ ];
938
954
  const deps = makeMockDeps({
939
955
  postUnitPostVerification: async () => {
956
+ postVerActions[postVerCallCount]?.();
940
957
  postVerCallCount++;
941
958
  deps.callLog.push("postUnitPostVerification");
942
- if (postVerCallCount === 1) {
943
- // First call (main unit): enqueue a sidecar item
944
- s.sidecarQueue.push({
945
- kind: "hook" as const,
946
- unitType: "hook/review",
947
- unitId: "M001/S01/T01/review",
948
- prompt: "review the code",
949
- });
950
- return "continue" as const;
951
- }
952
- // Second call (sidecar unit completed): done
953
- s.active = false;
954
959
  return "continue" as const;
955
960
  },
956
961
  });
@@ -1118,13 +1123,13 @@ test("startAuto calls selfHealRuntimeRecords before autoLoop (#1727)", () => {
1118
1123
  assert.ok(healIdx > -1, "startAuto must call selfHealRuntimeRecords");
1119
1124
  assert.ok(healIdx < loopIdx, "selfHealRuntimeRecords must be called before autoLoop");
1120
1125
 
1121
- // Verify the second autoLoop call site also has selfHeal before it
1126
+ // Verify the second autoLoop call site also has selfHeal before it (if present)
1122
1127
  const secondLoopIdx = fnBlock.indexOf("autoLoop(", loopIdx + 1);
1123
- if (secondLoopIdx > -1) {
1124
- const secondHealIdx = fnBlock.indexOf("selfHealRuntimeRecords", healIdx + 1);
1125
- assert.ok(secondHealIdx > -1, "second autoLoop call must also have selfHealRuntimeRecords");
1126
- assert.ok(secondHealIdx < secondLoopIdx, "second selfHealRuntimeRecords must precede second autoLoop");
1127
- }
1128
+ const secondHealIdx = fnBlock.indexOf("selfHealRuntimeRecords", healIdx + 1);
1129
+ assert.ok(
1130
+ secondLoopIdx === -1 || (secondHealIdx > -1 && secondHealIdx < secondLoopIdx),
1131
+ "if a second autoLoop call exists, it must also be preceded by selfHealRuntimeRecords",
1132
+ );
1128
1133
  });
1129
1134
 
1130
1135
  test("agent_end handler calls resolveAgentEnd (not handleAgentEnd)", () => {
@@ -1286,25 +1291,29 @@ test("stuck detection: window resets recovery when deriveState returns a differe
1286
1291
  const s = makeLoopSession();
1287
1292
 
1288
1293
  let deriveCallCount = 0;
1294
+ let postVerCallCount = 0;
1289
1295
  let stopCalled = false;
1290
1296
 
1297
+ // First 3 derives return T01, 4th returns T02; dispatch follows the derived task
1298
+ const derivedTaskIds = ["T01", "T01", "T01", "T02"];
1299
+
1291
1300
  const deps = makeMockDeps({
1292
1301
  deriveState: async () => {
1302
+ const taskId = derivedTaskIds[Math.min(deriveCallCount, derivedTaskIds.length - 1)];
1293
1303
  deriveCallCount++;
1294
1304
  deps.callLog.push("deriveState");
1295
1305
  return {
1296
1306
  phase: "executing",
1297
1307
  activeMilestone: { id: "M001", title: "Test", status: "active" },
1298
1308
  activeSlice: { id: "S01", title: "Slice 1" },
1299
- activeTask: { id: deriveCallCount <= 3 ? "T01" : "T02" },
1309
+ activeTask: { id: taskId },
1300
1310
  registry: [{ id: "M001", status: "active" }],
1301
1311
  blockers: [],
1302
1312
  } as any;
1303
1313
  },
1304
1314
  resolveDispatch: async () => {
1315
+ const taskId = derivedTaskIds[Math.min(deriveCallCount - 1, derivedTaskIds.length - 1)];
1305
1316
  deps.callLog.push("resolveDispatch");
1306
- // Return dispatch matching the task from deriveState
1307
- const taskId = deriveCallCount <= 3 ? "T01" : "T02";
1308
1317
  return {
1309
1318
  action: "dispatch" as const,
1310
1319
  unitType: "execute-task",
@@ -1318,11 +1327,11 @@ test("stuck detection: window resets recovery when deriveState returns a differe
1318
1327
  s.active = false;
1319
1328
  },
1320
1329
  postUnitPostVerification: async () => {
1330
+ postVerCallCount++;
1321
1331
  deps.callLog.push("postUnitPostVerification");
1322
- // After 4th iteration (unit changed on iter 4), exit
1323
- if (deriveCallCount >= 4) {
1324
- s.active = false;
1325
- }
1332
+ // Exit on the 4th call (after T02 unit completes)
1333
+ const shouldExit = postVerCallCount >= 4;
1334
+ s.active = !shouldExit;
1326
1335
  return "continue" as const;
1327
1336
  },
1328
1337
  });
@@ -1361,6 +1370,14 @@ test("stuck detection: does not push to window during verification retry", async
1361
1370
  let verifyCallCount = 0;
1362
1371
  let stopReason = "";
1363
1372
 
1373
+ // Pre-queued responses: 3 retries then a continue (exit)
1374
+ const verifyActions: Array<() => "retry" | "continue"> = [
1375
+ () => { s.pendingVerificationRetry = { unitId: "M001/S01/T01", failureContext: "test failed", attempt: 1 }; return "retry"; },
1376
+ () => { s.pendingVerificationRetry = { unitId: "M001/S01/T01", failureContext: "test failed", attempt: 2 }; return "retry"; },
1377
+ () => { s.pendingVerificationRetry = { unitId: "M001/S01/T01", failureContext: "test failed", attempt: 3 }; return "retry"; },
1378
+ () => { s.active = false; return "continue"; },
1379
+ ];
1380
+
1364
1381
  const deps = makeMockDeps({
1365
1382
  deriveState: async () =>
1366
1383
  ({
@@ -1378,20 +1395,10 @@ test("stuck detection: does not push to window during verification retry", async
1378
1395
  prompt: "do the thing",
1379
1396
  }),
1380
1397
  runPostUnitVerification: async () => {
1398
+ const action = verifyActions[verifyCallCount] ?? (() => { s.active = false; return "continue" as const; });
1381
1399
  verifyCallCount++;
1382
1400
  deps.callLog.push("runPostUnitVerification");
1383
- if (verifyCallCount <= 3) {
1384
- // Set pendingVerificationRetry — should prevent stuck counter increment
1385
- s.pendingVerificationRetry = {
1386
- unitId: "M001/S01/T01",
1387
- failureContext: "test failed",
1388
- attempt: verifyCallCount,
1389
- };
1390
- return "retry" as const;
1391
- }
1392
- // After 3 retries, exit gracefully
1393
- s.active = false;
1394
- return "continue" as const;
1401
+ return action();
1395
1402
  },
1396
1403
  stopAuto: async (_ctx?: any, _pi?: any, reason?: string) => {
1397
1404
  deps.callLog.push("stopAuto");
@@ -1543,7 +1550,7 @@ test("autoLoop lifecycle: advances through research → plan → execute → ver
1543
1550
  const dispatchedUnitTypes: string[] = [];
1544
1551
 
1545
1552
  // Phase sequence: each deriveState call returns a different phase.
1546
- // On the 6th call (start of iteration 6), we deactivate to exit.
1553
+ // The 6th entry (index 5) is the terminal "complete" phase that stops the loop.
1547
1554
  const phases = [
1548
1555
  // Call 1: researching → dispatches research-slice
1549
1556
  {
@@ -1575,6 +1582,12 @@ test("autoLoop lifecycle: advances through research → plan → execute → ver
1575
1582
  activeSlice: { id: "S01", title: "Complete Slice" },
1576
1583
  activeTask: null,
1577
1584
  },
1585
+ // Call 6: terminal — deactivate to exit the loop
1586
+ {
1587
+ phase: "complete",
1588
+ activeSlice: null,
1589
+ activeTask: null,
1590
+ },
1578
1591
  ];
1579
1592
 
1580
1593
  const dispatches = [
@@ -1587,46 +1600,26 @@ test("autoLoop lifecycle: advances through research → plan → execute → ver
1587
1600
 
1588
1601
  const deps = makeMockDeps({
1589
1602
  deriveState: async () => {
1603
+ const p = phases[Math.min(deriveCallCount, phases.length - 1)];
1590
1604
  deriveCallCount++;
1591
1605
  deps.callLog.push("deriveState");
1592
1606
 
1593
- if (deriveCallCount > phases.length) {
1594
- // 6th+ call: deactivate to exit the loop
1595
- s.active = false;
1596
- return {
1597
- phase: "complete",
1598
- activeMilestone: { id: "M001", title: "Test", status: "complete" },
1599
- activeSlice: null,
1600
- activeTask: null,
1601
- registry: [{ id: "M001", status: "complete" }],
1602
- blockers: [],
1603
- } as any;
1604
- }
1605
-
1606
- const p = phases[deriveCallCount - 1];
1607
+ const terminalPhases: Record<string, string> = { complete: "complete" };
1608
+ s.active = p.phase !== "complete";
1609
+ const milestoneStatus = terminalPhases[p.phase] ?? "active";
1607
1610
  return {
1608
1611
  phase: p.phase,
1609
- activeMilestone: { id: "M001", title: "Test", status: "active" },
1610
- activeSlice: p.activeSlice,
1611
- activeTask: p.activeTask,
1612
- registry: [{ id: "M001", status: "active" }],
1612
+ activeMilestone: { id: "M001", title: "Test", status: milestoneStatus },
1613
+ activeSlice: p.activeSlice ?? null,
1614
+ activeTask: p.activeTask ?? null,
1615
+ registry: [{ id: "M001", status: milestoneStatus }],
1613
1616
  blockers: [],
1614
1617
  } as any;
1615
1618
  },
1616
1619
  resolveDispatch: async () => {
1620
+ const d = dispatches[Math.min(dispatchCallCount, dispatches.length - 1)];
1617
1621
  dispatchCallCount++;
1618
1622
  deps.callLog.push("resolveDispatch");
1619
-
1620
- if (dispatchCallCount > dispatches.length) {
1621
- // Safety: shouldn't reach here, but stop if it does
1622
- return {
1623
- action: "stop" as const,
1624
- reason: "done",
1625
- level: "info" as const,
1626
- };
1627
- }
1628
-
1629
- const d = dispatches[dispatchCallCount - 1];
1630
1623
  dispatchedUnitTypes.push(d.unitType);
1631
1624
  return {
1632
1625
  action: "dispatch" as const,
@@ -1691,18 +1684,11 @@ test("autoLoop lifecycle: advances through research → plan → execute → ver
1691
1684
  `callLog should have at least 5 resolveDispatch entries (got ${dispatchEntries.length})`,
1692
1685
  );
1693
1686
 
1694
- // Verify interleaving: each resolveDispatch should follow a deriveState
1695
- let dispatchSeen = 0;
1696
- for (const entry of deps.callLog) {
1697
- if (entry === "resolveDispatch") {
1698
- dispatchSeen++;
1699
- }
1700
- if (entry === "deriveState" && dispatchSeen > 0) {
1701
- // A deriveState after a resolveDispatch confirms the loop advanced
1702
- break;
1703
- }
1704
- }
1705
- assert.ok(dispatchSeen > 0, "resolveDispatch should appear in callLog");
1687
+ // Verify interleaving: a deriveState must follow a resolveDispatch (confirms loop advanced)
1688
+ const firstDispatchIdx = deps.callLog.indexOf("resolveDispatch");
1689
+ const firstDeriveAfterDispatch = deps.callLog.indexOf("deriveState", firstDispatchIdx + 1);
1690
+ assert.ok(firstDispatchIdx >= 0, "resolveDispatch should appear in callLog");
1691
+ assert.ok(firstDeriveAfterDispatch > firstDispatchIdx, "deriveState should follow resolveDispatch to confirm loop advanced");
1706
1692
 
1707
1693
  // Assert the exact sequence of dispatched unit types
1708
1694
  assert.deepEqual(
@@ -1775,6 +1761,8 @@ test("autoLoop re-iterates when postUnitPreVerification returns retry (#1571)",
1775
1761
  const s = makeLoopSession();
1776
1762
 
1777
1763
  let preVerifyCallCount = 0;
1764
+ // Pre-queued responses: first call returns "retry", second returns "continue"
1765
+ const preVerifyResponses = ["retry", "continue"] as const;
1778
1766
 
1779
1767
  const deps = makeMockDeps({
1780
1768
  deriveState: async () => {
@@ -1790,11 +1778,7 @@ test("autoLoop re-iterates when postUnitPreVerification returns retry (#1571)",
1790
1778
  },
1791
1779
  postUnitPreVerification: async () => {
1792
1780
  deps.callLog.push("postUnitPreVerification");
1793
- preVerifyCallCount++;
1794
- if (preVerifyCallCount === 1) {
1795
- return "retry" as const;
1796
- }
1797
- return "continue" as const;
1781
+ return preVerifyResponses[preVerifyCallCount++] ?? "continue";
1798
1782
  },
1799
1783
  postUnitPostVerification: async () => {
1800
1784
  deps.callLog.push("postUnitPostVerification");
@@ -1907,9 +1891,8 @@ test("autoLoop rejects execute-task with 0 tool calls as hallucinated (#1833)",
1907
1891
  postUnitPostVerification: async () => {
1908
1892
  deps.callLog.push("postUnitPostVerification");
1909
1893
  iterationCount++;
1910
- if (iterationCount >= 2) {
1911
- s.active = false;
1912
- }
1894
+ // Deactivate after 2nd iteration
1895
+ s.active = iterationCount < 2;
1913
1896
  return "continue" as const;
1914
1897
  },
1915
1898
  });
@@ -2122,7 +2105,7 @@ test("autoLoop stops when worktree has no project files for execute-task (#1833)
2122
2105
  "should stop auto-mode when worktree has no project files",
2123
2106
  );
2124
2107
  const healthNotification = notifications.find(
2125
- (n) => n.includes("Worktree health check failed") && n.includes("no package.json or src/"),
2108
+ (n) => n.includes("Worktree health check failed") && n.includes("no recognized project files"),
2126
2109
  );
2127
2110
  assert.ok(
2128
2111
  healthNotification,
@@ -386,6 +386,91 @@ test("verifyExpectedArtifact plan-slice fails for plan with no tasks (#699)", ()
386
386
  }
387
387
  });
388
388
 
389
+ // ─── verifyExpectedArtifact: heading-style plan tasks (#1691) ─────────────
390
+
391
+ test("verifyExpectedArtifact accepts plan-slice with heading-style tasks (### T01 --)", () => {
392
+ const base = makeTmpBase();
393
+ try {
394
+ const sliceDir = join(base, ".gsd", "milestones", "M001", "slices", "S01");
395
+ const tasksDir = join(sliceDir, "tasks");
396
+ mkdirSync(tasksDir, { recursive: true });
397
+ writeFileSync(join(sliceDir, "S01-PLAN.md"), [
398
+ "# S01: Test Slice",
399
+ "",
400
+ "## Tasks",
401
+ "",
402
+ "### T01 -- Implement feature",
403
+ "",
404
+ "Feature description.",
405
+ "",
406
+ "### T02 -- Write tests",
407
+ "",
408
+ "Test description.",
409
+ ].join("\n"));
410
+ writeFileSync(join(tasksDir, "T01-PLAN.md"), "# T01 Plan");
411
+ writeFileSync(join(tasksDir, "T02-PLAN.md"), "# T02 Plan");
412
+ assert.strictEqual(
413
+ verifyExpectedArtifact("plan-slice", "M001/S01", base),
414
+ true,
415
+ "Heading-style plan with task entries should be treated as completed artifact",
416
+ );
417
+ } finally {
418
+ cleanup(base);
419
+ }
420
+ });
421
+
422
+ test("verifyExpectedArtifact accepts plan-slice with colon-style heading tasks (### T01:)", () => {
423
+ const base = makeTmpBase();
424
+ try {
425
+ const sliceDir = join(base, ".gsd", "milestones", "M001", "slices", "S01");
426
+ const tasksDir = join(sliceDir, "tasks");
427
+ mkdirSync(tasksDir, { recursive: true });
428
+ writeFileSync(join(sliceDir, "S01-PLAN.md"), [
429
+ "# S01: Test Slice",
430
+ "",
431
+ "## Tasks",
432
+ "",
433
+ "### T01: Implement feature",
434
+ "",
435
+ "Feature description.",
436
+ ].join("\n"));
437
+ writeFileSync(join(tasksDir, "T01-PLAN.md"), "# T01 Plan");
438
+ assert.strictEqual(
439
+ verifyExpectedArtifact("plan-slice", "M001/S01", base),
440
+ true,
441
+ "Colon heading-style plan should be treated as completed artifact",
442
+ );
443
+ } finally {
444
+ cleanup(base);
445
+ }
446
+ });
447
+
448
+ test("verifyExpectedArtifact execute-task passes for heading-style plan entry (#1691)", () => {
449
+ const base = makeTmpBase();
450
+ try {
451
+ const sliceDir = join(base, ".gsd", "milestones", "M001", "slices", "S01");
452
+ const tasksDir = join(sliceDir, "tasks");
453
+ mkdirSync(tasksDir, { recursive: true });
454
+ writeFileSync(join(sliceDir, "S01-PLAN.md"), [
455
+ "# S01: Test Slice",
456
+ "",
457
+ "## Tasks",
458
+ "",
459
+ "### T01 -- Implement feature",
460
+ "",
461
+ "Feature description.",
462
+ ].join("\n"));
463
+ writeFileSync(join(tasksDir, "T01-SUMMARY.md"), "# T01 Summary\n\nDone.");
464
+ assert.strictEqual(
465
+ verifyExpectedArtifact("execute-task", "M001/S01/T01", base),
466
+ true,
467
+ "execute-task should pass for heading-style plan entry when summary exists",
468
+ );
469
+ } finally {
470
+ cleanup(base);
471
+ }
472
+ });
473
+
389
474
  // ─── selfHealRuntimeRecords — worktree base path (#769) ──────────────────
390
475
 
391
476
  test("selfHealRuntimeRecords clears stale dispatched records (#769)", async () => {
@@ -101,8 +101,8 @@ test('secrets gate: pending keys exist — gate triggers collection, manifest up
101
101
  const status = await getManifestStatus(tmp, 'M001');
102
102
  assert.notStrictEqual(status, null, 'manifest should exist');
103
103
  assert.ok(status!.pending.length > 0, 'should have pending keys');
104
- assert.deepStrictEqual(status!.pending, ['GSD_GATE_TEST_PEND_A', 'GSD_GATE_TEST_PEND_B']);
105
- assert.deepStrictEqual(status!.existing, ['GSD_GATE_TEST_EXISTING']);
104
+ assert.deepStrictEqual(status!.pending, ['GSD_GATE_TEST_PEND_A', 'GSD_GATE_TEST_PEND_B'], 'pending keys');
105
+ assert.deepStrictEqual(status!.existing, ['GSD_GATE_TEST_EXISTING'], 'existing keys');
106
106
 
107
107
  // (b) Call collectSecretsFromManifest with no-UI context
108
108
  // With hasUI: false, collectOneSecret returns null → pending keys become "skipped"