gsd-pi 2.78.1-dev.84a383f51 → 2.78.1

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 (474) hide show
  1. package/README.md +7 -7
  2. package/dist/cli.js +55 -95
  3. package/dist/headless-query.d.ts +0 -22
  4. package/dist/headless-query.js +4 -24
  5. package/dist/headless.d.ts +0 -10
  6. package/dist/headless.js +1 -16
  7. package/dist/loader.js +10 -7
  8. package/dist/onboarding.d.ts +0 -10
  9. package/dist/onboarding.js +2 -2
  10. package/dist/provider-migrations.d.ts +2 -2
  11. package/dist/provider-migrations.js +2 -5
  12. package/dist/resource-loader.d.ts +2 -5
  13. package/dist/resource-loader.js +5 -28
  14. package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +601 -0
  15. package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +651 -0
  16. package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +91 -0
  17. package/dist/resources/extensions/gsd/auto/loop.js +0 -23
  18. package/dist/resources/extensions/gsd/auto/phases.js +2 -2
  19. package/dist/resources/extensions/gsd/auto/run-unit.js +1 -3
  20. package/dist/resources/extensions/gsd/auto/session.js +0 -3
  21. package/dist/resources/extensions/gsd/auto-recovery.js +4 -43
  22. package/dist/resources/extensions/gsd/auto-start.js +1 -1
  23. package/dist/resources/extensions/gsd/auto-tool-tracking.js +2 -2
  24. package/dist/resources/extensions/gsd/auto-worktree.js +0 -30
  25. package/dist/resources/extensions/gsd/auto.js +5 -14
  26. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +2 -14
  27. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +5 -7
  28. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +2 -2
  29. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +4 -5
  30. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +31 -94
  31. package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +6 -11
  32. package/dist/resources/extensions/gsd/bootstrap/system-context.js +8 -34
  33. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +2 -38
  34. package/dist/resources/extensions/gsd/commands/catalog.js +5 -69
  35. package/dist/resources/extensions/gsd/commands/handlers/core.js +1 -22
  36. package/dist/resources/extensions/gsd/commands-mcp-status.js +1 -3
  37. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +1 -10
  38. package/dist/resources/extensions/gsd/dashboard-overlay.js +1 -1
  39. package/dist/resources/extensions/gsd/docs/preferences-reference.md +0 -4
  40. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +1 -39
  41. package/dist/resources/extensions/gsd/error-classifier.js +1 -1
  42. package/dist/resources/extensions/gsd/forensics.js +2 -2
  43. package/dist/resources/extensions/gsd/git-service.js +5 -12
  44. package/dist/resources/extensions/gsd/gsd-db.js +2 -11
  45. package/dist/resources/extensions/gsd/guided-flow.js +23 -23
  46. package/dist/resources/extensions/gsd/memory-store.js +31 -66
  47. package/dist/resources/extensions/gsd/model-router.js +9 -114
  48. package/dist/resources/extensions/gsd/native-git-bridge.js +1 -7
  49. package/dist/resources/extensions/gsd/preferences-models.js +15 -91
  50. package/dist/resources/extensions/gsd/preferences-types.js +0 -2
  51. package/dist/resources/extensions/gsd/preferences-validation.js +0 -32
  52. package/dist/resources/extensions/gsd/preferences.js +3 -5
  53. package/dist/resources/extensions/gsd/prompt-loader.js +12 -23
  54. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +3 -9
  55. package/dist/resources/extensions/gsd/state.js +0 -42
  56. package/dist/resources/extensions/gsd/templates/PREFERENCES.md +0 -1
  57. package/dist/resources/extensions/gsd/tests/auto-supervisor.test.mjs +53 -0
  58. package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +112 -0
  59. package/dist/resources/extensions/gsd/tests/resolve-ts-hooks.mjs +23 -0
  60. package/dist/resources/extensions/gsd/tests/resolve-ts.mjs +5 -0
  61. package/dist/resources/extensions/gsd/tools/memory-tools.js +1 -18
  62. package/dist/resources/extensions/gsd/visualizer-overlay.js +1 -1
  63. package/dist/resources/extensions/gsd/watch/header-renderer.js +1 -3
  64. package/dist/resources/extensions/gsd/worktree-command.js +46 -26
  65. package/dist/resources/extensions/mcp-client/index.js +3 -6
  66. package/dist/resources/extensions/slash-commands/create-extension.js +22 -36
  67. package/dist/resources/skills/create-gsd-extension/SKILL.md +5 -9
  68. package/dist/resources/skills/create-gsd-extension/references/custom-commands.md +1 -1
  69. package/dist/resources/skills/create-gsd-extension/references/custom-rendering.md +5 -5
  70. package/dist/resources/skills/create-gsd-extension/references/custom-tools.md +4 -4
  71. package/dist/resources/skills/create-gsd-extension/references/custom-ui.md +6 -6
  72. package/dist/resources/skills/create-gsd-extension/references/events-reference.md +3 -3
  73. package/dist/resources/skills/create-gsd-extension/references/packaging-distribution.md +1 -1
  74. package/dist/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +3 -3
  75. package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +12 -32
  76. package/dist/resources/skills/github-workflows/references/gh/tests/__init__.py +0 -0
  77. package/dist/resources/skills/github-workflows/references/gh/tests/test_github_project_setup.py +608 -0
  78. package/dist/rtk-shared.d.ts +0 -3
  79. package/dist/rtk-shared.js +0 -17
  80. package/dist/rtk.d.ts +5 -2
  81. package/dist/rtk.js +20 -3
  82. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  83. package/dist/web/standalone/.next/BUILD_ID +1 -1
  84. package/dist/web/standalone/.next/app-path-routes-manifest.json +13 -13
  85. package/dist/web/standalone/.next/build-manifest.json +4 -4
  86. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  87. package/dist/web/standalone/.next/react-loadable-manifest.json +4 -44
  88. package/dist/web/standalone/.next/required-server-files.json +3 -3
  89. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  90. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  91. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  100. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  101. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  102. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  103. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  104. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  106. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  110. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  116. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  128. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  148. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  158. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -4
  164. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  178. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  180. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  182. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  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.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  193. package/dist/web/standalone/.next/server/app/index.html +1 -1
  194. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  195. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  196. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  197. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  198. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  199. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  200. package/dist/web/standalone/.next/server/app/page.js +2 -2
  201. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  202. package/dist/web/standalone/.next/server/app-paths-manifest.json +13 -13
  203. package/dist/web/standalone/.next/server/chunks/63.js +3 -3
  204. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  205. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  206. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  207. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  208. package/dist/web/standalone/.next/server/middleware.js +2 -2
  209. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  210. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  211. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  212. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  213. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  214. package/dist/web/standalone/.next/server/webpack-runtime.js +1 -1
  215. package/dist/web/standalone/.next/static/chunks/2826.e9f5195e91f9cad2.js +11 -0
  216. package/dist/web/standalone/.next/static/chunks/3621.fc7480022c972438.js +20 -0
  217. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-f2a7482d42a5614b.js → page-2f24283c162b6ab3.js} +1 -1
  218. package/dist/web/standalone/.next/static/chunks/app/{layout-a16c7a7ecdf0c2cf.js → layout-9ecfd95f343793f0.js} +1 -1
  219. package/dist/web/standalone/.next/static/chunks/app/page-151349214571e2b6.js +1 -0
  220. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +1 -0
  221. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +1 -0
  222. package/dist/web/standalone/.next/static/chunks/webpack-2e68521d7c82f7c2.js +1 -0
  223. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  224. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  225. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  226. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  227. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  228. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  229. package/dist/web/standalone/package.json +1 -2
  230. package/dist/web/standalone/server.js +1 -1
  231. package/package.json +1 -1
  232. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  233. package/packages/mcp-server/dist/workflow-tools.js +46 -74
  234. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  235. package/packages/mcp-server/src/workflow-tools.test.ts +0 -26
  236. package/packages/mcp-server/src/workflow-tools.ts +58 -93
  237. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  238. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  239. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
  240. package/packages/pi-ai/dist/providers/anthropic-shared.js +19 -48
  241. package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
  242. package/packages/pi-ai/dist/types.d.ts +0 -13
  243. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  244. package/packages/pi-ai/dist/types.js.map +1 -1
  245. package/packages/pi-ai/dist/utils/repair-tool-json.d.ts.map +1 -1
  246. package/packages/pi-ai/dist/utils/repair-tool-json.js +3 -24
  247. package/packages/pi-ai/dist/utils/repair-tool-json.js.map +1 -1
  248. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js +0 -26
  249. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js.map +1 -1
  250. package/packages/pi-ai/src/providers/anthropic-shared.ts +20 -52
  251. package/packages/pi-ai/src/types.ts +0 -13
  252. package/packages/pi-ai/src/utils/repair-tool-json.ts +3 -24
  253. package/packages/pi-ai/src/utils/tests/repair-tool-json.test.ts +0 -32
  254. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  255. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  256. package/packages/pi-coding-agent/dist/core/agent-session.js +0 -6
  257. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  258. package/packages/pi-coding-agent/dist/core/messages.d.ts.map +1 -1
  259. package/packages/pi-coding-agent/dist/core/messages.js +0 -4
  260. package/packages/pi-coding-agent/dist/core/messages.js.map +1 -1
  261. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +2 -19
  262. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
  263. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +0 -10
  264. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  265. package/packages/pi-coding-agent/dist/core/model-registry.js +0 -18
  266. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  267. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +0 -13
  268. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  269. package/packages/pi-coding-agent/dist/core/system-prompt.js +16 -20
  270. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  271. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +1 -1
  272. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  273. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +1 -14
  274. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  275. package/packages/pi-coding-agent/src/core/agent-session.ts +0 -7
  276. package/packages/pi-coding-agent/src/core/messages.ts +0 -4
  277. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +2 -32
  278. package/packages/pi-coding-agent/src/core/model-registry.ts +0 -21
  279. package/packages/pi-coding-agent/src/core/system-prompt.ts +15 -33
  280. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +1 -17
  281. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +1 -1
  282. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  283. package/packages/pi-tui/dist/__tests__/autocomplete.test.js +3 -17
  284. package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
  285. package/packages/pi-tui/src/__tests__/autocomplete.test.ts +3 -20
  286. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  287. package/src/resources/extensions/gsd/auto/loop.ts +2 -24
  288. package/src/resources/extensions/gsd/auto/phases.ts +3 -3
  289. package/src/resources/extensions/gsd/auto/run-unit.ts +1 -3
  290. package/src/resources/extensions/gsd/auto/session.ts +0 -3
  291. package/src/resources/extensions/gsd/auto/types.ts +0 -1
  292. package/src/resources/extensions/gsd/auto-recovery.ts +8 -46
  293. package/src/resources/extensions/gsd/auto-start.ts +1 -1
  294. package/src/resources/extensions/gsd/auto-tool-tracking.ts +4 -2
  295. package/src/resources/extensions/gsd/auto-worktree.ts +0 -38
  296. package/src/resources/extensions/gsd/auto.ts +4 -14
  297. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +13 -15
  298. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +7 -8
  299. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +2 -2
  300. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +9 -10
  301. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +31 -102
  302. package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +6 -12
  303. package/src/resources/extensions/gsd/bootstrap/system-context.ts +8 -39
  304. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +11 -39
  305. package/src/resources/extensions/gsd/commands/catalog.ts +5 -75
  306. package/src/resources/extensions/gsd/commands/handlers/core.ts +1 -22
  307. package/src/resources/extensions/gsd/commands-mcp-status.ts +1 -3
  308. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +1 -15
  309. package/src/resources/extensions/gsd/dashboard-overlay.ts +1 -1
  310. package/src/resources/extensions/gsd/docs/preferences-reference.md +0 -4
  311. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +1 -39
  312. package/src/resources/extensions/gsd/doctor-types.ts +1 -3
  313. package/src/resources/extensions/gsd/error-classifier.ts +1 -1
  314. package/src/resources/extensions/gsd/forensics.ts +2 -2
  315. package/src/resources/extensions/gsd/git-service.ts +5 -13
  316. package/src/resources/extensions/gsd/gsd-db.ts +2 -12
  317. package/src/resources/extensions/gsd/guided-flow.ts +25 -25
  318. package/src/resources/extensions/gsd/memory-store.ts +28 -81
  319. package/src/resources/extensions/gsd/model-router.ts +9 -172
  320. package/src/resources/extensions/gsd/native-git-bridge.ts +1 -7
  321. package/src/resources/extensions/gsd/preferences-models.ts +15 -101
  322. package/src/resources/extensions/gsd/preferences-types.ts +0 -6
  323. package/src/resources/extensions/gsd/preferences-validation.ts +0 -35
  324. package/src/resources/extensions/gsd/preferences.ts +2 -16
  325. package/src/resources/extensions/gsd/prompt-loader.ts +12 -26
  326. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +3 -9
  327. package/src/resources/extensions/gsd/state.ts +0 -42
  328. package/src/resources/extensions/gsd/templates/PREFERENCES.md +0 -1
  329. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +1 -178
  330. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +0 -58
  331. package/src/resources/extensions/gsd/tests/auto-session-encapsulation.test.ts +5 -9
  332. package/src/resources/extensions/gsd/tests/auto-supervisor.test.mjs +4 -21
  333. package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +1 -1
  334. package/src/resources/extensions/gsd/tests/budget-prediction.test.ts +211 -138
  335. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +59 -142
  336. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +4 -7
  337. package/src/resources/extensions/gsd/tests/completed-at-reconcile.test.ts +32 -89
  338. package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +22 -0
  339. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +23 -41
  340. package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +43 -3
  341. package/src/resources/extensions/gsd/tests/debug-logger.test.ts +3 -5
  342. package/src/resources/extensions/gsd/tests/discuss-empty-db-fallback.test.ts +87 -22
  343. package/src/resources/extensions/gsd/tests/discuss-queued-milestones.test.ts +118 -7
  344. package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +47 -0
  345. package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +60 -18
  346. package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +76 -14
  347. package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +75 -0
  348. package/src/resources/extensions/gsd/tests/false-degraded-mode-warning.test.ts +83 -22
  349. package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +63 -1
  350. package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +1 -26
  351. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +0 -30
  352. package/src/resources/extensions/gsd/tests/headless-answers.test.ts +4 -14
  353. package/src/resources/extensions/gsd/tests/health-widget.test.ts +12 -22
  354. package/src/resources/extensions/gsd/tests/init-prefs-routing.test.ts +1 -64
  355. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +0 -22
  356. package/src/resources/extensions/gsd/tests/integration/token-savings.test.ts +23 -0
  357. package/src/resources/extensions/gsd/tests/memory-store.test.ts +0 -128
  358. package/src/resources/extensions/gsd/tests/memory-tools.test.ts +1 -33
  359. package/src/resources/extensions/gsd/tests/model-router.test.ts +8 -169
  360. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +0 -8
  361. package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +43 -32
  362. package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +10 -4
  363. package/src/resources/extensions/gsd/tests/preferences.test.ts +0 -127
  364. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +0 -16
  365. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +0 -7
  366. package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +6 -6
  367. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +19 -168
  368. package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +1 -7
  369. package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +1 -23
  370. package/src/resources/extensions/gsd/tests/token-profile.test.ts +4 -51
  371. package/src/resources/extensions/gsd/tests/turn-epoch.test.ts +16 -7
  372. package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +7 -5
  373. package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +1 -15
  374. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +6 -6
  375. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +0 -15
  376. package/src/resources/extensions/gsd/tools/memory-tools.ts +1 -17
  377. package/src/resources/extensions/gsd/unit-context-manifest.ts +8 -8
  378. package/src/resources/extensions/gsd/visualizer-overlay.ts +1 -1
  379. package/src/resources/extensions/gsd/watch/header-renderer.ts +1 -3
  380. package/src/resources/extensions/gsd/workflow-logger.ts +0 -1
  381. package/src/resources/extensions/gsd/worktree-command.ts +44 -31
  382. package/src/resources/extensions/mcp-client/index.ts +3 -6
  383. package/src/resources/extensions/slash-commands/create-extension.ts +24 -38
  384. package/src/resources/skills/create-gsd-extension/SKILL.md +5 -9
  385. package/src/resources/skills/create-gsd-extension/references/custom-commands.md +1 -1
  386. package/src/resources/skills/create-gsd-extension/references/custom-rendering.md +5 -5
  387. package/src/resources/skills/create-gsd-extension/references/custom-tools.md +4 -4
  388. package/src/resources/skills/create-gsd-extension/references/custom-ui.md +6 -6
  389. package/src/resources/skills/create-gsd-extension/references/events-reference.md +3 -3
  390. package/src/resources/skills/create-gsd-extension/references/packaging-distribution.md +1 -1
  391. package/src/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +3 -3
  392. package/src/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +2 -2
  393. package/src/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +3 -3
  394. package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +12 -32
  395. package/dist/cli-policy.d.ts +0 -13
  396. package/dist/cli-policy.js +0 -17
  397. package/dist/resources/.managed-resources-content-hash +0 -1
  398. package/dist/resources/extensions/gsd/auto-runtime-state.js +0 -31
  399. package/dist/resources/extensions/gsd/milestone-id-reservation.js +0 -36
  400. package/dist/resources/extensions/gsd/worktree-session-state.js +0 -33
  401. package/dist/runtime-checks.d.ts +0 -27
  402. package/dist/runtime-checks.js +0 -38
  403. package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +0 -1
  404. package/dist/web/standalone/.next/static/chunks/2824.08296bc2f9654698.js +0 -1
  405. package/dist/web/standalone/.next/static/chunks/3026.3af53b279375f082.js +0 -1
  406. package/dist/web/standalone/.next/static/chunks/315.6f68ae79b67d25cf.js +0 -1
  407. package/dist/web/standalone/.next/static/chunks/3497.4bfc60a3b3dea717.js +0 -1
  408. package/dist/web/standalone/.next/static/chunks/5516.4a07c872b5c3a663.js +0 -1
  409. package/dist/web/standalone/.next/static/chunks/8336.31b019697882acfb.js +0 -10
  410. package/dist/web/standalone/.next/static/chunks/8845.c9702695e8c5a9c5.js +0 -2
  411. package/dist/web/standalone/.next/static/chunks/9058.01ef3a463bda88f1.js +0 -20
  412. package/dist/web/standalone/.next/static/chunks/9441.1081da1125d1764f.js +0 -1
  413. package/dist/web/standalone/.next/static/chunks/app/page-9bf2e0c50fb2ca05.js +0 -1
  414. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +0 -1
  415. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +0 -1
  416. package/dist/web/standalone/.next/static/chunks/webpack-f9f0dc45e4f3ac10.js +0 -1
  417. package/dist/worktree-status-banner.d.ts +0 -1
  418. package/dist/worktree-status-banner.js +0 -132
  419. package/packages/mcp-server/dist/alias-telemetry.d.ts +0 -8
  420. package/packages/mcp-server/dist/alias-telemetry.d.ts.map +0 -1
  421. package/packages/mcp-server/dist/alias-telemetry.js +0 -30
  422. package/packages/mcp-server/dist/alias-telemetry.js.map +0 -1
  423. package/packages/mcp-server/src/alias-telemetry.test.ts +0 -78
  424. package/packages/mcp-server/src/alias-telemetry.ts +0 -30
  425. package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.d.ts +0 -2
  426. package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.d.ts.map +0 -1
  427. package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.js +0 -231
  428. package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.js.map +0 -1
  429. package/packages/pi-ai/src/providers/anthropic-shared.cache-breakpoint.test.ts +0 -289
  430. package/packages/pi-coding-agent/dist/core/token-telemetry.d.ts +0 -37
  431. package/packages/pi-coding-agent/dist/core/token-telemetry.d.ts.map +0 -1
  432. package/packages/pi-coding-agent/dist/core/token-telemetry.js +0 -49
  433. package/packages/pi-coding-agent/dist/core/token-telemetry.js.map +0 -1
  434. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.d.ts +0 -2
  435. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.d.ts.map +0 -1
  436. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +0 -133
  437. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +0 -1
  438. package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.d.ts +0 -2
  439. package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.d.ts.map +0 -1
  440. package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.js +0 -78
  441. package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.js.map +0 -1
  442. package/packages/pi-coding-agent/dist/tests/token-telemetry.test.d.ts +0 -2
  443. package/packages/pi-coding-agent/dist/tests/token-telemetry.test.d.ts.map +0 -1
  444. package/packages/pi-coding-agent/dist/tests/token-telemetry.test.js +0 -181
  445. package/packages/pi-coding-agent/dist/tests/token-telemetry.test.js.map +0 -1
  446. package/packages/pi-coding-agent/src/core/token-telemetry.ts +0 -77
  447. package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +0 -212
  448. package/packages/pi-coding-agent/src/tests/system-prompt-cache-stability.test.ts +0 -102
  449. package/packages/pi-coding-agent/src/tests/token-telemetry.test.ts +0 -200
  450. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts +0 -2
  451. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts.map +0 -1
  452. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js +0 -161
  453. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js.map +0 -1
  454. package/packages/pi-tui/src/components/__tests__/leak-fixes-runtime.test.ts +0 -219
  455. package/src/resources/extensions/gsd/auto-runtime-state.ts +0 -51
  456. package/src/resources/extensions/gsd/milestone-id-reservation.ts +0 -47
  457. package/src/resources/extensions/gsd/tests/deferred-milestone-dir-4996.test.ts +0 -116
  458. package/src/resources/extensions/gsd/tests/doctor-orphan-milestone-4996.test.ts +0 -100
  459. package/src/resources/extensions/gsd/tests/ensure-preconditions-guard-4996.test.ts +0 -93
  460. package/src/resources/extensions/gsd/tests/find-missing-summaries-closed-runtime.test.ts +0 -47
  461. package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +0 -63
  462. package/src/resources/extensions/gsd/tests/gsd-no-project-error-runtime.test.ts +0 -81
  463. package/src/resources/extensions/gsd/tests/help-menu-coverage.test.ts +0 -57
  464. package/src/resources/extensions/gsd/tests/import-done-milestones-runtime.test.ts +0 -145
  465. package/src/resources/extensions/gsd/tests/merge-self-branch-guard.test.ts +0 -124
  466. package/src/resources/extensions/gsd/tests/milestone-id-gap-reuse-4996.test.ts +0 -152
  467. package/src/resources/extensions/gsd/tests/native-git-infra-errors.test.ts +0 -50
  468. package/src/resources/extensions/gsd/tests/register-hooks-compaction-checkpoint.test.ts +0 -93
  469. package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +0 -101
  470. package/src/resources/extensions/gsd/worktree-session-state.ts +0 -35
  471. package/src/resources/extensions/mcp-client/tests/global-config.test.ts +0 -91
  472. package/src/resources/skills/create-gsd-extension/templates/templates.test.ts +0 -58
  473. /package/dist/web/standalone/.next/static/{UF5VF4F1tB0miEtJS7LyX → 7afp7gq8-DVbxum83zRQ-}/_buildManifest.js +0 -0
  474. /package/dist/web/standalone/.next/static/{UF5VF4F1tB0miEtJS7LyX → 7afp7gq8-DVbxum83zRQ-}/_ssgManifest.js +0 -0
@@ -16,9 +16,11 @@
16
16
 
17
17
  import { describe, test, afterEach } from "node:test";
18
18
  import assert from "node:assert/strict";
19
- import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
19
+ import { mkdtempSync, mkdirSync, rmSync, writeFileSync, readFileSync } from "node:fs";
20
20
  import { join } from "node:path";
21
21
  import { tmpdir } from "node:os";
22
+ import { fileURLToPath } from "node:url";
23
+ import { dirname } from "node:path";
22
24
 
23
25
  import { deriveState } from "../state.ts";
24
26
  import { invalidateAllCaches } from "../cache.ts";
@@ -55,6 +57,12 @@ function writeRoadmap(base: string, mid: string, content: string): void {
55
57
  writeFileSync(join(base, ".gsd", "milestones", mid, `${mid}-ROADMAP.md`), content);
56
58
  }
57
59
 
60
+ function readGuidedFlowSource(): string {
61
+ const thisFile = fileURLToPath(import.meta.url);
62
+ const thisDir = dirname(thisFile);
63
+ return readFileSync(join(thisDir, "..", "guided-flow.ts"), "utf-8");
64
+ }
65
+
58
66
  // ─── Tests ────────────────────────────────────────────────────────────────────
59
67
 
60
68
  describe("discuss-queued-milestones (#2307)", () => {
@@ -161,10 +169,113 @@ describe("discuss-queued-milestones (#2307)", () => {
161
169
  }
162
170
  });
163
171
 
164
- // The earlier tests 6-13 source-grepped guided-flow.ts for identifier
165
- // names (showDiscussQueuedMilestone, dispatchDiscussForMilestone),
166
- // UI-copy strings ("[queued]", "Discuss a queued milestone"), and
167
- // regex-on-function-body assertions for the #3150 routing — all
168
- // structural rather than behavioural (Refs #4826). They were dropped
169
- // when this file was tightened against handler-level assertions.
172
+ test("6. guided-flow no longer hard-exits when no active milestone but pending exist", () => {
173
+ const source = readGuidedFlowSource();
174
+
175
+ // The old guard was a simple early-exit:
176
+ // if (!state.activeMilestone) {
177
+ // ctx.ui.notify("No active milestone. Run /gsd to create one first.", "warning");
178
+ // return;
179
+ // }
180
+ //
181
+ // The new guard should check for pending milestones and route instead.
182
+ const oldGuardPattern = /if\s*\(!state\.activeMilestone\)\s*\{\s*ctx\.ui\.notify\("No active milestone/;
183
+ assert.ok(
184
+ !oldGuardPattern.test(source),
185
+ "guided-flow must not unconditionally exit when activeMilestone is null",
186
+ );
187
+ });
188
+
189
+ test("7. showDiscussQueuedMilestone helper exists in guided-flow", () => {
190
+ const source = readGuidedFlowSource();
191
+ assert.ok(
192
+ source.includes("showDiscussQueuedMilestone"),
193
+ "guided-flow must export showDiscussQueuedMilestone helper",
194
+ );
195
+ });
196
+
197
+ test("8. dispatchDiscussForMilestone helper exists in guided-flow", () => {
198
+ const source = readGuidedFlowSource();
199
+ assert.ok(
200
+ source.includes("dispatchDiscussForMilestone"),
201
+ "guided-flow must export dispatchDiscussForMilestone helper",
202
+ );
203
+ });
204
+
205
+ test("9. dispatchDiscussForMilestone does not set pendingAutoStart", () => {
206
+ const source = readGuidedFlowSource();
207
+
208
+ // Extract the dispatchDiscussForMilestone function body
209
+ const fnMatch = source.match(
210
+ /async function dispatchDiscussForMilestone\s*\([^)]*\)[^{]*\{([\s\S]*?)\n\}/,
211
+ );
212
+ assert.ok(!!fnMatch, "dispatchDiscussForMilestone function body must be present");
213
+
214
+ if (fnMatch) {
215
+ assert.ok(
216
+ !fnMatch[1].includes("pendingAutoStart"),
217
+ "dispatchDiscussForMilestone must NOT set pendingAutoStart — discussing a queued milestone must not activate it",
218
+ );
219
+ }
220
+ });
221
+
222
+ test("10. slice picker includes queued milestone option when pending milestones exist", () => {
223
+ const source = readGuidedFlowSource();
224
+ assert.ok(
225
+ source.includes("discuss_queued_milestone"),
226
+ "slice picker must include a 'discuss_queued_milestone' action id for queued milestones",
227
+ );
228
+ assert.ok(
229
+ source.includes("Discuss a queued milestone"),
230
+ "slice picker must label the queued milestone action clearly",
231
+ );
232
+ });
233
+
234
+ test("11. queued milestone picker labels entries with [queued]", () => {
235
+ const source = readGuidedFlowSource();
236
+ assert.ok(
237
+ source.includes("[queued]"),
238
+ "queued milestone picker must label entries with [queued] to distinguish from active",
239
+ );
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
+ });
170
281
  });
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Regression test for discuss-slice structured questions availability
3
+ *
4
+ * The guided-discuss-slice.md template must use the structuredQuestionsAvailable
5
+ * template variable to conditionally switch between ask_user_questions tool
6
+ * calls and plain-text questions, so the prompt works correctly when the
7
+ * structured questions tool is not available.
8
+ */
9
+
10
+ import { describe, it } from 'node:test'
11
+ import assert from 'node:assert/strict'
12
+ import { readFileSync } from 'node:fs'
13
+ import { resolve } from 'node:path'
14
+ import { extractSourceRegion } from "./test-helpers.ts";
15
+
16
+ const template = readFileSync(
17
+ resolve(process.cwd(), 'src', 'resources', 'extensions', 'gsd', 'prompts', 'guided-discuss-slice.md'),
18
+ 'utf-8',
19
+ )
20
+
21
+ describe('discuss-slice structuredQuestionsAvailable template variable', () => {
22
+ it('template references structuredQuestionsAvailable variable', () => {
23
+ assert.ok(
24
+ template.includes('{{structuredQuestionsAvailable}}'),
25
+ 'guided-discuss-slice.md must use {{structuredQuestionsAvailable}} template variable',
26
+ )
27
+ })
28
+
29
+ it('template handles both true and false cases', () => {
30
+ const trueCase = template.includes('`{{structuredQuestionsAvailable}}` is `true`')
31
+ const falseCase = template.includes('`{{structuredQuestionsAvailable}}` is `false`')
32
+
33
+ assert.ok(trueCase, 'template must have a branch for structuredQuestionsAvailable=true')
34
+ assert.ok(falseCase, 'template must have a branch for structuredQuestionsAvailable=false')
35
+ })
36
+
37
+ it('false case instructs plain text questions', () => {
38
+ const falseIdx = template.indexOf('`{{structuredQuestionsAvailable}}` is `false`')
39
+ assert.ok(falseIdx !== -1)
40
+
41
+ const afterFalse = extractSourceRegion(template, '`{{structuredQuestionsAvailable}}` is `false`')
42
+ assert.ok(
43
+ afterFalse.includes('plain text'),
44
+ 'when structuredQuestionsAvailable is false, questions should be in plain text',
45
+ )
46
+ })
47
+ })
@@ -1,35 +1,77 @@
1
- // GSD-2 — Behavioural regression test for #3616.
2
- //
3
- // Bug: After a discuss session narrows the active tool set via setActiveTools,
4
- // the narrowed list persisted into the next auto-mode session because newSession()
5
- // did not restore extension tools when cwd was unchanged. This caused
6
- // gsd_plan_slice and other DB tools to be missing from plan-slice subagent
7
- // sessions.
8
- //
9
- // The behavioural invariant we can pin without grepping source: gsd_plan_slice
10
- // (a heavy planning tool) is NOT inside the discuss allowlist. The remaining
11
- // guarantees (newSession including all extension tools in both branches) are
12
- // covered by agent-session.test.ts inside packages/pi-coding-agent.
13
- //
14
- // Refs #4826 (rewrite from source-grep on guided-flow.ts / agent-session.ts).
1
+ // GSD-2 — Regression test for #3616: discuss tool scoping must not leak into subsequent sessions
2
+ // Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
3
+
4
+ /**
5
+ * Bug #3616: After a discuss session narrows the active tool set via
6
+ * setActiveTools(), the narrowed list persisted into the next auto-mode
7
+ * session because newSession() did not restore extension tools when cwd
8
+ * was unchanged. This caused gsd_plan_slice and other DB tools to be
9
+ * missing from plan-slice subagent sessions.
10
+ *
11
+ * This test verifies the structural properties that prevent the leak:
12
+ * 1. guided-flow.ts narrows tools ONLY for discuss-* unit types
13
+ * 2. The narrowed set explicitly excludes gsd_plan_slice (a HEAVY_TOOL)
14
+ * 3. agent-session.ts:newSession() has an else-branch that restores
15
+ * all extension tools even when cwd hasn't changed
16
+ */
15
17
 
16
18
  import { describe, test } from "node:test";
17
19
  import assert from "node:assert/strict";
20
+ import { readFileSync } from "node:fs";
21
+ import { join, dirname } from "node:path";
22
+ import { fileURLToPath } from "node:url";
18
23
 
19
24
  import { DISCUSS_TOOLS_ALLOWLIST } from "../constants.ts";
25
+ import { extractSourceRegion } from "./test-helpers.ts";
26
+
27
+ const __dirname = dirname(fileURLToPath(import.meta.url));
28
+ const guidedFlowSource = readFileSync(join(__dirname, "..", "guided-flow.ts"), "utf-8");
20
29
 
21
30
  describe("#3616 — discuss tool scoping must not leak across sessions", () => {
22
31
  test("gsd_plan_slice is NOT in DISCUSS_TOOLS_ALLOWLIST", () => {
23
32
  assert.ok(
24
33
  !DISCUSS_TOOLS_ALLOWLIST.includes("gsd_plan_slice"),
25
- `gsd_plan_slice (a heavy planning tool) must be excluded from the discuss scope; allowlist=${JSON.stringify(DISCUSS_TOOLS_ALLOWLIST)}`,
34
+ "gsd_plan_slice should be excluded from discuss scope (it's a heavy planning tool)",
35
+ );
36
+ });
37
+
38
+ test("tool scoping only activates for discuss-* unit types", () => {
39
+ // The guard must be: if (unitType?.startsWith("discuss-"))
40
+ assert.ok(
41
+ guidedFlowSource.includes('unitType?.startsWith("discuss-")'),
42
+ "tool scoping should only trigger for discuss-* unit types",
26
43
  );
27
44
  });
28
45
 
29
- test("DISCUSS_TOOLS_ALLOWLIST is non-empty (sanity)", () => {
46
+ test("discuss tool scoping uses setActiveTools (not setTools) for reversibility", () => {
47
+ // setActiveTools changes the active subset but doesn't remove tools from
48
+ // the registry. newSession()'s _refreshToolRegistry can restore them.
49
+ assert.ok(
50
+ guidedFlowSource.includes("pi.setActiveTools(scopedTools)"),
51
+ "should use pi.setActiveTools to narrow tools (preserving registry)",
52
+ );
53
+ });
54
+
55
+ test("newSession() in agent-session.ts has defense against tool narrowing persistence", () => {
56
+ const agentSessionSource = readFileSync(
57
+ join(process.cwd(), "packages/pi-coding-agent/src/core/agent-session.ts"),
58
+ "utf-8",
59
+ );
60
+ const newSessionStart = agentSessionSource.indexOf("async newSession(options?:");
61
+ assert.ok(newSessionStart >= 0, "should find newSession");
62
+ const body = extractSourceRegion(agentSessionSource, "async newSession(options?:");
63
+
64
+ // Both branches (cwd-changed and cwd-unchanged) must include extension tools
65
+ assert.ok(
66
+ body.includes("includeAllExtensionTools: true"),
67
+ "newSession() must include all extension tools in both branches",
68
+ );
69
+
70
+ // Count occurrences — should be at least 2 (one per branch)
71
+ const matches = body.match(/includeAllExtensionTools:\s*true/g);
30
72
  assert.ok(
31
- DISCUSS_TOOLS_ALLOWLIST.length > 0,
32
- "discuss scope should include at least one tool — empty allowlist would break /gsd discuss",
73
+ matches && matches.length >= 2,
74
+ `expected >=2 includeAllExtensionTools:true in newSession(), got ${matches?.length ?? 0}`,
33
75
  );
34
76
  });
35
77
  });
@@ -1,20 +1,82 @@
1
- /**
2
- * Behavioural regression test for #2645 — double mergeAndExit guard.
3
- *
4
- * AutoSession.milestoneMergedInPhases is the producer-side flag set by the
5
- * "complete" / "all-milestones-complete" branches in phases.ts after they
6
- * call mergeAndExit. stopAuto reads it to skip the redundant Step-4 merge
7
- * (which previously failed because the branch was already deleted).
8
- *
9
- * Refs #4829 (rewrite from positional source-grep on phases.ts/auto.ts).
10
- */
11
-
12
1
  import { describe, test } from "node:test";
13
2
  import assert from "node:assert/strict";
3
+ import { readFileSync } from "node:fs";
4
+ import { join, dirname } from "node:path";
5
+ import { fileURLToPath } from "node:url";
14
6
  import { AutoSession } from "../auto/session.ts";
7
+ import { extractSourceRegion } from "./test-helpers.ts";
8
+
9
+ const __dirname = dirname(fileURLToPath(import.meta.url));
10
+
11
+ describe("double mergeAndExit guard (#2645)", () => {
12
+ test("phases.ts sets milestoneMergedInPhases after mergeAndExit in milestone-complete path", () => {
13
+ // Source audit: the "complete" phase path must set the guard flag
14
+ // after calling mergeAndExit so that stopAuto skips the second merge.
15
+ const phasesSrc = readFileSync(
16
+ join(__dirname, "..", "auto", "phases.ts"),
17
+ "utf-8",
18
+ );
19
+
20
+ // Find the "complete" phase block
21
+ const completeIdx = phasesSrc.indexOf('state.phase === "complete"');
22
+ assert.ok(completeIdx > 0, "phases.ts should have a 'complete' phase check");
23
+
24
+ const afterComplete = extractSourceRegion(phasesSrc, 'state.phase === "complete"');
25
+ const mergeIdx = afterComplete.indexOf("deps.resolver.mergeAndExit");
26
+ const flagIdx = afterComplete.indexOf("s.milestoneMergedInPhases = true");
27
+
28
+ assert.ok(mergeIdx > 0, "complete path should call mergeAndExit");
29
+ assert.ok(flagIdx > 0, "complete path should set milestoneMergedInPhases");
30
+ assert.ok(
31
+ flagIdx > mergeIdx,
32
+ "milestoneMergedInPhases must be set AFTER mergeAndExit (not before)",
33
+ );
34
+ });
35
+
36
+ test("phases.ts sets milestoneMergedInPhases after mergeAndExit in all-milestones-complete path", () => {
37
+ const phasesSrc = readFileSync(
38
+ join(__dirname, "..", "auto", "phases.ts"),
39
+ "utf-8",
40
+ );
41
+
42
+ // The "all milestones complete" block checks incomplete.length === 0
43
+ const allCompleteIdx = phasesSrc.indexOf("incomplete.length === 0");
44
+ assert.ok(allCompleteIdx > 0, "phases.ts should have an all-milestones-complete check");
45
+
46
+ const afterAllComplete = extractSourceRegion(phasesSrc, "incomplete.length === 0");
47
+ const mergeIdx = afterAllComplete.indexOf("deps.resolver.mergeAndExit");
48
+ const flagIdx = afterAllComplete.indexOf("s.milestoneMergedInPhases = true");
49
+
50
+ assert.ok(mergeIdx > 0, "all-complete path should call mergeAndExit");
51
+ assert.ok(flagIdx > 0, "all-complete path should set milestoneMergedInPhases");
52
+ assert.ok(
53
+ flagIdx > mergeIdx,
54
+ "milestoneMergedInPhases must be set AFTER mergeAndExit (not before)",
55
+ );
56
+ });
57
+
58
+ test("stopAuto checks milestoneMergedInPhases before calling mergeAndExit", () => {
59
+ const autoSrc = readFileSync(
60
+ join(__dirname, "..", "auto.ts"),
61
+ "utf-8",
62
+ );
63
+
64
+ // The Step 4 worktree exit block must check the guard flag
65
+ const step4Idx = autoSrc.indexOf("Step 4: Auto-worktree exit");
66
+ assert.ok(step4Idx > 0, "auto.ts should have Step 4 worktree exit");
67
+
68
+ const step4Block = extractSourceRegion(autoSrc, "Step 4: Auto-worktree exit");
69
+ assert.ok(
70
+ step4Block.includes("milestoneMergedInPhases"),
71
+ "stopAuto Step 4 must check milestoneMergedInPhases before merging",
72
+ );
73
+ assert.ok(
74
+ step4Block.includes("!s.milestoneMergedInPhases"),
75
+ "stopAuto should skip merge when milestoneMergedInPhases is true",
76
+ );
77
+ });
15
78
 
16
- describe("AutoSession.milestoneMergedInPhases (#2645)", () => {
17
- test("defaults to false on a fresh session", () => {
79
+ test("AutoSession.milestoneMergedInPhases defaults to false", () => {
18
80
  const session = new AutoSession();
19
81
  assert.equal(
20
82
  session.milestoneMergedInPhases,
@@ -23,7 +85,7 @@ describe("AutoSession.milestoneMergedInPhases (#2645)", () => {
23
85
  );
24
86
  });
25
87
 
26
- test("reset() clears the flag back to false", () => {
88
+ test("AutoSession.reset() clears milestoneMergedInPhases", () => {
27
89
  const session = new AutoSession();
28
90
  session.milestoneMergedInPhases = true;
29
91
  session.reset();
@@ -0,0 +1,75 @@
1
+ /**
2
+ * empty-content-abort-loop.test.ts — Regression test for #2695.
3
+ *
4
+ * When the LLM sends an assistant message with empty `content: []` and
5
+ * `stopReason: "aborted"`, this is NOT a fatal abort — it is a non-fatal
6
+ * end-of-turn. The abort handler in agent-end-recovery.ts must distinguish
7
+ * this case and NOT pause auto-mode, allowing the loop to continue via
8
+ * resolveAgentEnd instead of entering a stuck re-dispatch loop.
9
+ */
10
+
11
+ import test from "node:test";
12
+ import assert from "node:assert/strict";
13
+ import { readFileSync } from "node:fs";
14
+ import { join, dirname } from "node:path";
15
+ import { fileURLToPath } from "node:url";
16
+ import { extractSourceRegion } from "./test-helpers.ts";
17
+
18
+ const __dirname = dirname(fileURLToPath(import.meta.url));
19
+ const RECOVERY_PATH = join(__dirname, "..", "bootstrap", "agent-end-recovery.ts");
20
+
21
+ function getRecoverySource(): string {
22
+ return readFileSync(RECOVERY_PATH, "utf-8");
23
+ }
24
+
25
+ test("agent-end-recovery.ts does not pause on aborted messages with empty content (#2695)", () => {
26
+ const source = getRecoverySource();
27
+
28
+ // The abort handler at `stopReason === "aborted"` must check for empty content
29
+ // before deciding to pause. An empty content array is a non-fatal agent stop.
30
+ const abortIdx = source.indexOf('stopReason === "aborted"');
31
+ assert.ok(abortIdx > -1, "abort handler must exist in agent-end-recovery.ts");
32
+
33
+ // Extract the region around the abort handler (enough to see the guard logic)
34
+ const abortRegion = extractSourceRegion(source, 'stopReason === "aborted"', { fromIdx: abortIdx });
35
+
36
+ // Must check for empty content before pausing
37
+ assert.ok(
38
+ abortRegion.includes("content") && (abortRegion.includes("length") || abortRegion.includes("?.length")),
39
+ "abort handler must inspect content array length to distinguish empty-content aborts from fatal aborts (#2695)",
40
+ );
41
+ });
42
+
43
+ test("agent-end-recovery.ts routes empty-content aborted messages to resolveAgentEnd (#2695)", () => {
44
+ const source = getRecoverySource();
45
+
46
+ // The abort block must have a path that calls resolveAgentEnd for empty-content messages
47
+ // instead of unconditionally calling pauseAuto
48
+ const abortIdx = source.indexOf('stopReason === "aborted"');
49
+ assert.ok(abortIdx > -1, "abort handler must exist");
50
+
51
+ // Get the full abort handling block (from the if to the next stopReason check or success path)
52
+ const afterAbort = extractSourceRegion(source, 'stopReason === "aborted"');
53
+
54
+ // The abort block must have a code path that calls resolveAgentEnd (for empty-content case)
55
+ assert.ok(
56
+ afterAbort.includes("resolveAgentEnd"),
57
+ "abort handler must route empty-content aborted messages to resolveAgentEnd instead of always pausing (#2695)",
58
+ );
59
+ });
60
+
61
+ test("agent-end-recovery.ts checks for errorMessage presence in abort handler (#2695)", () => {
62
+ const source = getRecoverySource();
63
+
64
+ const abortIdx = source.indexOf('stopReason === "aborted"');
65
+ assert.ok(abortIdx > -1, "abort handler must exist");
66
+
67
+ const abortRegion = extractSourceRegion(source, 'stopReason === "aborted"');
68
+
69
+ // Fatal aborts should have error context (errorMessage field).
70
+ // The handler should check for this to distinguish fatal from non-fatal aborts.
71
+ assert.ok(
72
+ abortRegion.includes("errorMessage"),
73
+ "abort handler must check for errorMessage to distinguish fatal aborts from empty-content non-fatal stops (#2695)",
74
+ );
75
+ });
@@ -1,43 +1,104 @@
1
1
  /**
2
- * Behavioural regression tests for #3922.
2
+ * false-degraded-mode-warning.test.ts Regression tests for #3922.
3
3
  *
4
- * Before this fix, deriveState() logged "DB unavailable — degraded mode"
5
- * even when the DB had not been opened yet (e.g. during
6
- * before_agent_start context injection). The fix introduced
7
- * wasDbOpenAttempted() so the warning fires only after a real open attempt.
4
+ * Before this fix, deriveState() logged a "DB unavailable — degraded mode"
5
+ * warning even when the DB simply hadn't been opened yet (e.g. during
6
+ * before_agent_start context injection). The fix introduces wasDbOpenAttempted()
7
+ * to distinguish "not yet initialized" from "genuinely unavailable."
8
8
  *
9
- * The earlier tests source-grepped state.ts for the warning string and the
10
- * preceding line (POSITIONAL/SOURCE_GREP per #4826/#4829). They are
11
- * replaced here with direct calls to the wasDbOpenAttempted flag.
9
+ * Two aspects:
10
+ * 1. gsd-db: wasDbOpenAttempted() tracks whether openDatabase() was ever called.
11
+ * 2. state: the degraded-mode warning is gated behind wasDbOpenAttempted().
12
12
  */
13
13
 
14
- import { describe, test, beforeEach, afterEach } from "node:test";
14
+ import { describe, test } from "node:test";
15
15
  import assert from "node:assert/strict";
16
+ import { readFileSync } from "node:fs";
17
+ import { dirname, join } from "node:path";
18
+ import { fileURLToPath } from "node:url";
16
19
  import {
17
20
  openDatabase,
18
21
  closeDatabase,
22
+ isDbAvailable,
19
23
  wasDbOpenAttempted,
20
24
  } from "../gsd-db.ts";
21
25
 
26
+ const __dirname = dirname(fileURLToPath(import.meta.url));
27
+ const stateSource = readFileSync(join(__dirname, "..", "state.ts"), "utf-8");
28
+
29
+ // ═══════════════════════════════════════════════════════════════════════════
30
+ // 1. gsd-db: wasDbOpenAttempted flag
31
+ // ═══════════════════════════════════════════════════════════════════════════
32
+
22
33
  describe("wasDbOpenAttempted (#3922)", () => {
23
- beforeEach(() => { closeDatabase(); });
24
- afterEach(() => { closeDatabase(); });
25
34
 
26
- test("returns true after a successful openDatabase call", () => {
35
+ test("wasDbOpenAttempted returns true after openDatabase is called", () => {
36
+ // By this point in the test suite, openDatabase may or may not have been
37
+ // called by other tests. So we call it explicitly and verify it returns true.
27
38
  openDatabase(":memory:");
28
- assert.strictEqual(
29
- wasDbOpenAttempted(),
30
- true,
31
- "wasDbOpenAttempted should report true after openDatabase succeeds",
32
- );
39
+ assert.strictEqual(wasDbOpenAttempted(), true,
40
+ "wasDbOpenAttempted should be true after openDatabase call");
41
+ closeDatabase();
33
42
  });
34
43
 
35
- test("remains true after a failed open attempt the attempt is what matters", () => {
44
+ test("openDatabase sets the flag even if it fails on invalid path", () => {
45
+ // openDatabase with an unreachable path may fail, but the flag should
46
+ // still be set because the attempt was made.
36
47
  try { openDatabase("/nonexistent/path/that/will/fail.db"); } catch { /* expected */ }
37
- assert.strictEqual(
38
- wasDbOpenAttempted(),
39
- true,
40
- "wasDbOpenAttempted should be true even when openDatabase throws — the warning gate keys on the attempt, not the outcome",
48
+ assert.strictEqual(wasDbOpenAttempted(), true,
49
+ "wasDbOpenAttempted should be true even after a failed open attempt");
50
+ });
51
+ });
52
+
53
+ // ═══════════════════════════════════════════════════════════════════════════
54
+ // 2. state.ts: degraded-mode warning is gated behind wasDbOpenAttempted
55
+ // ═══════════════════════════════════════════════════════════════════════════
56
+
57
+ describe("degraded-mode warning guard (#3922)", () => {
58
+
59
+ test("state.ts imports wasDbOpenAttempted from gsd-db", () => {
60
+ assert.ok(
61
+ stateSource.includes("wasDbOpenAttempted"),
62
+ "state.ts must import wasDbOpenAttempted to gate the degraded-mode warning",
41
63
  );
42
64
  });
65
+
66
+ test("degraded-mode warning is inside a wasDbOpenAttempted() guard", () => {
67
+ // Find the degraded-mode warning string
68
+ const warningStr = 'DB unavailable — using filesystem state derivation (degraded mode)';
69
+ const warningIdx = stateSource.indexOf(warningStr);
70
+ assert.ok(warningIdx > 0, "degraded-mode warning string must exist in state.ts");
71
+
72
+ // The wasDbOpenAttempted() check must appear BEFORE the warning,
73
+ // within the same else-branch (i.e. within a reasonable distance).
74
+ // Look backwards from the warning for the guard.
75
+ const searchWindow = stateSource.slice(Math.max(0, warningIdx - 300), warningIdx);
76
+ assert.ok(
77
+ searchWindow.includes("wasDbOpenAttempted()"),
78
+ "wasDbOpenAttempted() guard must appear shortly before the degraded-mode warning " +
79
+ "to prevent false warnings when DB has not been initialized yet",
80
+ );
81
+ });
82
+
83
+ test("warning is NOT emitted unconditionally in the else branch", () => {
84
+ // The old code had `logWarning(...)` directly in the else branch.
85
+ // The fix wraps it in `if (wasDbOpenAttempted())`.
86
+ // Verify the logWarning call is inside a conditional, not bare.
87
+ const lines = stateSource.split("\n");
88
+ for (let i = 0; i < lines.length; i++) {
89
+ if (lines[i]!.includes("DB unavailable") && lines[i]!.includes("degraded mode")) {
90
+ // This line has the warning. Check that the preceding non-empty line
91
+ // contains an if-condition (wasDbOpenAttempted), not a bare else.
92
+ let prev = i - 1;
93
+ while (prev >= 0 && lines[prev]!.trim() === "") prev--;
94
+ const prevLine = lines[prev]!.trim();
95
+ assert.ok(
96
+ prevLine.includes("wasDbOpenAttempted"),
97
+ `Line ${i + 1} emits degraded-mode warning — preceding line ${prev + 1} must ` +
98
+ `contain wasDbOpenAttempted guard, but found: "${prevLine}"`,
99
+ );
100
+ break;
101
+ }
102
+ }
103
+ });
43
104
  });