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,271 @@
1
+ /**
2
+ * engine-interfaces-contract.test.ts — Source-level contract tests for the
3
+ * engine abstraction layer (S01).
4
+ *
5
+ * TypeScript interfaces are erased by --experimental-strip-types, so these
6
+ * tests use source-level regex assertions on the .ts files to verify shapes.
7
+ * Runtime assertions cover AutoSession.activeEngineId and resolveEngine().
8
+ *
9
+ * Follows the same conventions as auto-session-encapsulation.test.ts.
10
+ */
11
+
12
+ import test, { describe } from "node:test";
13
+ import assert from "node:assert/strict";
14
+ import { readFileSync } from "node:fs";
15
+ import { join, dirname } from "node:path";
16
+ import { fileURLToPath } from "node:url";
17
+
18
+ const __dirname = dirname(fileURLToPath(import.meta.url));
19
+ const ENGINE_TYPES_PATH = join(__dirname, "..", "engine-types.ts");
20
+ const WORKFLOW_ENGINE_PATH = join(__dirname, "..", "workflow-engine.ts");
21
+ const EXECUTION_POLICY_PATH = join(__dirname, "..", "execution-policy.ts");
22
+ const ENGINE_RESOLVER_PATH = join(__dirname, "..", "engine-resolver.ts");
23
+
24
+ function readSource(path: string): string {
25
+ return readFileSync(path, "utf-8");
26
+ }
27
+
28
+ // ── Import smoke tests ──────────────────────────────────────────────────────
29
+
30
+ describe("Import smoke tests", () => {
31
+ test("engine-types.ts can be dynamically imported", async () => {
32
+ const mod = await import("../engine-types.ts");
33
+ assert.ok(mod, "engine-types.ts should import without error");
34
+ });
35
+
36
+ test("workflow-engine.ts can be dynamically imported", async () => {
37
+ const mod = await import("../workflow-engine.ts");
38
+ assert.ok(mod, "workflow-engine.ts should import without error");
39
+ });
40
+
41
+ test("execution-policy.ts can be dynamically imported", async () => {
42
+ const mod = await import("../execution-policy.ts");
43
+ assert.ok(mod, "execution-policy.ts should import without error");
44
+ });
45
+
46
+ test("engine-resolver.ts can be dynamically imported", async () => {
47
+ const mod = await import("../engine-resolver.ts");
48
+ assert.ok(mod, "engine-resolver.ts should import without error");
49
+ assert.ok(
50
+ typeof mod.resolveEngine === "function",
51
+ "engine-resolver.ts should export resolveEngine function",
52
+ );
53
+ });
54
+ });
55
+
56
+ // ── Leaf-node constraint ────────────────────────────────────────────────────
57
+
58
+ describe("Leaf-node constraint", () => {
59
+ test("engine-types.ts has zero imports from GSD modules (only node: allowed)", () => {
60
+ const source = readSource(ENGINE_TYPES_PATH);
61
+ const lines = source.split("\n");
62
+ const violations: string[] = [];
63
+
64
+ for (let i = 0; i < lines.length; i++) {
65
+ const line = lines[i]!;
66
+ // Match import lines that reference relative paths (../ or ./)
67
+ if (/^import\s/.test(line) && /['"]\.\.?\// .test(line)) {
68
+ violations.push(`line ${i + 1}: ${line.trim()}`);
69
+ }
70
+ }
71
+
72
+ assert.equal(
73
+ violations.length,
74
+ 0,
75
+ `engine-types.ts must be a leaf node with zero GSD imports. ` +
76
+ `Only node: imports are allowed.\nViolations:\n${violations.join("\n")}`,
77
+ );
78
+ });
79
+ });
80
+
81
+ // ── EngineState shape ───────────────────────────────────────────────────────
82
+
83
+ describe("EngineState shape", () => {
84
+ test("EngineState has all required fields with correct types", () => {
85
+ const source = readSource(ENGINE_TYPES_PATH);
86
+
87
+ const requiredFields = [
88
+ "phase",
89
+ "currentMilestoneId",
90
+ "activeSliceId",
91
+ "activeTaskId",
92
+ "isComplete",
93
+ "raw",
94
+ ];
95
+
96
+ for (const field of requiredFields) {
97
+ assert.ok(
98
+ source.includes(field),
99
+ `EngineState must contain field: ${field}`,
100
+ );
101
+ }
102
+
103
+ // raw must be typed unknown — not a GSD-specific type
104
+ assert.ok(
105
+ /raw:\s*unknown/.test(source),
106
+ "EngineState.raw must be typed 'unknown', not a GSD-specific type",
107
+ );
108
+ });
109
+ });
110
+
111
+ // ── EngineDispatchAction shape ──────────────────────────────────────────────
112
+
113
+ describe("EngineDispatchAction shape", () => {
114
+ test("EngineDispatchAction has dispatch, stop, and skip variants", () => {
115
+ const source = readSource(ENGINE_TYPES_PATH);
116
+
117
+ assert.ok(
118
+ /action:\s*"dispatch"/.test(source),
119
+ 'EngineDispatchAction must have action: "dispatch" variant',
120
+ );
121
+ assert.ok(
122
+ /action:\s*"stop"/.test(source),
123
+ 'EngineDispatchAction must have action: "stop" variant',
124
+ );
125
+ assert.ok(
126
+ /action:\s*"skip"/.test(source),
127
+ 'EngineDispatchAction must have action: "skip" variant',
128
+ );
129
+ });
130
+ });
131
+
132
+ // ── WorkflowEngine interface shape ──────────────────────────────────────────
133
+
134
+ describe("WorkflowEngine interface shape", () => {
135
+ test("WorkflowEngine has engineId and all required methods", () => {
136
+ const source = readSource(WORKFLOW_ENGINE_PATH);
137
+
138
+ const requiredMembers = [
139
+ "engineId",
140
+ "deriveState",
141
+ "resolveDispatch",
142
+ "reconcile",
143
+ "getDisplayMetadata",
144
+ ];
145
+
146
+ for (const member of requiredMembers) {
147
+ assert.ok(
148
+ source.includes(member),
149
+ `WorkflowEngine must contain member: ${member}`,
150
+ );
151
+ }
152
+ });
153
+ });
154
+
155
+ // ── ExecutionPolicy interface shape ─────────────────────────────────────────
156
+
157
+ describe("ExecutionPolicy interface shape", () => {
158
+ test("ExecutionPolicy has all required methods", () => {
159
+ const source = readSource(EXECUTION_POLICY_PATH);
160
+
161
+ const requiredMethods = [
162
+ "prepareWorkspace",
163
+ "selectModel",
164
+ "verify",
165
+ "recover",
166
+ "closeout",
167
+ ];
168
+
169
+ for (const method of requiredMethods) {
170
+ assert.ok(
171
+ source.includes(method),
172
+ `ExecutionPolicy must contain method: ${method}`,
173
+ );
174
+ }
175
+ });
176
+ });
177
+
178
+ // ── Resolver stub behavior ──────────────────────────────────────────────────
179
+
180
+ describe("Resolver stub behavior", () => {
181
+ test("resolveEngine returns dev engine for null activeEngineId", async () => {
182
+ const { resolveEngine } = await import("../engine-resolver.ts");
183
+ const result = resolveEngine({ activeEngineId: null });
184
+ assert.ok(result.engine, "should return engine for null");
185
+ assert.equal(
186
+ result.engine.engineId,
187
+ "dev",
188
+ "engine.engineId should be 'dev' for null activeEngineId",
189
+ );
190
+ });
191
+
192
+ test("resolveEngine returns dev engine for 'dev' activeEngineId", async () => {
193
+ const { resolveEngine } = await import("../engine-resolver.ts");
194
+ const result = resolveEngine({ activeEngineId: "dev" });
195
+ assert.ok(result.engine, "should return engine for 'dev'");
196
+ assert.equal(
197
+ result.engine.engineId,
198
+ "dev",
199
+ "engine.engineId should be 'dev'",
200
+ );
201
+ });
202
+
203
+ test("resolveEngine throws for unknown activeEngineId without activeRunDir", async () => {
204
+ const { resolveEngine } = await import("../engine-resolver.ts");
205
+ assert.throws(
206
+ () => resolveEngine({ activeEngineId: "custom-xyz" }),
207
+ /activeRunDir/,
208
+ "resolveEngine should throw when custom engine has no activeRunDir",
209
+ );
210
+ });
211
+
212
+ test("resolveEngine returns custom engine for non-dev activeEngineId with activeRunDir", async () => {
213
+ const { resolveEngine } = await import("../engine-resolver.ts");
214
+ const result = resolveEngine({ activeEngineId: "custom-xyz", activeRunDir: "/tmp/test-run" });
215
+ assert.ok(result.engine, "should return engine for custom ID");
216
+ assert.equal(
217
+ result.engine.engineId,
218
+ "custom",
219
+ "engine.engineId should be 'custom' for non-dev activeEngineId",
220
+ );
221
+ });
222
+
223
+ test("ResolvedEngine type is exported (source check)", () => {
224
+ const source = readSource(ENGINE_RESOLVER_PATH);
225
+ assert.ok(
226
+ /export\s+(interface|type)\s+ResolvedEngine/.test(source),
227
+ "engine-resolver.ts must export ResolvedEngine type",
228
+ );
229
+ });
230
+ });
231
+
232
+ // ── AutoSession.activeEngineId ──────────────────────────────────────────────
233
+
234
+ describe("AutoSession.activeEngineId", () => {
235
+ test("defaults to null on a fresh AutoSession", async () => {
236
+ const { AutoSession } = await import("../auto/session.ts");
237
+ const session = new AutoSession();
238
+ assert.equal(
239
+ session.activeEngineId,
240
+ null,
241
+ "activeEngineId should default to null",
242
+ );
243
+ });
244
+
245
+ test("is null after reset()", async () => {
246
+ const { AutoSession } = await import("../auto/session.ts");
247
+ const session = new AutoSession();
248
+ session.activeEngineId = "dev";
249
+ session.reset();
250
+ assert.equal(
251
+ session.activeEngineId,
252
+ null,
253
+ "activeEngineId should be null after reset()",
254
+ );
255
+ });
256
+
257
+ test("appears in toJSON() output", async () => {
258
+ const { AutoSession } = await import("../auto/session.ts");
259
+ const session = new AutoSession();
260
+ const json = session.toJSON();
261
+ assert.ok(
262
+ "activeEngineId" in json,
263
+ "toJSON() must include activeEngineId",
264
+ );
265
+ assert.equal(
266
+ json.activeEngineId,
267
+ null,
268
+ "toJSON().activeEngineId should be null by default",
269
+ );
270
+ });
271
+ });
@@ -48,3 +48,58 @@ test("/exit requests graceful shutdown instead of process.exit", async () => {
48
48
  assert.equal(stopAutoCalls, 1, "handler should stop auto-mode exactly once before shutdown");
49
49
  assert.equal(shutdownCalls, 1, "handler should request graceful shutdown exactly once");
50
50
  });
51
+
52
+ // ─── #1839 regression: ESM cache mismatch must not crash exit ────────────────
53
+
54
+ test("/exit still shuts down gracefully when stopAuto throws (ESM module cache mismatch)", async () => {
55
+ const commands = new Map<string, { description?: string; handler: (args: string, ctx: any) => Promise<void> }>();
56
+
57
+ const pi = {
58
+ registerCommand(name: string, options: any) {
59
+ commands.set(name, options);
60
+ },
61
+ };
62
+
63
+ // Simulate the ESM cache mismatch: stopAuto throws because a static import
64
+ // in the dependency chain references an export absent from the cached module.
65
+ registerExitCommand(pi as any, {
66
+ async stopAuto() {
67
+ throw new Error(
68
+ "The requested module './native-git-bridge.js' does not provide an export named 'nativeAddAllWithExclusions'",
69
+ );
70
+ },
71
+ });
72
+
73
+ const exit = commands.get("exit")!;
74
+
75
+ let shutdownCalls = 0;
76
+ const notifications: Array<{ msg: string; level: string }> = [];
77
+
78
+ const originalExit = process.exit;
79
+ process.exit = ((code?: number) => {
80
+ throw new Error(`process.exit should not be called: ${code ?? "undefined"}`);
81
+ }) as typeof process.exit;
82
+
83
+ try {
84
+ await exit.handler("", {
85
+ async shutdown() {
86
+ shutdownCalls += 1;
87
+ },
88
+ ui: {
89
+ notify(msg: string, level: string) {
90
+ notifications.push({ msg, level });
91
+ },
92
+ },
93
+ });
94
+ } finally {
95
+ process.exit = originalExit;
96
+ }
97
+
98
+ assert.equal(shutdownCalls, 1, "shutdown must still be called even when stopAuto throws");
99
+ assert.equal(notifications.length, 1, "should emit exactly one warning notification");
100
+ assert.equal(notifications[0].level, "warning", "notification level should be warning");
101
+ assert.ok(
102
+ notifications[0].msg.includes("module version mismatch"),
103
+ "notification should mention module version mismatch",
104
+ );
105
+ });
@@ -0,0 +1,48 @@
1
+ import { describe, it } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { readFileSync } from "node:fs";
4
+ import { join, dirname } from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+
7
+ const __dirname = dirname(fileURLToPath(import.meta.url));
8
+ const gsdDir = join(__dirname, "..");
9
+
10
+ describe("forensics dedup (#2096)", () => {
11
+ it("forensics_dedup is in KNOWN_PREFERENCE_KEYS", () => {
12
+ const source = readFileSync(join(gsdDir, "preferences-types.ts"), "utf-8");
13
+ assert.ok(source.includes('"forensics_dedup"'),
14
+ "KNOWN_PREFERENCE_KEYS must contain forensics_dedup");
15
+ assert.ok(source.includes("forensics_dedup?: boolean"),
16
+ "GSDPreferences must declare forensics_dedup as optional boolean");
17
+ });
18
+
19
+ it("forensics prompt contains {{dedupSection}} placeholder", () => {
20
+ const prompt = readFileSync(join(gsdDir, "prompts", "forensics.md"), "utf-8");
21
+ assert.ok(prompt.includes("{{dedupSection}}"),
22
+ "forensics.md must contain {{dedupSection}} placeholder");
23
+ });
24
+
25
+ it("DEDUP_PROMPT_SECTION contains required search commands", async () => {
26
+ const source = readFileSync(join(gsdDir, "forensics.ts"), "utf-8");
27
+ assert.ok(source.includes("DEDUP_PROMPT_SECTION"), "forensics.ts must define DEDUP_PROMPT_SECTION");
28
+ assert.ok(source.includes("gh issue list --repo gsd-build/gsd-2 --state closed"));
29
+ assert.ok(source.includes("gh pr list --repo gsd-build/gsd-2 --state open"));
30
+ assert.ok(source.includes("gh pr list --repo gsd-build/gsd-2 --state merged"));
31
+ });
32
+
33
+ it("handleForensics checks forensics_dedup preference", () => {
34
+ const source = readFileSync(join(gsdDir, "forensics.ts"), "utf-8");
35
+ assert.ok(source.includes("forensics_dedup"),
36
+ "handleForensics must reference forensics_dedup preference");
37
+ assert.ok(source.includes("dedupSection"),
38
+ "handleForensics must pass dedupSection to loadPrompt");
39
+ });
40
+
41
+ it("first-time opt-in shows when preference is undefined", () => {
42
+ const source = readFileSync(join(gsdDir, "forensics.ts"), "utf-8");
43
+ assert.ok(source.includes("=== undefined"),
44
+ "first-time detection must check for undefined (not false)");
45
+ assert.ok(source.includes("Duplicate detection available") || source.includes("duplicate detection"),
46
+ "opt-in notice must mention duplicate detection");
47
+ });
48
+ });
@@ -0,0 +1,43 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { readFileSync } from "node:fs";
4
+ import { join } from "node:path";
5
+
6
+ const promptsDir = join(process.cwd(), "src/resources/extensions/gsd/prompts");
7
+
8
+ function readPrompt(name: string): string {
9
+ return readFileSync(join(promptsDir, `${name}.md`), "utf-8");
10
+ }
11
+
12
+ test("forensics prompt explicitly forbids github_issues tool for issue creation", () => {
13
+ const prompt = readPrompt("forensics");
14
+
15
+ // Must contain an explicit prohibition against using the github_issues tool
16
+ assert.match(
17
+ prompt,
18
+ /Do NOT use the `?github_issues`? tool/i,
19
+ "Prompt must explicitly prohibit the github_issues tool",
20
+ );
21
+ });
22
+
23
+ test("forensics prompt requires gh CLI with --repo gsd-build/gsd-2 for issue creation", () => {
24
+ const prompt = readPrompt("forensics");
25
+
26
+ // Must contain the exact gh CLI command with the correct repo flag
27
+ assert.match(
28
+ prompt,
29
+ /gh issue create --repo gsd-build\/gsd-2/,
30
+ "Prompt must specify gh issue create --repo gsd-build/gsd-2",
31
+ );
32
+ });
33
+
34
+ test("forensics prompt routes issue creation through bash tool, not github_issues", () => {
35
+ const prompt = readPrompt("forensics");
36
+
37
+ // The constraint about using bash tool must be present
38
+ assert.match(
39
+ prompt,
40
+ /`?bash`? tool/i,
41
+ "Prompt must instruct use of the bash tool for issue creation",
42
+ );
43
+ });
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Regression tests for #1997: git locale not forced to C.
3
+ *
4
+ * Validates that GIT_NO_PROMPT_ENV includes LC_ALL=C so git always produces
5
+ * English output, and that nativeMergeSquash passes the env to execFileSync.
6
+ */
7
+
8
+ import { mkdtempSync, mkdirSync, writeFileSync, rmSync, readFileSync } from "node:fs";
9
+ import { join } from "node:path";
10
+ import { tmpdir } from "node:os";
11
+ import { execFileSync } from "node:child_process";
12
+
13
+ import { GIT_NO_PROMPT_ENV } from "../git-constants.ts";
14
+ import { nativeAddAllWithExclusions } from "../native-git-bridge.ts";
15
+ import { RUNTIME_EXCLUSION_PATHS } from "../git-service.ts";
16
+ import { createTestContext } from "./test-helpers.ts";
17
+
18
+ const { assertEq, assertTrue, report } = createTestContext();
19
+
20
+ function git(cwd: string, ...args: string[]): string {
21
+ return execFileSync("git", args, { cwd, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }).trim();
22
+ }
23
+
24
+ function initTempRepo(): string {
25
+ const dir = mkdtempSync(join(tmpdir(), "gsd-locale-"));
26
+ git(dir, "init");
27
+ git(dir, "config", "user.email", "test@test.com");
28
+ git(dir, "config", "user.name", "Test");
29
+ // Initial commit so HEAD exists
30
+ writeFileSync(join(dir, "init.txt"), "init");
31
+ git(dir, "add", "-A");
32
+ git(dir, "commit", "-m", "init");
33
+ return dir;
34
+ }
35
+
36
+ function createFile(base: string, relPath: string, content: string): void {
37
+ const full = join(base, relPath);
38
+ mkdirSync(join(full, ".."), { recursive: true });
39
+ writeFileSync(full, content);
40
+ }
41
+
42
+ async function main(): Promise<void> {
43
+ // ─── GIT_NO_PROMPT_ENV includes LC_ALL=C ─────────────────────────────
44
+
45
+ console.log("\n=== GIT_NO_PROMPT_ENV includes LC_ALL=C ===");
46
+
47
+ assertEq(
48
+ GIT_NO_PROMPT_ENV.LC_ALL,
49
+ "C",
50
+ "GIT_NO_PROMPT_ENV must set LC_ALL to 'C' to force English git output"
51
+ );
52
+
53
+ assertTrue(
54
+ "GIT_TERMINAL_PROMPT" in GIT_NO_PROMPT_ENV,
55
+ "GIT_NO_PROMPT_ENV still contains GIT_TERMINAL_PROMPT"
56
+ );
57
+
58
+ // ─── nativeAddAllWithExclusions: non-English locale does not throw ───
59
+
60
+ console.log("\n=== nativeAddAllWithExclusions: non-English locale does not throw ===");
61
+
62
+ {
63
+ // Simulate what happens on a German system: .gsd is gitignored,
64
+ // exclusion pathspecs trigger an advisory warning exit code 1.
65
+ // With LC_ALL=C the English stderr guard should match and suppress.
66
+ const repo = initTempRepo();
67
+
68
+ writeFileSync(join(repo, ".gitignore"), ".gsd\n");
69
+ createFile(repo, ".gsd/STATE.md", "# State");
70
+ createFile(repo, "src/app.ts", "export const x = 1;");
71
+
72
+ // Save original LC_ALL / LANG and force German locale env
73
+ const origLcAll = process.env.LC_ALL;
74
+ const origLang = process.env.LANG;
75
+ process.env.LANG = "de_DE.UTF-8";
76
+ delete process.env.LC_ALL;
77
+
78
+ let threw = false;
79
+ try {
80
+ nativeAddAllWithExclusions(repo, RUNTIME_EXCLUSION_PATHS);
81
+ } catch (e) {
82
+ threw = true;
83
+ console.error(" unexpected error:", e);
84
+ }
85
+
86
+ // Restore
87
+ if (origLcAll !== undefined) process.env.LC_ALL = origLcAll;
88
+ else delete process.env.LC_ALL;
89
+ if (origLang !== undefined) process.env.LANG = origLang;
90
+ else delete process.env.LANG;
91
+
92
+ assertTrue(
93
+ !threw,
94
+ "nativeAddAllWithExclusions must not throw on non-English locale when .gsd is gitignored (#1997)"
95
+ );
96
+
97
+ const staged = git(repo, "diff", "--cached", "--name-only");
98
+ assertTrue(staged.includes("src/app.ts"), "real file staged despite German locale");
99
+
100
+ rmSync(repo, { recursive: true, force: true });
101
+ }
102
+
103
+ // ─── nativeMergeSquash: env is passed (merge-squash stderr is English) ─
104
+
105
+ console.log("\n=== nativeMergeSquash fallback uses GIT_NO_PROMPT_ENV ===");
106
+
107
+ {
108
+ // We verify indirectly: the source code must pass env: GIT_NO_PROMPT_ENV.
109
+ // Read the source and check for the pattern. This is a static check.
110
+ const src = readFileSync(
111
+ join(import.meta.dirname, "..", "native-git-bridge.ts"),
112
+ "utf-8"
113
+ );
114
+
115
+ // Find the nativeMergeSquash function and check it uses GIT_NO_PROMPT_ENV
116
+ const fnStart = src.indexOf("export function nativeMergeSquash");
117
+ assertTrue(fnStart !== -1, "nativeMergeSquash function exists in source");
118
+
119
+ const fnBody = src.slice(fnStart, src.indexOf("\nexport function", fnStart + 1));
120
+ const hasEnv = fnBody.includes("env: GIT_NO_PROMPT_ENV");
121
+ assertTrue(
122
+ hasEnv,
123
+ "nativeMergeSquash fallback must pass env: GIT_NO_PROMPT_ENV to execFileSync (#1997)"
124
+ );
125
+ }
126
+
127
+ report();
128
+ }
129
+
130
+ main().catch((error) => {
131
+ console.error(error);
132
+ process.exit(1);
133
+ });
@@ -1411,6 +1411,50 @@ async function main(): Promise<void> {
1411
1411
  rmSync(repo, { recursive: true, force: true });
1412
1412
  }
1413
1413
 
1414
+ // ─── autoCommit: symlinked .gsd does NOT stage milestone artifacts (#2247) ──
1415
+
1416
+ console.log("\n=== autoCommit: symlinked .gsd does NOT stage milestone artifacts (#2247) ===");
1417
+
1418
+ {
1419
+ // When .gsd is a symlink (external state project), .gsd/ files live outside
1420
+ // the repo by design. smartStage() must NOT force-stage them into git — the
1421
+ // .gitignore exclusion is correct and intentional.
1422
+ const repo = initTempRepo();
1423
+
1424
+ // Create an external .gsd directory and symlink it into the repo
1425
+ const externalGsd = mkdtempSync(join(tmpdir(), "gsd-external-symlink-"));
1426
+ mkdirSync(join(externalGsd, "milestones", "M009"), { recursive: true });
1427
+ mkdirSync(join(externalGsd, "activity"), { recursive: true });
1428
+ mkdirSync(join(externalGsd, "runtime"), { recursive: true });
1429
+
1430
+ symlinkSync(externalGsd, join(repo, ".gsd"));
1431
+
1432
+ // .gitignore blocks .gsd (as ensureGitignore would do for symlink projects)
1433
+ writeFileSync(join(repo, ".gitignore"), ".gsd\n");
1434
+ run('git add .gitignore', repo);
1435
+ run('git commit -m "add gitignore"', repo);
1436
+
1437
+ // Simulate new milestone artifacts created during execution
1438
+ writeFileSync(join(externalGsd, "milestones", "M009", "M009-SUMMARY.md"), "# M009 Summary");
1439
+ writeFileSync(join(externalGsd, "milestones", "M009", "S01-SUMMARY.md"), "# S01 Summary");
1440
+ writeFileSync(join(externalGsd, "milestones", "M009", "T01-VERIFY.json"), '{"passed":true}');
1441
+
1442
+ // Also create a normal source file change
1443
+ createFile(repo, "src/feature.ts", "export const feature = true;");
1444
+
1445
+ const svc = new GitServiceImpl(repo);
1446
+ const msg = svc.autoCommit("complete-milestone", "M009");
1447
+ assertTrue(msg !== null, "symlink autoCommit: commit succeeds");
1448
+
1449
+ const committed = run("git show --name-only HEAD", repo);
1450
+ assertTrue(committed.includes("src/feature.ts"), "symlink autoCommit: source file committed");
1451
+ assertTrue(!committed.includes(".gsd/milestones/"),
1452
+ "symlink autoCommit: .gsd/milestones/ files are NOT staged (external state stays external)");
1453
+
1454
+ try { rmSync(repo, { recursive: true, force: true }); } catch {}
1455
+ try { rmSync(externalGsd, { recursive: true, force: true }); } catch {}
1456
+ }
1457
+
1414
1458
  report();
1415
1459
  }
1416
1460