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
@@ -0,0 +1,164 @@
1
+ /**
2
+ * custom-workflow-engine.ts — WorkflowEngine implementation for custom workflows.
3
+ *
4
+ * Drives the auto-loop using GRAPH.yaml step state from a run directory.
5
+ * Each iteration: deriveState reads the graph, resolveDispatch picks the
6
+ * next eligible step, reconcile marks it complete and persists.
7
+ *
8
+ * Observability:
9
+ * - All state reads/writes go through graph.ts YAML I/O — inspectable on disk.
10
+ * - `resolveDispatch` returns unitType "custom-step" with unitId "<name>/<stepId>".
11
+ * - `getDisplayMetadata` provides step N/M progress for dashboard rendering.
12
+ * - Phase transitions are derivable from GRAPH.yaml step statuses.
13
+ */
14
+ import { readFileSync } from "node:fs";
15
+ import { join } from "node:path";
16
+ import { parse } from "yaml";
17
+ import { readGraph, writeGraph, getNextPendingStep, markStepComplete, expandIteration, } from "./graph.js";
18
+ import { injectContext } from "./context-injector.js";
19
+ /** Read and parse the frozen DEFINITION.yaml from a run directory. */
20
+ export function readFrozenDefinition(runDir) {
21
+ const defPath = join(runDir, "DEFINITION.yaml");
22
+ const raw = readFileSync(defPath, "utf-8");
23
+ return parse(raw, { schema: "core" });
24
+ }
25
+ export class CustomWorkflowEngine {
26
+ engineId = "custom";
27
+ runDir;
28
+ constructor(runDir) {
29
+ this.runDir = runDir;
30
+ }
31
+ /**
32
+ * Derive engine state from GRAPH.yaml on disk.
33
+ *
34
+ * Phase is "complete" when all steps are complete or expanded,
35
+ * "running" otherwise (any pending or active steps remain).
36
+ */
37
+ async deriveState(_basePath) {
38
+ const graph = readGraph(this.runDir);
39
+ const allDone = graph.steps.every((s) => s.status === "complete" || s.status === "expanded");
40
+ const phase = allDone ? "complete" : "running";
41
+ return {
42
+ phase,
43
+ currentMilestoneId: null,
44
+ activeSliceId: null,
45
+ activeTaskId: null,
46
+ isComplete: allDone,
47
+ raw: graph,
48
+ };
49
+ }
50
+ /**
51
+ * Resolve the next dispatch action from graph state.
52
+ *
53
+ * Uses getNextPendingStep to find the first step whose dependencies
54
+ * are all satisfied. If the step has an `iterate` config in the frozen
55
+ * DEFINITION.yaml, expands it into instance steps before dispatching.
56
+ *
57
+ * Returns a dispatch with unitType "custom-step" and unitId in
58
+ * "<workflowName>/<stepId>" format.
59
+ *
60
+ * Observability:
61
+ * - Iterate expansion is logged to stderr with item count and parent step ID.
62
+ * - Missing source artifacts throw with the full resolved path for diagnosis.
63
+ * - Zero-match expansions return a stop action with level "info".
64
+ * - Expanded GRAPH.yaml is written to disk before dispatch — inspectable on disk.
65
+ */
66
+ async resolveDispatch(state, _context) {
67
+ let graph = state.raw;
68
+ let next = getNextPendingStep(graph);
69
+ if (!next) {
70
+ return {
71
+ action: "stop",
72
+ reason: "All steps complete",
73
+ level: "info",
74
+ };
75
+ }
76
+ // Check frozen DEFINITION.yaml for iterate config on this step
77
+ const def = readFrozenDefinition(this.runDir);
78
+ const stepDef = def.steps.find((s) => s.id === next.id);
79
+ if (stepDef?.iterate) {
80
+ const iterate = stepDef.iterate;
81
+ // Read source artifact
82
+ const sourcePath = join(this.runDir, iterate.source);
83
+ let sourceContent;
84
+ try {
85
+ sourceContent = readFileSync(sourcePath, "utf-8");
86
+ }
87
+ catch {
88
+ throw new Error(`Iterate source artifact not found: ${sourcePath} (step "${next.id}", source: "${iterate.source}")`);
89
+ }
90
+ // Extract items via regex with global+multiline flags.
91
+ // Guard against ReDoS: if matching takes too long on large inputs, bail.
92
+ const regex = new RegExp(iterate.pattern, "gm");
93
+ const items = [];
94
+ const matchStart = Date.now();
95
+ let match;
96
+ while ((match = regex.exec(sourceContent)) !== null) {
97
+ if (match[1] !== undefined)
98
+ items.push(match[1]);
99
+ if (Date.now() - matchStart > 5_000) {
100
+ throw new Error(`Iterate pattern "${iterate.pattern}" exceeded 5s timeout on step "${next.id}" — possible ReDoS`);
101
+ }
102
+ }
103
+ // Expand the graph
104
+ const expandedGraph = expandIteration(graph, next.id, items, next.prompt);
105
+ writeGraph(this.runDir, expandedGraph);
106
+ graph = expandedGraph;
107
+ // Re-query for first instance step
108
+ next = getNextPendingStep(expandedGraph);
109
+ if (!next) {
110
+ return {
111
+ action: "stop",
112
+ reason: "Iterate expansion produced no instances",
113
+ level: "info",
114
+ };
115
+ }
116
+ }
117
+ // Enrich prompt with context from prior step artifacts
118
+ const enrichedPrompt = injectContext(this.runDir, next.id, next.prompt);
119
+ return {
120
+ action: "dispatch",
121
+ step: {
122
+ unitType: "custom-step",
123
+ unitId: `${graph.metadata.name}/${next.id}`,
124
+ prompt: enrichedPrompt,
125
+ },
126
+ };
127
+ }
128
+ /**
129
+ * Reconcile state after a step completes.
130
+ *
131
+ * Extracts the stepId from the completedStep's unitId (last segment after `/`),
132
+ * marks it complete in the graph, and writes the updated GRAPH.yaml to disk.
133
+ *
134
+ * Returns "milestone-complete" when all steps are now done, "continue" otherwise.
135
+ */
136
+ async reconcile(state, completedStep) {
137
+ const graph = state.raw;
138
+ // Extract stepId from "<workflowName>/<stepId>"
139
+ const parts = completedStep.unitId.split("/");
140
+ const stepId = parts[parts.length - 1];
141
+ const updatedGraph = markStepComplete(graph, stepId);
142
+ writeGraph(this.runDir, updatedGraph);
143
+ const allDone = updatedGraph.steps.every((s) => s.status === "complete" || s.status === "expanded");
144
+ return {
145
+ outcome: allDone ? "milestone-complete" : "continue",
146
+ };
147
+ }
148
+ /**
149
+ * Return UI-facing metadata for progress display.
150
+ *
151
+ * Shows "Step N/M" progress where N = completed count and M = total.
152
+ */
153
+ getDisplayMetadata(state) {
154
+ const graph = state.raw;
155
+ const total = graph.steps.length;
156
+ const completed = graph.steps.filter((s) => s.status === "complete").length;
157
+ return {
158
+ engineLabel: "WORKFLOW",
159
+ currentPhase: state.phase,
160
+ progressSummary: `Step ${completed}/${total}`,
161
+ stepCount: { completed, total },
162
+ };
163
+ }
164
+ }
@@ -30,6 +30,7 @@ function unitLabel(type) {
30
30
  case "triage-captures": return "Triage";
31
31
  case "quick-task": return "Quick Task";
32
32
  case "replan-slice": return "Replan";
33
+ case "custom-step": return "Workflow Step";
33
34
  default: return type;
34
35
  }
35
36
  }
@@ -30,8 +30,8 @@ export function generateDecisionsMd(decisions) {
30
30
  lines.push(' To reverse a decision, add a new row that supersedes it.');
31
31
  lines.push(' Read this file at the start of any planning or research phase. -->');
32
32
  lines.push('');
33
- lines.push('| # | When | Scope | Decision | Choice | Rationale | Revisable? |');
34
- lines.push('|---|------|-------|----------|--------|-----------|------------|');
33
+ lines.push('| # | When | Scope | Decision | Choice | Rationale | Revisable? | Made By |');
34
+ lines.push('|---|------|-------|----------|--------|-----------|------------|---------|');
35
35
  for (const d of decisions) {
36
36
  // Escape pipe characters within cell values to preserve table structure
37
37
  const cells = [
@@ -42,6 +42,7 @@ export function generateDecisionsMd(decisions) {
42
42
  d.choice,
43
43
  d.rationale,
44
44
  d.revisable,
45
+ d.made_by ?? 'agent',
45
46
  ].map(cell => (cell ?? '').replace(/\|/g, '\\|'));
46
47
  lines.push(`| ${cells.join(' | ')} |`);
47
48
  }
@@ -172,6 +173,7 @@ export async function saveDecisionToDb(fields, basePath) {
172
173
  choice: fields.choice,
173
174
  rationale: fields.rationale,
174
175
  revisable: fields.revisable ?? 'Yes',
176
+ made_by: fields.made_by ?? 'agent',
175
177
  superseded_by: null,
176
178
  });
177
179
  // Fetch all decisions (including superseded for the full register)
@@ -188,6 +190,7 @@ export async function saveDecisionToDb(fields, basePath) {
188
190
  choice: row['choice'],
189
191
  rationale: row['rationale'],
190
192
  revisable: row['revisable'],
193
+ made_by: row['made_by'] ?? 'agent',
191
194
  superseded_by: row['superseded_by'] ?? null,
192
195
  }));
193
196
  }
@@ -0,0 +1,352 @@
1
+ /**
2
+ * definition-loader.ts — Parse and validate V1 YAML workflow definitions.
3
+ *
4
+ * Loads definition YAML files from `.gsd/workflow-defs/`, validates the
5
+ * V1 schema shape, and returns typed TypeScript objects. Pure functions
6
+ * with no engine or runtime dependencies — just `yaml` and `node:fs`.
7
+ *
8
+ * YAML uses snake_case (`depends_on`, `context_from`) per project convention (P005).
9
+ * TypeScript uses camelCase (`dependsOn`, `contextFrom`).
10
+ *
11
+ * Observability: All validation errors are collected into a string[] — callers
12
+ * can log, surface in dashboards, or return to agents for self-repair.
13
+ * substituteParams errors include the offending key name for traceability.
14
+ */
15
+ import { parse } from "yaml";
16
+ import { readFileSync, existsSync } from "node:fs";
17
+ import { join } from "node:path";
18
+ // ─── Validation ──────────────────────────────────────────────────────────
19
+ /**
20
+ * Validate a parsed (but untyped) YAML object against the V1 workflow schema.
21
+ *
22
+ * Collects all errors (does not short-circuit) so a single call reveals
23
+ * every problem with the definition.
24
+ *
25
+ * Unknown fields are silently accepted for forward compatibility with
26
+ * S05/S06 features (`context_from`, `verify`, `iterate`).
27
+ */
28
+ export function validateDefinition(parsed) {
29
+ const errors = [];
30
+ if (parsed == null || typeof parsed !== "object") {
31
+ return { valid: false, errors: ["Definition must be a non-null object"] };
32
+ }
33
+ const def = parsed;
34
+ // version: must be 1 (number)
35
+ if (def.version === undefined || def.version === null) {
36
+ errors.push("Missing required field: version");
37
+ }
38
+ else if (def.version !== 1) {
39
+ errors.push(`Unsupported version: ${def.version} (expected 1)`);
40
+ }
41
+ // name: must be a non-empty string
42
+ if (typeof def.name !== "string" || def.name.trim() === "") {
43
+ errors.push("Missing or empty required field: name");
44
+ }
45
+ // steps: must be a non-empty array
46
+ if (!Array.isArray(def.steps)) {
47
+ errors.push("Missing required field: steps (must be an array)");
48
+ }
49
+ else if (def.steps.length === 0) {
50
+ errors.push("steps must contain at least one step");
51
+ }
52
+ else {
53
+ // Track whether all steps have valid IDs — graph-level checks only run when true
54
+ let allStepIdsValid = true;
55
+ for (let i = 0; i < def.steps.length; i++) {
56
+ const step = def.steps[i];
57
+ if (step == null || typeof step !== "object") {
58
+ errors.push(`Step at index ${i} is not an object`);
59
+ allStepIdsValid = false;
60
+ continue;
61
+ }
62
+ // Required step fields
63
+ if (typeof step.id !== "string" || step.id.trim() === "") {
64
+ errors.push(`Step at index ${i} missing required field: id`);
65
+ allStepIdsValid = false;
66
+ }
67
+ if (typeof step.name !== "string" || step.name.trim() === "") {
68
+ errors.push(`Step at index ${i} missing required field: name`);
69
+ }
70
+ if (typeof step.prompt !== "string" || step.prompt.trim() === "") {
71
+ errors.push(`Step at index ${i} missing required field: prompt`);
72
+ }
73
+ // produces: path traversal guard
74
+ if (Array.isArray(step.produces)) {
75
+ for (const p of step.produces) {
76
+ if (typeof p === "string" && p.includes("..")) {
77
+ errors.push(`Step "${step.id}" produces path contains disallowed '..': ${p}`);
78
+ }
79
+ }
80
+ }
81
+ // iterate: optional, but if present must conform to IterateConfig shape
82
+ if (step.iterate !== undefined) {
83
+ const it = step.iterate;
84
+ const sid = typeof step.id === "string" ? step.id : `index ${i}`;
85
+ if (it == null || typeof it !== "object" || Array.isArray(it)) {
86
+ errors.push(`Step "${sid}" iterate must be an object with "source" and "pattern" fields`);
87
+ }
88
+ else {
89
+ const itObj = it;
90
+ if (typeof itObj.source !== "string" || itObj.source.trim() === "") {
91
+ errors.push(`Step "${sid}" iterate.source must be a non-empty string`);
92
+ }
93
+ else if (itObj.source.includes("..")) {
94
+ errors.push(`Step "${sid}" iterate.source contains disallowed '..' path traversal`);
95
+ }
96
+ if (typeof itObj.pattern !== "string" || itObj.pattern.trim() === "") {
97
+ errors.push(`Step "${sid}" iterate.pattern must be a non-empty string`);
98
+ }
99
+ else {
100
+ const pat = itObj.pattern;
101
+ let regexValid = true;
102
+ try {
103
+ new RegExp(pat);
104
+ }
105
+ catch {
106
+ regexValid = false;
107
+ errors.push(`Step "${sid}" iterate.pattern is not a valid regex: ${pat}`);
108
+ }
109
+ if (regexValid && !/\((?!\?)/.test(pat)) {
110
+ errors.push(`Step "${sid}" iterate.pattern must contain at least one capture group`);
111
+ }
112
+ }
113
+ }
114
+ }
115
+ // verify: optional, but if present must conform to VerifyPolicy shape
116
+ if (step.verify !== undefined) {
117
+ const v = step.verify;
118
+ const sid = typeof step.id === "string" ? step.id : `index ${i}`;
119
+ if (v == null || typeof v !== "object" || Array.isArray(v)) {
120
+ errors.push(`Step "${sid}" verify must be an object with a "policy" field`);
121
+ }
122
+ else {
123
+ const vObj = v;
124
+ const VALID_POLICIES = ["content-heuristic", "shell-command", "prompt-verify", "human-review"];
125
+ if (typeof vObj.policy !== "string" || !VALID_POLICIES.includes(vObj.policy)) {
126
+ errors.push(`Step "${sid}" verify.policy must be one of: ${VALID_POLICIES.join(", ")}`);
127
+ }
128
+ else {
129
+ // Policy-specific required field checks
130
+ if (vObj.policy === "shell-command") {
131
+ if (typeof vObj.command !== "string" || vObj.command.trim() === "") {
132
+ errors.push(`Step "${sid}" verify policy "shell-command" requires a non-empty "command" field`);
133
+ }
134
+ }
135
+ if (vObj.policy === "prompt-verify") {
136
+ if (typeof vObj.prompt !== "string" || vObj.prompt.trim() === "") {
137
+ errors.push(`Step "${sid}" verify policy "prompt-verify" requires a non-empty "prompt" field`);
138
+ }
139
+ }
140
+ }
141
+ }
142
+ }
143
+ }
144
+ // ─── Graph-level validations (only when all step IDs are valid) ────
145
+ if (allStepIdsValid) {
146
+ const steps = def.steps;
147
+ // 1. Duplicate step ID check
148
+ const idCounts = new Map();
149
+ for (const step of steps) {
150
+ const id = step.id;
151
+ idCounts.set(id, (idCounts.get(id) ?? 0) + 1);
152
+ }
153
+ for (const [id, count] of idCounts) {
154
+ if (count > 1) {
155
+ errors.push(`Duplicate step id: ${id}`);
156
+ }
157
+ }
158
+ // Build valid ID set for remaining checks
159
+ const validIds = new Set(steps.map((s) => s.id));
160
+ // 2. Dangling dependency check + 3. Self-referencing dependency check
161
+ for (const step of steps) {
162
+ const sid = step.id;
163
+ const deps = Array.isArray(step.requires)
164
+ ? step.requires
165
+ : Array.isArray(step.depends_on)
166
+ ? step.depends_on
167
+ : [];
168
+ for (const depId of deps) {
169
+ if (depId === sid) {
170
+ errors.push(`Step '${sid}' depends on itself`);
171
+ }
172
+ else if (!validIds.has(depId)) {
173
+ errors.push(`Step '${sid}' requires unknown step '${depId}'`);
174
+ }
175
+ }
176
+ }
177
+ // 4. Cycle detection (DFS) — only when no duplicate IDs
178
+ if (![...idCounts.values()].some((c) => c > 1)) {
179
+ // Build adjacency list: step → its dependencies
180
+ const adj = new Map();
181
+ for (const step of steps) {
182
+ const sid = step.id;
183
+ const deps = Array.isArray(step.requires)
184
+ ? step.requires
185
+ : Array.isArray(step.depends_on)
186
+ ? step.depends_on
187
+ : [];
188
+ adj.set(sid, deps.filter((d) => validIds.has(d) && d !== sid));
189
+ }
190
+ const WHITE = 0, GRAY = 1, BLACK = 2;
191
+ const color = new Map();
192
+ for (const id of validIds)
193
+ color.set(id, WHITE);
194
+ const parent = new Map();
195
+ function dfs(node) {
196
+ color.set(node, GRAY);
197
+ for (const dep of adj.get(node) ?? []) {
198
+ if (color.get(dep) === GRAY) {
199
+ // Back edge found — reconstruct cycle path
200
+ const cycle = [dep, node];
201
+ let cur = node;
202
+ while (parent.has(cur) && parent.get(cur) !== null && parent.get(cur) !== dep) {
203
+ cur = parent.get(cur);
204
+ cycle.push(cur);
205
+ }
206
+ cycle.push(dep);
207
+ cycle.reverse();
208
+ return cycle;
209
+ }
210
+ if (color.get(dep) === WHITE) {
211
+ parent.set(dep, node);
212
+ const result = dfs(dep);
213
+ if (result)
214
+ return result;
215
+ }
216
+ }
217
+ color.set(node, BLACK);
218
+ return null;
219
+ }
220
+ for (const id of validIds) {
221
+ if (color.get(id) === WHITE) {
222
+ parent.set(id, null);
223
+ const cycle = dfs(id);
224
+ if (cycle) {
225
+ errors.push(`Cycle detected: ${cycle.join(" → ")}`);
226
+ break; // One cycle error is enough
227
+ }
228
+ }
229
+ }
230
+ }
231
+ }
232
+ }
233
+ return { valid: errors.length === 0, errors };
234
+ }
235
+ // ─── Loading ─────────────────────────────────────────────────────────────
236
+ /**
237
+ * Load and validate a YAML workflow definition from the filesystem.
238
+ *
239
+ * Reads `<defsDir>/<name>.yaml`, parses YAML, validates the V1 schema,
240
+ * and converts snake_case YAML keys to camelCase TypeScript types.
241
+ *
242
+ * @param defsDir — directory containing definition YAML files
243
+ * @param name — definition filename without extension
244
+ * @returns Parsed and validated WorkflowDefinition
245
+ * @throws Error if file is missing, YAML is malformed, or schema is invalid
246
+ */
247
+ export function loadDefinition(defsDir, name) {
248
+ const filePath = join(defsDir, `${name}.yaml`);
249
+ if (!existsSync(filePath)) {
250
+ throw new Error(`Definition file not found: ${filePath}`);
251
+ }
252
+ const raw = readFileSync(filePath, "utf-8");
253
+ let parsed;
254
+ try {
255
+ parsed = parse(raw);
256
+ }
257
+ catch (e) {
258
+ const msg = e instanceof Error ? e.message : String(e);
259
+ throw new Error(`Failed to parse YAML in ${filePath}: ${msg}`);
260
+ }
261
+ const { valid, errors } = validateDefinition(parsed);
262
+ if (!valid) {
263
+ throw new Error(`Invalid workflow definition in ${filePath}:\n - ${errors.join("\n - ")}`);
264
+ }
265
+ // Convert snake_case YAML → camelCase TypeScript
266
+ const yamlDef = parsed;
267
+ const yamlSteps = yamlDef.steps;
268
+ return {
269
+ version: yamlDef.version,
270
+ name: yamlDef.name,
271
+ description: typeof yamlDef.description === "string" ? yamlDef.description : undefined,
272
+ params: yamlDef.params != null && typeof yamlDef.params === "object"
273
+ ? Object.fromEntries(Object.entries(yamlDef.params).map(([k, v]) => [k, String(v)]))
274
+ : undefined,
275
+ steps: yamlSteps.map((s) => ({
276
+ id: s.id,
277
+ name: s.name,
278
+ prompt: s.prompt,
279
+ requires: Array.isArray(s.requires)
280
+ ? s.requires
281
+ : Array.isArray(s.depends_on)
282
+ ? s.depends_on
283
+ : [],
284
+ produces: Array.isArray(s.produces) ? s.produces : [],
285
+ contextFrom: Array.isArray(s.context_from) ? s.context_from : undefined,
286
+ verify: s.verify,
287
+ iterate: (s.iterate != null && typeof s.iterate === "object")
288
+ ? s.iterate
289
+ : undefined,
290
+ })),
291
+ };
292
+ }
293
+ // ─── Parameter Substitution ──────────────────────────────────────────────
294
+ /** Regex matching `{{key}}` placeholders — captures the key name. */
295
+ const PARAM_PATTERN = /\{\{(\w+)\}\}/g;
296
+ /**
297
+ * Replace `{{key}}` placeholders in a single prompt string.
298
+ *
299
+ * Exported for use by the engine on iteration-instance prompts that live
300
+ * in GRAPH.yaml (outside the definition's step list).
301
+ *
302
+ * @throws Error if any merged param value contains `..` (path-traversal guard)
303
+ */
304
+ export function substitutePromptString(prompt, merged) {
305
+ return prompt.replace(PARAM_PATTERN, (match, key) => {
306
+ const value = merged[key];
307
+ return value !== undefined ? value : match;
308
+ });
309
+ }
310
+ /**
311
+ * Replace `{{key}}` placeholders in all step prompts with param values.
312
+ *
313
+ * Merge order: `definition.params` (defaults) ← `overrides` (CLI wins).
314
+ * Returns a **new** WorkflowDefinition — the input is never mutated.
315
+ *
316
+ * @throws Error if any param value contains `..` (path-traversal guard)
317
+ * @throws Error if any `{{key}}` remains unresolved after substitution
318
+ */
319
+ export function substituteParams(definition, overrides) {
320
+ const merged = {
321
+ ...(definition.params ?? {}),
322
+ ...(overrides ?? {}),
323
+ };
324
+ // Path-traversal guard: reject any value containing ".."
325
+ for (const [key, value] of Object.entries(merged)) {
326
+ if (value.includes("..")) {
327
+ throw new Error(`Parameter "${key}" contains disallowed '..' (path traversal): ${value}`);
328
+ }
329
+ }
330
+ // Substitute in each step prompt
331
+ const substitutedSteps = definition.steps.map((step) => ({
332
+ ...step,
333
+ prompt: substitutePromptString(step.prompt, merged),
334
+ }));
335
+ // Check for unresolved placeholders
336
+ const unresolved = new Set();
337
+ for (const step of substitutedSteps) {
338
+ let m;
339
+ const re = new RegExp(PARAM_PATTERN.source, "g");
340
+ while ((m = re.exec(step.prompt)) !== null) {
341
+ unresolved.add(m[1]);
342
+ }
343
+ }
344
+ if (unresolved.size > 0) {
345
+ const keys = [...unresolved].sort().join(", ");
346
+ throw new Error(`Unresolved parameter(s) in step prompts: ${keys}`);
347
+ }
348
+ return {
349
+ ...definition,
350
+ steps: substitutedSteps,
351
+ };
352
+ }
@@ -11,7 +11,7 @@ import { homedir } from "node:os";
11
11
  import { gsdRoot } from "./paths.js";
12
12
  const gsdHome = process.env.GSD_HOME || join(homedir(), ".gsd");
13
13
  // ─── Project File Markers ───────────────────────────────────────────────────────
14
- const PROJECT_FILES = [
14
+ export const PROJECT_FILES = [
15
15
  "package.json",
16
16
  "Cargo.toml",
17
17
  "go.mod",
@@ -29,6 +29,18 @@ const PROJECT_FILES = [
29
29
  "mix.exs",
30
30
  "deno.json",
31
31
  "deno.jsonc",
32
+ // .NET
33
+ ".sln",
34
+ ".csproj",
35
+ "Directory.Build.props",
36
+ // Git submodules
37
+ ".gitmodules",
38
+ // Xcode
39
+ "project.yml",
40
+ ".xcodeproj",
41
+ ".xcworkspace",
42
+ // Docker
43
+ "Dockerfile",
32
44
  ];
33
45
  const LANGUAGE_MAP = {
34
46
  "package.json": "javascript/typescript",
@@ -47,6 +59,13 @@ const LANGUAGE_MAP = {
47
59
  "mix.exs": "elixir",
48
60
  "deno.json": "typescript/deno",
49
61
  "deno.jsonc": "typescript/deno",
62
+ ".sln": "dotnet",
63
+ ".csproj": "dotnet",
64
+ "Directory.Build.props": "dotnet",
65
+ "project.yml": "swift/xcode",
66
+ ".xcodeproj": "swift/xcode",
67
+ ".xcworkspace": "swift/xcode",
68
+ "Dockerfile": "docker",
50
69
  };
51
70
  const MONOREPO_MARKERS = [
52
71
  "lerna.json",
@@ -0,0 +1,24 @@
1
+ /**
2
+ * dev-execution-policy.ts — DevExecutionPolicy implementation.
3
+ *
4
+ * Stub policy for the dev engine. All methods return safe defaults.
5
+ * Real verification/closeout continues running through phases.ts via LoopDeps.
6
+ * Wiring this policy into the loop is S04's responsibility.
7
+ */
8
+ export class DevExecutionPolicy {
9
+ async prepareWorkspace(_basePath, _milestoneId) {
10
+ // no-op — workspace preparation handled by existing GSD logic
11
+ }
12
+ async selectModel(_unitType, _unitId, _context) {
13
+ return null; // use default model selection
14
+ }
15
+ async verify(_unitType, _unitId, _context) {
16
+ return "continue";
17
+ }
18
+ async recover(_unitType, _unitId, _context) {
19
+ return { outcome: "retry" };
20
+ }
21
+ async closeout(_unitType, _unitId, _context) {
22
+ return { committed: false, artifacts: [] };
23
+ }
24
+ }