gsd-pi 2.57.0-dev.f22a903 → 2.58.0-dev.778d6ac

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 (643) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.js +49 -35
  3. package/dist/headless-ui.d.ts +17 -0
  4. package/dist/headless-ui.js +97 -3
  5. package/dist/headless.js +67 -6
  6. package/dist/help-text.js +1 -0
  7. package/dist/onboarding.js +44 -0
  8. package/dist/resource-loader.js +16 -1
  9. package/dist/resources/agents/researcher.md +1 -1
  10. package/dist/resources/extensions/ask-user-questions.js +16 -3
  11. package/dist/resources/extensions/async-jobs/extension-manifest.json +1 -1
  12. package/dist/resources/extensions/bg-shell/extension-manifest.json +1 -1
  13. package/dist/resources/extensions/browser-tools/extension-manifest.json +1 -1
  14. package/dist/resources/extensions/claude-code-cli/partial-builder.js +14 -6
  15. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +59 -36
  16. package/dist/resources/extensions/context7/extension-manifest.json +1 -1
  17. package/dist/resources/extensions/get-secrets-from-user.js +8 -5
  18. package/dist/resources/extensions/google-search/extension-manifest.json +1 -1
  19. package/dist/resources/extensions/google-search/index.js +2 -1
  20. package/dist/resources/extensions/gsd/auto/phases.js +25 -21
  21. package/dist/resources/extensions/gsd/auto-artifact-paths.js +2 -2
  22. package/dist/resources/extensions/gsd/auto-dashboard.js +37 -20
  23. package/dist/resources/extensions/gsd/auto-dispatch.js +17 -2
  24. package/dist/resources/extensions/gsd/auto-model-selection.js +26 -3
  25. package/dist/resources/extensions/gsd/auto-post-unit.js +16 -4
  26. package/dist/resources/extensions/gsd/auto-prompts.js +1 -1
  27. package/dist/resources/extensions/gsd/auto-recovery.js +13 -5
  28. package/dist/resources/extensions/gsd/auto-start.js +35 -22
  29. package/dist/resources/extensions/gsd/auto-worktree.js +196 -12
  30. package/dist/resources/extensions/gsd/auto.js +4 -0
  31. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +32 -0
  32. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +80 -8
  33. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +32 -1
  34. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +33 -18
  35. package/dist/resources/extensions/gsd/bootstrap/system-context.js +44 -11
  36. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +67 -0
  37. package/dist/resources/extensions/gsd/captures.js +56 -4
  38. package/dist/resources/extensions/gsd/db-writer.js +116 -8
  39. package/dist/resources/extensions/gsd/doctor-git-checks.js +28 -0
  40. package/dist/resources/extensions/gsd/doctor-providers.js +2 -1
  41. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +5 -4
  42. package/dist/resources/extensions/gsd/doctor.js +3 -1
  43. package/dist/resources/extensions/gsd/error-classifier.js +13 -10
  44. package/dist/resources/extensions/gsd/extension-manifest.json +16 -1
  45. package/dist/resources/extensions/gsd/forensics.js +123 -20
  46. package/dist/resources/extensions/gsd/git-service.js +23 -1
  47. package/dist/resources/extensions/gsd/gitignore.js +33 -0
  48. package/dist/resources/extensions/gsd/gsd-db.js +36 -9
  49. package/dist/resources/extensions/gsd/guided-flow.js +106 -44
  50. package/dist/resources/extensions/gsd/health-widget-core.js +31 -0
  51. package/dist/resources/extensions/gsd/health-widget.js +17 -0
  52. package/dist/resources/extensions/gsd/index.js +1 -1
  53. package/dist/resources/extensions/gsd/memory-extractor.js +7 -0
  54. package/dist/resources/extensions/gsd/migrate-external.js +8 -1
  55. package/dist/resources/extensions/gsd/milestone-validation-gates.js +45 -0
  56. package/dist/resources/extensions/gsd/model-cost-table.js +18 -0
  57. package/dist/resources/extensions/gsd/model-router.js +35 -1
  58. package/dist/resources/extensions/gsd/native-git-bridge.js +17 -0
  59. package/dist/resources/extensions/gsd/notifications.js +16 -1
  60. package/dist/resources/extensions/gsd/parallel-eligibility.js +13 -2
  61. package/dist/resources/extensions/gsd/parallel-merge.js +78 -5
  62. package/dist/resources/extensions/gsd/parsers-legacy.js +20 -3
  63. package/dist/resources/extensions/gsd/paths.js +43 -0
  64. package/dist/resources/extensions/gsd/preferences-models.js +14 -1
  65. package/dist/resources/extensions/gsd/preferences-types.js +2 -1
  66. package/dist/resources/extensions/gsd/preferences.js +13 -16
  67. package/dist/resources/extensions/gsd/prompt-loader.js +4 -1
  68. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  69. package/dist/resources/extensions/gsd/prompts/complete-slice.md +4 -2
  70. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +1 -1
  71. package/dist/resources/extensions/gsd/prompts/discuss.md +1 -1
  72. package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -1
  73. package/dist/resources/extensions/gsd/prompts/forensics.md +2 -2
  74. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  75. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
  76. package/dist/resources/extensions/gsd/prompts/plan-slice.md +2 -0
  77. package/dist/resources/extensions/gsd/prompts/rethink.md +1 -1
  78. package/dist/resources/extensions/gsd/prompts/triage-captures.md +1 -0
  79. package/dist/resources/extensions/gsd/repo-identity.js +205 -11
  80. package/dist/resources/extensions/gsd/rethink.js +5 -0
  81. package/dist/resources/extensions/gsd/roadmap-slices.js +5 -4
  82. package/dist/resources/extensions/gsd/state.js +85 -27
  83. package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +20 -1
  84. package/dist/resources/extensions/gsd/tools/complete-task.js +34 -71
  85. package/dist/resources/extensions/gsd/tools/plan-milestone.js +12 -2
  86. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +29 -1
  87. package/dist/resources/extensions/gsd/tools/validate-milestone.js +14 -3
  88. package/dist/resources/extensions/gsd/triage-resolution.js +22 -7
  89. package/dist/resources/extensions/gsd/undo.js +2 -2
  90. package/dist/resources/extensions/gsd/unit-ownership.js +164 -33
  91. package/dist/resources/extensions/gsd/verdict-parser.js +20 -8
  92. package/dist/resources/extensions/gsd/workflow-manifest.js +24 -5
  93. package/dist/resources/extensions/gsd/workflow-projections.js +95 -63
  94. package/dist/resources/extensions/gsd/workflow-reconcile.js +35 -5
  95. package/dist/resources/extensions/gsd/workspace-index.js +24 -0
  96. package/dist/resources/extensions/gsd/worktree-manager.js +105 -1
  97. package/dist/resources/extensions/gsd/worktree-resolver.js +20 -3
  98. package/dist/resources/extensions/mcp-client/index.js +11 -7
  99. package/dist/resources/extensions/ollama/index.js +112 -0
  100. package/dist/resources/extensions/ollama/model-capabilities.js +115 -0
  101. package/dist/resources/extensions/ollama/ollama-client.js +168 -0
  102. package/dist/resources/extensions/ollama/ollama-commands.js +194 -0
  103. package/dist/resources/extensions/ollama/ollama-discovery.js +69 -0
  104. package/dist/resources/extensions/ollama/ollama-tool.js +184 -0
  105. package/dist/resources/extensions/ollama/types.js +2 -0
  106. package/dist/resources/extensions/search-the-web/extension-manifest.json +1 -1
  107. package/dist/resources/extensions/shared/interview-ui.js +11 -1
  108. package/dist/resources/skills/create-gsd-extension/SKILL.md +5 -3
  109. package/dist/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +5 -4
  110. package/dist/resources/skills/create-gsd-extension/workflows/add-capability.md +2 -2
  111. package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +4 -4
  112. package/dist/resources/skills/create-gsd-extension/workflows/debug-extension.md +5 -3
  113. package/dist/startup-model-validation.d.ts +39 -0
  114. package/dist/startup-model-validation.js +50 -0
  115. package/dist/web/standalone/.next/BUILD_ID +1 -1
  116. package/dist/web/standalone/.next/app-path-routes-manifest.json +16 -16
  117. package/dist/web/standalone/.next/build-manifest.json +3 -3
  118. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  119. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  120. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  122. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  128. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  130. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  131. package/dist/web/standalone/.next/server/app/_not-found.rsc +2 -2
  132. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  133. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  134. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  135. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  136. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  137. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  138. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.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_client-reference-manifest.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  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_client-reference-manifest.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  192. package/dist/web/standalone/.next/server/app/index.html +1 -1
  193. package/dist/web/standalone/.next/server/app/index.rsc +2 -2
  194. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  195. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
  196. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  197. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +2 -2
  198. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  199. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  200. package/dist/web/standalone/.next/server/app-paths-manifest.json +16 -16
  201. package/dist/web/standalone/.next/server/chunks/2229.js +2 -2
  202. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  203. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  204. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  205. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  206. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  207. package/dist/web/standalone/.next/static/chunks/6502.7593d7797a4b3999.js +9 -0
  208. package/dist/web/standalone/.next/static/chunks/{webpack-61d3afac6d0f0ce7.js → webpack-a1c1e452c6b32d04.js} +1 -1
  209. package/dist/web/standalone/.next/static/css/f6e8833d46e738d8.css +1 -0
  210. package/dist/web-mode.js +2 -1
  211. package/package.json +2 -2
  212. package/packages/daemon/src/cli.ts +49 -0
  213. package/packages/daemon/src/daemon.test.ts +104 -1
  214. package/packages/daemon/src/daemon.ts +24 -1
  215. package/packages/daemon/src/discord-bot.ts +73 -3
  216. package/packages/daemon/src/event-bridge.ts +15 -9
  217. package/packages/daemon/src/event-formatter.ts +30 -2
  218. package/packages/daemon/src/index.ts +9 -0
  219. package/packages/daemon/src/launchd.test.ts +356 -0
  220. package/packages/daemon/src/launchd.ts +242 -0
  221. package/packages/daemon/src/message-batcher.test.ts +2 -2
  222. package/packages/daemon/src/message-batcher.ts +9 -3
  223. package/packages/daemon/src/orchestrator.test.ts +1 -0
  224. package/packages/daemon/src/orchestrator.ts +106 -2
  225. package/packages/native/dist/ast/index.js +9 -5
  226. package/packages/native/dist/ast/types.js +2 -1
  227. package/packages/native/dist/clipboard/index.js +12 -7
  228. package/packages/native/dist/clipboard/types.js +2 -1
  229. package/packages/native/dist/diff/index.js +12 -7
  230. package/packages/native/dist/diff/types.js +2 -1
  231. package/packages/native/dist/fd/index.js +6 -3
  232. package/packages/native/dist/fd/types.js +2 -1
  233. package/packages/native/dist/glob/index.js +9 -5
  234. package/packages/native/dist/glob/types.js +2 -1
  235. package/packages/native/dist/grep/index.js +9 -5
  236. package/packages/native/dist/grep/types.js +2 -1
  237. package/packages/native/dist/gsd-parser/index.js +18 -11
  238. package/packages/native/dist/gsd-parser/types.js +2 -1
  239. package/packages/native/dist/highlight/index.js +12 -7
  240. package/packages/native/dist/highlight/types.js +2 -1
  241. package/packages/native/dist/html/index.js +6 -3
  242. package/packages/native/dist/html/types.js +2 -1
  243. package/packages/native/dist/image/index.js +10 -5
  244. package/packages/native/dist/image/types.js +7 -4
  245. package/packages/native/dist/index.js +70 -17
  246. package/packages/native/dist/json-parse/index.js +13 -8
  247. package/packages/native/dist/native.js +47 -10
  248. package/packages/native/dist/ps/index.js +15 -9
  249. package/packages/native/dist/ps/types.js +2 -1
  250. package/packages/native/dist/stream-process/index.js +12 -7
  251. package/packages/native/dist/text/index.js +24 -14
  252. package/packages/native/dist/text/types.js +5 -2
  253. package/packages/native/dist/truncate/index.js +12 -7
  254. package/packages/native/dist/ttsr/index.js +12 -7
  255. package/packages/native/dist/ttsr/types.js +2 -1
  256. package/packages/native/dist/xxhash/index.js +9 -5
  257. package/packages/native/package.json +19 -19
  258. package/packages/native/src/__tests__/module-compat.test.mjs +91 -0
  259. package/packages/native/src/native.ts +9 -8
  260. package/packages/pi-agent-core/dist/agent-loop.js +3 -2
  261. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  262. package/packages/pi-agent-core/dist/proxy.d.ts +1 -1
  263. package/packages/pi-agent-core/dist/proxy.d.ts.map +1 -1
  264. package/packages/pi-agent-core/dist/proxy.js.map +1 -1
  265. package/packages/pi-agent-core/src/agent-loop.test.ts +45 -0
  266. package/packages/pi-agent-core/src/agent-loop.ts +3 -2
  267. package/packages/pi-agent-core/src/proxy.ts +1 -1
  268. package/packages/pi-ai/dist/env-api-keys.js +1 -0
  269. package/packages/pi-ai/dist/env-api-keys.js.map +1 -1
  270. package/packages/pi-ai/dist/index.d.ts +1 -0
  271. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  272. package/packages/pi-ai/dist/index.js +1 -0
  273. package/packages/pi-ai/dist/index.js.map +1 -1
  274. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
  275. package/packages/pi-ai/dist/providers/anthropic-shared.js +19 -2
  276. package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
  277. package/packages/pi-ai/dist/providers/anthropic-shared.test.d.ts +2 -0
  278. package/packages/pi-ai/dist/providers/anthropic-shared.test.d.ts.map +1 -0
  279. package/packages/pi-ai/dist/providers/anthropic-shared.test.js +25 -0
  280. package/packages/pi-ai/dist/providers/anthropic-shared.test.js.map +1 -0
  281. package/packages/pi-ai/dist/types.d.ts +3 -3
  282. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  283. package/packages/pi-ai/dist/types.js.map +1 -1
  284. package/packages/pi-ai/dist/utils/json-parse.d.ts +3 -0
  285. package/packages/pi-ai/dist/utils/json-parse.d.ts.map +1 -1
  286. package/packages/pi-ai/dist/utils/json-parse.js +24 -1
  287. package/packages/pi-ai/dist/utils/json-parse.js.map +1 -1
  288. package/packages/pi-ai/dist/utils/repair-tool-json.d.ts +37 -0
  289. package/packages/pi-ai/dist/utils/repair-tool-json.d.ts.map +1 -0
  290. package/packages/pi-ai/dist/utils/repair-tool-json.js +75 -0
  291. package/packages/pi-ai/dist/utils/repair-tool-json.js.map +1 -0
  292. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.d.ts +2 -0
  293. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.d.ts.map +1 -0
  294. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js +73 -0
  295. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js.map +1 -0
  296. package/packages/pi-ai/src/env-api-keys.ts +1 -0
  297. package/packages/pi-ai/src/index.ts +1 -0
  298. package/packages/pi-ai/src/providers/anthropic-shared.test.ts +29 -0
  299. package/packages/pi-ai/src/providers/anthropic-shared.ts +17 -2
  300. package/packages/pi-ai/src/types.ts +3 -2
  301. package/packages/pi-ai/src/utils/json-parse.ts +28 -1
  302. package/packages/pi-ai/src/utils/repair-tool-json.ts +88 -0
  303. package/packages/pi-ai/src/utils/tests/repair-tool-json.test.ts +102 -0
  304. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +4 -0
  305. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  306. package/packages/pi-coding-agent/dist/core/agent-session.js +31 -0
  307. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  308. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +17 -1
  309. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  310. package/packages/pi-coding-agent/dist/core/compaction/compaction.js +62 -2
  311. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  312. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.d.ts +6 -0
  313. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.d.ts.map +1 -0
  314. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js +176 -0
  315. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js.map +1 -0
  316. package/packages/pi-coding-agent/dist/core/exec.d.ts.map +1 -1
  317. package/packages/pi-coding-agent/dist/core/exec.js +3 -1
  318. package/packages/pi-coding-agent/dist/core/exec.js.map +1 -1
  319. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.d.ts +28 -0
  320. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.d.ts.map +1 -0
  321. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.js +37 -0
  322. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.js.map +1 -0
  323. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.d.ts +2 -0
  324. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.d.ts.map +1 -0
  325. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.js +63 -0
  326. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.js.map +1 -0
  327. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.d.ts +19 -0
  328. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.d.ts.map +1 -0
  329. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.js +115 -0
  330. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.js.map +1 -0
  331. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.d.ts +2 -0
  332. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.d.ts.map +1 -0
  333. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.js +109 -0
  334. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.js.map +1 -0
  335. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +4 -0
  336. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
  337. package/packages/pi-coding-agent/dist/core/extensions/index.js +2 -0
  338. package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
  339. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +5 -0
  340. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  341. package/packages/pi-coding-agent/dist/core/extensions/loader.js +5 -0
  342. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  343. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.d.ts +44 -0
  344. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.d.ts.map +1 -0
  345. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.js +97 -0
  346. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.js.map +1 -0
  347. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.d.ts +2 -0
  348. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.d.ts.map +1 -0
  349. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.js +181 -0
  350. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.js.map +1 -0
  351. package/packages/pi-coding-agent/dist/core/index.d.ts +1 -1
  352. package/packages/pi-coding-agent/dist/core/index.d.ts.map +1 -1
  353. package/packages/pi-coding-agent/dist/core/index.js +1 -1
  354. package/packages/pi-coding-agent/dist/core/index.js.map +1 -1
  355. package/packages/pi-coding-agent/dist/core/lsp/index.d.ts.map +1 -1
  356. package/packages/pi-coding-agent/dist/core/lsp/index.js +3 -0
  357. package/packages/pi-coding-agent/dist/core/lsp/index.js.map +1 -1
  358. package/packages/pi-coding-agent/dist/core/lsp/lspmux.d.ts.map +1 -1
  359. package/packages/pi-coding-agent/dist/core/lsp/lspmux.js +3 -0
  360. package/packages/pi-coding-agent/dist/core/lsp/lspmux.js.map +1 -1
  361. package/packages/pi-coding-agent/dist/core/messages.d.ts.map +1 -1
  362. package/packages/pi-coding-agent/dist/core/messages.js +31 -2
  363. package/packages/pi-coding-agent/dist/core/messages.js.map +1 -1
  364. package/packages/pi-coding-agent/dist/core/messages.test.d.ts +9 -0
  365. package/packages/pi-coding-agent/dist/core/messages.test.d.ts.map +1 -0
  366. package/packages/pi-coding-agent/dist/core/messages.test.js +86 -0
  367. package/packages/pi-coding-agent/dist/core/messages.test.js.map +1 -0
  368. package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
  369. package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -0
  370. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  371. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts +10 -0
  372. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
  373. package/packages/pi-coding-agent/dist/core/resource-loader.js +12 -1
  374. package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
  375. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts +6 -0
  376. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
  377. package/packages/pi-coding-agent/dist/core/retry-handler.js +48 -1
  378. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  379. package/packages/pi-coding-agent/dist/core/retry-handler.test.d.ts +9 -0
  380. package/packages/pi-coding-agent/dist/core/retry-handler.test.d.ts.map +1 -0
  381. package/packages/pi-coding-agent/dist/core/retry-handler.test.js +193 -0
  382. package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -0
  383. package/packages/pi-coding-agent/dist/core/tools/hashline-read.d.ts.map +1 -1
  384. package/packages/pi-coding-agent/dist/core/tools/hashline-read.js +10 -3
  385. package/packages/pi-coding-agent/dist/core/tools/hashline-read.js.map +1 -1
  386. package/packages/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
  387. package/packages/pi-coding-agent/dist/core/tools/read.js +13 -4
  388. package/packages/pi-coding-agent/dist/core/tools/read.js.map +1 -1
  389. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.d.ts +16 -0
  390. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.d.ts.map +1 -0
  391. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js +80 -0
  392. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js.map +1 -0
  393. package/packages/pi-coding-agent/dist/index.d.ts +2 -2
  394. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  395. package/packages/pi-coding-agent/dist/index.js +1 -1
  396. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  397. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  398. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +4 -0
  399. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  400. package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.d.ts +1 -0
  401. package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.d.ts.map +1 -1
  402. package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.js +5 -0
  403. package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.js.map +1 -1
  404. package/packages/pi-coding-agent/package.json +1 -1
  405. package/packages/pi-coding-agent/src/core/agent-session.ts +38 -1
  406. package/packages/pi-coding-agent/src/core/compaction/compaction.test.ts +236 -0
  407. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +94 -1
  408. package/packages/pi-coding-agent/src/core/exec.ts +3 -1
  409. package/packages/pi-coding-agent/src/core/extensions/extension-manifest.test.ts +77 -0
  410. package/packages/pi-coding-agent/src/core/extensions/extension-manifest.ts +62 -0
  411. package/packages/pi-coding-agent/src/core/extensions/extension-sort.test.ts +134 -0
  412. package/packages/pi-coding-agent/src/core/extensions/extension-sort.ts +137 -0
  413. package/packages/pi-coding-agent/src/core/extensions/index.ts +4 -0
  414. package/packages/pi-coding-agent/src/core/extensions/loader.ts +5 -0
  415. package/packages/pi-coding-agent/src/core/image-overflow-recovery.test.ts +228 -0
  416. package/packages/pi-coding-agent/src/core/image-overflow-recovery.ts +118 -0
  417. package/packages/pi-coding-agent/src/core/index.ts +6 -0
  418. package/packages/pi-coding-agent/src/core/lsp/index.ts +3 -0
  419. package/packages/pi-coding-agent/src/core/lsp/lspmux.ts +3 -0
  420. package/packages/pi-coding-agent/src/core/messages.test.ts +114 -0
  421. package/packages/pi-coding-agent/src/core/messages.ts +29 -2
  422. package/packages/pi-coding-agent/src/core/model-resolver.ts +1 -0
  423. package/packages/pi-coding-agent/src/core/resource-loader.ts +20 -1
  424. package/packages/pi-coding-agent/src/core/retry-handler.test.ts +255 -0
  425. package/packages/pi-coding-agent/src/core/retry-handler.ts +52 -1
  426. package/packages/pi-coding-agent/src/core/tools/hashline-read.ts +11 -3
  427. package/packages/pi-coding-agent/src/core/tools/read.ts +14 -4
  428. package/packages/pi-coding-agent/src/core/tools/spawn-shell-windows.test.ts +92 -0
  429. package/packages/pi-coding-agent/src/index.ts +6 -0
  430. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +7 -0
  431. package/packages/pi-coding-agent/src/modes/rpc/remote-terminal.ts +6 -0
  432. package/packages/pi-tui/dist/terminal.d.ts +2 -0
  433. package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
  434. package/packages/pi-tui/dist/terminal.js +9 -0
  435. package/packages/pi-tui/dist/terminal.js.map +1 -1
  436. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  437. package/packages/pi-tui/dist/tui.js +9 -0
  438. package/packages/pi-tui/dist/tui.js.map +1 -1
  439. package/packages/pi-tui/src/terminal.ts +14 -0
  440. package/packages/pi-tui/src/tui.ts +8 -0
  441. package/pkg/package.json +1 -1
  442. package/scripts/ensure-workspace-builds.cjs +45 -14
  443. package/src/resources/agents/researcher.md +1 -1
  444. package/src/resources/extensions/ask-user-questions.ts +21 -3
  445. package/src/resources/extensions/async-jobs/extension-manifest.json +1 -1
  446. package/src/resources/extensions/bg-shell/extension-manifest.json +1 -1
  447. package/src/resources/extensions/browser-tools/extension-manifest.json +1 -1
  448. package/src/resources/extensions/claude-code-cli/partial-builder.ts +13 -6
  449. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +63 -35
  450. package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +28 -0
  451. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +108 -1
  452. package/src/resources/extensions/context7/extension-manifest.json +1 -1
  453. package/src/resources/extensions/get-secrets-from-user.ts +8 -5
  454. package/src/resources/extensions/google-search/extension-manifest.json +1 -1
  455. package/src/resources/extensions/google-search/index.ts +2 -1
  456. package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
  457. package/src/resources/extensions/gsd/auto/phases.ts +43 -34
  458. package/src/resources/extensions/gsd/auto-artifact-paths.ts +2 -2
  459. package/src/resources/extensions/gsd/auto-dashboard.ts +37 -19
  460. package/src/resources/extensions/gsd/auto-dispatch.ts +18 -2
  461. package/src/resources/extensions/gsd/auto-model-selection.ts +26 -5
  462. package/src/resources/extensions/gsd/auto-post-unit.ts +18 -4
  463. package/src/resources/extensions/gsd/auto-prompts.ts +1 -1
  464. package/src/resources/extensions/gsd/auto-recovery.ts +12 -5
  465. package/src/resources/extensions/gsd/auto-start.ts +35 -26
  466. package/src/resources/extensions/gsd/auto-worktree.ts +190 -9
  467. package/src/resources/extensions/gsd/auto.ts +5 -0
  468. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +31 -0
  469. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +85 -8
  470. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +38 -1
  471. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +31 -19
  472. package/src/resources/extensions/gsd/bootstrap/system-context.ts +50 -11
  473. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +75 -0
  474. package/src/resources/extensions/gsd/captures.ts +63 -3
  475. package/src/resources/extensions/gsd/db-writer.ts +140 -7
  476. package/src/resources/extensions/gsd/doctor-git-checks.ts +26 -0
  477. package/src/resources/extensions/gsd/doctor-providers.ts +2 -1
  478. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +5 -4
  479. package/src/resources/extensions/gsd/doctor.ts +3 -1
  480. package/src/resources/extensions/gsd/error-classifier.ts +14 -11
  481. package/src/resources/extensions/gsd/extension-manifest.json +16 -1
  482. package/src/resources/extensions/gsd/forensics.ts +144 -20
  483. package/src/resources/extensions/gsd/git-service.ts +26 -3
  484. package/src/resources/extensions/gsd/gitignore.ts +33 -0
  485. package/src/resources/extensions/gsd/gsd-db.ts +43 -7
  486. package/src/resources/extensions/gsd/guided-flow.ts +114 -45
  487. package/src/resources/extensions/gsd/health-widget-core.ts +34 -0
  488. package/src/resources/extensions/gsd/health-widget.ts +17 -0
  489. package/src/resources/extensions/gsd/index.ts +1 -0
  490. package/src/resources/extensions/gsd/memory-extractor.ts +8 -0
  491. package/src/resources/extensions/gsd/migrate-external.ts +9 -1
  492. package/src/resources/extensions/gsd/milestone-validation-gates.ts +56 -0
  493. package/src/resources/extensions/gsd/model-cost-table.ts +19 -0
  494. package/src/resources/extensions/gsd/model-router.ts +35 -1
  495. package/src/resources/extensions/gsd/native-git-bridge.ts +17 -0
  496. package/src/resources/extensions/gsd/notifications.ts +16 -0
  497. package/src/resources/extensions/gsd/parallel-eligibility.ts +15 -2
  498. package/src/resources/extensions/gsd/parallel-merge.ts +87 -4
  499. package/src/resources/extensions/gsd/parsers-legacy.ts +22 -3
  500. package/src/resources/extensions/gsd/paths.ts +42 -0
  501. package/src/resources/extensions/gsd/preferences-models.ts +14 -1
  502. package/src/resources/extensions/gsd/preferences-types.ts +2 -1
  503. package/src/resources/extensions/gsd/preferences.ts +13 -15
  504. package/src/resources/extensions/gsd/prompt-loader.ts +4 -1
  505. package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  506. package/src/resources/extensions/gsd/prompts/complete-slice.md +4 -2
  507. package/src/resources/extensions/gsd/prompts/discuss-headless.md +1 -1
  508. package/src/resources/extensions/gsd/prompts/discuss.md +1 -1
  509. package/src/resources/extensions/gsd/prompts/execute-task.md +3 -1
  510. package/src/resources/extensions/gsd/prompts/forensics.md +2 -2
  511. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  512. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
  513. package/src/resources/extensions/gsd/prompts/plan-slice.md +2 -0
  514. package/src/resources/extensions/gsd/prompts/rethink.md +1 -1
  515. package/src/resources/extensions/gsd/prompts/triage-captures.md +1 -0
  516. package/src/resources/extensions/gsd/repo-identity.ts +186 -11
  517. package/src/resources/extensions/gsd/rethink.ts +6 -0
  518. package/src/resources/extensions/gsd/roadmap-slices.ts +5 -4
  519. package/src/resources/extensions/gsd/state.ts +84 -32
  520. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +47 -0
  521. package/src/resources/extensions/gsd/tests/auto-mode-interactive-guard.test.ts +71 -0
  522. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +71 -1
  523. package/src/resources/extensions/gsd/tests/captures.test.ts +103 -0
  524. package/src/resources/extensions/gsd/tests/cli-provider-rate-limit.test.ts +47 -0
  525. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +27 -0
  526. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +21 -0
  527. package/src/resources/extensions/gsd/tests/completion-hierarchy-guards.test.ts +192 -0
  528. package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +131 -0
  529. package/src/resources/extensions/gsd/tests/db-writer.test.ts +7 -12
  530. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +78 -5
  531. package/src/resources/extensions/gsd/tests/derive-state.test.ts +29 -0
  532. package/src/resources/extensions/gsd/tests/discord-invite-links.test.ts +47 -0
  533. package/src/resources/extensions/gsd/tests/discuss-empty-db-fallback.test.ts +127 -0
  534. package/src/resources/extensions/gsd/tests/discuss-queued-milestones.test.ts +40 -0
  535. package/src/resources/extensions/gsd/tests/dist-redirect.mjs +20 -1
  536. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +117 -0
  537. package/src/resources/extensions/gsd/tests/dynamic-routing-default.test.ts +20 -0
  538. package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +74 -0
  539. package/src/resources/extensions/gsd/tests/event-replay-idempotency.test.ts +140 -0
  540. package/src/resources/extensions/gsd/tests/forensics-context-persist.test.ts +129 -0
  541. package/src/resources/extensions/gsd/tests/forensics-db-completion.test.ts +96 -0
  542. package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +31 -0
  543. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +125 -12
  544. package/src/resources/extensions/gsd/tests/gsdroot-worktree-detection.test.ts +164 -0
  545. package/src/resources/extensions/gsd/tests/guided-flow-dynamic-routing.test.ts +135 -0
  546. package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +97 -0
  547. package/src/resources/extensions/gsd/tests/health-widget.test.ts +67 -0
  548. package/src/resources/extensions/gsd/tests/hook-key-parsing.test.ts +107 -0
  549. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +111 -1
  550. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +101 -0
  551. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +59 -0
  552. package/src/resources/extensions/gsd/tests/integration/doctor-false-positives.test.ts +243 -0
  553. package/src/resources/extensions/gsd/tests/integration/gitignore-staging-2570.test.ts +150 -0
  554. package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +110 -0
  555. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +1 -1
  556. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +959 -0
  557. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +85 -2
  558. package/src/resources/extensions/gsd/tests/migrate-external-worktree.test.ts +105 -0
  559. package/src/resources/extensions/gsd/tests/milestone-status-authoritative.test.ts +116 -0
  560. package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +34 -0
  561. package/src/resources/extensions/gsd/tests/model-router.test.ts +68 -3
  562. package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +28 -0
  563. package/src/resources/extensions/gsd/tests/notifications.test.ts +45 -0
  564. package/src/resources/extensions/gsd/tests/parallel-commit-scope.test.ts +159 -0
  565. package/src/resources/extensions/gsd/tests/parallel-eligibility-ghost.test.ts +150 -0
  566. package/src/resources/extensions/gsd/tests/plan-milestone-title.test.ts +70 -0
  567. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +33 -1
  568. package/src/resources/extensions/gsd/tests/project-relocation-recovery.test.ts +297 -0
  569. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +29 -0
  570. package/src/resources/extensions/gsd/tests/prompt-loader-replacement.test.ts +178 -0
  571. package/src/resources/extensions/gsd/tests/prompt-tool-names.test.ts +69 -0
  572. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +38 -0
  573. package/src/resources/extensions/gsd/tests/queue-execution-guard.test.ts +157 -0
  574. package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +90 -0
  575. package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +117 -0
  576. package/src/resources/extensions/gsd/tests/reconciliation-edge-cases.test.ts +162 -0
  577. package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +97 -0
  578. package/src/resources/extensions/gsd/tests/secure-env-collect.test.ts +134 -0
  579. package/src/resources/extensions/gsd/tests/slice-disk-reconcile.test.ts +233 -0
  580. package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +305 -0
  581. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +405 -0
  582. package/src/resources/extensions/gsd/tests/state-derivation-parity.test.ts +257 -0
  583. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +1628 -0
  584. package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +106 -0
  585. package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +174 -0
  586. package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +221 -0
  587. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +2 -1
  588. package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +8 -0
  589. package/src/resources/extensions/gsd/tests/uat-stuck-loop-orphaned-worktree.test.ts +289 -0
  590. package/src/resources/extensions/gsd/tests/unit-ownership.test.ts +100 -17
  591. package/src/resources/extensions/gsd/tests/vacuum-recovery.test.ts +154 -0
  592. package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +4 -1
  593. package/src/resources/extensions/gsd/tests/verdict-parser.test.ts +156 -0
  594. package/src/resources/extensions/gsd/tests/verification-operational-gate.test.ts +82 -0
  595. package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +48 -0
  596. package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +92 -0
  597. package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +4 -2
  598. package/src/resources/extensions/gsd/tests/worktree-db-respawn-truncation.test.ts +140 -0
  599. package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +101 -0
  600. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +48 -1
  601. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +29 -5
  602. package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +95 -0
  603. package/src/resources/extensions/gsd/tools/complete-task.ts +36 -74
  604. package/src/resources/extensions/gsd/tools/plan-milestone.ts +13 -1
  605. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +36 -0
  606. package/src/resources/extensions/gsd/tools/validate-milestone.ts +20 -2
  607. package/src/resources/extensions/gsd/triage-resolution.ts +23 -6
  608. package/src/resources/extensions/gsd/types.ts +4 -2
  609. package/src/resources/extensions/gsd/undo.ts +2 -2
  610. package/src/resources/extensions/gsd/unit-ownership.ts +206 -35
  611. package/src/resources/extensions/gsd/verdict-parser.ts +21 -6
  612. package/src/resources/extensions/gsd/workflow-logger.ts +3 -1
  613. package/src/resources/extensions/gsd/workflow-manifest.ts +22 -5
  614. package/src/resources/extensions/gsd/workflow-projections.ts +97 -64
  615. package/src/resources/extensions/gsd/workflow-reconcile.ts +39 -10
  616. package/src/resources/extensions/gsd/workspace-index.ts +30 -0
  617. package/src/resources/extensions/gsd/worktree-manager.ts +120 -1
  618. package/src/resources/extensions/gsd/worktree-resolver.ts +22 -3
  619. package/src/resources/extensions/mcp-client/index.ts +13 -7
  620. package/src/resources/extensions/mcp-client/tests/server-name-spaces.test.ts +55 -0
  621. package/src/resources/extensions/ollama/index.ts +130 -0
  622. package/src/resources/extensions/ollama/model-capabilities.ts +145 -0
  623. package/src/resources/extensions/ollama/ollama-client.ts +196 -0
  624. package/src/resources/extensions/ollama/ollama-commands.ts +248 -0
  625. package/src/resources/extensions/ollama/ollama-discovery.ts +106 -0
  626. package/src/resources/extensions/ollama/ollama-tool.ts +218 -0
  627. package/src/resources/extensions/ollama/tests/model-capabilities.test.ts +162 -0
  628. package/src/resources/extensions/ollama/tests/ollama-client.test.ts +38 -0
  629. package/src/resources/extensions/ollama/tests/ollama-discovery.test.ts +28 -0
  630. package/src/resources/extensions/ollama/types.ts +130 -0
  631. package/src/resources/extensions/search-the-web/extension-manifest.json +1 -1
  632. package/src/resources/extensions/shared/interview-ui.ts +12 -1
  633. package/src/resources/extensions/shared/tests/ask-user-freetext.test.ts +156 -0
  634. package/src/resources/skills/create-gsd-extension/SKILL.md +5 -3
  635. package/src/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +5 -4
  636. package/src/resources/skills/create-gsd-extension/workflows/add-capability.md +2 -2
  637. package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +4 -4
  638. package/src/resources/skills/create-gsd-extension/workflows/debug-extension.md +5 -3
  639. package/dist/web/standalone/.next/static/chunks/6502.8b732f67a11b11b4.js +0 -9
  640. package/dist/web/standalone/.next/static/css/a58ef8a151aa0493.css +0 -1
  641. package/src/resources/extensions/gsd/tests/empty-db-reconciliation.test.ts +0 -79
  642. /package/dist/web/standalone/.next/static/{OS7_z6QaL6uqp8q5pjHSJ → R0D4xaIPl5kg93edN7Oo0}/_buildManifest.js +0 -0
  643. /package/dist/web/standalone/.next/static/{OS7_z6QaL6uqp8q5pjHSJ → R0D4xaIPl5kg93edN7Oo0}/_ssgManifest.js +0 -0
@@ -0,0 +1,131 @@
1
+ /**
2
+ * db-path-worktree-symlink.test.ts — #2517
3
+ *
4
+ * Regression test for the db_unavailable loop in worktree/symlink layouts.
5
+ *
6
+ * The path resolver must handle BOTH worktree path families:
7
+ * - /.gsd/worktrees/<MID>/... (direct layout)
8
+ * - /.gsd/projects/<hash>/worktrees/<MID>/... (symlink-resolved layout)
9
+ *
10
+ * When the second layout is not recognised, ensureDbOpen derives a wrong DB
11
+ * path, the open fails silently, and every completion tool call returns
12
+ * db_unavailable — triggering an artifact retry re-dispatch loop.
13
+ *
14
+ * Additionally, the post-unit artifact retry path must NOT retry when the
15
+ * completion tool failed due to db_unavailable (infra failure), because
16
+ * retrying can never succeed and causes cost spikes.
17
+ */
18
+
19
+ import { readFileSync } from "node:fs";
20
+ import { join, sep } from "node:path";
21
+ import { createTestContext } from "./test-helpers.ts";
22
+
23
+ const { assertEq, assertTrue, report } = createTestContext();
24
+
25
+ // ── Part 1: resolveProjectRootDbPath handles symlink-resolved layout ─────
26
+
27
+ console.log("\n=== #2517 Part 1: resolveProjectRootDbPath symlink layout ===");
28
+
29
+ // Import the resolver directly
30
+ const { resolveProjectRootDbPath } = await import("../bootstrap/dynamic-tools.js");
31
+
32
+ // Standard worktree layout (already works)
33
+ const standardPath = `/home/user/myproject/.gsd/worktrees/M001/work`;
34
+ const standardResult = resolveProjectRootDbPath(standardPath);
35
+ assertEq(
36
+ standardResult,
37
+ join("/home/user/myproject", ".gsd", "gsd.db"),
38
+ "Standard worktree layout resolves to project root DB path",
39
+ );
40
+
41
+ // Symlink-resolved layout (the regression — /.gsd/projects/<hash>/worktrees/...)
42
+ const symlinkPath = `/home/user/myproject/.gsd/projects/abc123def/worktrees/M001/work`;
43
+ const symlinkResult = resolveProjectRootDbPath(symlinkPath);
44
+ assertEq(
45
+ symlinkResult,
46
+ join("/home/user/myproject", ".gsd", "gsd.db"),
47
+ "Symlink-resolved layout (/.gsd/projects/<hash>/worktrees/) resolves to project root DB path (#2517)",
48
+ );
49
+
50
+ // Windows-style separators for symlink layout
51
+ if (sep === "\\") {
52
+ const winSymlinkPath = `C:\\Users\\dev\\project\\.gsd\\projects\\abc123def\\worktrees\\M001\\work`;
53
+ const winResult = resolveProjectRootDbPath(winSymlinkPath);
54
+ assertEq(
55
+ winResult,
56
+ join("C:\\Users\\dev\\project", ".gsd", "gsd.db"),
57
+ "Windows symlink layout resolves correctly",
58
+ );
59
+ } else {
60
+ // On non-Windows, test forward-slash variant explicitly
61
+ const fwdSymlinkPath = `/home/user/myproject/.gsd/projects/abc123def/worktrees/M001/work`;
62
+ const fwdResult = resolveProjectRootDbPath(fwdSymlinkPath);
63
+ assertEq(
64
+ fwdResult,
65
+ join("/home/user/myproject", ".gsd", "gsd.db"),
66
+ "Forward-slash symlink layout resolves correctly on POSIX",
67
+ );
68
+ }
69
+
70
+ // Edge: deeper nesting under projects/<hash>/worktrees
71
+ const deepSymlinkPath = `/home/user/myproject/.gsd/projects/deadbeef42/worktrees/M003/sub/dir`;
72
+ const deepResult = resolveProjectRootDbPath(deepSymlinkPath);
73
+ assertEq(
74
+ deepResult,
75
+ join("/home/user/myproject", ".gsd", "gsd.db"),
76
+ "Deep symlink worktree path still resolves to project root DB",
77
+ );
78
+
79
+ // Non-worktree path should be unchanged
80
+ const normalPath = `/home/user/myproject`;
81
+ const normalResult = resolveProjectRootDbPath(normalPath);
82
+ assertEq(
83
+ normalResult,
84
+ join("/home/user/myproject", ".gsd", "gsd.db"),
85
+ "Non-worktree path is unchanged",
86
+ );
87
+
88
+ // ── Part 2: ensureDbOpen returns structured failure context ──────────────
89
+
90
+ console.log("\n=== #2517 Part 2: ensureDbOpen structured diagnostics ===");
91
+
92
+ const dynamicToolsSrc = readFileSync(
93
+ join(import.meta.dirname, "..", "bootstrap", "dynamic-tools.ts"),
94
+ "utf-8",
95
+ );
96
+
97
+ // ensureDbOpen should return a structured result, not just boolean false
98
+ // Check that the catch block provides diagnostic information
99
+ assertTrue(
100
+ dynamicToolsSrc.includes("resolvedPath") || dynamicToolsSrc.includes("diagnostic"),
101
+ "ensureDbOpen catch block surfaces diagnostic information (resolvedPath or diagnostic) instead of bare false (#2517)",
102
+ );
103
+
104
+ // ── Part 3: post-unit does NOT artifact-retry on db_unavailable ──────────
105
+
106
+ console.log("\n=== #2517 Part 3: post-unit db_unavailable is infra-fatal ===");
107
+
108
+ const postUnitSrc = readFileSync(
109
+ join(import.meta.dirname, "..", "auto-post-unit.ts"),
110
+ "utf-8",
111
+ );
112
+
113
+ // The artifact retry block should check DB availability and skip retry
114
+ // when the DB is unavailable (infra failure, not a missing artifact).
115
+ assertTrue(
116
+ postUnitSrc.includes("db_unavailable") || postUnitSrc.includes("isDbAvailable"),
117
+ "post-unit artifact retry path checks DB availability to avoid retry loop (#2517)",
118
+ );
119
+
120
+ // Verify the retry block is guarded: when !isDbAvailable(), the code must
121
+ // NOT return "retry". The pattern should be: if (!verified && !isDbAvailable()) { skip }
122
+ // followed by else if (!verified) { ... return "retry" }
123
+ const dbUnavailableGuard = postUnitSrc.match(
124
+ /!triggerArtifactVerified\s*&&\s*!isDbAvailable\(\)/,
125
+ );
126
+ assertTrue(
127
+ !!dbUnavailableGuard,
128
+ "The retry block explicitly guards against !isDbAvailable() before returning 'retry' (#2517)",
129
+ );
130
+
131
+ report();
@@ -416,23 +416,18 @@ describe('db-writer', () => {
416
416
  }
417
417
  });
418
418
 
419
- test('updateRequirementInDb — not found', async () => {
419
+ test('updateRequirementInDb — upserts when not found (#2919)', async () => {
420
420
  const tmpDir = makeTmpDir();
421
421
  const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
422
422
  openDatabase(dbPath);
423
423
 
424
424
  try {
425
- let threw = false;
426
- try {
427
- await updateRequirementInDb('R999', { status: 'validated' }, tmpDir);
428
- } catch (err) {
429
- threw = true;
430
- assert.ok(
431
- (err as Error).message.includes('R999'),
432
- 'error message mentions the missing ID',
433
- );
434
- }
435
- assert.ok(threw, 'throws when requirement not found');
425
+ // Previously threw; now upserts a skeleton requirement with the provided updates
426
+ await updateRequirementInDb('R999', { status: 'validated' }, tmpDir);
427
+ const created = getRequirementById('R999');
428
+ assert.ok(created !== null, 'R999 should be created by upsert');
429
+ assert.deepStrictEqual(created!.status, 'validated', 'Upserted requirement should have validated status');
430
+ assert.deepStrictEqual(created!.id, 'R999', 'Upserted requirement should keep the provided ID');
436
431
  } finally {
437
432
  closeDatabase();
438
433
  cleanupDir(tmpDir);
@@ -4,7 +4,7 @@ import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
4
4
  import { join } from 'node:path';
5
5
  import { tmpdir } from 'node:os';
6
6
 
7
- import { deriveState, invalidateStateCache, _deriveStateImpl, deriveStateFromDb } from '../state.ts';
7
+ import { deriveState, invalidateStateCache, _deriveStateImpl, deriveStateFromDb, isGhostMilestone } from '../state.ts';
8
8
  import {
9
9
  openDatabase,
10
10
  closeDatabase,
@@ -934,8 +934,8 @@ describe('derive-state-db', async () => {
934
934
  }
935
935
  });
936
936
 
937
- // ─── Test 21: Ghost milestone skipped ─────────────────────────────────
938
- test('derive-state-db: ghost milestone skipped', async () => {
937
+ // ─── Test 21: Ghost milestone skipped (no DB row, no worktree) ─────────
938
+ test('derive-state-db: ghost milestone skipped when no DB row and no worktree', async () => {
939
939
  const base = createFixtureBase();
940
940
  try {
941
941
  // Ghost: milestone dir exists with only META.json, no context/roadmap/summary
@@ -948,8 +948,7 @@ describe('derive-state-db', async () => {
948
948
  const fileState = await _deriveStateImpl(base);
949
949
 
950
950
  openDatabase(':memory:');
951
- // Ghost milestone in DB — no slices, status active
952
- insertMilestone({ id: 'M001', title: '', status: 'active' });
951
+ // Only insert M002M001 has no DB row (simulates row loss / never inserted)
953
952
  insertMilestone({ id: 'M002', title: 'Real', status: 'active' });
954
953
 
955
954
  invalidateStateCache();
@@ -1051,4 +1050,78 @@ describe('derive-state-db', async () => {
1051
1050
  closeDatabase();
1052
1051
  }
1053
1052
  });
1053
+
1054
+ // ─── Queued milestone with worktree not flagged as ghost (#2921) ──────
1055
+ test('derive-state-db: queued milestone with worktree not flagged as ghost (#2921)', async () => {
1056
+ const base = createFixtureBase();
1057
+ try {
1058
+ // M001: complete milestone with summary
1059
+ writeFile(base, 'milestones/M001/M001-SUMMARY.md', '# M001 Summary\n\nDone.');
1060
+
1061
+ // M002: queued milestone — directory + slices dir exists, but no content files.
1062
+ // This is what happens when ensureMilestoneDbRow creates M002 but the DB row
1063
+ // is lost during worktree teardown.
1064
+ mkdirSync(join(base, '.gsd', 'milestones', 'M002', 'slices'), { recursive: true });
1065
+
1066
+ // A worktree exists for M002, proving it's a legitimate milestone
1067
+ mkdirSync(join(base, '.gsd', 'worktrees', 'M002'), { recursive: true });
1068
+
1069
+ // isGhostMilestone should NOT treat M002 as ghost when worktree exists
1070
+ assert.ok(!isGhostMilestone(base, 'M002'), 'ghost-wt: M002 with worktree is NOT a ghost');
1071
+
1072
+ // DB has M001 complete but M002 row was lost
1073
+ openDatabase(':memory:');
1074
+ insertMilestone({ id: 'M001', title: 'First', status: 'complete' });
1075
+ // No M002 row — simulates DB row loss during worktree teardown
1076
+
1077
+ invalidateStateCache();
1078
+ const dbState = await deriveStateFromDb(base);
1079
+
1080
+ // M002 should be reconciled from disk (not skipped as ghost) and become active
1081
+ const m002Entry = dbState.registry.find(e => e.id === 'M002');
1082
+ assert.ok(m002Entry !== undefined, 'ghost-wt: M002 should be in registry');
1083
+ assert.deepStrictEqual(dbState.activeMilestone?.id, 'M002', 'ghost-wt: M002 should be active');
1084
+ // Should NOT be phase: complete
1085
+ assert.notEqual(dbState.phase, 'complete', 'ghost-wt: phase should not be complete');
1086
+
1087
+ closeDatabase();
1088
+ } finally {
1089
+ closeDatabase();
1090
+ cleanup(base);
1091
+ }
1092
+ });
1093
+
1094
+ // ─── Queued milestone with DB row not flagged as ghost (#2921) ────────
1095
+ test('derive-state-db: queued milestone with DB row not flagged as ghost (#2921)', async () => {
1096
+ const base = createFixtureBase();
1097
+ try {
1098
+ // M001: complete milestone with summary
1099
+ writeFile(base, 'milestones/M001/M001-SUMMARY.md', '# M001 Summary\n\nDone.');
1100
+
1101
+ // M002: queued milestone — directory exists, no content files, but has DB row
1102
+ mkdirSync(join(base, '.gsd', 'milestones', 'M002', 'slices'), { recursive: true });
1103
+
1104
+ // DB has both M001 complete and M002 queued
1105
+ openDatabase(':memory:');
1106
+ insertMilestone({ id: 'M001', title: 'First', status: 'complete' });
1107
+ insertMilestone({ id: 'M002', title: 'Second', status: 'queued' });
1108
+
1109
+ // isGhostMilestone should NOT treat M002 as ghost when DB row exists
1110
+ assert.ok(!isGhostMilestone(base, 'M002'), 'ghost-dbrow: M002 with DB row is NOT a ghost');
1111
+
1112
+ invalidateStateCache();
1113
+ const dbState = await deriveStateFromDb(base);
1114
+
1115
+ // M002 should not be skipped
1116
+ const m002Entry = dbState.registry.find(e => e.id === 'M002');
1117
+ assert.ok(m002Entry !== undefined, 'ghost-dbrow: M002 should be in registry');
1118
+ assert.deepStrictEqual(dbState.activeMilestone?.id, 'M002', 'ghost-dbrow: M002 should be active');
1119
+ assert.notEqual(dbState.phase, 'complete', 'ghost-dbrow: phase should not be complete');
1120
+
1121
+ closeDatabase();
1122
+ } finally {
1123
+ closeDatabase();
1124
+ cleanup(base);
1125
+ }
1126
+ });
1054
1127
  });
@@ -930,6 +930,35 @@ slice: S01
930
930
  }
931
931
  });
932
932
 
933
+ // ─── Test: queued milestone with worktree not flagged as ghost (#2921) ──
934
+ test('queued milestone with worktree not flagged as ghost (#2921)', async () => {
935
+ const base = createFixtureBase();
936
+ try {
937
+ // Create a milestone directory with only an empty slices subdir — no content files.
938
+ // This would normally be a ghost, but it has a worktree directory.
939
+ const milestoneDir = join(base, '.gsd', 'milestones', 'M002');
940
+ mkdirSync(join(milestoneDir, 'slices'), { recursive: true });
941
+
942
+ // Create a worktree directory for M002, simulating an active worktree
943
+ const worktreeDir = join(base, '.gsd', 'worktrees', 'M002');
944
+ mkdirSync(worktreeDir, { recursive: true });
945
+
946
+ // isGhostMilestone should return false because the worktree exists
947
+ assert.ok(!isGhostMilestone(base, 'M002'), 'M002 with worktree should NOT be a ghost');
948
+
949
+ // Also create a completed M001 so deriveState has something before M002
950
+ writeMilestoneSummary(base, 'M001', '# M001 Summary\n\nDone.');
951
+
952
+ const state = await deriveState(base);
953
+ // M002 should appear in the registry (not filtered as ghost)
954
+ const m002Entry = state.registry.find(e => e.id === 'M002');
955
+ assert.ok(m002Entry !== undefined, 'M002 should be in registry when worktree exists');
956
+ assert.deepStrictEqual(state.activeMilestone?.id, 'M002', 'M002 should be active milestone');
957
+ } finally {
958
+ cleanup(base);
959
+ }
960
+ });
961
+
933
962
  // ─── Test: zero-slice roadmap → pre-planning, not blocked (#1785) ────
934
963
  test('zero-slice roadmap → pre-planning, not blocked (#1785)', async () => {
935
964
  const base = createFixtureBase();
@@ -0,0 +1,47 @@
1
+ import assert from "node:assert/strict";
2
+ import { describe, it } from "node:test";
3
+ import { readFileSync } from "node:fs";
4
+ import { join } from "node:path";
5
+
6
+ /**
7
+ * Validates that all Discord invite links in user-facing files point to valid,
8
+ * consistent invite URLs — not expired vanity links.
9
+ *
10
+ * Regression test for https://github.com/gsd-build/gsd-2/issues/2699
11
+ */
12
+
13
+ const ROOT = process.cwd();
14
+
15
+ /** Canonical Discord invite for the GSD community. */
16
+ const VALID_INVITE = "https://discord.com/invite/nKXTsAcmbT";
17
+
18
+ /** Files that contain user-facing Discord invite links. */
19
+ const FILES_WITH_INVITE_LINKS: string[] = [
20
+ "README.md",
21
+ "docs/what-is-pi/15-pi-packages-the-ecosystem.md",
22
+ ];
23
+
24
+ describe("Discord invite links (#2699)", () => {
25
+ for (const relPath of FILES_WITH_INVITE_LINKS) {
26
+ it(`${relPath} contains only the canonical Discord invite`, () => {
27
+ const content = readFileSync(join(ROOT, relPath), "utf8");
28
+
29
+ // Extract all Discord invite URLs (discord.gg/X or discord.com/invite/X)
30
+ const invitePattern = /https?:\/\/(?:discord\.gg|discord\.com\/invite)\/[A-Za-z0-9]+/g;
31
+ const matches = content.match(invitePattern);
32
+
33
+ assert.ok(
34
+ matches && matches.length > 0,
35
+ `Expected at least one Discord invite link in ${relPath}`,
36
+ );
37
+
38
+ for (const link of matches) {
39
+ assert.equal(
40
+ link,
41
+ VALID_INVITE,
42
+ `Invalid Discord invite in ${relPath}: found "${link}", expected "${VALID_INVITE}"`,
43
+ );
44
+ }
45
+ });
46
+ }
47
+ });
@@ -0,0 +1,127 @@
1
+ /**
2
+ * discuss-empty-db-fallback.test.ts — Tests for #2892.
3
+ *
4
+ * When the DB is open but empty (e.g., after crash/truncation),
5
+ * getMilestoneSlices() returns [] and showDiscuss() incorrectly declares
6
+ * "All slices are complete." The fix adds a roadmap fallback: when the DB
7
+ * returns zero slices but a ROADMAP file exists, parse slices from the
8
+ * roadmap instead of treating zero slices as "all complete."
9
+ */
10
+
11
+ import { describe, test } from "node:test";
12
+ import assert from "node:assert/strict";
13
+ import { readFileSync } from "node:fs";
14
+ import { fileURLToPath } from "node:url";
15
+ import { dirname, join } from "node:path";
16
+ import { parseRoadmapSlices } from "../roadmap-slices.ts";
17
+
18
+ // ─── Helpers ─────────────────────────────────────────────────────────────────
19
+
20
+ function readGuidedFlowSource(): string {
21
+ const thisFile = fileURLToPath(import.meta.url);
22
+ const thisDir = dirname(thisFile);
23
+ return readFileSync(join(thisDir, "..", "guided-flow.ts"), "utf-8");
24
+ }
25
+
26
+ const SAMPLE_ROADMAP = `# M012 Roadmap
27
+
28
+ ## Slices
29
+ - [ ] **S01: Core setup** \`risk:low\` \`depends:[]\`
30
+ > After this: basic project scaffolding works
31
+ - [ ] **S02: Auth module** \`risk:medium\` \`depends:[S01]\`
32
+ > After this: users can log in
33
+ - [ ] **S03: Dashboard** \`risk:low\` \`depends:[S02]\`
34
+ > After this: dashboard renders
35
+ `;
36
+
37
+ // ─── Tests ───────────────────────────────────────────────────────────────────
38
+
39
+ describe("discuss-empty-db-fallback (#2892)", () => {
40
+
41
+ test("1. parseRoadmapSlices extracts slices from a valid ROADMAP", () => {
42
+ const slices = parseRoadmapSlices(SAMPLE_ROADMAP);
43
+ assert.strictEqual(slices.length, 3, "should parse 3 slices from sample roadmap");
44
+ assert.strictEqual(slices[0]!.id, "S01");
45
+ assert.strictEqual(slices[1]!.id, "S02");
46
+ assert.strictEqual(slices[2]!.id, "S03");
47
+ // All slices are incomplete ([ ] not [x])
48
+ assert.ok(slices.every(s => !s.done), "all slices should be incomplete");
49
+ });
50
+
51
+ test("2. guided-flow imports parseRoadmapSlices for roadmap fallback", () => {
52
+ const source = readGuidedFlowSource();
53
+ assert.ok(
54
+ source.includes("parseRoadmapSlices"),
55
+ "guided-flow must import parseRoadmapSlices to support roadmap fallback when DB is empty",
56
+ );
57
+ });
58
+
59
+ test("3. guided-flow has roadmap fallback when normSlices is empty but roadmapContent exists", () => {
60
+ const source = readGuidedFlowSource();
61
+ // The fix must add a fallback that checks normSlices.length === 0 && roadmapContent
62
+ // and repopulates normSlices from the roadmap before the pendingSlices guard.
63
+ //
64
+ // Pattern: after DB query produces normSlices, if empty + roadmap exists,
65
+ // fall back to parseRoadmapSlices(roadmapContent).
66
+ const fallbackPattern = /normSlices\.length\s*===\s*0\s*&&\s*roadmapContent/;
67
+ assert.ok(
68
+ fallbackPattern.test(source),
69
+ "guided-flow must check normSlices.length === 0 && roadmapContent to trigger roadmap fallback",
70
+ );
71
+ });
72
+
73
+ test("4. guided-flow no longer has unguarded pendingSlices === 0 exit after DB-only query", () => {
74
+ const source = readGuidedFlowSource();
75
+ // Extract the showDiscuss function body
76
+ const fnMatch = source.match(
77
+ /async function showDiscuss\s*\([^)]*\)[^{]*\{([\s\S]*?)\nfunction\s/,
78
+ );
79
+ assert.ok(!!fnMatch, "showDiscuss function body must be found");
80
+
81
+ if (fnMatch) {
82
+ const body = fnMatch[1]!;
83
+ // After the DB query block (isDbAvailable/getMilestoneSlices), there should
84
+ // be a roadmap fallback BEFORE the pendingSlices.length === 0 check.
85
+ // Find the getMilestoneSlices call and the pendingSlices === 0 check
86
+ const dbQueryIdx = body.indexOf("getMilestoneSlices");
87
+ const fallbackIdx = body.indexOf("parseRoadmapSlices");
88
+ const pendingGuardIdx = body.indexOf('pendingSlices.length === 0');
89
+
90
+ assert.ok(dbQueryIdx > 0, "getMilestoneSlices call must exist");
91
+ assert.ok(fallbackIdx > 0, "parseRoadmapSlices fallback must exist");
92
+ assert.ok(pendingGuardIdx > 0, "pendingSlices.length === 0 guard must exist");
93
+ assert.ok(
94
+ fallbackIdx > dbQueryIdx && fallbackIdx < pendingGuardIdx,
95
+ "parseRoadmapSlices fallback must appear BETWEEN DB query and pendingSlices === 0 guard",
96
+ );
97
+ }
98
+ });
99
+
100
+ test("5. roadmap-parsed slices map to NormSlice format with done=false by default", () => {
101
+ // When falling back to roadmap, incomplete slices ([ ]) should map to done:false,
102
+ // ensuring they appear as pending and are NOT falsely reported as complete.
103
+ const slices = parseRoadmapSlices(SAMPLE_ROADMAP);
104
+ const normSlices = slices.map(s => ({ id: s.id, done: s.done, title: s.title }));
105
+ const pendingSlices = normSlices.filter(s => !s.done);
106
+ assert.strictEqual(pendingSlices.length, 3,
107
+ "all 3 incomplete roadmap slices should be pending — not falsely treated as complete");
108
+ });
109
+
110
+ test("6. roadmap with completed slices correctly reports them as done", () => {
111
+ const completedRoadmap = `# M012 Roadmap
112
+
113
+ ## Slices
114
+ - [x] **S01: Core setup** \`risk:low\` \`depends:[]\`
115
+ > After this: basic project scaffolding works
116
+ - [ ] **S02: Auth module** \`risk:medium\` \`depends:[S01]\`
117
+ > After this: users can log in
118
+ - [x] **S03: Dashboard** \`risk:low\` \`depends:[S02]\`
119
+ > After this: dashboard renders
120
+ `;
121
+ const slices = parseRoadmapSlices(completedRoadmap);
122
+ const normSlices = slices.map(s => ({ id: s.id, done: s.done, title: s.title }));
123
+ const pendingSlices = normSlices.filter(s => !s.done);
124
+ assert.strictEqual(pendingSlices.length, 1, "only S02 should be pending");
125
+ assert.strictEqual(pendingSlices[0]!.id, "S02");
126
+ });
127
+ });
@@ -238,4 +238,44 @@ describe("discuss-queued-milestones (#2307)", () => {
238
238
  "queued milestone picker must label entries with [queued] to distinguish from active",
239
239
  );
240
240
  });
241
+
242
+ // ─── #3150: allDiscussed early-return must not block queued milestone discussion ──
243
+
244
+ test("12. allDiscussed path checks for pending milestones before returning (#3150)", () => {
245
+ const source = readGuidedFlowSource();
246
+
247
+ // Extract the allDiscussed block — the if (allDiscussed) { ... } body
248
+ const allDiscussedMatch = source.match(
249
+ /const allDiscussed = pendingSlices\.every\([\s\S]*?\n if \(allDiscussed\) \{([\s\S]*?)\n \}/,
250
+ );
251
+ assert.ok(!!allDiscussedMatch, "allDiscussed guard block must exist in showDiscuss()");
252
+
253
+ if (allDiscussedMatch) {
254
+ const body = allDiscussedMatch[1];
255
+ // The fix must check for pending milestones and route to showDiscussQueuedMilestone
256
+ assert.ok(
257
+ body.includes("pending") && body.includes("showDiscussQueuedMilestone"),
258
+ "allDiscussed block must check for pending milestones and call showDiscussQueuedMilestone before returning (#3150)",
259
+ );
260
+ }
261
+ });
262
+
263
+ test("13. pendingSlices.length===0 path checks for pending milestones before returning (#3150)", () => {
264
+ const source = readGuidedFlowSource();
265
+
266
+ // Find the pendingSlices.length === 0 guard block
267
+ const zeroSlicesMatch = source.match(
268
+ /if \(pendingSlices\.length === 0\) \{([\s\S]*?)\n \}/,
269
+ );
270
+ assert.ok(!!zeroSlicesMatch, "pendingSlices.length === 0 guard block must exist in showDiscuss()");
271
+
272
+ if (zeroSlicesMatch) {
273
+ const body = zeroSlicesMatch[1];
274
+ // The fix must check for pending milestones and route to showDiscussQueuedMilestone
275
+ assert.ok(
276
+ body.includes("pending") && body.includes("showDiscussQueuedMilestone"),
277
+ "pendingSlices.length===0 block must check for pending milestones and call showDiscussQueuedMilestone before returning (#3150)",
278
+ );
279
+ }
280
+ });
241
281
  });
@@ -87,7 +87,26 @@ export function load(url, context, nextLoad) {
87
87
  emitDecoratorMetadata: true,
88
88
  },
89
89
  });
90
- return { format: 'module', source: outputText, shortCircuit: true };
90
+ // Inject CJS-compatible globals (__dirname, __filename, require) so that
91
+ // workspace packages compiled as ESM can still use them. This avoids the
92
+ // need for import.meta.url behind indirect invocation patterns that fail in
93
+ // CJS and in dynamically-created scopes.
94
+ // Only inject globals that the source file doesn't already declare itself.
95
+ const preambleLines = [
96
+ 'import { fileURLToPath as __preamble_fUTP } from "node:url";',
97
+ 'import { dirname as __preamble_dn } from "node:path";',
98
+ 'import { createRequire as __preamble_cR } from "node:module";',
99
+ ];
100
+ if (!outputText.includes('const __filename') && !outputText.includes('let __filename')) {
101
+ preambleLines.push('const __filename = __preamble_fUTP(import.meta.url);');
102
+ }
103
+ if (!outputText.includes('const __dirname') && !outputText.includes('let __dirname')) {
104
+ preambleLines.push('const __dirname = __preamble_dn(__preamble_fUTP(import.meta.url));');
105
+ }
106
+ if (!outputText.includes('const require') && !outputText.includes('let require')) {
107
+ preambleLines.push('const require = __preamble_cR(import.meta.url);');
108
+ }
109
+ return { format: 'module', source: preambleLines.join('\n') + '\n' + outputText, shortCircuit: true };
91
110
  }
92
111
  return nextLoad(url, context);
93
112
  }