gsd-pi 2.41.0 → 2.42.0-dev.eedc83f

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (483) hide show
  1. package/README.md +92 -29
  2. package/dist/cli-web-branch.d.ts +6 -0
  3. package/dist/cli-web-branch.js +17 -0
  4. package/dist/cli.js +15 -1
  5. package/dist/onboarding.js +2 -1
  6. package/dist/resource-loader.js +39 -6
  7. package/dist/resources/extensions/async-jobs/async-bash-tool.js +52 -4
  8. package/dist/resources/extensions/gsd/auto/loop.js +89 -1
  9. package/dist/resources/extensions/gsd/auto/phases.js +28 -10
  10. package/dist/resources/extensions/gsd/auto/session.js +6 -0
  11. package/dist/resources/extensions/gsd/auto-dashboard.js +8 -2
  12. package/dist/resources/extensions/gsd/auto-dispatch.js +19 -2
  13. package/dist/resources/extensions/gsd/auto-post-unit.js +7 -0
  14. package/dist/resources/extensions/gsd/auto-prompts.js +1 -1
  15. package/dist/resources/extensions/gsd/auto-recovery.js +12 -4
  16. package/dist/resources/extensions/gsd/auto-start.js +8 -3
  17. package/dist/resources/extensions/gsd/auto-worktree.js +147 -13
  18. package/dist/resources/extensions/gsd/auto.js +64 -2
  19. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +199 -164
  20. package/dist/resources/extensions/gsd/bootstrap/journal-tools.js +62 -0
  21. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +2 -0
  22. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +25 -3
  23. package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +7 -2
  24. package/dist/resources/extensions/gsd/commands/catalog.js +40 -1
  25. package/dist/resources/extensions/gsd/commands/handlers/core.js +1 -0
  26. package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
  27. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +146 -0
  28. package/dist/resources/extensions/gsd/context-injector.js +74 -0
  29. package/dist/resources/extensions/gsd/context-store.js +4 -3
  30. package/dist/resources/extensions/gsd/custom-execution-policy.js +47 -0
  31. package/dist/resources/extensions/gsd/custom-verification.js +145 -0
  32. package/dist/resources/extensions/gsd/custom-workflow-engine.js +164 -0
  33. package/dist/resources/extensions/gsd/dashboard-overlay.js +1 -0
  34. package/dist/resources/extensions/gsd/db-writer.js +5 -2
  35. package/dist/resources/extensions/gsd/definition-loader.js +352 -0
  36. package/dist/resources/extensions/gsd/detection.js +20 -1
  37. package/dist/resources/extensions/gsd/dev-execution-policy.js +24 -0
  38. package/dist/resources/extensions/gsd/dev-workflow-engine.js +82 -0
  39. package/dist/resources/extensions/gsd/doctor-checks.js +31 -1
  40. package/dist/resources/extensions/gsd/doctor-providers.js +10 -0
  41. package/dist/resources/extensions/gsd/doctor.js +11 -1
  42. package/dist/resources/extensions/gsd/engine-resolver.js +40 -0
  43. package/dist/resources/extensions/gsd/engine-types.js +8 -0
  44. package/dist/resources/extensions/gsd/execution-policy.js +8 -0
  45. package/dist/resources/extensions/gsd/exit-command.js +12 -2
  46. package/dist/resources/extensions/gsd/export.js +9 -13
  47. package/dist/resources/extensions/gsd/extension-manifest.json +2 -2
  48. package/dist/resources/extensions/gsd/files.js +28 -11
  49. package/dist/resources/extensions/gsd/forensics.js +94 -3
  50. package/dist/resources/extensions/gsd/git-constants.js +1 -0
  51. package/dist/resources/extensions/gsd/git-service.js +73 -3
  52. package/dist/resources/extensions/gsd/graph.js +225 -0
  53. package/dist/resources/extensions/gsd/gsd-db.js +25 -8
  54. package/dist/resources/extensions/gsd/guided-flow-queue.js +1 -1
  55. package/dist/resources/extensions/gsd/guided-flow.js +7 -3
  56. package/dist/resources/extensions/gsd/journal.js +85 -0
  57. package/dist/resources/extensions/gsd/md-importer.js +5 -0
  58. package/dist/resources/extensions/gsd/milestone-ids.js +1 -1
  59. package/dist/resources/extensions/gsd/native-git-bridge.js +3 -2
  60. package/dist/resources/extensions/gsd/post-unit-hooks.js +24 -412
  61. package/dist/resources/extensions/gsd/preferences-types.js +2 -0
  62. package/dist/resources/extensions/gsd/preferences.js +60 -8
  63. package/dist/resources/extensions/gsd/prompt-loader.js +34 -4
  64. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +11 -10
  65. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +2 -2
  66. package/dist/resources/extensions/gsd/prompts/discuss.md +1 -1
  67. package/dist/resources/extensions/gsd/prompts/forensics.md +12 -5
  68. package/dist/resources/extensions/gsd/prompts/queue.md +1 -1
  69. package/dist/resources/extensions/gsd/repo-identity.js +92 -7
  70. package/dist/resources/extensions/gsd/rule-registry.js +489 -0
  71. package/dist/resources/extensions/gsd/rule-types.js +6 -0
  72. package/dist/resources/extensions/gsd/run-manager.js +134 -0
  73. package/dist/resources/extensions/gsd/service-tier.js +147 -0
  74. package/dist/resources/extensions/gsd/session-lock.js +2 -2
  75. package/dist/resources/extensions/gsd/structured-data-formatter.js +2 -1
  76. package/dist/resources/extensions/gsd/templates/decisions.md +2 -2
  77. package/dist/resources/extensions/gsd/workflow-engine.js +7 -0
  78. package/dist/resources/extensions/gsd/workflow-templates.js +13 -1
  79. package/dist/resources/extensions/gsd/worktree-manager.js +20 -6
  80. package/dist/resources/extensions/gsd/worktree-resolver.js +21 -4
  81. package/dist/resources/extensions/mcp-client/index.js +2 -1
  82. package/dist/resources/extensions/search-the-web/tool-search.js +3 -3
  83. package/dist/resources/extensions/subagent/index.js +7 -3
  84. package/dist/resources/extensions/voice/index.js +4 -4
  85. package/dist/resources/skills/create-workflow/SKILL.md +103 -0
  86. package/dist/resources/skills/create-workflow/references/feature-patterns.md +128 -0
  87. package/dist/resources/skills/create-workflow/references/verification-policies.md +76 -0
  88. package/dist/resources/skills/create-workflow/references/yaml-schema-v1.md +46 -0
  89. package/dist/resources/skills/create-workflow/templates/blog-post-pipeline.yaml +60 -0
  90. package/dist/resources/skills/create-workflow/templates/code-audit.yaml +60 -0
  91. package/dist/resources/skills/create-workflow/templates/release-checklist.yaml +66 -0
  92. package/dist/resources/skills/create-workflow/templates/workflow-definition.yaml +32 -0
  93. package/dist/resources/skills/create-workflow/workflows/create-from-scratch.md +104 -0
  94. package/dist/resources/skills/create-workflow/workflows/create-from-template.md +72 -0
  95. package/dist/web/standalone/.next/BUILD_ID +1 -1
  96. package/dist/web/standalone/.next/app-path-routes-manifest.json +13 -13
  97. package/dist/web/standalone/.next/build-manifest.json +4 -4
  98. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  99. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  100. package/dist/web/standalone/.next/required-server-files.json +3 -3
  101. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  102. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  103. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  104. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  112. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  113. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  114. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  115. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  116. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  118. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  128. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +5 -5
  166. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  172. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  186. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  188. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  190. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  195. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  196. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  197. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  199. package/dist/web/standalone/.next/server/app/index.html +1 -1
  200. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  201. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  202. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  203. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  204. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  205. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  206. package/dist/web/standalone/.next/server/app/page.js +2 -2
  207. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  208. package/dist/web/standalone/.next/server/app-paths-manifest.json +13 -13
  209. package/dist/web/standalone/.next/server/chunks/229.js +3 -3
  210. package/dist/web/standalone/.next/server/chunks/471.js +3 -3
  211. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  212. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  213. package/dist/web/standalone/.next/server/middleware.js +2 -2
  214. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  215. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  216. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  217. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  218. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  219. package/dist/web/standalone/.next/static/chunks/4024.c195dc1fdd2adbea.js +9 -0
  220. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-f2a7482d42a5614b.js +1 -0
  221. package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +1 -0
  222. package/dist/web/standalone/.next/static/chunks/app/page-b9367c5ae13b99c6.js +1 -0
  223. package/dist/web/standalone/.next/static/chunks/{main-app-2f2ee7b85712c2bd.js → main-app-fdab67f7802d7832.js} +1 -1
  224. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  225. package/dist/web/standalone/.next/static/chunks/{webpack-9afaaebf6042a1d7.js → webpack-fa307370fcf9fb2c.js} +1 -1
  226. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  227. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  228. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  229. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  230. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  231. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  232. package/dist/web/standalone/server.js +1 -1
  233. package/dist/web-mode.d.ts +4 -0
  234. package/dist/web-mode.js +69 -11
  235. package/package.json +1 -1
  236. package/packages/native/src/__tests__/text.test.mjs +33 -0
  237. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  238. package/packages/pi-agent-core/dist/agent.js +2 -0
  239. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  240. package/packages/pi-agent-core/dist/types.d.ts +6 -0
  241. package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
  242. package/packages/pi-agent-core/dist/types.js.map +1 -1
  243. package/packages/pi-agent-core/src/agent.test.ts +53 -0
  244. package/packages/pi-agent-core/src/agent.ts +3 -0
  245. package/packages/pi-agent-core/src/types.ts +6 -0
  246. package/packages/pi-agent-core/tsconfig.json +1 -1
  247. package/packages/pi-ai/dist/models.d.ts +5 -3
  248. package/packages/pi-ai/dist/models.d.ts.map +1 -1
  249. package/packages/pi-ai/dist/models.generated.d.ts +801 -1468
  250. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  251. package/packages/pi-ai/dist/models.generated.js +1135 -1588
  252. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  253. package/packages/pi-ai/dist/models.js.map +1 -1
  254. package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
  255. package/packages/pi-ai/dist/utils/oauth/github-copilot.js +60 -2
  256. package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
  257. package/packages/pi-ai/scripts/generate-models.ts +1543 -0
  258. package/packages/pi-ai/src/models.generated.ts +1140 -1593
  259. package/packages/pi-ai/src/models.ts +7 -4
  260. package/packages/pi-ai/src/utils/oauth/github-copilot.ts +74 -2
  261. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  262. package/packages/pi-coding-agent/dist/core/agent-session.js +8 -1
  263. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  264. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +7 -0
  265. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  266. package/packages/pi-coding-agent/dist/core/auth-storage.js +29 -2
  267. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  268. package/packages/pi-coding-agent/dist/core/auth-storage.test.js +60 -0
  269. package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
  270. package/packages/pi-coding-agent/dist/core/discovery-cache.test.js +3 -1
  271. package/packages/pi-coding-agent/dist/core/discovery-cache.test.js.map +1 -1
  272. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  273. package/packages/pi-coding-agent/dist/core/extensions/loader.js +18 -0
  274. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  275. package/packages/pi-coding-agent/dist/core/lsp/client.d.ts.map +1 -1
  276. package/packages/pi-coding-agent/dist/core/lsp/client.js +23 -0
  277. package/packages/pi-coding-agent/dist/core/lsp/client.js.map +1 -1
  278. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  279. package/packages/pi-coding-agent/dist/core/model-registry.js +2 -0
  280. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  281. package/packages/pi-coding-agent/dist/core/package-manager.d.ts +6 -0
  282. package/packages/pi-coding-agent/dist/core/package-manager.d.ts.map +1 -1
  283. package/packages/pi-coding-agent/dist/core/package-manager.js +63 -11
  284. package/packages/pi-coding-agent/dist/core/package-manager.js.map +1 -1
  285. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts +9 -0
  286. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
  287. package/packages/pi-coding-agent/dist/core/resource-loader.js +20 -6
  288. package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
  289. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  290. package/packages/pi-coding-agent/dist/core/system-prompt.js +6 -5
  291. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  292. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  293. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-editor.js +3 -0
  294. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-editor.js.map +1 -1
  295. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  296. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +9 -6
  297. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  298. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  299. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +10 -7
  300. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js.map +1 -1
  301. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  302. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +34 -10
  303. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  304. package/packages/pi-coding-agent/package.json +1 -1
  305. package/packages/pi-coding-agent/src/core/agent-session.ts +7 -1
  306. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +68 -0
  307. package/packages/pi-coding-agent/src/core/auth-storage.ts +30 -2
  308. package/packages/pi-coding-agent/src/core/discovery-cache.test.ts +4 -2
  309. package/packages/pi-coding-agent/src/core/extensions/loader.ts +18 -0
  310. package/packages/pi-coding-agent/src/core/lsp/client.ts +29 -0
  311. package/packages/pi-coding-agent/src/core/model-registry.ts +3 -0
  312. package/packages/pi-coding-agent/src/core/package-manager.ts +99 -58
  313. package/packages/pi-coding-agent/src/core/resource-loader.ts +24 -6
  314. package/packages/pi-coding-agent/src/core/system-prompt.ts +6 -5
  315. package/packages/pi-coding-agent/src/modes/interactive/components/extension-editor.ts +3 -0
  316. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +10 -6
  317. package/packages/pi-coding-agent/src/modes/interactive/components/login-dialog.ts +11 -7
  318. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +36 -11
  319. package/pkg/package.json +1 -1
  320. package/src/resources/extensions/async-jobs/async-bash-timeout.test.ts +122 -0
  321. package/src/resources/extensions/async-jobs/async-bash-tool.ts +40 -4
  322. package/src/resources/extensions/gsd/auto/loop-deps.ts +5 -1
  323. package/src/resources/extensions/gsd/auto/loop.ts +101 -1
  324. package/src/resources/extensions/gsd/auto/phases.ts +30 -10
  325. package/src/resources/extensions/gsd/auto/session.ts +6 -0
  326. package/src/resources/extensions/gsd/auto/types.ts +4 -0
  327. package/src/resources/extensions/gsd/auto-dashboard.ts +9 -2
  328. package/src/resources/extensions/gsd/auto-dispatch.ts +25 -5
  329. package/src/resources/extensions/gsd/auto-post-unit.ts +8 -0
  330. package/src/resources/extensions/gsd/auto-prompts.ts +1 -1
  331. package/src/resources/extensions/gsd/auto-recovery.ts +12 -4
  332. package/src/resources/extensions/gsd/auto-start.ts +8 -3
  333. package/src/resources/extensions/gsd/auto-worktree.ts +162 -18
  334. package/src/resources/extensions/gsd/auto.ts +71 -2
  335. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +209 -162
  336. package/src/resources/extensions/gsd/bootstrap/journal-tools.ts +62 -0
  337. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +2 -0
  338. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +25 -4
  339. package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +9 -2
  340. package/src/resources/extensions/gsd/commands/catalog.ts +40 -1
  341. package/src/resources/extensions/gsd/commands/handlers/core.ts +1 -0
  342. package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
  343. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +164 -0
  344. package/src/resources/extensions/gsd/context-injector.ts +100 -0
  345. package/src/resources/extensions/gsd/context-store.ts +4 -3
  346. package/src/resources/extensions/gsd/custom-execution-policy.ts +73 -0
  347. package/src/resources/extensions/gsd/custom-verification.ts +180 -0
  348. package/src/resources/extensions/gsd/custom-workflow-engine.ts +216 -0
  349. package/src/resources/extensions/gsd/dashboard-overlay.ts +1 -0
  350. package/src/resources/extensions/gsd/db-writer.ts +6 -2
  351. package/src/resources/extensions/gsd/definition-loader.ts +462 -0
  352. package/src/resources/extensions/gsd/detection.ts +20 -1
  353. package/src/resources/extensions/gsd/dev-execution-policy.ts +51 -0
  354. package/src/resources/extensions/gsd/dev-workflow-engine.ts +110 -0
  355. package/src/resources/extensions/gsd/doctor-checks.ts +32 -1
  356. package/src/resources/extensions/gsd/doctor-providers.ts +13 -0
  357. package/src/resources/extensions/gsd/doctor-types.ts +1 -0
  358. package/src/resources/extensions/gsd/doctor.ts +12 -1
  359. package/src/resources/extensions/gsd/engine-resolver.ts +57 -0
  360. package/src/resources/extensions/gsd/engine-types.ts +71 -0
  361. package/src/resources/extensions/gsd/execution-policy.ts +43 -0
  362. package/src/resources/extensions/gsd/exit-command.ts +14 -2
  363. package/src/resources/extensions/gsd/export.ts +8 -15
  364. package/src/resources/extensions/gsd/extension-manifest.json +2 -2
  365. package/src/resources/extensions/gsd/files.ts +29 -12
  366. package/src/resources/extensions/gsd/forensics.ts +101 -3
  367. package/src/resources/extensions/gsd/git-constants.ts +1 -0
  368. package/src/resources/extensions/gsd/git-service.ts +76 -6
  369. package/src/resources/extensions/gsd/graph.ts +312 -0
  370. package/src/resources/extensions/gsd/gsd-db.ts +37 -8
  371. package/src/resources/extensions/gsd/guided-flow-queue.ts +1 -1
  372. package/src/resources/extensions/gsd/guided-flow.ts +7 -3
  373. package/src/resources/extensions/gsd/journal.ts +134 -0
  374. package/src/resources/extensions/gsd/md-importer.ts +6 -0
  375. package/src/resources/extensions/gsd/milestone-ids.ts +1 -1
  376. package/src/resources/extensions/gsd/native-git-bridge.ts +3 -2
  377. package/src/resources/extensions/gsd/post-unit-hooks.ts +24 -462
  378. package/src/resources/extensions/gsd/preferences-types.ts +6 -0
  379. package/src/resources/extensions/gsd/preferences.ts +63 -6
  380. package/src/resources/extensions/gsd/prompt-loader.ts +35 -4
  381. package/src/resources/extensions/gsd/prompts/complete-milestone.md +11 -10
  382. package/src/resources/extensions/gsd/prompts/discuss-headless.md +2 -2
  383. package/src/resources/extensions/gsd/prompts/discuss.md +1 -1
  384. package/src/resources/extensions/gsd/prompts/forensics.md +12 -5
  385. package/src/resources/extensions/gsd/prompts/queue.md +1 -1
  386. package/src/resources/extensions/gsd/repo-identity.ts +95 -7
  387. package/src/resources/extensions/gsd/rule-registry.ts +599 -0
  388. package/src/resources/extensions/gsd/rule-types.ts +68 -0
  389. package/src/resources/extensions/gsd/run-manager.ts +180 -0
  390. package/src/resources/extensions/gsd/service-tier.ts +184 -0
  391. package/src/resources/extensions/gsd/session-lock.ts +2 -2
  392. package/src/resources/extensions/gsd/structured-data-formatter.ts +3 -1
  393. package/src/resources/extensions/gsd/templates/decisions.md +2 -2
  394. package/src/resources/extensions/gsd/tests/activity-log.test.ts +31 -69
  395. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +103 -120
  396. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +85 -0
  397. package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +2 -2
  398. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +202 -0
  399. package/src/resources/extensions/gsd/tests/bundled-workflow-defs.test.ts +180 -0
  400. package/src/resources/extensions/gsd/tests/captures.test.ts +12 -1
  401. package/src/resources/extensions/gsd/tests/commands-workflow-custom.test.ts +283 -0
  402. package/src/resources/extensions/gsd/tests/context-injector.test.ts +313 -0
  403. package/src/resources/extensions/gsd/tests/context-store.test.ts +10 -5
  404. package/src/resources/extensions/gsd/tests/continue-here.test.ts +20 -20
  405. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +540 -0
  406. package/src/resources/extensions/gsd/tests/custom-verification.test.ts +382 -0
  407. package/src/resources/extensions/gsd/tests/custom-workflow-engine.test.ts +339 -0
  408. package/src/resources/extensions/gsd/tests/dashboard-custom-engine.test.ts +87 -0
  409. package/src/resources/extensions/gsd/tests/db-writer.test.ts +10 -0
  410. package/src/resources/extensions/gsd/tests/definition-loader.test.ts +778 -0
  411. package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +318 -0
  412. package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +15 -10
  413. package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +5 -4
  414. package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +167 -0
  415. package/src/resources/extensions/gsd/tests/doctor-task-done-missing-summary-slice-loop.test.ts +174 -0
  416. package/src/resources/extensions/gsd/tests/e2e-workflow-pipeline-integration.test.ts +476 -0
  417. package/src/resources/extensions/gsd/tests/engine-interfaces-contract.test.ts +271 -0
  418. package/src/resources/extensions/gsd/tests/exit-command.test.ts +55 -0
  419. package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +48 -0
  420. package/src/resources/extensions/gsd/tests/forensics-issue-routing.test.ts +43 -0
  421. package/src/resources/extensions/gsd/tests/git-locale.test.ts +133 -0
  422. package/src/resources/extensions/gsd/tests/git-service.test.ts +49 -0
  423. package/src/resources/extensions/gsd/tests/graph-operations.test.ts +599 -0
  424. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +8 -1
  425. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +7 -7
  426. package/src/resources/extensions/gsd/tests/iterate-engine-integration.test.ts +429 -0
  427. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +513 -0
  428. package/src/resources/extensions/gsd/tests/journal-query-tool.test.ts +147 -0
  429. package/src/resources/extensions/gsd/tests/journal.test.ts +341 -0
  430. package/src/resources/extensions/gsd/tests/manifest-status.test.ts +73 -82
  431. package/src/resources/extensions/gsd/tests/md-importer.test.ts +31 -1
  432. package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
  433. package/src/resources/extensions/gsd/tests/milestone-id-reservation.test.ts +1 -1
  434. package/src/resources/extensions/gsd/tests/parsers.test.ts +110 -0
  435. package/src/resources/extensions/gsd/tests/preferences.test.ts +47 -25
  436. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +3 -1
  437. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +61 -1
  438. package/src/resources/extensions/gsd/tests/routing-history.test.ts +11 -22
  439. package/src/resources/extensions/gsd/tests/rule-registry.test.ts +413 -0
  440. package/src/resources/extensions/gsd/tests/run-manager.test.ts +229 -0
  441. package/src/resources/extensions/gsd/tests/service-tier.test.ts +127 -0
  442. package/src/resources/extensions/gsd/tests/skill-lifecycle.test.ts +2 -2
  443. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +102 -0
  444. package/src/resources/extensions/gsd/tests/structured-data-formatter.test.ts +4 -3
  445. package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +151 -0
  446. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +45 -0
  447. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +117 -0
  448. package/src/resources/extensions/gsd/tests/triage-dispatch.test.ts +6 -1
  449. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +156 -263
  450. package/src/resources/extensions/gsd/tests/windows-path-normalization.test.ts +99 -0
  451. package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +1 -0
  452. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +4 -0
  453. package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +135 -0
  454. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +203 -106
  455. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +78 -3
  456. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +140 -0
  457. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +74 -0
  458. package/src/resources/extensions/gsd/types.ts +3 -0
  459. package/src/resources/extensions/gsd/workflow-engine.ts +38 -0
  460. package/src/resources/extensions/gsd/workflow-templates.ts +12 -1
  461. package/src/resources/extensions/gsd/worktree-manager.ts +21 -6
  462. package/src/resources/extensions/gsd/worktree-resolver.ts +32 -11
  463. package/src/resources/extensions/mcp-client/index.ts +5 -1
  464. package/src/resources/extensions/search-the-web/tool-search.ts +3 -3
  465. package/src/resources/extensions/subagent/index.ts +7 -3
  466. package/src/resources/extensions/voice/index.ts +4 -4
  467. package/src/resources/skills/create-workflow/SKILL.md +103 -0
  468. package/src/resources/skills/create-workflow/references/feature-patterns.md +128 -0
  469. package/src/resources/skills/create-workflow/references/verification-policies.md +76 -0
  470. package/src/resources/skills/create-workflow/references/yaml-schema-v1.md +46 -0
  471. package/src/resources/skills/create-workflow/templates/blog-post-pipeline.yaml +60 -0
  472. package/src/resources/skills/create-workflow/templates/code-audit.yaml +60 -0
  473. package/src/resources/skills/create-workflow/templates/release-checklist.yaml +66 -0
  474. package/src/resources/skills/create-workflow/templates/workflow-definition.yaml +32 -0
  475. package/src/resources/skills/create-workflow/workflows/create-from-scratch.md +104 -0
  476. package/src/resources/skills/create-workflow/workflows/create-from-template.md +72 -0
  477. package/dist/web/standalone/.next/static/chunks/4024.279c423e4661ece1.js +0 -9
  478. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-e07acdb7dd069836.js +0 -1
  479. package/dist/web/standalone/.next/static/chunks/app/layout-745c6ed5fea5fb06.js +0 -1
  480. package/dist/web/standalone/.next/static/chunks/app/page-801b53eff6e83579.js +0 -1
  481. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-e6255954dccfcf0a.js +0 -1
  482. /package/dist/web/standalone/.next/static/{Ute3pMouVczQyT15qrBBO → JUBX5FUR73jiViQU5a-Cx}/_buildManifest.js +0 -0
  483. /package/dist/web/standalone/.next/static/{Ute3pMouVczQyT15qrBBO → JUBX5FUR73jiViQU5a-Cx}/_ssgManifest.js +0 -0
@@ -0,0 +1,341 @@
1
+ import { describe, test, beforeEach, afterEach } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import {
4
+ mkdirSync,
5
+ readFileSync,
6
+ existsSync,
7
+ rmSync,
8
+ chmodSync,
9
+ writeFileSync,
10
+ } from "node:fs";
11
+ import { join } from "node:path";
12
+ import { tmpdir } from "node:os";
13
+ import { randomUUID } from "node:crypto";
14
+
15
+ import {
16
+ emitJournalEvent,
17
+ queryJournal,
18
+ type JournalEntry,
19
+ } from "../journal.ts";
20
+
21
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
22
+
23
+ function makeTmpBase(): string {
24
+ const base = join(tmpdir(), `gsd-journal-test-${randomUUID()}`);
25
+ mkdirSync(join(base, ".gsd"), { recursive: true });
26
+ return base;
27
+ }
28
+
29
+ function cleanup(base: string): void {
30
+ try {
31
+ rmSync(base, { recursive: true, force: true });
32
+ } catch {
33
+ /* */
34
+ }
35
+ }
36
+
37
+ function makeEntry(overrides: Partial<JournalEntry> = {}): JournalEntry {
38
+ return {
39
+ ts: "2025-03-21T10:00:00.000Z",
40
+ flowId: "flow-aaa",
41
+ seq: 0,
42
+ eventType: "iteration-start",
43
+ ...overrides,
44
+ };
45
+ }
46
+
47
+ // ─── emitJournalEvent ─────────────────────────────────────────────────────────
48
+
49
+ describe("emitJournalEvent", () => {
50
+ let base: string;
51
+ beforeEach(() => { base = makeTmpBase(); });
52
+ afterEach(() => { cleanup(base); });
53
+
54
+ test("creates journal directory and JSONL file", () => {
55
+ const entry = makeEntry();
56
+ emitJournalEvent(base, entry);
57
+
58
+ const filePath = join(base, ".gsd", "journal", "2025-03-21.jsonl");
59
+ assert.ok(existsSync(filePath), "JSONL file should exist");
60
+
61
+ const raw = readFileSync(filePath, "utf-8").trim();
62
+ const parsed = JSON.parse(raw);
63
+ assert.equal(parsed.ts, entry.ts);
64
+ assert.equal(parsed.flowId, entry.flowId);
65
+ assert.equal(parsed.seq, entry.seq);
66
+ assert.equal(parsed.eventType, entry.eventType);
67
+ });
68
+
69
+ test("appends multiple lines to the same file", () => {
70
+ emitJournalEvent(base, makeEntry({ seq: 0 }));
71
+ emitJournalEvent(base, makeEntry({ seq: 1, eventType: "dispatch-match" }));
72
+ emitJournalEvent(base, makeEntry({ seq: 2, eventType: "unit-start" }));
73
+
74
+ const filePath = join(base, ".gsd", "journal", "2025-03-21.jsonl");
75
+ const lines = readFileSync(filePath, "utf-8").trim().split("\n");
76
+ assert.equal(lines.length, 3, "Should have 3 lines");
77
+
78
+ const parsed = lines.map(l => JSON.parse(l));
79
+ assert.equal(parsed[0].seq, 0);
80
+ assert.equal(parsed[1].seq, 1);
81
+ assert.equal(parsed[2].seq, 2);
82
+ assert.equal(parsed[1].eventType, "dispatch-match");
83
+ });
84
+
85
+ test("preserves optional fields (rule, causedBy, data)", () => {
86
+ const entry = makeEntry({
87
+ rule: "my-dispatch-rule",
88
+ causedBy: { flowId: "flow-prior", seq: 3 },
89
+ data: { unitId: "M001/S01/T01", status: "ok" },
90
+ });
91
+ emitJournalEvent(base, entry);
92
+
93
+ const filePath = join(base, ".gsd", "journal", "2025-03-21.jsonl");
94
+ const parsed = JSON.parse(readFileSync(filePath, "utf-8").trim());
95
+ assert.equal(parsed.rule, "my-dispatch-rule");
96
+ assert.deepEqual(parsed.causedBy, { flowId: "flow-prior", seq: 3 });
97
+ assert.equal(parsed.data.unitId, "M001/S01/T01");
98
+ assert.equal(parsed.data.status, "ok");
99
+ });
100
+
101
+ test("silently catches read-only directory errors", () => {
102
+ const journalDir = join(base, ".gsd", "journal");
103
+ mkdirSync(journalDir, { recursive: true });
104
+
105
+ // Make the journal directory read-only
106
+ chmodSync(journalDir, 0o444);
107
+
108
+ // Should not throw
109
+ assert.doesNotThrow(() => {
110
+ emitJournalEvent(base, makeEntry());
111
+ });
112
+
113
+ // Restore permissions for cleanup
114
+ try {
115
+ chmodSync(journalDir, 0o755);
116
+ } catch {
117
+ /* */
118
+ }
119
+ });
120
+ });
121
+
122
+ describe("emitJournalEvent — auto-creates parent directory", () => {
123
+ let base: string;
124
+ beforeEach(() => {
125
+ base = join(tmpdir(), `gsd-journal-test-${randomUUID()}`);
126
+ // Don't create .gsd/ — emitJournalEvent should handle it via mkdirSync recursive
127
+ });
128
+ afterEach(() => { cleanup(base); });
129
+
130
+ test("auto-creates nonexistent parent directory", () => {
131
+ emitJournalEvent(base, makeEntry());
132
+ const filePath = join(base, ".gsd", "journal", "2025-03-21.jsonl");
133
+ assert.ok(existsSync(filePath), "File should exist even when parent dirs did not");
134
+ });
135
+ });
136
+
137
+ test("emitJournalEvent silently catches write errors (no throw)", () => {
138
+ // Use a path that can't be created — null bytes in path
139
+ assert.doesNotThrow(() => {
140
+ emitJournalEvent("/dev/null/impossible\0path", makeEntry());
141
+ });
142
+ });
143
+
144
+ // ─── Daily Rotation ───────────────────────────────────────────────────────────
145
+
146
+ describe("daily rotation", () => {
147
+ let base: string;
148
+ beforeEach(() => { base = makeTmpBase(); });
149
+ afterEach(() => { cleanup(base); });
150
+
151
+ test("events with different dates go to different files", () => {
152
+ emitJournalEvent(base, makeEntry({ ts: "2025-03-20T23:59:59.000Z" }));
153
+ emitJournalEvent(base, makeEntry({ ts: "2025-03-21T00:00:01.000Z" }));
154
+ emitJournalEvent(base, makeEntry({ ts: "2025-03-22T12:00:00.000Z" }));
155
+
156
+ const journalDir = join(base, ".gsd", "journal");
157
+ assert.ok(existsSync(join(journalDir, "2025-03-20.jsonl")));
158
+ assert.ok(existsSync(join(journalDir, "2025-03-21.jsonl")));
159
+ assert.ok(existsSync(join(journalDir, "2025-03-22.jsonl")));
160
+
161
+ // Verify each file has exactly one line
162
+ for (const date of ["2025-03-20", "2025-03-21", "2025-03-22"]) {
163
+ const lines = readFileSync(join(journalDir, `${date}.jsonl`), "utf-8")
164
+ .trim()
165
+ .split("\n");
166
+ assert.equal(lines.length, 1, `${date}.jsonl should have 1 line`);
167
+ }
168
+ });
169
+ });
170
+
171
+ // ─── queryJournal ─────────────────────────────────────────────────────────────
172
+
173
+ describe("queryJournal", () => {
174
+ let base: string;
175
+ beforeEach(() => { base = makeTmpBase(); });
176
+ afterEach(() => { cleanup(base); });
177
+
178
+ test("returns all entries when no filters provided", () => {
179
+ emitJournalEvent(base, makeEntry({ seq: 0 }));
180
+ emitJournalEvent(base, makeEntry({ seq: 1, eventType: "dispatch-match" }));
181
+
182
+ const results = queryJournal(base);
183
+ assert.equal(results.length, 2);
184
+ assert.equal(results[0].seq, 0);
185
+ assert.equal(results[1].seq, 1);
186
+ });
187
+
188
+ test("filters by flowId", () => {
189
+ emitJournalEvent(base, makeEntry({ flowId: "flow-aaa", seq: 0 }));
190
+ emitJournalEvent(base, makeEntry({ flowId: "flow-bbb", seq: 1 }));
191
+ emitJournalEvent(base, makeEntry({ flowId: "flow-aaa", seq: 2 }));
192
+
193
+ const results = queryJournal(base, { flowId: "flow-aaa" });
194
+ assert.equal(results.length, 2);
195
+ assert.ok(results.every(e => e.flowId === "flow-aaa"));
196
+ });
197
+
198
+ test("filters by eventType", () => {
199
+ emitJournalEvent(base, makeEntry({ eventType: "iteration-start", seq: 0 }));
200
+ emitJournalEvent(base, makeEntry({ eventType: "dispatch-match", seq: 1 }));
201
+ emitJournalEvent(base, makeEntry({ eventType: "unit-start", seq: 2 }));
202
+ emitJournalEvent(base, makeEntry({ eventType: "dispatch-match", seq: 3 }));
203
+
204
+ const results = queryJournal(base, { eventType: "dispatch-match" });
205
+ assert.equal(results.length, 2);
206
+ assert.ok(results.every(e => e.eventType === "dispatch-match"));
207
+ });
208
+
209
+ test("filters by unitId (from data.unitId)", () => {
210
+ emitJournalEvent(
211
+ base,
212
+ makeEntry({ seq: 0, data: { unitId: "M001/S01/T01" } }),
213
+ );
214
+ emitJournalEvent(
215
+ base,
216
+ makeEntry({ seq: 1, data: { unitId: "M001/S01/T02" } }),
217
+ );
218
+ emitJournalEvent(
219
+ base,
220
+ makeEntry({ seq: 2, data: { unitId: "M001/S01/T01" } }),
221
+ );
222
+ emitJournalEvent(base, makeEntry({ seq: 3 })); // no data
223
+
224
+ const results = queryJournal(base, { unitId: "M001/S01/T01" });
225
+ assert.equal(results.length, 2);
226
+ assert.ok(
227
+ results.every(
228
+ e => (e.data as Record<string, unknown>)?.unitId === "M001/S01/T01",
229
+ ),
230
+ );
231
+ });
232
+
233
+ test("filters by time range (after/before)", () => {
234
+ emitJournalEvent(base, makeEntry({ ts: "2025-03-20T08:00:00.000Z", seq: 0 }));
235
+ emitJournalEvent(base, makeEntry({ ts: "2025-03-21T10:00:00.000Z", seq: 1 }));
236
+ emitJournalEvent(base, makeEntry({ ts: "2025-03-21T15:00:00.000Z", seq: 2 }));
237
+ emitJournalEvent(base, makeEntry({ ts: "2025-03-22T20:00:00.000Z", seq: 3 }));
238
+
239
+ // After only
240
+ const afterResults = queryJournal(base, { after: "2025-03-21T00:00:00.000Z" });
241
+ assert.equal(afterResults.length, 3, "3 entries on or after 2025-03-21");
242
+
243
+ // Before only
244
+ const beforeResults = queryJournal(base, { before: "2025-03-21T12:00:00.000Z" });
245
+ assert.equal(beforeResults.length, 2, "2 entries on or before noon on 03-21");
246
+
247
+ // Both after and before
248
+ const rangeResults = queryJournal(base, {
249
+ after: "2025-03-21T00:00:00.000Z",
250
+ before: "2025-03-21T23:59:59.000Z",
251
+ });
252
+ assert.equal(rangeResults.length, 2, "2 entries within 2025-03-21");
253
+ });
254
+
255
+ test("combines multiple filters", () => {
256
+ emitJournalEvent(
257
+ base,
258
+ makeEntry({ flowId: "flow-aaa", eventType: "unit-start", seq: 0 }),
259
+ );
260
+ emitJournalEvent(
261
+ base,
262
+ makeEntry({ flowId: "flow-aaa", eventType: "dispatch-match", seq: 1 }),
263
+ );
264
+ emitJournalEvent(
265
+ base,
266
+ makeEntry({ flowId: "flow-bbb", eventType: "unit-start", seq: 2 }),
267
+ );
268
+
269
+ const results = queryJournal(base, {
270
+ flowId: "flow-aaa",
271
+ eventType: "unit-start",
272
+ });
273
+ assert.equal(results.length, 1);
274
+ assert.equal(results[0].flowId, "flow-aaa");
275
+ assert.equal(results[0].eventType, "unit-start");
276
+ });
277
+
278
+ test("skips malformed JSON lines gracefully", () => {
279
+ const journalDir = join(base, ".gsd", "journal");
280
+ mkdirSync(journalDir, { recursive: true });
281
+
282
+ // Write a file with a mix of valid and invalid lines
283
+ const validEntry = JSON.stringify(makeEntry({ seq: 0 }));
284
+ const content = `${validEntry}\n{not valid json\n${JSON.stringify(makeEntry({ seq: 1 }))}\n`;
285
+ writeFileSync(join(journalDir, "2025-03-21.jsonl"), content);
286
+
287
+ const results = queryJournal(base);
288
+ assert.equal(results.length, 2, "Should skip the malformed line");
289
+ assert.equal(results[0].seq, 0);
290
+ assert.equal(results[1].seq, 1);
291
+ });
292
+
293
+ test("reads across multiple daily files", () => {
294
+ emitJournalEvent(base, makeEntry({ ts: "2025-03-20T12:00:00.000Z", seq: 0 }));
295
+ emitJournalEvent(base, makeEntry({ ts: "2025-03-21T12:00:00.000Z", seq: 1 }));
296
+ emitJournalEvent(base, makeEntry({ ts: "2025-03-22T12:00:00.000Z", seq: 2 }));
297
+
298
+ const results = queryJournal(base);
299
+ assert.equal(results.length, 3, "Should read from all 3 files");
300
+ // Files are sorted, so order should be chronological
301
+ assert.equal(results[0].ts, "2025-03-20T12:00:00.000Z");
302
+ assert.equal(results[1].ts, "2025-03-21T12:00:00.000Z");
303
+ assert.equal(results[2].ts, "2025-03-22T12:00:00.000Z");
304
+ });
305
+
306
+ test("filters by rule", () => {
307
+ emitJournalEvent(
308
+ base,
309
+ makeEntry({ seq: 0, eventType: "dispatch-match", rule: "dispatch-task" }),
310
+ );
311
+ emitJournalEvent(
312
+ base,
313
+ makeEntry({ seq: 1, eventType: "post-unit-hook", rule: "post-unit-hook" }),
314
+ );
315
+ emitJournalEvent(
316
+ base,
317
+ makeEntry({ seq: 2, eventType: "dispatch-match", rule: "dispatch-task" }),
318
+ );
319
+
320
+ const results = queryJournal(base, { rule: "dispatch-task" });
321
+ assert.equal(results.length, 2, "Should return only dispatch-task entries");
322
+ assert.ok(
323
+ results.every(e => e.rule === "dispatch-task"),
324
+ "All results should have rule === 'dispatch-task'",
325
+ );
326
+ });
327
+ });
328
+
329
+ describe("queryJournal — nonexistent directory", () => {
330
+ let base: string;
331
+ beforeEach(() => {
332
+ base = join(tmpdir(), `gsd-journal-test-${randomUUID()}`);
333
+ // Don't create anything
334
+ });
335
+ afterEach(() => { cleanup(base); });
336
+
337
+ test("on nonexistent directory returns empty array", () => {
338
+ const results = queryJournal(base);
339
+ assert.deepEqual(results, []);
340
+ });
341
+ });
@@ -8,7 +8,7 @@
8
8
  * Uses temp directories with real .gsd/milestones/M001/ structure.
9
9
  */
10
10
 
11
- import test from 'node:test';
11
+ import { describe, test, beforeEach, afterEach } from 'node:test';
12
12
  import assert from 'node:assert/strict';
13
13
  import { mkdirSync, writeFileSync, rmSync } from 'node:fs';
14
14
  import { join } from 'node:path';
@@ -30,12 +30,21 @@ function writeManifest(base: string, content: string): void {
30
30
 
31
31
  // ─── Mixed statuses ──────────────────────────────────────────────────────────
32
32
 
33
- test('getManifestStatus: mixed statuses — categorizes entries correctly', async () => {
34
- const tmp = makeTempDir('manifest-mixed');
35
- const savedVal = process.env.GSD_TEST_EXISTING_KEY_001;
36
- try {
33
+ describe('getManifestStatus: mixed statuses', () => {
34
+ let tmp: string;
35
+ let savedVal: string | undefined;
36
+ beforeEach(() => {
37
+ tmp = makeTempDir('manifest-mixed');
38
+ savedVal = process.env.GSD_TEST_EXISTING_KEY_001;
37
39
  process.env.GSD_TEST_EXISTING_KEY_001 = 'some-value';
40
+ });
41
+ afterEach(() => {
42
+ delete process.env.GSD_TEST_EXISTING_KEY_001;
43
+ if (savedVal !== undefined) process.env.GSD_TEST_EXISTING_KEY_001 = savedVal;
44
+ rmSync(tmp, { recursive: true, force: true });
45
+ });
38
46
 
47
+ test('categorizes entries correctly', async () => {
39
48
  writeManifest(tmp, `# Secrets Manifest
40
49
 
41
50
  **Milestone:** M001
@@ -80,18 +89,17 @@ test('getManifestStatus: mixed statuses — categorizes entries correctly', asyn
80
89
  assert.deepStrictEqual(result!.collected, ['COLLECTED_KEY']);
81
90
  assert.deepStrictEqual(result!.skipped, ['SKIPPED_KEY']);
82
91
  assert.deepStrictEqual(result!.existing, ['GSD_TEST_EXISTING_KEY_001']);
83
- } finally {
84
- delete process.env.GSD_TEST_EXISTING_KEY_001;
85
- if (savedVal !== undefined) process.env.GSD_TEST_EXISTING_KEY_001 = savedVal;
86
- rmSync(tmp, { recursive: true, force: true });
87
- }
92
+ });
88
93
  });
89
94
 
90
95
  // ─── All pending ─────────────────────────────────────────────────────────────
91
96
 
92
- test('getManifestStatus: all pending 3 pending entries, none in env', async () => {
93
- const tmp = makeTempDir('manifest-pending');
94
- try {
97
+ describe('getManifestStatus: simple temp dir tests', () => {
98
+ let tmp: string;
99
+ beforeEach(() => { tmp = makeTempDir('manifest-test'); });
100
+ afterEach(() => { rmSync(tmp, { recursive: true, force: true }); });
101
+
102
+ test('all pending — 3 pending entries, none in env', async () => {
95
103
  // Ensure none of these are in process.env
96
104
  delete process.env.PEND_A;
97
105
  delete process.env.PEND_B;
@@ -133,16 +141,11 @@ test('getManifestStatus: all pending — 3 pending entries, none in env', async
133
141
  assert.deepStrictEqual(result!.collected, []);
134
142
  assert.deepStrictEqual(result!.skipped, []);
135
143
  assert.deepStrictEqual(result!.existing, []);
136
- } finally {
137
- rmSync(tmp, { recursive: true, force: true });
138
- }
139
- });
144
+ });
140
145
 
141
- // ─── All collected ───────────────────────────────────────────────────────────
146
+ // ─── All collected ───────────────────────────────────────────────────────────
142
147
 
143
- test('getManifestStatus: all collected — 2 collected entries, none in env', async () => {
144
- const tmp = makeTempDir('manifest-collected');
145
- try {
148
+ test('all collected — 2 collected entries, none in env', async () => {
146
149
  delete process.env.COLL_X;
147
150
  delete process.env.COLL_Y;
148
151
 
@@ -174,64 +177,19 @@ test('getManifestStatus: all collected — 2 collected entries, none in env', as
174
177
  assert.deepStrictEqual(result!.collected, ['COLL_X', 'COLL_Y']);
175
178
  assert.deepStrictEqual(result!.skipped, []);
176
179
  assert.deepStrictEqual(result!.existing, []);
177
- } finally {
178
- rmSync(tmp, { recursive: true, force: true });
179
- }
180
- });
181
-
182
- // ─── Key in env overrides manifest status ────────────────────────────────────
183
-
184
- test('getManifestStatus: key in env overrides manifest status — collected key in env goes to existing', async () => {
185
- const tmp = makeTempDir('manifest-override');
186
- const savedVal = process.env.GSD_TEST_OVERRIDE_KEY;
187
- try {
188
- process.env.GSD_TEST_OVERRIDE_KEY = 'already-here';
189
-
190
- writeManifest(tmp, `# Secrets Manifest
191
-
192
- **Milestone:** M001
193
- **Generated:** 2025-06-20T10:00:00Z
194
-
195
- ### GSD_TEST_OVERRIDE_KEY
196
-
197
- **Service:** Override
198
- **Status:** collected
199
- **Destination:** dotenv
200
-
201
- 1. Was collected but now in env
202
- `);
203
-
204
- const result = await getManifestStatus(tmp, 'M001');
205
- assert.notStrictEqual(result, null);
206
- assert.deepStrictEqual(result!.pending, []);
207
- assert.deepStrictEqual(result!.collected, []);
208
- assert.deepStrictEqual(result!.skipped, []);
209
- assert.deepStrictEqual(result!.existing, ['GSD_TEST_OVERRIDE_KEY']);
210
- } finally {
211
- delete process.env.GSD_TEST_OVERRIDE_KEY;
212
- if (savedVal !== undefined) process.env.GSD_TEST_OVERRIDE_KEY = savedVal;
213
- rmSync(tmp, { recursive: true, force: true });
214
- }
215
- });
180
+ });
216
181
 
217
- // ─── Missing manifest ────────────────────────────────────────────────────────
182
+ // ─── Missing manifest ────────────────────────────────────────────────────────
218
183
 
219
- test('getManifestStatus: missing manifest — returns null', async () => {
220
- const tmp = makeTempDir('manifest-missing');
221
- try {
184
+ test('missing manifest — returns null', async () => {
222
185
  // No .gsd directory at all
223
186
  const result = await getManifestStatus(tmp, 'M001');
224
187
  assert.strictEqual(result, null);
225
- } finally {
226
- rmSync(tmp, { recursive: true, force: true });
227
- }
228
- });
188
+ });
229
189
 
230
- // ─── Empty manifest (no entries) ─────────────────────────────────────────────
190
+ // ─── Empty manifest (no entries) ─────────────────────────────────────────────
231
191
 
232
- test('getManifestStatus: empty manifest — exists but no H3 sections', async () => {
233
- const tmp = makeTempDir('manifest-empty');
234
- try {
192
+ test('empty manifest — exists but no H3 sections', async () => {
235
193
  writeManifest(tmp, `# Secrets Manifest
236
194
 
237
195
  **Milestone:** M001
@@ -244,16 +202,11 @@ test('getManifestStatus: empty manifest — exists but no H3 sections', async ()
244
202
  assert.deepStrictEqual(result!.collected, []);
245
203
  assert.deepStrictEqual(result!.skipped, []);
246
204
  assert.deepStrictEqual(result!.existing, []);
247
- } finally {
248
- rmSync(tmp, { recursive: true, force: true });
249
- }
250
- });
205
+ });
251
206
 
252
- // ─── Env via .env file (not just process.env) ────────────────────────────────
207
+ // ─── Env via .env file (not just process.env) ────────────────────────────────
253
208
 
254
- test('getManifestStatus: key in .env file counts as existing', async () => {
255
- const tmp = makeTempDir('manifest-dotenv');
256
- try {
209
+ test('key in .env file counts as existing', async () => {
257
210
  delete process.env.DOTENV_ONLY_KEY;
258
211
 
259
212
  writeManifest(tmp, `# Secrets Manifest
@@ -277,7 +230,45 @@ test('getManifestStatus: key in .env file counts as existing', async () => {
277
230
  assert.notStrictEqual(result, null);
278
231
  assert.deepStrictEqual(result!.existing, ['DOTENV_ONLY_KEY']);
279
232
  assert.deepStrictEqual(result!.pending, []);
280
- } finally {
233
+ });
234
+ });
235
+
236
+ // ─── Key in env overrides manifest status ────────────────────────────────────
237
+
238
+ describe('getManifestStatus: key in env overrides manifest status', () => {
239
+ let tmp: string;
240
+ let savedVal: string | undefined;
241
+ beforeEach(() => {
242
+ tmp = makeTempDir('manifest-override');
243
+ savedVal = process.env.GSD_TEST_OVERRIDE_KEY;
244
+ process.env.GSD_TEST_OVERRIDE_KEY = 'already-here';
245
+ });
246
+ afterEach(() => {
247
+ delete process.env.GSD_TEST_OVERRIDE_KEY;
248
+ if (savedVal !== undefined) process.env.GSD_TEST_OVERRIDE_KEY = savedVal;
281
249
  rmSync(tmp, { recursive: true, force: true });
282
- }
250
+ });
251
+
252
+ test('collected key in env goes to existing', async () => {
253
+ writeManifest(tmp, `# Secrets Manifest
254
+
255
+ **Milestone:** M001
256
+ **Generated:** 2025-06-20T10:00:00Z
257
+
258
+ ### GSD_TEST_OVERRIDE_KEY
259
+
260
+ **Service:** Override
261
+ **Status:** collected
262
+ **Destination:** dotenv
263
+
264
+ 1. Was collected but now in env
265
+ `);
266
+
267
+ const result = await getManifestStatus(tmp, 'M001');
268
+ assert.notStrictEqual(result, null);
269
+ assert.deepStrictEqual(result!.pending, []);
270
+ assert.deepStrictEqual(result!.collected, []);
271
+ assert.deepStrictEqual(result!.skipped, []);
272
+ assert.deepStrictEqual(result!.existing, ['GSD_TEST_OVERRIDE_KEY']);
273
+ });
283
274
  });
@@ -187,6 +187,36 @@ console.log('=== md-importer: malformed/empty rows skipped ===');
187
187
  assertEq(decisions[1].id, 'D003', 'second valid row (skipping malformed)');
188
188
  }
189
189
 
190
+ console.log('=== md-importer: made_by backward compatibility (old 7-column format) ===');
191
+
192
+ {
193
+ const decisions = parseDecisionsTable(DECISIONS_MD);
194
+ // Old format has no Made By column — should default to 'agent'
195
+ for (const d of decisions) {
196
+ assertEq(d.made_by, 'agent', `${d.id} made_by defaults to agent for legacy format`);
197
+ }
198
+ }
199
+
200
+ console.log('=== md-importer: made_by column parsing (new 8-column format) ===');
201
+
202
+ {
203
+ const newFormatMd = `# Decisions Register
204
+
205
+ | # | When | Scope | Decision | Choice | Rationale | Revisable? | Made By |
206
+ |---|------|-------|----------|--------|-----------|------------|---------|
207
+ | D001 | M001 | library | SQLite library | better-sqlite3 | Sync API | No | human |
208
+ | D002 | M001 | arch | DB location | .gsd/gsd.db | Derived state | No | agent |
209
+ | D003 | M002 | impl | Config format | JSON | Simple | Yes | collaborative |
210
+ | D004 | M002 | impl | Cache strategy | LRU | Predictable | No | bogus |
211
+ `;
212
+ const decisions = parseDecisionsTable(newFormatMd);
213
+ assertEq(decisions.length, 4, 'should parse 4 decisions with new format');
214
+ assertEq(decisions[0].made_by, 'human', 'D001 made_by = human');
215
+ assertEq(decisions[1].made_by, 'agent', 'D002 made_by = agent');
216
+ assertEq(decisions[2].made_by, 'collaborative', 'D003 made_by = collaborative');
217
+ assertEq(decisions[3].made_by, 'agent', 'D004 invalid made_by defaults to agent');
218
+ }
219
+
190
220
  // ═══════════════════════════════════════════════════════════════════════════
191
221
  // md-importer: parseRequirementsSections
192
222
  // ═══════════════════════════════════════════════════════════════════════════
@@ -354,7 +384,7 @@ console.log('=== md-importer: schema v1→v2 migration ===');
354
384
  openDatabase(':memory:');
355
385
  const adapter = _getAdapter();
356
386
  const version = adapter?.prepare('SELECT MAX(version) as v FROM schema_version').get();
357
- assertEq(version?.v, 3, 'new DB should be at schema version 3');
387
+ assertEq(version?.v, 4, 'new DB should be at schema version 4');
358
388
 
359
389
  // Artifacts table should exist
360
390
  const tableCheck = adapter?.prepare("SELECT count(*) as c FROM sqlite_master WHERE type='table' AND name='artifacts'").get();
@@ -335,9 +335,9 @@ console.log('\n=== memory-store: schema includes memories table ===');
335
335
  const viewCount = adapter.prepare('SELECT count(*) as cnt FROM active_memories').get();
336
336
  assertEq(viewCount?.['cnt'], 0, 'active_memories view should exist');
337
337
 
338
- // Verify schema version is 3
338
+ // Verify schema version is 4
339
339
  const version = adapter.prepare('SELECT MAX(version) as v FROM schema_version').get();
340
- assertEq(version?.['v'], 3, 'schema version should be 3');
340
+ assertEq(version?.['v'], 4, 'schema version should be 4');
341
341
 
342
342
  closeDatabase();
343
343
  }
@@ -1,5 +1,5 @@
1
1
  // milestone-id-reservation — Verifies that preview IDs from guided-flow
2
- // match the IDs claimed by gsd_generate_milestone_id via the shared
2
+ // match the IDs claimed by gsd_milestone_generate_id via the shared
3
3
  // reservation mechanism in milestone-ids.ts.
4
4
  //
5
5
  // Regression test for #1569.