gsd-pi 2.80.0-dev.4ea7d80e7 → 2.80.0-dev.7582bf37a

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 (656) hide show
  1. package/README.md +4 -2
  2. package/dist/claude-cli-check.d.ts +30 -0
  3. package/dist/claude-cli-check.js +18 -7
  4. package/dist/cli.js +0 -19
  5. package/dist/headless-query.d.ts +10 -0
  6. package/dist/headless-query.js +6 -4
  7. package/dist/loader-entrypoint.d.ts +8 -0
  8. package/dist/loader-entrypoint.js +27 -0
  9. package/dist/loader.js +2 -11
  10. package/dist/mcp-server.d.ts +1 -0
  11. package/dist/mcp-server.js +6 -3
  12. package/dist/resources/.managed-resources-content-hash +1 -1
  13. package/dist/resources/GSD-WORKFLOW.md +2 -2
  14. package/dist/resources/extensions/claude-code-cli/readiness.js +18 -7
  15. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +40 -3
  16. package/dist/resources/extensions/github-sync/sync.js +4 -1
  17. package/dist/resources/extensions/gsd/auto/loop.js +103 -9
  18. package/dist/resources/extensions/gsd/auto/phases.js +240 -139
  19. package/dist/resources/extensions/gsd/auto/resolve.js +29 -0
  20. package/dist/resources/extensions/gsd/auto/run-unit.js +22 -30
  21. package/dist/resources/extensions/gsd/auto/session.js +8 -0
  22. package/dist/resources/extensions/gsd/auto/workflow-dispatch-claim.js +33 -1
  23. package/dist/resources/extensions/gsd/auto/workflow-worker-heartbeat.js +9 -1
  24. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +5 -32
  25. package/dist/resources/extensions/gsd/auto-dispatch.js +16 -0
  26. package/dist/resources/extensions/gsd/auto-post-unit.js +104 -86
  27. package/dist/resources/extensions/gsd/auto-prompts.js +214 -17
  28. package/dist/resources/extensions/gsd/auto-recovery.js +43 -1
  29. package/dist/resources/extensions/gsd/auto-start.js +238 -12
  30. package/dist/resources/extensions/gsd/auto-supervisor.js +8 -1
  31. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +2 -2
  32. package/dist/resources/extensions/gsd/auto-worktree.js +209 -81
  33. package/dist/resources/extensions/gsd/auto.js +159 -44
  34. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +99 -10
  35. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +44 -37
  36. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +37 -10
  37. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +30 -20
  38. package/dist/resources/extensions/gsd/bootstrap/journal-tools.js +4 -1
  39. package/dist/resources/extensions/gsd/bootstrap/memory-tools.js +6 -4
  40. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +5 -3
  41. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +1 -1
  42. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +319 -54
  43. package/dist/resources/extensions/gsd/bootstrap/sanitize-complete-milestone.js +4 -0
  44. package/dist/resources/extensions/gsd/bootstrap/system-context.js +82 -23
  45. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +19 -2
  46. package/dist/resources/extensions/gsd/clean-root-preflight.js +65 -9
  47. package/dist/resources/extensions/gsd/commands/dispatcher.js +5 -0
  48. package/dist/resources/extensions/gsd/commands/handlers/ops.js +2 -2
  49. package/dist/resources/extensions/gsd/commands-config.js +1 -1
  50. package/dist/resources/extensions/gsd/commands-eval-review.js +2 -2
  51. package/dist/resources/extensions/gsd/commands-handlers.js +23 -9
  52. package/dist/resources/extensions/gsd/context-budget.js +37 -2
  53. package/dist/resources/extensions/gsd/crash-recovery.js +56 -10
  54. package/dist/resources/extensions/gsd/dashboard-overlay.js +1 -1
  55. package/dist/resources/extensions/gsd/db/unit-dispatches.js +92 -0
  56. package/dist/resources/extensions/gsd/db-base-schema.js +4 -2
  57. package/dist/resources/extensions/gsd/db-migration-steps.js +6 -0
  58. package/dist/resources/extensions/gsd/detection.js +106 -0
  59. package/dist/resources/extensions/gsd/ecosystem/gsd-extension-api.js +2 -0
  60. package/dist/resources/extensions/gsd/git-service.js +73 -5
  61. package/dist/resources/extensions/gsd/gsd-db.js +46 -13
  62. package/dist/resources/extensions/gsd/guided-flow.js +141 -46
  63. package/dist/resources/extensions/gsd/init-wizard.js +4 -1
  64. package/dist/resources/extensions/gsd/memory-store.js +69 -12
  65. package/dist/resources/extensions/gsd/migrate/command.js +40 -1
  66. package/dist/resources/extensions/gsd/migration-auto-check.js +87 -0
  67. package/dist/resources/extensions/gsd/native-git-bridge.js +32 -8
  68. package/dist/resources/extensions/gsd/orphan-stash-audit.js +101 -0
  69. package/dist/resources/extensions/gsd/parallel-orchestrator.js +13 -3
  70. package/dist/resources/extensions/gsd/planning-path-scope.js +26 -0
  71. package/dist/resources/extensions/gsd/pre-execution-checks.js +22 -0
  72. package/dist/resources/extensions/gsd/prompt-loader.js +28 -2
  73. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +27 -23
  74. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  75. package/dist/resources/extensions/gsd/prompts/execute-task.md +4 -2
  76. package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +1 -1
  77. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +3 -1
  78. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  79. package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -5
  80. package/dist/resources/extensions/gsd/prompts/replan-slice.md +2 -2
  81. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
  82. package/dist/resources/extensions/gsd/quick.js +34 -2
  83. package/dist/resources/extensions/gsd/safety/evidence-collector.js +10 -2
  84. package/dist/resources/extensions/gsd/slice-cadence.js +45 -2
  85. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +15 -9
  86. package/dist/resources/extensions/gsd/tools/complete-milestone.js +6 -7
  87. package/dist/resources/extensions/gsd/tools/complete-task.js +1 -1
  88. package/dist/resources/extensions/gsd/tools/context-mode-tool-result.js +15 -0
  89. package/dist/resources/extensions/gsd/tools/exec-search-tool.js +5 -0
  90. package/dist/resources/extensions/gsd/tools/exec-tool.js +3 -15
  91. package/dist/resources/extensions/gsd/tools/memory-tools.js +1 -0
  92. package/dist/resources/extensions/gsd/tools/plan-slice.js +9 -0
  93. package/dist/resources/extensions/gsd/tools/plan-task.js +9 -0
  94. package/dist/resources/extensions/gsd/tools/resume-tool.js +5 -0
  95. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +1 -1
  96. package/dist/resources/extensions/gsd/unit-context-composer.js +12 -3
  97. package/dist/resources/extensions/gsd/unit-runtime.js +22 -0
  98. package/dist/resources/extensions/gsd/workflow-protocol.js +131 -0
  99. package/dist/resources/extensions/gsd/worktree-manager.js +16 -14
  100. package/dist/resources/extensions/gsd/worktree-resolver.js +90 -22
  101. package/dist/resources/skills/web-quality-audit/scripts/analyze.sh +0 -0
  102. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  103. package/dist/web/standalone/.next/BUILD_ID +1 -1
  104. package/dist/web/standalone/.next/app-path-routes-manifest.json +14 -14
  105. package/dist/web/standalone/.next/build-manifest.json +3 -3
  106. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  107. package/dist/web/standalone/.next/react-loadable-manifest.json +2 -2
  108. package/dist/web/standalone/.next/required-server-files.json +1 -1
  109. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  110. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  111. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  120. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  122. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/index.html +1 -1
  128. package/dist/web/standalone/.next/server/app/index.rsc +2 -2
  129. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  130. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
  131. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  132. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  133. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  134. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app-paths-manifest.json +14 -14
  136. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  138. package/dist/web/standalone/.next/server/middleware.js +3 -3
  139. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  140. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  141. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  142. package/dist/web/standalone/.next/static/chunks/8359.e059d86b255fce1c.js +10 -0
  143. package/dist/web/standalone/.next/static/chunks/app/{page-fab3ebb85b006001.js → page-752f1e2ebdaa3e45.js} +1 -1
  144. package/dist/web/standalone/.next/static/chunks/{webpack-0481f1221120a7c6.js → webpack-de742b64187e13fe.js} +1 -1
  145. package/dist/web/standalone/server.js +1 -1
  146. package/dist/welcome-screen.d.ts +2 -0
  147. package/dist/welcome-screen.js +9 -7
  148. package/package.json +3 -3
  149. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  150. package/packages/mcp-server/dist/workflow-tools.js +22 -17
  151. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  152. package/packages/mcp-server/src/workflow-tools.test.ts +75 -2
  153. package/packages/mcp-server/src/workflow-tools.ts +30 -16
  154. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  155. package/packages/native/tsconfig.tsbuildinfo +1 -1
  156. package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  157. package/packages/pi-agent-core/dist/agent-loop.js +4 -1
  158. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  159. package/packages/pi-agent-core/dist/agent.d.ts +5 -0
  160. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  161. package/packages/pi-agent-core/dist/agent.js +2 -0
  162. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  163. package/packages/pi-agent-core/dist/index.d.ts +1 -0
  164. package/packages/pi-agent-core/dist/index.d.ts.map +1 -1
  165. package/packages/pi-agent-core/dist/index.js +2 -0
  166. package/packages/pi-agent-core/dist/index.js.map +1 -1
  167. package/packages/pi-agent-core/dist/token-audit.d.ts +47 -0
  168. package/packages/pi-agent-core/dist/token-audit.d.ts.map +1 -0
  169. package/packages/pi-agent-core/dist/token-audit.js +221 -0
  170. package/packages/pi-agent-core/dist/token-audit.js.map +1 -0
  171. package/packages/pi-agent-core/dist/types.d.ts +9 -0
  172. package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
  173. package/packages/pi-agent-core/dist/types.js.map +1 -1
  174. package/packages/pi-agent-core/src/agent-loop.test.ts +128 -0
  175. package/packages/pi-agent-core/src/agent-loop.ts +4 -1
  176. package/packages/pi-agent-core/src/agent.ts +8 -0
  177. package/packages/pi-agent-core/src/index.ts +2 -0
  178. package/packages/pi-agent-core/src/token-audit.test.ts +189 -0
  179. package/packages/pi-agent-core/src/token-audit.ts +287 -0
  180. package/packages/pi-agent-core/src/types.ts +14 -0
  181. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  182. package/packages/pi-ai/dist/providers/anthropic-auth.test.js +35 -13
  183. package/packages/pi-ai/dist/providers/anthropic-auth.test.js.map +1 -1
  184. package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.js +21 -11
  185. package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.js.map +1 -1
  186. package/packages/pi-ai/dist/providers/anthropic.d.ts +7 -0
  187. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  188. package/packages/pi-ai/dist/providers/anthropic.js +9 -7
  189. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  190. package/packages/pi-ai/dist/providers/minimax-tool-name.test.js +23 -14
  191. package/packages/pi-ai/dist/providers/minimax-tool-name.test.js.map +1 -1
  192. package/packages/pi-ai/dist/types.d.ts +2 -0
  193. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  194. package/packages/pi-ai/dist/types.js.map +1 -1
  195. package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js +48 -21
  196. package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js.map +1 -1
  197. package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.js +22 -21
  198. package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.js.map +1 -1
  199. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.js +22 -21
  200. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.js.map +1 -1
  201. package/packages/pi-ai/src/providers/anthropic-auth.test.ts +39 -25
  202. package/packages/pi-ai/src/providers/anthropic-bearer-auth.test.ts +26 -22
  203. package/packages/pi-ai/src/providers/anthropic.ts +22 -9
  204. package/packages/pi-ai/src/providers/minimax-tool-name.test.ts +34 -21
  205. package/packages/pi-ai/src/types.ts +3 -0
  206. package/packages/pi-ai/src/utils/oauth/github-copilot.test.ts +56 -22
  207. package/packages/pi-ai/src/utils/oauth/google-antigravity.test.ts +24 -28
  208. package/packages/pi-ai/src/utils/oauth/google-gemini-cli.test.ts +24 -28
  209. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  210. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +32 -0
  211. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
  212. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +30 -1
  213. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -1
  214. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +17 -0
  215. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  216. package/packages/pi-coding-agent/dist/core/agent-session.js +52 -7
  217. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  218. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +6 -2
  219. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
  220. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +11 -0
  221. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  222. package/packages/pi-coding-agent/dist/core/compaction/compaction.js +9 -0
  223. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  224. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.d.ts +2 -0
  225. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.d.ts.map +1 -0
  226. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.js +103 -0
  227. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.js.map +1 -0
  228. package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts +15 -0
  229. package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts.map +1 -0
  230. package/packages/pi-coding-agent/dist/core/db-snapshot.js +66 -0
  231. package/packages/pi-coding-agent/dist/core/db-snapshot.js.map +1 -0
  232. package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts +2 -0
  233. package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts.map +1 -0
  234. package/packages/pi-coding-agent/dist/core/db-snapshot.test.js +24 -0
  235. package/packages/pi-coding-agent/dist/core/db-snapshot.test.js.map +1 -0
  236. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  237. package/packages/pi-coding-agent/dist/core/extensions/loader.js +8 -0
  238. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  239. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +3 -0
  240. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  241. package/packages/pi-coding-agent/dist/core/extensions/runner.js +6 -6
  242. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  243. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +5 -3
  244. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
  245. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +41 -3
  246. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  247. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  248. package/packages/pi-coding-agent/dist/core/hooks-runner.test.js +2 -0
  249. package/packages/pi-coding-agent/dist/core/hooks-runner.test.js.map +1 -1
  250. package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.d.ts +2 -0
  251. package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.d.ts.map +1 -0
  252. package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.js +46 -0
  253. package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.js.map +1 -0
  254. package/packages/pi-coding-agent/dist/core/sdk.d.ts +10 -2
  255. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  256. package/packages/pi-coding-agent/dist/core/sdk.js +81 -4
  257. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  258. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +20 -0
  259. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  260. package/packages/pi-coding-agent/dist/core/settings-manager.js +25 -0
  261. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  262. package/packages/pi-coding-agent/dist/core/skill-tool.test.js +22 -0
  263. package/packages/pi-coding-agent/dist/core/skill-tool.test.js.map +1 -1
  264. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +6 -7
  265. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  266. package/packages/pi-coding-agent/dist/core/system-prompt.js +2 -3
  267. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  268. package/packages/pi-coding-agent/dist/core/tools/bash-spawn-windows.test.js +22 -56
  269. package/packages/pi-coding-agent/dist/core/tools/bash-spawn-windows.test.js.map +1 -1
  270. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts +1 -0
  271. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
  272. package/packages/pi-coding-agent/dist/core/tools/bash.js +3 -1
  273. package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
  274. package/packages/pi-coding-agent/dist/core/tools/edit.d.ts +2 -0
  275. package/packages/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
  276. package/packages/pi-coding-agent/dist/core/tools/edit.js +12 -1
  277. package/packages/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
  278. package/packages/pi-coding-agent/dist/core/tools/find.d.ts +2 -0
  279. package/packages/pi-coding-agent/dist/core/tools/find.d.ts.map +1 -1
  280. package/packages/pi-coding-agent/dist/core/tools/find.js +14 -6
  281. package/packages/pi-coding-agent/dist/core/tools/find.js.map +1 -1
  282. package/packages/pi-coding-agent/dist/core/tools/grep.d.ts +2 -0
  283. package/packages/pi-coding-agent/dist/core/tools/grep.d.ts.map +1 -1
  284. package/packages/pi-coding-agent/dist/core/tools/grep.js +12 -3
  285. package/packages/pi-coding-agent/dist/core/tools/grep.js.map +1 -1
  286. package/packages/pi-coding-agent/dist/core/tools/hashline-read.d.ts +2 -0
  287. package/packages/pi-coding-agent/dist/core/tools/hashline-read.d.ts.map +1 -1
  288. package/packages/pi-coding-agent/dist/core/tools/hashline-read.js +3 -1
  289. package/packages/pi-coding-agent/dist/core/tools/hashline-read.js.map +1 -1
  290. package/packages/pi-coding-agent/dist/core/tools/index.d.ts +2 -1
  291. package/packages/pi-coding-agent/dist/core/tools/index.d.ts.map +1 -1
  292. package/packages/pi-coding-agent/dist/core/tools/index.js +1 -0
  293. package/packages/pi-coding-agent/dist/core/tools/index.js.map +1 -1
  294. package/packages/pi-coding-agent/dist/core/tools/ls.d.ts +2 -0
  295. package/packages/pi-coding-agent/dist/core/tools/ls.d.ts.map +1 -1
  296. package/packages/pi-coding-agent/dist/core/tools/ls.js +10 -3
  297. package/packages/pi-coding-agent/dist/core/tools/ls.js.map +1 -1
  298. package/packages/pi-coding-agent/dist/core/tools/read.d.ts +2 -0
  299. package/packages/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
  300. package/packages/pi-coding-agent/dist/core/tools/read.js +3 -1
  301. package/packages/pi-coding-agent/dist/core/tools/read.js.map +1 -1
  302. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js +7 -62
  303. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js.map +1 -1
  304. package/packages/pi-coding-agent/dist/core/tools/tool-target-metadata.test.d.ts +2 -0
  305. package/packages/pi-coding-agent/dist/core/tools/tool-target-metadata.test.d.ts.map +1 -0
  306. package/packages/pi-coding-agent/dist/core/tools/tool-target-metadata.test.js +115 -0
  307. package/packages/pi-coding-agent/dist/core/tools/tool-target-metadata.test.js.map +1 -0
  308. package/packages/pi-coding-agent/dist/core/tools/tool-target.d.ts +19 -0
  309. package/packages/pi-coding-agent/dist/core/tools/tool-target.d.ts.map +1 -0
  310. package/packages/pi-coding-agent/dist/core/tools/tool-target.js +20 -0
  311. package/packages/pi-coding-agent/dist/core/tools/tool-target.js.map +1 -0
  312. package/packages/pi-coding-agent/dist/core/tools/write.d.ts +4 -0
  313. package/packages/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
  314. package/packages/pi-coding-agent/dist/core/tools/write.js +9 -1
  315. package/packages/pi-coding-agent/dist/core/tools/write.js.map +1 -1
  316. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +89 -2
  317. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  318. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +25 -1
  319. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -1
  320. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +6 -0
  321. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  322. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +155 -7
  323. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  324. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  325. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +31 -6
  326. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  327. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js +71 -0
  328. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js.map +1 -1
  329. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +2 -0
  330. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  331. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +22 -0
  332. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  333. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts +2 -0
  334. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts.map +1 -0
  335. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js +28 -0
  336. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js.map +1 -0
  337. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.d.ts.map +1 -1
  338. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js +3 -2
  339. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js.map +1 -1
  340. package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +36 -0
  341. package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +40 -1
  342. package/packages/pi-coding-agent/src/core/agent-session.ts +59 -7
  343. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +6 -2
  344. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +18 -0
  345. package/packages/pi-coding-agent/src/core/compaction-threshold.test.ts +121 -0
  346. package/packages/pi-coding-agent/src/core/db-snapshot.test.ts +32 -0
  347. package/packages/pi-coding-agent/src/core/db-snapshot.ts +66 -0
  348. package/packages/pi-coding-agent/src/core/extensions/loader.ts +10 -0
  349. package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +5 -3
  350. package/packages/pi-coding-agent/src/core/extensions/runner.ts +8 -5
  351. package/packages/pi-coding-agent/src/core/extensions/types.ts +44 -2
  352. package/packages/pi-coding-agent/src/core/hooks-runner.test.ts +2 -0
  353. package/packages/pi-coding-agent/src/core/sdk-tool-filter.test.ts +60 -0
  354. package/packages/pi-coding-agent/src/core/sdk.ts +92 -4
  355. package/packages/pi-coding-agent/src/core/settings-manager.ts +39 -1
  356. package/packages/pi-coding-agent/src/core/skill-tool.test.ts +28 -0
  357. package/packages/pi-coding-agent/src/core/system-prompt.ts +8 -10
  358. package/packages/pi-coding-agent/src/core/tools/bash-spawn-windows.test.ts +22 -66
  359. package/packages/pi-coding-agent/src/core/tools/bash.ts +4 -1
  360. package/packages/pi-coding-agent/src/core/tools/edit.ts +13 -1
  361. package/packages/pi-coding-agent/src/core/tools/find.ts +15 -6
  362. package/packages/pi-coding-agent/src/core/tools/grep.ts +13 -3
  363. package/packages/pi-coding-agent/src/core/tools/hashline-read.ts +4 -1
  364. package/packages/pi-coding-agent/src/core/tools/index.ts +8 -0
  365. package/packages/pi-coding-agent/src/core/tools/ls.ts +11 -3
  366. package/packages/pi-coding-agent/src/core/tools/read.ts +4 -1
  367. package/packages/pi-coding-agent/src/core/tools/spawn-shell-windows.test.ts +11 -72
  368. package/packages/pi-coding-agent/src/core/tools/tool-target-metadata.test.ts +127 -0
  369. package/packages/pi-coding-agent/src/core/tools/tool-target.ts +48 -0
  370. package/packages/pi-coding-agent/src/core/tools/write.ts +14 -2
  371. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +119 -2
  372. package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +31 -1
  373. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +180 -7
  374. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.test.ts +75 -0
  375. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +39 -8
  376. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +24 -0
  377. package/packages/pi-coding-agent/src/resources/extensions/memory/storage-safety-guard.test.ts +31 -0
  378. package/packages/pi-coding-agent/src/resources/extensions/memory/storage.ts +3 -2
  379. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  380. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  381. package/packages/pi-tui/dist/tui.js +18 -8
  382. package/packages/pi-tui/dist/tui.js.map +1 -1
  383. package/packages/pi-tui/src/tui.ts +20 -8
  384. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  385. package/src/resources/GSD-WORKFLOW.md +2 -2
  386. package/src/resources/extensions/claude-code-cli/readiness.ts +25 -7
  387. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +42 -3
  388. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +67 -0
  389. package/src/resources/extensions/github-sync/sync.ts +8 -1
  390. package/src/resources/extensions/github-sync/tests/sync-source.test.ts +6 -18
  391. package/src/resources/extensions/gsd/auto/loop-deps.ts +3 -2
  392. package/src/resources/extensions/gsd/auto/loop.ts +134 -16
  393. package/src/resources/extensions/gsd/auto/phases.ts +328 -200
  394. package/src/resources/extensions/gsd/auto/resolve.ts +42 -1
  395. package/src/resources/extensions/gsd/auto/run-unit.ts +28 -30
  396. package/src/resources/extensions/gsd/auto/session.ts +8 -0
  397. package/src/resources/extensions/gsd/auto/workflow-dispatch-claim.ts +63 -1
  398. package/src/resources/extensions/gsd/auto/workflow-worker-heartbeat.ts +14 -1
  399. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +8 -34
  400. package/src/resources/extensions/gsd/auto-dispatch.ts +16 -0
  401. package/src/resources/extensions/gsd/auto-post-unit.ts +117 -88
  402. package/src/resources/extensions/gsd/auto-prompts.ts +228 -16
  403. package/src/resources/extensions/gsd/auto-recovery.ts +54 -0
  404. package/src/resources/extensions/gsd/auto-start.ts +286 -15
  405. package/src/resources/extensions/gsd/auto-supervisor.ts +7 -0
  406. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +2 -2
  407. package/src/resources/extensions/gsd/auto-worktree.ts +241 -72
  408. package/src/resources/extensions/gsd/auto.ts +208 -39
  409. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +120 -8
  410. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +45 -37
  411. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +36 -10
  412. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +32 -19
  413. package/src/resources/extensions/gsd/bootstrap/journal-tools.ts +5 -1
  414. package/src/resources/extensions/gsd/bootstrap/memory-tools.ts +7 -4
  415. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +6 -3
  416. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +1 -1
  417. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +369 -54
  418. package/src/resources/extensions/gsd/bootstrap/sanitize-complete-milestone.ts +4 -0
  419. package/src/resources/extensions/gsd/bootstrap/system-context.ts +90 -22
  420. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +19 -2
  421. package/src/resources/extensions/gsd/clean-root-preflight.ts +72 -9
  422. package/src/resources/extensions/gsd/commands/dispatcher.ts +6 -0
  423. package/src/resources/extensions/gsd/commands/handlers/ops.ts +4 -2
  424. package/src/resources/extensions/gsd/commands-config.ts +1 -1
  425. package/src/resources/extensions/gsd/commands-eval-review.ts +2 -2
  426. package/src/resources/extensions/gsd/commands-handlers.ts +34 -15
  427. package/src/resources/extensions/gsd/context-budget.ts +44 -2
  428. package/src/resources/extensions/gsd/crash-recovery.ts +67 -10
  429. package/src/resources/extensions/gsd/dashboard-overlay.ts +1 -1
  430. package/src/resources/extensions/gsd/db/unit-dispatches.ts +107 -0
  431. package/src/resources/extensions/gsd/db-base-schema.ts +4 -2
  432. package/src/resources/extensions/gsd/db-migration-steps.ts +8 -0
  433. package/src/resources/extensions/gsd/detection.ts +128 -0
  434. package/src/resources/extensions/gsd/ecosystem/gsd-extension-api.ts +3 -0
  435. package/src/resources/extensions/gsd/git-service.ts +87 -10
  436. package/src/resources/extensions/gsd/gsd-db.ts +50 -13
  437. package/src/resources/extensions/gsd/guided-flow.ts +167 -53
  438. package/src/resources/extensions/gsd/init-wizard.ts +5 -1
  439. package/src/resources/extensions/gsd/memory-store.ts +77 -12
  440. package/src/resources/extensions/gsd/migrate/command.ts +47 -1
  441. package/src/resources/extensions/gsd/migration-auto-check.ts +129 -0
  442. package/src/resources/extensions/gsd/native-git-bridge.ts +39 -6
  443. package/src/resources/extensions/gsd/orphan-stash-audit.ts +117 -0
  444. package/src/resources/extensions/gsd/parallel-orchestrator.ts +13 -3
  445. package/src/resources/extensions/gsd/planning-path-scope.ts +35 -0
  446. package/src/resources/extensions/gsd/pre-execution-checks.ts +23 -0
  447. package/src/resources/extensions/gsd/preferences-types.ts +1 -1
  448. package/src/resources/extensions/gsd/prompt-loader.ts +27 -2
  449. package/src/resources/extensions/gsd/prompts/complete-milestone.md +27 -23
  450. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  451. package/src/resources/extensions/gsd/prompts/execute-task.md +4 -2
  452. package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +1 -1
  453. package/src/resources/extensions/gsd/prompts/plan-milestone.md +3 -1
  454. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  455. package/src/resources/extensions/gsd/prompts/quick-task.md +1 -5
  456. package/src/resources/extensions/gsd/prompts/replan-slice.md +2 -2
  457. package/src/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
  458. package/src/resources/extensions/gsd/quick.ts +37 -2
  459. package/src/resources/extensions/gsd/safety/evidence-collector.ts +11 -2
  460. package/src/resources/extensions/gsd/slice-cadence.ts +49 -2
  461. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +23 -9
  462. package/src/resources/extensions/gsd/tests/agent-end-retry.test.ts +59 -89
  463. package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +47 -172
  464. package/src/resources/extensions/gsd/tests/artifacts-table-preserved-on-cache-invalidate.test.ts +0 -35
  465. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +35 -9
  466. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +433 -11
  467. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +80 -59
  468. package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +3 -47
  469. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +76 -18
  470. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +160 -11
  471. package/src/resources/extensions/gsd/tests/auto-pr-bugs.test.ts +54 -95
  472. package/src/resources/extensions/gsd/tests/auto-project-root-env.test.ts +67 -26
  473. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +14 -1
  474. package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +32 -30
  475. package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +32 -128
  476. package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +20 -54
  477. package/src/resources/extensions/gsd/tests/auto-start-cold-db-bootstrap.test.ts +20 -30
  478. package/src/resources/extensions/gsd/tests/auto-start-index-lock.test.ts +17 -29
  479. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +138 -0
  480. package/src/resources/extensions/gsd/tests/auto-start-time-persistence.test.ts +21 -39
  481. package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +15 -24
  482. package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +44 -29
  483. package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +39 -51
  484. package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +159 -213
  485. package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +15 -32
  486. package/src/resources/extensions/gsd/tests/browser-teardown.test.ts +0 -41
  487. package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +97 -2
  488. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +34 -27
  489. package/src/resources/extensions/gsd/tests/cmux.test.ts +51 -53
  490. package/src/resources/extensions/gsd/tests/cold-resume-db-reopen.test.ts +39 -61
  491. package/src/resources/extensions/gsd/tests/commands-config.test.ts +26 -19
  492. package/src/resources/extensions/gsd/tests/compaction-snapshot.test.ts +14 -1
  493. package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +31 -0
  494. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +140 -0
  495. package/src/resources/extensions/gsd/tests/complete-slice-composer.test.ts +3 -2
  496. package/src/resources/extensions/gsd/tests/complete-task-normalize-lists.test.ts +29 -33
  497. package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +45 -108
  498. package/src/resources/extensions/gsd/tests/context-budget.test.ts +10 -1
  499. package/src/resources/extensions/gsd/tests/context-store.test.ts +7 -1
  500. package/src/resources/extensions/gsd/tests/crash-handler-secondary.test.ts +90 -31
  501. package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +22 -0
  502. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +5 -1
  503. package/src/resources/extensions/gsd/tests/cwd-fallback-hardening.test.ts +138 -0
  504. package/src/resources/extensions/gsd/tests/dashboard-custom-engine.test.ts +4 -68
  505. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +4 -9
  506. package/src/resources/extensions/gsd/tests/deferred-milestone-dir-4996.test.ts +14 -65
  507. package/src/resources/extensions/gsd/tests/detection.test.ts +140 -0
  508. package/src/resources/extensions/gsd/tests/discuss-tool-scoping.test.ts +44 -37
  509. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +58 -40
  510. package/src/resources/extensions/gsd/tests/dispatch-guard-closed-status.test.ts +25 -15
  511. package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +313 -0
  512. package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +35 -17
  513. package/src/resources/extensions/gsd/tests/error-success-mask.test.ts +16 -21
  514. package/src/resources/extensions/gsd/tests/est-annotation-timeout.test.ts +15 -82
  515. package/src/resources/extensions/gsd/tests/exec-history.test.ts +15 -0
  516. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +65 -0
  517. package/src/resources/extensions/gsd/tests/execute-task-rendering.test.ts +5 -2
  518. package/src/resources/extensions/gsd/tests/fast-forward-reused-milestone-branch.test.ts +219 -0
  519. package/src/resources/extensions/gsd/tests/finalize-survivor-branch.test.ts +132 -0
  520. package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +2 -20
  521. package/src/resources/extensions/gsd/tests/frontmatter-parse-noise.test.ts +18 -26
  522. package/src/resources/extensions/gsd/tests/init-skip-git.test.ts +9 -12
  523. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +40 -0
  524. package/src/resources/extensions/gsd/tests/integration/commands-eval-review.integration.test.ts +4 -2
  525. package/src/resources/extensions/gsd/tests/integration/git-locale.test.ts +31 -20
  526. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +66 -0
  527. package/src/resources/extensions/gsd/tests/integration/milestone-transition-worktree.test.ts +0 -47
  528. package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +60 -202
  529. package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +13 -56
  530. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +239 -1
  531. package/src/resources/extensions/gsd/tests/journal-query-tool.test.ts +32 -0
  532. package/src/resources/extensions/gsd/tests/knowledge.test.ts +47 -0
  533. package/src/resources/extensions/gsd/tests/lazy-pi-tui-import.test.ts +44 -6
  534. package/src/resources/extensions/gsd/tests/memory-decay-factor.test.ts +90 -0
  535. package/src/resources/extensions/gsd/tests/memory-pressure-stuck-state.test.ts +21 -35
  536. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +1 -0
  537. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +48 -0
  538. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +127 -0
  539. package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +242 -0
  540. package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +79 -98
  541. package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +70 -278
  542. package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +34 -2
  543. package/src/resources/extensions/gsd/tests/needs-remediation-revalidation.test.ts +37 -30
  544. package/src/resources/extensions/gsd/tests/note-captures-executed.test.ts +32 -28
  545. package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +3 -0
  546. package/src/resources/extensions/gsd/tests/orphan-merge-bootstrap.test.ts +133 -0
  547. package/src/resources/extensions/gsd/tests/orphan-stash-audit.test.ts +201 -0
  548. package/src/resources/extensions/gsd/tests/parallel-orchestrator-fast-forward.test.ts +113 -0
  549. package/src/resources/extensions/gsd/tests/phantom-ghost-detection.test.ts +24 -37
  550. package/src/resources/extensions/gsd/tests/phantom-milestone-default-queued.test.ts +9 -24
  551. package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +91 -75
  552. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +50 -0
  553. package/src/resources/extensions/gsd/tests/plan-task.test.ts +21 -0
  554. package/src/resources/extensions/gsd/tests/post-unit-state-rebuild.test.ts +36 -22
  555. package/src/resources/extensions/gsd/tests/pre-exec-backtick-strip.test.ts +36 -30
  556. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +45 -5
  557. package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +74 -4
  558. package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +20 -22
  559. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +130 -32
  560. package/src/resources/extensions/gsd/tests/project-root-cwd-crash.test.ts +18 -36
  561. package/src/resources/extensions/gsd/tests/projection-no-plan-overwrite.test.ts +35 -73
  562. package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +76 -138
  563. package/src/resources/extensions/gsd/tests/prompt-duplication-cuts.test.ts +230 -0
  564. package/src/resources/extensions/gsd/tests/prompt-path-audit.test.ts +40 -0
  565. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +70 -106
  566. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +59 -161
  567. package/src/resources/extensions/gsd/tests/query-tools-db-open.test.ts +33 -29
  568. package/src/resources/extensions/gsd/tests/queue-auto-guard.test.ts +22 -196
  569. package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +23 -93
  570. package/src/resources/extensions/gsd/tests/quick-external-gsd.test.ts +40 -0
  571. package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +50 -79
  572. package/src/resources/extensions/gsd/tests/reassess-default-optin.test.ts +27 -13
  573. package/src/resources/extensions/gsd/tests/remote-questions.test.ts +151 -251
  574. package/src/resources/extensions/gsd/tests/resource-loader-import-path.test.ts +41 -29
  575. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +58 -69
  576. package/src/resources/extensions/gsd/tests/resume-dispatch-worktree.test.ts +32 -164
  577. package/src/resources/extensions/gsd/tests/right-sized-workflow-prompts.test.ts +192 -0
  578. package/src/resources/extensions/gsd/tests/run-uat-replay-cap.test.ts +57 -41
  579. package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +29 -0
  580. package/src/resources/extensions/gsd/tests/schema-v27-v28-sequence.test.ts +156 -0
  581. package/src/resources/extensions/gsd/tests/select-resumable-milestone.test.ts +96 -0
  582. package/src/resources/extensions/gsd/tests/session-model-override.test.ts +14 -9
  583. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +77 -0
  584. package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +166 -0
  585. package/src/resources/extensions/gsd/tests/show-config-command.test.ts +44 -42
  586. package/src/resources/extensions/gsd/tests/signal-handlers.test.ts +27 -0
  587. package/src/resources/extensions/gsd/tests/skip-slice-state-rebuild.test.ts +56 -24
  588. package/src/resources/extensions/gsd/tests/skipped-validation-db-atomicity.test.ts +51 -11
  589. package/src/resources/extensions/gsd/tests/slice-cadence.test.ts +23 -0
  590. package/src/resources/extensions/gsd/tests/slice-context-injection.test.ts +66 -50
  591. package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +68 -107
  592. package/src/resources/extensions/gsd/tests/slice-sequence-insert.test.ts +115 -42
  593. package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +21 -59
  594. package/src/resources/extensions/gsd/tests/smart-entry-draft.test.ts +25 -116
  595. package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +21 -57
  596. package/src/resources/extensions/gsd/tests/stale-dirlistcache-4648.test.ts +29 -76
  597. package/src/resources/extensions/gsd/tests/stale-lockfile-recovery.test.ts +33 -24
  598. package/src/resources/extensions/gsd/tests/stale-slice-rows.test.ts +39 -30
  599. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +49 -1
  600. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +55 -0
  601. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +1 -0
  602. package/src/resources/extensions/gsd/tests/status-db-open.test.ts +35 -40
  603. package/src/resources/extensions/gsd/tests/stop-auto-merge-back.test.ts +48 -46
  604. package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +14 -102
  605. package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +78 -232
  606. package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +32 -35
  607. package/src/resources/extensions/gsd/tests/system-context-memory.test.ts +112 -0
  608. package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +7 -9
  609. package/src/resources/extensions/gsd/tests/token-profile.test.ts +84 -309
  610. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +291 -0
  611. package/src/resources/extensions/gsd/tests/triage-dispatch.test.ts +134 -341
  612. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +136 -4
  613. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +8 -25
  614. package/src/resources/extensions/gsd/tests/unit-dispatches.test.ts +80 -1
  615. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +37 -0
  616. package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +5 -99
  617. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +43 -36
  618. package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +84 -444
  619. package/src/resources/extensions/gsd/tests/workflow-dispatch-claim.test.ts +142 -0
  620. package/src/resources/extensions/gsd/tests/workflow-logger-wiring.test.ts +44 -189
  621. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -57
  622. package/src/resources/extensions/gsd/tests/workflow-protocol-excerpt.test.ts +99 -0
  623. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +3 -0
  624. package/src/resources/extensions/gsd/tests/workflow-worker-heartbeat.test.ts +32 -1
  625. package/src/resources/extensions/gsd/tests/worktree-db-same-file.test.ts +21 -44
  626. package/src/resources/extensions/gsd/tests/worktree-expected-warnings.test.ts +27 -26
  627. package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +38 -6
  628. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +1 -0
  629. package/src/resources/extensions/gsd/tests/worktree-main-branch.test.ts +20 -18
  630. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +7 -0
  631. package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +9 -2
  632. package/src/resources/extensions/gsd/tests/worktree-path-injection.test.ts +22 -19
  633. package/src/resources/extensions/gsd/tests/worktree-project-root-degrade.test.ts +66 -0
  634. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +203 -4
  635. package/src/resources/extensions/gsd/tests/write-gate.test.ts +40 -1
  636. package/src/resources/extensions/gsd/tests/zero-slice-roadmap-guided.test.ts +19 -13
  637. package/src/resources/extensions/gsd/tools/complete-milestone.ts +14 -15
  638. package/src/resources/extensions/gsd/tools/complete-task.ts +1 -1
  639. package/src/resources/extensions/gsd/tools/context-mode-tool-result.ts +25 -0
  640. package/src/resources/extensions/gsd/tools/exec-search-tool.ts +7 -7
  641. package/src/resources/extensions/gsd/tools/exec-tool.ts +4 -23
  642. package/src/resources/extensions/gsd/tools/memory-tools.ts +1 -0
  643. package/src/resources/extensions/gsd/tools/plan-slice.ts +13 -0
  644. package/src/resources/extensions/gsd/tools/plan-task.ts +10 -0
  645. package/src/resources/extensions/gsd/tools/resume-tool.ts +7 -7
  646. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +1 -1
  647. package/src/resources/extensions/gsd/unit-context-composer.ts +19 -4
  648. package/src/resources/extensions/gsd/unit-runtime.ts +25 -0
  649. package/src/resources/extensions/gsd/workflow-protocol.ts +160 -0
  650. package/src/resources/extensions/gsd/worktree-manager.ts +15 -4
  651. package/src/resources/extensions/gsd/worktree-resolver.ts +119 -20
  652. package/src/resources/skills/create-gsd-extension/templates/templates.test.ts +86 -40
  653. package/src/resources/skills/web-quality-audit/scripts/analyze.sh +0 -0
  654. package/dist/web/standalone/.next/static/chunks/8336.631939fb583761fa.js +0 -10
  655. /package/dist/web/standalone/.next/static/{vIAZSyxIuvqNkCvXt9oqb → Y9yOOsO4ZA5BPTOS8ixvP}/_buildManifest.js +0 -0
  656. /package/dist/web/standalone/.next/static/{vIAZSyxIuvqNkCvXt9oqb → Y9yOOsO4ZA5BPTOS8ixvP}/_ssgManifest.js +0 -0
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=storage-safety-guard.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage-safety-guard.test.d.ts","sourceRoot":"","sources":["../../../../src/resources/extensions/memory/storage-safety-guard.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,28 @@
1
+ import assert from "node:assert/strict";
2
+ import { lstatSync, mkdtempSync, readFileSync, rmSync, symlinkSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import test from "node:test";
6
+ import { MemoryStorage } from "./storage.js";
7
+ test("MemoryStorage replaces a symlinked DB path instead of overwriting the symlink target", async (t) => {
8
+ const dir = mkdtempSync(join(tmpdir(), "memory-storage-atomic-"));
9
+ t.after(() => rmSync(dir, { recursive: true, force: true }));
10
+ const canaryPath = join(dir, "canary.txt");
11
+ const dbPath = join(dir, "memory.db");
12
+ const canaryStorage = await MemoryStorage.create(canaryPath);
13
+ canaryStorage.close();
14
+ const originalCanary = readFileSync(canaryPath);
15
+ symlinkSync(canaryPath, dbPath);
16
+ const storage = await MemoryStorage.create(dbPath);
17
+ storage.upsertThreads([{
18
+ threadId: "thread-1",
19
+ filePath: join(dir, "thread.jsonl"),
20
+ fileSize: 1,
21
+ fileMtime: 1,
22
+ cwd: dir,
23
+ }]);
24
+ storage.close();
25
+ assert.deepEqual(readFileSync(canaryPath), originalCanary);
26
+ assert.equal(lstatSync(dbPath).isSymbolicLink(), false, "atomic snapshot write should replace the symlink");
27
+ });
28
+ //# sourceMappingURL=storage-safety-guard.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage-safety-guard.test.js","sourceRoot":"","sources":["../../../../src/resources/extensions/memory/storage-safety-guard.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACpF,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,IAAI,CAAC,sFAAsF,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IACxG,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,wBAAwB,CAAC,CAAC,CAAC;IAClE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAE7D,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IACtC,MAAM,aAAa,GAAG,MAAM,aAAa,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC7D,aAAa,CAAC,KAAK,EAAE,CAAC;IACtB,MAAM,cAAc,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC;IAChD,WAAW,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAEhC,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACnD,OAAO,CAAC,aAAa,CAAC,CAAC;YACtB,QAAQ,EAAE,UAAU;YACpB,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC;YACnC,QAAQ,EAAE,CAAC;YACX,SAAS,EAAE,CAAC;YACZ,GAAG,EAAE,GAAG;SACR,CAAC,CAAC,CAAC;IACJ,OAAO,CAAC,KAAK,EAAE,CAAC;IAEhB,MAAM,CAAC,SAAS,CAAC,YAAY,CAAC,UAAU,CAAC,EAAE,cAAc,CAAC,CAAC;IAC3D,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,cAAc,EAAE,EAAE,KAAK,EAAE,kDAAkD,CAAC,CAAC;AAC7G,CAAC,CAAC,CAAC","sourcesContent":["import assert from \"node:assert/strict\";\nimport { lstatSync, mkdtempSync, readFileSync, rmSync, symlinkSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport test from \"node:test\";\nimport { MemoryStorage } from \"./storage.js\";\n\ntest(\"MemoryStorage replaces a symlinked DB path instead of overwriting the symlink target\", async (t) => {\n\tconst dir = mkdtempSync(join(tmpdir(), \"memory-storage-atomic-\"));\n\tt.after(() => rmSync(dir, { recursive: true, force: true }));\n\n\tconst canaryPath = join(dir, \"canary.txt\");\n\tconst dbPath = join(dir, \"memory.db\");\n\tconst canaryStorage = await MemoryStorage.create(canaryPath);\n\tcanaryStorage.close();\n\tconst originalCanary = readFileSync(canaryPath);\n\tsymlinkSync(canaryPath, dbPath);\n\n\tconst storage = await MemoryStorage.create(dbPath);\n\tstorage.upsertThreads([{\n\t\tthreadId: \"thread-1\",\n\t\tfilePath: join(dir, \"thread.jsonl\"),\n\t\tfileSize: 1,\n\t\tfileMtime: 1,\n\t\tcwd: dir,\n\t}]);\n\tstorage.close();\n\n\tassert.deepEqual(readFileSync(canaryPath), originalCanary);\n\tassert.equal(lstatSync(dbPath).isSymbolicLink(), false, \"atomic snapshot write should replace the symlink\");\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../../src/resources/extensions/memory/storage.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../../src/resources/extensions/memory/storage.ts"],"names":[],"mappings":"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"}
@@ -8,8 +8,9 @@
8
8
  */
9
9
  import initSqlJs from "sql.js";
10
10
  import { randomUUID } from "crypto";
11
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
11
+ import { existsSync, mkdirSync, readFileSync } from "fs";
12
12
  import { dirname } from "path";
13
+ import { atomicWriteDbSnapshotSync } from "../../../core/db-snapshot.js";
13
14
  export class MemoryStorage {
14
15
  constructor(db, dbPath) {
15
16
  this.persistTimer = null;
@@ -33,7 +34,7 @@ export class MemoryStorage {
33
34
  }
34
35
  persist() {
35
36
  const data = this.db.export();
36
- writeFileSync(this.dbPath, Buffer.from(data));
37
+ atomicWriteDbSnapshotSync(this.dbPath, data);
37
38
  }
38
39
  schedulePersist() {
39
40
  if (this.persistTimer) {
@@ -1 +1 @@
1
- {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../../src/resources/extensions/memory/storage.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * SQLite storage for the memory extraction pipeline.\n *\n * Tables:\n * - threads: tracks session files and their processing state\n * - stage1_outputs: stores per-thread extraction results\n * - jobs: lease-based job queue for pipeline phases\n */\n\nimport initSqlJs, { type Database as SqlJsDatabase } from \"sql.js\";\nimport { randomUUID } from \"crypto\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"fs\";\nimport { dirname } from \"path\";\n\nexport interface ThreadRow {\n\tthread_id: string;\n\tfile_path: string;\n\tfile_size: number;\n\tfile_mtime: number;\n\tcwd: string;\n\tstatus: \"pending\" | \"processing\" | \"done\" | \"error\";\n\terror_message: string | null;\n\tcreated_at: string;\n\tupdated_at: string;\n}\n\nexport interface Stage1OutputRow {\n\tthread_id: string;\n\textraction_json: string;\n\tcreated_at: string;\n}\n\nexport interface JobRow {\n\tid: string;\n\tphase: \"stage1\" | \"stage2\";\n\tthread_id: string | null;\n\tstatus: \"pending\" | \"claimed\" | \"done\" | \"error\";\n\tworker_id: string | null;\n\townership_token: string | null;\n\tlease_expires_at: string | null;\n\terror_message: string | null;\n\tcreated_at: string;\n\tupdated_at: string;\n}\n\nexport class MemoryStorage {\n\tprivate db: SqlJsDatabase;\n\tprivate dbPath: string;\n\tprivate persistTimer: ReturnType<typeof setTimeout> | null = null;\n\n\tprivate constructor(db: SqlJsDatabase, dbPath: string) {\n\t\tthis.db = db;\n\t\tthis.dbPath = dbPath;\n\t}\n\n\tstatic async create(dbPath: string): Promise<MemoryStorage> {\n\t\tconst dir = dirname(dbPath);\n\t\tif (!existsSync(dir)) {\n\t\t\tmkdirSync(dir, { recursive: true });\n\t\t}\n\n\t\tconst SQL = await initSqlJs();\n\t\tconst buffer = existsSync(dbPath) ? readFileSync(dbPath) : undefined;\n\t\tconst db = buffer ? new SQL.Database(buffer) : new SQL.Database();\n\n\t\tdb.run(\"PRAGMA journal_mode = WAL\");\n\t\tdb.run(\"PRAGMA synchronous = NORMAL\");\n\t\tdb.run(\"PRAGMA busy_timeout = 5000\");\n\n\t\tconst storage = new MemoryStorage(db, dbPath);\n\t\tstorage.initSchema();\n\t\treturn storage;\n\t}\n\n\tprivate persist(): void {\n\t\tconst data = this.db.export();\n\t\twriteFileSync(this.dbPath, Buffer.from(data));\n\t}\n\n\tprivate schedulePersist(): void {\n\t\tif (this.persistTimer) {\n\t\t\tclearTimeout(this.persistTimer);\n\t\t}\n\t\tthis.persistTimer = setTimeout(() => {\n\t\t\tthis.persistTimer = null;\n\t\t\tthis.persist();\n\t\t}, 500);\n\t}\n\n\tprivate initSchema(): void {\n\t\tthis.db.run(`\n\t\t\tCREATE TABLE IF NOT EXISTS threads (\n\t\t\t\tthread_id TEXT PRIMARY KEY,\n\t\t\t\tfile_path TEXT NOT NULL,\n\t\t\t\tfile_size INTEGER NOT NULL DEFAULT 0,\n\t\t\t\tfile_mtime INTEGER NOT NULL DEFAULT 0,\n\t\t\t\tcwd TEXT NOT NULL DEFAULT '',\n\t\t\t\tstatus TEXT NOT NULL DEFAULT 'pending',\n\t\t\t\terror_message TEXT,\n\t\t\t\tcreated_at TEXT NOT NULL DEFAULT (datetime('now')),\n\t\t\t\tupdated_at TEXT NOT NULL DEFAULT (datetime('now'))\n\t\t\t)\n\t\t`);\n\t\tthis.db.run(`\n\t\t\tCREATE TABLE IF NOT EXISTS stage1_outputs (\n\t\t\t\tthread_id TEXT PRIMARY KEY,\n\t\t\t\textraction_json TEXT NOT NULL,\n\t\t\t\tcreated_at TEXT NOT NULL DEFAULT (datetime('now')),\n\t\t\t\tFOREIGN KEY (thread_id) REFERENCES threads(thread_id) ON DELETE CASCADE\n\t\t\t)\n\t\t`);\n\t\tthis.db.run(`\n\t\t\tCREATE TABLE IF NOT EXISTS jobs (\n\t\t\t\tid TEXT PRIMARY KEY,\n\t\t\t\tphase TEXT NOT NULL,\n\t\t\t\tthread_id TEXT,\n\t\t\t\tstatus TEXT NOT NULL DEFAULT 'pending',\n\t\t\t\tworker_id TEXT,\n\t\t\t\townership_token TEXT,\n\t\t\t\tlease_expires_at TEXT,\n\t\t\t\terror_message TEXT,\n\t\t\t\tcreated_at TEXT NOT NULL DEFAULT (datetime('now')),\n\t\t\t\tupdated_at TEXT NOT NULL DEFAULT (datetime('now'))\n\t\t\t)\n\t\t`);\n\t\tthis.db.run(\"CREATE INDEX IF NOT EXISTS idx_jobs_phase_status ON jobs(phase, status)\");\n\t\tthis.db.run(\"CREATE INDEX IF NOT EXISTS idx_threads_status ON threads(status)\");\n\t\tthis.db.run(\"CREATE INDEX IF NOT EXISTS idx_threads_cwd ON threads(cwd)\");\n\t\tthis.persist();\n\t}\n\n\tprivate queryAll<T>(sql: string, params: unknown[] = []): T[] {\n\t\tconst stmt = this.db.prepare(sql);\n\t\tstmt.bind(params as (string | number | null | Uint8Array)[]);\n\t\tconst rows: T[] = [];\n\t\twhile (stmt.step()) {\n\t\t\trows.push(stmt.getAsObject() as T);\n\t\t}\n\t\tstmt.free();\n\t\treturn rows;\n\t}\n\n\tprivate queryOne<T>(sql: string, params: unknown[] = []): T | undefined {\n\t\tconst rows = this.queryAll<T>(sql, params);\n\t\treturn rows[0];\n\t}\n\n\t/**\n\t * Insert or update thread records. Skips threads whose file hasn't changed\n\t * (same size + mtime = watermark match).\n\t */\n\tupsertThreads(\n\t\tthreads: Array<{\n\t\t\tthreadId: string;\n\t\t\tfilePath: string;\n\t\t\tfileSize: number;\n\t\t\tfileMtime: number;\n\t\t\tcwd: string;\n\t\t}>,\n\t): { inserted: number; updated: number; skipped: number } {\n\t\tlet inserted = 0;\n\t\tlet updated = 0;\n\t\tlet skipped = 0;\n\n\t\tfor (const t of threads) {\n\t\t\tconst existing = this.queryOne<{ file_size: number; file_mtime: number; status: string }>(\n\t\t\t\t\"SELECT file_size, file_mtime, status FROM threads WHERE thread_id = ?\",\n\t\t\t\t[t.threadId],\n\t\t\t);\n\n\t\t\tif (!existing) {\n\t\t\t\tthis.db.run(\n\t\t\t\t\t\"INSERT INTO threads (thread_id, file_path, file_size, file_mtime, cwd, status) VALUES (?, ?, ?, ?, ?, 'pending')\",\n\t\t\t\t\t[t.threadId, t.filePath, t.fileSize, t.fileMtime, t.cwd],\n\t\t\t\t);\n\t\t\t\tthis.db.run(\n\t\t\t\t\t\"INSERT OR IGNORE INTO jobs (id, phase, thread_id, status) VALUES (?, 'stage1', ?, 'pending')\",\n\t\t\t\t\t[randomUUID(), t.threadId],\n\t\t\t\t);\n\t\t\t\tinserted++;\n\t\t\t} else if (existing.file_size !== t.fileSize || existing.file_mtime !== t.fileMtime) {\n\t\t\t\tthis.db.run(\n\t\t\t\t\t\"UPDATE threads SET file_path = ?, file_size = ?, file_mtime = ?, cwd = ?, status = 'pending', updated_at = datetime('now') WHERE thread_id = ?\",\n\t\t\t\t\t[t.filePath, t.fileSize, t.fileMtime, t.cwd, t.threadId],\n\t\t\t\t);\n\t\t\t\tif (existing.status === \"done\" || existing.status === \"error\") {\n\t\t\t\t\tthis.db.run(\n\t\t\t\t\t\t\"INSERT OR IGNORE INTO jobs (id, phase, thread_id, status) VALUES (?, 'stage1', ?, 'pending')\",\n\t\t\t\t\t\t[randomUUID(), t.threadId],\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tupdated++;\n\t\t\t} else {\n\t\t\t\tskipped++;\n\t\t\t}\n\t\t}\n\n\t\tthis.schedulePersist();\n\t\treturn { inserted, updated, skipped };\n\t}\n\n\t/**\n\t * Claim up to `limit` stage1 jobs for the given worker.\n\t * Uses lease-based ownership with an ownership_token UUID.\n\t */\n\tclaimStage1Jobs(\n\t\tworkerId: string,\n\t\tlimit: number,\n\t\tleaseSeconds: number,\n\t): Array<{ jobId: string; threadId: string; ownershipToken: string }> {\n\t\tconst token = randomUUID();\n\t\tconst expiresAt = new Date(Date.now() + leaseSeconds * 1000).toISOString();\n\n\t\tthis.db.run(\n\t\t\t`UPDATE jobs SET\n\t\t\t\tstatus = 'claimed',\n\t\t\t\tworker_id = ?,\n\t\t\t\townership_token = ?,\n\t\t\t\tlease_expires_at = ?,\n\t\t\t\tupdated_at = datetime('now')\n\t\t\tWHERE id IN (\n\t\t\t\tSELECT id FROM jobs\n\t\t\t\tWHERE phase = 'stage1'\n\t\t\t\t\tAND (status = 'pending' OR (status = 'claimed' AND lease_expires_at < datetime('now')))\n\t\t\t\tLIMIT ?\n\t\t\t)`,\n\t\t\t[workerId, token, expiresAt, limit],\n\t\t);\n\n\t\tconst rows = this.queryAll<{ id: string; thread_id: string }>(\n\t\t\t\"SELECT id, thread_id FROM jobs WHERE ownership_token = ? AND status = 'claimed'\",\n\t\t\t[token],\n\t\t);\n\n\t\tthis.schedulePersist();\n\n\t\treturn rows.map((r) => ({\n\t\t\tjobId: r.id,\n\t\t\tthreadId: r.thread_id,\n\t\t\townershipToken: token,\n\t\t}));\n\t}\n\n\t/**\n\t * Mark a stage1 job as complete and store the extraction output.\n\t */\n\tcompleteStage1Job(threadId: string, output: string): void {\n\t\tthis.db.run(\n\t\t\t\"UPDATE jobs SET status = 'done', updated_at = datetime('now') WHERE thread_id = ? AND phase = 'stage1' AND status = 'claimed'\",\n\t\t\t[threadId],\n\t\t);\n\t\tthis.db.run(\n\t\t\t\"INSERT OR REPLACE INTO stage1_outputs (thread_id, extraction_json, created_at) VALUES (?, ?, datetime('now'))\",\n\t\t\t[threadId, output],\n\t\t);\n\t\tthis.db.run(\n\t\t\t\"UPDATE threads SET status = 'done', updated_at = datetime('now') WHERE thread_id = ?\",\n\t\t\t[threadId],\n\t\t);\n\t\tthis.schedulePersist();\n\t}\n\n\t/**\n\t * Mark a stage1 job as errored.\n\t */\n\tfailStage1Job(threadId: string, errorMessage: string): void {\n\t\tthis.db.run(\n\t\t\t\"UPDATE jobs SET status = 'error', error_message = ?, updated_at = datetime('now') WHERE thread_id = ? AND phase = 'stage1' AND status = 'claimed'\",\n\t\t\t[errorMessage, threadId],\n\t\t);\n\t\tthis.db.run(\n\t\t\t\"UPDATE threads SET status = 'error', error_message = ?, updated_at = datetime('now') WHERE thread_id = ?\",\n\t\t\t[errorMessage, threadId],\n\t\t);\n\t\tthis.schedulePersist();\n\t}\n\n\t/**\n\t * Try to claim the global phase 2 consolidation job.\n\t * Only one worker can hold this at a time.\n\t */\n\ttryClaimGlobalPhase2Job(\n\t\tworkerId: string,\n\t\tleaseSeconds: number,\n\t): { jobId: string; ownershipToken: string } | null {\n\t\tconst token = randomUUID();\n\t\tconst expiresAt = new Date(Date.now() + leaseSeconds * 1000).toISOString();\n\n\t\tconst pendingStage1 = this.queryOne<{ cnt: number }>(\n\t\t\t\"SELECT COUNT(*) as cnt FROM jobs WHERE phase = 'stage1' AND status IN ('pending', 'claimed')\",\n\t\t);\n\n\t\tif (pendingStage1 && pendingStage1.cnt > 0) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst existingPhase2 = this.queryOne<{ id: string }>(\n\t\t\t\"SELECT id FROM jobs WHERE phase = 'stage2' AND status = 'claimed' AND lease_expires_at > datetime('now')\",\n\t\t);\n\n\t\tif (existingPhase2) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst outputCount = this.queryOne<{ cnt: number }>(\n\t\t\t\"SELECT COUNT(*) as cnt FROM stage1_outputs\",\n\t\t);\n\n\t\tif (!outputCount || outputCount.cnt === 0) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst jobId = randomUUID();\n\t\tthis.db.run(\n\t\t\t\"INSERT INTO jobs (id, phase, status, worker_id, ownership_token, lease_expires_at) VALUES (?, 'stage2', 'claimed', ?, ?, ?)\",\n\t\t\t[jobId, workerId, token, expiresAt],\n\t\t);\n\n\t\tthis.schedulePersist();\n\t\treturn { jobId, ownershipToken: token };\n\t}\n\n\t/**\n\t * Complete the phase 2 consolidation job.\n\t */\n\tcompletePhase2Job(jobId: string): void {\n\t\tthis.db.run(\n\t\t\t\"UPDATE jobs SET status = 'done', updated_at = datetime('now') WHERE id = ? AND phase = 'stage2'\",\n\t\t\t[jobId],\n\t\t);\n\t\tthis.schedulePersist();\n\t}\n\n\t/**\n\t * Get all stage1 extraction outputs.\n\t */\n\tgetStage1Outputs(): Array<{ threadId: string; extractionJson: string }> {\n\t\tconst rows = this.queryAll<{ thread_id: string; extraction_json: string }>(\n\t\t\t\"SELECT thread_id, extraction_json FROM stage1_outputs\",\n\t\t);\n\n\t\treturn rows.map((r) => ({\n\t\t\tthreadId: r.thread_id,\n\t\t\textractionJson: r.extraction_json,\n\t\t}));\n\t}\n\n\t/**\n\t * Get all stage1 outputs for a specific cwd.\n\t */\n\tgetStage1OutputsForCwd(cwd: string): Array<{ threadId: string; extractionJson: string }> {\n\t\tconst rows = this.queryAll<{ thread_id: string; extraction_json: string }>(\n\t\t\t`SELECT s.thread_id, s.extraction_json FROM stage1_outputs s\n\t\t\tINNER JOIN threads t ON t.thread_id = s.thread_id\n\t\t\tWHERE t.cwd = ?`,\n\t\t\t[cwd],\n\t\t);\n\n\t\treturn rows.map((r) => ({\n\t\t\tthreadId: r.thread_id,\n\t\t\textractionJson: r.extraction_json,\n\t\t}));\n\t}\n\n\t/**\n\t * Get thread info by ID.\n\t */\n\tgetThread(threadId: string): ThreadRow | undefined {\n\t\treturn this.queryOne<ThreadRow>(\n\t\t\t\"SELECT * FROM threads WHERE thread_id = ?\",\n\t\t\t[threadId],\n\t\t);\n\t}\n\n\t/**\n\t * Get pipeline statistics.\n\t */\n\tgetStats(): {\n\t\ttotalThreads: number;\n\t\tpendingThreads: number;\n\t\tdoneThreads: number;\n\t\terrorThreads: number;\n\t\ttotalStage1Outputs: number;\n\t\tpendingStage1Jobs: number;\n\t} {\n\t\tconst threads = this.queryOne<{ total: number; pending: number; done: number; errors: number }>(`\n\t\t\tSELECT\n\t\t\t\tCOUNT(*) as total,\n\t\t\t\tSUM(CASE WHEN status = 'pending' THEN 1 ELSE 0 END) as pending,\n\t\t\t\tSUM(CASE WHEN status = 'done' THEN 1 ELSE 0 END) as done,\n\t\t\t\tSUM(CASE WHEN status = 'error' THEN 1 ELSE 0 END) as errors\n\t\t\tFROM threads\n\t\t`)!;\n\n\t\tconst outputs = this.queryOne<{ cnt: number }>(\n\t\t\t\"SELECT COUNT(*) as cnt FROM stage1_outputs\",\n\t\t)!;\n\n\t\tconst pendingJobs = this.queryOne<{ cnt: number }>(\n\t\t\t\"SELECT COUNT(*) as cnt FROM jobs WHERE phase = 'stage1' AND status IN ('pending', 'claimed')\",\n\t\t)!;\n\n\t\treturn {\n\t\t\ttotalThreads: threads.total,\n\t\t\tpendingThreads: threads.pending,\n\t\t\tdoneThreads: threads.done,\n\t\t\terrorThreads: threads.errors,\n\t\t\ttotalStage1Outputs: outputs.cnt,\n\t\t\tpendingStage1Jobs: pendingJobs.cnt,\n\t\t};\n\t}\n\n\t/**\n\t * Clear all data (for /memory clear).\n\t */\n\tclearAll(): void {\n\t\tthis.db.run(\"DELETE FROM stage1_outputs\");\n\t\tthis.db.run(\"DELETE FROM jobs\");\n\t\tthis.db.run(\"DELETE FROM threads\");\n\t\tthis.schedulePersist();\n\t}\n\n\t/**\n\t * Clear data for a specific cwd (for /memory clear in project scope).\n\t */\n\tclearForCwd(cwd: string): void {\n\t\tthis.db.run(\n\t\t\t\"DELETE FROM stage1_outputs WHERE thread_id IN (SELECT thread_id FROM threads WHERE cwd = ?)\",\n\t\t\t[cwd],\n\t\t);\n\t\tthis.db.run(\n\t\t\t\"DELETE FROM jobs WHERE thread_id IN (SELECT thread_id FROM threads WHERE cwd = ?)\",\n\t\t\t[cwd],\n\t\t);\n\t\tthis.db.run(\"DELETE FROM threads WHERE cwd = ?\", [cwd]);\n\t\tthis.schedulePersist();\n\t}\n\n\t/**\n\t * Reset all threads to pending (for /memory rebuild).\n\t */\n\tresetAllForCwd(cwd: string): void {\n\t\tthis.db.run(\n\t\t\t\"DELETE FROM stage1_outputs WHERE thread_id IN (SELECT thread_id FROM threads WHERE cwd = ?)\",\n\t\t\t[cwd],\n\t\t);\n\t\tthis.db.run(\n\t\t\t\"DELETE FROM jobs WHERE thread_id IN (SELECT thread_id FROM threads WHERE cwd = ?)\",\n\t\t\t[cwd],\n\t\t);\n\t\tthis.db.run(\n\t\t\t\"UPDATE threads SET status = 'pending', updated_at = datetime('now') WHERE cwd = ?\",\n\t\t\t[cwd],\n\t\t);\n\n\t\tconst threads = this.queryAll<{ thread_id: string }>(\n\t\t\t\"SELECT thread_id FROM threads WHERE cwd = ?\",\n\t\t\t[cwd],\n\t\t);\n\n\t\tfor (const t of threads) {\n\t\t\tthis.db.run(\n\t\t\t\t\"INSERT INTO jobs (id, phase, thread_id, status) VALUES (?, 'stage1', ?, 'pending')\",\n\t\t\t\t[randomUUID(), t.thread_id],\n\t\t\t);\n\t\t}\n\t\tthis.schedulePersist();\n\t}\n\n\tclose(): void {\n\t\tif (this.persistTimer) {\n\t\t\tclearTimeout(this.persistTimer);\n\t\t\tthis.persistTimer = null;\n\t\t}\n\t\tthis.persist();\n\t\tthis.db.close();\n\t}\n}\n"]}
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../../src/resources/extensions/memory/storage.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,SAA6C,MAAM,QAAQ,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AACzD,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AAiCzE,MAAM,OAAO,aAAa;IAKzB,YAAoB,EAAiB,EAAE,MAAc;QAF7C,iBAAY,GAAyC,IAAI,CAAC;QAGjE,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACtB,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAc;QACjC,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;QAC5B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACtB,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrC,CAAC;QAED,MAAM,GAAG,GAAG,MAAM,SAAS,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACrE,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;QAElE,EAAE,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;QACpC,EAAE,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;QACtC,EAAE,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;QAErC,MAAM,OAAO,GAAG,IAAI,aAAa,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QAC9C,OAAO,CAAC,UAAU,EAAE,CAAC;QACrB,OAAO,OAAO,CAAC;IAChB,CAAC;IAEO,OAAO;QACd,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC;QAC9B,yBAAyB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC9C,CAAC;IAEO,eAAe;QACtB,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACvB,YAAY,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACjC,CAAC;QACD,IAAI,CAAC,YAAY,GAAG,UAAU,CAAC,GAAG,EAAE;YACnC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;YACzB,IAAI,CAAC,OAAO,EAAE,CAAC;QAChB,CAAC,EAAE,GAAG,CAAC,CAAC;IACT,CAAC;IAEO,UAAU;QACjB,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC;;;;;;;;;;;;GAYX,CAAC,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC;;;;;;;GAOX,CAAC,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC;;;;;;;;;;;;;GAaX,CAAC,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,yEAAyE,CAAC,CAAC;QACvF,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,kEAAkE,CAAC,CAAC;QAChF,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,4DAA4D,CAAC,CAAC;QAC1E,IAAI,CAAC,OAAO,EAAE,CAAC;IAChB,CAAC;IAEO,QAAQ,CAAI,GAAW,EAAE,SAAoB,EAAE;QACtD,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,IAAI,CAAC,MAAiD,CAAC,CAAC;QAC7D,MAAM,IAAI,GAAQ,EAAE,CAAC;QACrB,OAAO,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;YACpB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAO,CAAC,CAAC;QACpC,CAAC;QACD,IAAI,CAAC,IAAI,EAAE,CAAC;QACZ,OAAO,IAAI,CAAC;IACb,CAAC;IAEO,QAAQ,CAAI,GAAW,EAAE,SAAoB,EAAE;QACtD,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAI,GAAG,EAAE,MAAM,CAAC,CAAC;QAC3C,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC;IAChB,CAAC;IAED;;;OAGG;IACH,aAAa,CACZ,OAME;QAEF,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,IAAI,OAAO,GAAG,CAAC,CAAC;QAEhB,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAC7B,uEAAuE,EACvE,CAAC,CAAC,CAAC,QAAQ,CAAC,CACZ,CAAC;YAEF,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACf,IAAI,CAAC,EAAE,CAAC,GAAG,CACV,kHAAkH,EAClH,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,CACxD,CAAC;gBACF,IAAI,CAAC,EAAE,CAAC,GAAG,CACV,8FAA8F,EAC9F,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,CAC1B,CAAC;gBACF,QAAQ,EAAE,CAAC;YACZ,CAAC;iBAAM,IAAI,QAAQ,CAAC,SAAS,KAAK,CAAC,CAAC,QAAQ,IAAI,QAAQ,CAAC,UAAU,KAAK,CAAC,CAAC,SAAS,EAAE,CAAC;gBACrF,IAAI,CAAC,EAAE,CAAC,GAAG,CACV,gJAAgJ,EAChJ,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,QAAQ,CAAC,CACxD,CAAC;gBACF,IAAI,QAAQ,CAAC,MAAM,KAAK,MAAM,IAAI,QAAQ,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;oBAC/D,IAAI,CAAC,EAAE,CAAC,GAAG,CACV,8FAA8F,EAC9F,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,CAC1B,CAAC;gBACH,CAAC;gBACD,OAAO,EAAE,CAAC;YACX,CAAC;iBAAM,CAAC;gBACP,OAAO,EAAE,CAAC;YACX,CAAC;QACF,CAAC;QAED,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;IACvC,CAAC;IAED;;;OAGG;IACH,eAAe,CACd,QAAgB,EAChB,KAAa,EACb,YAAoB;QAEpB,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC;QAC3B,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,YAAY,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;QAE3E,IAAI,CAAC,EAAE,CAAC,GAAG,CACV;;;;;;;;;;;KAWE,EACF,CAAC,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,CAAC,CACnC,CAAC;QAEF,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CACzB,iFAAiF,EACjF,CAAC,KAAK,CAAC,CACP,CAAC;QAEF,IAAI,CAAC,eAAe,EAAE,CAAC;QAEvB,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACvB,KAAK,EAAE,CAAC,CAAC,EAAE;YACX,QAAQ,EAAE,CAAC,CAAC,SAAS;YACrB,cAAc,EAAE,KAAK;SACrB,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,iBAAiB,CAAC,QAAgB,EAAE,MAAc;QACjD,IAAI,CAAC,EAAE,CAAC,GAAG,CACV,+HAA+H,EAC/H,CAAC,QAAQ,CAAC,CACV,CAAC;QACF,IAAI,CAAC,EAAE,CAAC,GAAG,CACV,+GAA+G,EAC/G,CAAC,QAAQ,EAAE,MAAM,CAAC,CAClB,CAAC;QACF,IAAI,CAAC,EAAE,CAAC,GAAG,CACV,sFAAsF,EACtF,CAAC,QAAQ,CAAC,CACV,CAAC;QACF,IAAI,CAAC,eAAe,EAAE,CAAC;IACxB,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,QAAgB,EAAE,YAAoB;QACnD,IAAI,CAAC,EAAE,CAAC,GAAG,CACV,mJAAmJ,EACnJ,CAAC,YAAY,EAAE,QAAQ,CAAC,CACxB,CAAC;QACF,IAAI,CAAC,EAAE,CAAC,GAAG,CACV,0GAA0G,EAC1G,CAAC,YAAY,EAAE,QAAQ,CAAC,CACxB,CAAC;QACF,IAAI,CAAC,eAAe,EAAE,CAAC;IACxB,CAAC;IAED;;;OAGG;IACH,uBAAuB,CACtB,QAAgB,EAChB,YAAoB;QAEpB,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC;QAC3B,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,YAAY,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;QAE3E,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ,CAClC,8FAA8F,CAC9F,CAAC;QAEF,IAAI,aAAa,IAAI,aAAa,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC;YAC5C,OAAO,IAAI,CAAC;QACb,CAAC;QAED,MAAM,cAAc,GAAG,IAAI,CAAC,QAAQ,CACnC,0GAA0G,CAC1G,CAAC;QAEF,IAAI,cAAc,EAAE,CAAC;YACpB,OAAO,IAAI,CAAC;QACb,CAAC;QAED,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAChC,4CAA4C,CAC5C,CAAC;QAEF,IAAI,CAAC,WAAW,IAAI,WAAW,CAAC,GAAG,KAAK,CAAC,EAAE,CAAC;YAC3C,OAAO,IAAI,CAAC;QACb,CAAC;QAED,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC;QAC3B,IAAI,CAAC,EAAE,CAAC,GAAG,CACV,6HAA6H,EAC7H,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,CAAC,CACnC,CAAC;QAEF,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC;IACzC,CAAC;IAED;;OAEG;IACH,iBAAiB,CAAC,KAAa;QAC9B,IAAI,CAAC,EAAE,CAAC,GAAG,CACV,iGAAiG,EACjG,CAAC,KAAK,CAAC,CACP,CAAC;QACF,IAAI,CAAC,eAAe,EAAE,CAAC;IACxB,CAAC;IAED;;OAEG;IACH,gBAAgB;QACf,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CACzB,uDAAuD,CACvD,CAAC;QAEF,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACvB,QAAQ,EAAE,CAAC,CAAC,SAAS;YACrB,cAAc,EAAE,CAAC,CAAC,eAAe;SACjC,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,sBAAsB,CAAC,GAAW;QACjC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CACzB;;mBAEgB,EAChB,CAAC,GAAG,CAAC,CACL,CAAC;QAEF,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACvB,QAAQ,EAAE,CAAC,CAAC,SAAS;YACrB,cAAc,EAAE,CAAC,CAAC,eAAe;SACjC,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,SAAS,CAAC,QAAgB;QACzB,OAAO,IAAI,CAAC,QAAQ,CACnB,2CAA2C,EAC3C,CAAC,QAAQ,CAAC,CACV,CAAC;IACH,CAAC;IAED;;OAEG;IACH,QAAQ;QAQP,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAmE;;;;;;;GAO/F,CAAE,CAAC;QAEJ,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAC5B,4CAA4C,CAC3C,CAAC;QAEH,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAChC,8FAA8F,CAC7F,CAAC;QAEH,OAAO;YACN,YAAY,EAAE,OAAO,CAAC,KAAK;YAC3B,cAAc,EAAE,OAAO,CAAC,OAAO;YAC/B,WAAW,EAAE,OAAO,CAAC,IAAI;YACzB,YAAY,EAAE,OAAO,CAAC,MAAM;YAC5B,kBAAkB,EAAE,OAAO,CAAC,GAAG;YAC/B,iBAAiB,EAAE,WAAW,CAAC,GAAG;SAClC,CAAC;IACH,CAAC;IAED;;OAEG;IACH,QAAQ;QACP,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;QAC1C,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;QAChC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;QACnC,IAAI,CAAC,eAAe,EAAE,CAAC;IACxB,CAAC;IAED;;OAEG;IACH,WAAW,CAAC,GAAW;QACtB,IAAI,CAAC,EAAE,CAAC,GAAG,CACV,6FAA6F,EAC7F,CAAC,GAAG,CAAC,CACL,CAAC;QACF,IAAI,CAAC,EAAE,CAAC,GAAG,CACV,mFAAmF,EACnF,CAAC,GAAG,CAAC,CACL,CAAC;QACF,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,mCAAmC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QACxD,IAAI,CAAC,eAAe,EAAE,CAAC;IACxB,CAAC;IAED;;OAEG;IACH,cAAc,CAAC,GAAW;QACzB,IAAI,CAAC,EAAE,CAAC,GAAG,CACV,6FAA6F,EAC7F,CAAC,GAAG,CAAC,CACL,CAAC;QACF,IAAI,CAAC,EAAE,CAAC,GAAG,CACV,mFAAmF,EACnF,CAAC,GAAG,CAAC,CACL,CAAC;QACF,IAAI,CAAC,EAAE,CAAC,GAAG,CACV,mFAAmF,EACnF,CAAC,GAAG,CAAC,CACL,CAAC;QAEF,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAC5B,6CAA6C,EAC7C,CAAC,GAAG,CAAC,CACL,CAAC;QAEF,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACzB,IAAI,CAAC,EAAE,CAAC,GAAG,CACV,oFAAoF,EACpF,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,CAC3B,CAAC;QACH,CAAC;QACD,IAAI,CAAC,eAAe,EAAE,CAAC;IACxB,CAAC;IAED,KAAK;QACJ,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACvB,YAAY,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAChC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QAC1B,CAAC;QACD,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;IACjB,CAAC;CACD","sourcesContent":["/**\n * SQLite storage for the memory extraction pipeline.\n *\n * Tables:\n * - threads: tracks session files and their processing state\n * - stage1_outputs: stores per-thread extraction results\n * - jobs: lease-based job queue for pipeline phases\n */\n\nimport initSqlJs, { type Database as SqlJsDatabase } from \"sql.js\";\nimport { randomUUID } from \"crypto\";\nimport { existsSync, mkdirSync, readFileSync } from \"fs\";\nimport { dirname } from \"path\";\nimport { atomicWriteDbSnapshotSync } from \"../../../core/db-snapshot.js\";\n\nexport interface ThreadRow {\n\tthread_id: string;\n\tfile_path: string;\n\tfile_size: number;\n\tfile_mtime: number;\n\tcwd: string;\n\tstatus: \"pending\" | \"processing\" | \"done\" | \"error\";\n\terror_message: string | null;\n\tcreated_at: string;\n\tupdated_at: string;\n}\n\nexport interface Stage1OutputRow {\n\tthread_id: string;\n\textraction_json: string;\n\tcreated_at: string;\n}\n\nexport interface JobRow {\n\tid: string;\n\tphase: \"stage1\" | \"stage2\";\n\tthread_id: string | null;\n\tstatus: \"pending\" | \"claimed\" | \"done\" | \"error\";\n\tworker_id: string | null;\n\townership_token: string | null;\n\tlease_expires_at: string | null;\n\terror_message: string | null;\n\tcreated_at: string;\n\tupdated_at: string;\n}\n\nexport class MemoryStorage {\n\tprivate db: SqlJsDatabase;\n\tprivate dbPath: string;\n\tprivate persistTimer: ReturnType<typeof setTimeout> | null = null;\n\n\tprivate constructor(db: SqlJsDatabase, dbPath: string) {\n\t\tthis.db = db;\n\t\tthis.dbPath = dbPath;\n\t}\n\n\tstatic async create(dbPath: string): Promise<MemoryStorage> {\n\t\tconst dir = dirname(dbPath);\n\t\tif (!existsSync(dir)) {\n\t\t\tmkdirSync(dir, { recursive: true });\n\t\t}\n\n\t\tconst SQL = await initSqlJs();\n\t\tconst buffer = existsSync(dbPath) ? readFileSync(dbPath) : undefined;\n\t\tconst db = buffer ? new SQL.Database(buffer) : new SQL.Database();\n\n\t\tdb.run(\"PRAGMA journal_mode = WAL\");\n\t\tdb.run(\"PRAGMA synchronous = NORMAL\");\n\t\tdb.run(\"PRAGMA busy_timeout = 5000\");\n\n\t\tconst storage = new MemoryStorage(db, dbPath);\n\t\tstorage.initSchema();\n\t\treturn storage;\n\t}\n\n\tprivate persist(): void {\n\t\tconst data = this.db.export();\n\t\tatomicWriteDbSnapshotSync(this.dbPath, data);\n\t}\n\n\tprivate schedulePersist(): void {\n\t\tif (this.persistTimer) {\n\t\t\tclearTimeout(this.persistTimer);\n\t\t}\n\t\tthis.persistTimer = setTimeout(() => {\n\t\t\tthis.persistTimer = null;\n\t\t\tthis.persist();\n\t\t}, 500);\n\t}\n\n\tprivate initSchema(): void {\n\t\tthis.db.run(`\n\t\t\tCREATE TABLE IF NOT EXISTS threads (\n\t\t\t\tthread_id TEXT PRIMARY KEY,\n\t\t\t\tfile_path TEXT NOT NULL,\n\t\t\t\tfile_size INTEGER NOT NULL DEFAULT 0,\n\t\t\t\tfile_mtime INTEGER NOT NULL DEFAULT 0,\n\t\t\t\tcwd TEXT NOT NULL DEFAULT '',\n\t\t\t\tstatus TEXT NOT NULL DEFAULT 'pending',\n\t\t\t\terror_message TEXT,\n\t\t\t\tcreated_at TEXT NOT NULL DEFAULT (datetime('now')),\n\t\t\t\tupdated_at TEXT NOT NULL DEFAULT (datetime('now'))\n\t\t\t)\n\t\t`);\n\t\tthis.db.run(`\n\t\t\tCREATE TABLE IF NOT EXISTS stage1_outputs (\n\t\t\t\tthread_id TEXT PRIMARY KEY,\n\t\t\t\textraction_json TEXT NOT NULL,\n\t\t\t\tcreated_at TEXT NOT NULL DEFAULT (datetime('now')),\n\t\t\t\tFOREIGN KEY (thread_id) REFERENCES threads(thread_id) ON DELETE CASCADE\n\t\t\t)\n\t\t`);\n\t\tthis.db.run(`\n\t\t\tCREATE TABLE IF NOT EXISTS jobs (\n\t\t\t\tid TEXT PRIMARY KEY,\n\t\t\t\tphase TEXT NOT NULL,\n\t\t\t\tthread_id TEXT,\n\t\t\t\tstatus TEXT NOT NULL DEFAULT 'pending',\n\t\t\t\tworker_id TEXT,\n\t\t\t\townership_token TEXT,\n\t\t\t\tlease_expires_at TEXT,\n\t\t\t\terror_message TEXT,\n\t\t\t\tcreated_at TEXT NOT NULL DEFAULT (datetime('now')),\n\t\t\t\tupdated_at TEXT NOT NULL DEFAULT (datetime('now'))\n\t\t\t)\n\t\t`);\n\t\tthis.db.run(\"CREATE INDEX IF NOT EXISTS idx_jobs_phase_status ON jobs(phase, status)\");\n\t\tthis.db.run(\"CREATE INDEX IF NOT EXISTS idx_threads_status ON threads(status)\");\n\t\tthis.db.run(\"CREATE INDEX IF NOT EXISTS idx_threads_cwd ON threads(cwd)\");\n\t\tthis.persist();\n\t}\n\n\tprivate queryAll<T>(sql: string, params: unknown[] = []): T[] {\n\t\tconst stmt = this.db.prepare(sql);\n\t\tstmt.bind(params as (string | number | null | Uint8Array)[]);\n\t\tconst rows: T[] = [];\n\t\twhile (stmt.step()) {\n\t\t\trows.push(stmt.getAsObject() as T);\n\t\t}\n\t\tstmt.free();\n\t\treturn rows;\n\t}\n\n\tprivate queryOne<T>(sql: string, params: unknown[] = []): T | undefined {\n\t\tconst rows = this.queryAll<T>(sql, params);\n\t\treturn rows[0];\n\t}\n\n\t/**\n\t * Insert or update thread records. Skips threads whose file hasn't changed\n\t * (same size + mtime = watermark match).\n\t */\n\tupsertThreads(\n\t\tthreads: Array<{\n\t\t\tthreadId: string;\n\t\t\tfilePath: string;\n\t\t\tfileSize: number;\n\t\t\tfileMtime: number;\n\t\t\tcwd: string;\n\t\t}>,\n\t): { inserted: number; updated: number; skipped: number } {\n\t\tlet inserted = 0;\n\t\tlet updated = 0;\n\t\tlet skipped = 0;\n\n\t\tfor (const t of threads) {\n\t\t\tconst existing = this.queryOne<{ file_size: number; file_mtime: number; status: string }>(\n\t\t\t\t\"SELECT file_size, file_mtime, status FROM threads WHERE thread_id = ?\",\n\t\t\t\t[t.threadId],\n\t\t\t);\n\n\t\t\tif (!existing) {\n\t\t\t\tthis.db.run(\n\t\t\t\t\t\"INSERT INTO threads (thread_id, file_path, file_size, file_mtime, cwd, status) VALUES (?, ?, ?, ?, ?, 'pending')\",\n\t\t\t\t\t[t.threadId, t.filePath, t.fileSize, t.fileMtime, t.cwd],\n\t\t\t\t);\n\t\t\t\tthis.db.run(\n\t\t\t\t\t\"INSERT OR IGNORE INTO jobs (id, phase, thread_id, status) VALUES (?, 'stage1', ?, 'pending')\",\n\t\t\t\t\t[randomUUID(), t.threadId],\n\t\t\t\t);\n\t\t\t\tinserted++;\n\t\t\t} else if (existing.file_size !== t.fileSize || existing.file_mtime !== t.fileMtime) {\n\t\t\t\tthis.db.run(\n\t\t\t\t\t\"UPDATE threads SET file_path = ?, file_size = ?, file_mtime = ?, cwd = ?, status = 'pending', updated_at = datetime('now') WHERE thread_id = ?\",\n\t\t\t\t\t[t.filePath, t.fileSize, t.fileMtime, t.cwd, t.threadId],\n\t\t\t\t);\n\t\t\t\tif (existing.status === \"done\" || existing.status === \"error\") {\n\t\t\t\t\tthis.db.run(\n\t\t\t\t\t\t\"INSERT OR IGNORE INTO jobs (id, phase, thread_id, status) VALUES (?, 'stage1', ?, 'pending')\",\n\t\t\t\t\t\t[randomUUID(), t.threadId],\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tupdated++;\n\t\t\t} else {\n\t\t\t\tskipped++;\n\t\t\t}\n\t\t}\n\n\t\tthis.schedulePersist();\n\t\treturn { inserted, updated, skipped };\n\t}\n\n\t/**\n\t * Claim up to `limit` stage1 jobs for the given worker.\n\t * Uses lease-based ownership with an ownership_token UUID.\n\t */\n\tclaimStage1Jobs(\n\t\tworkerId: string,\n\t\tlimit: number,\n\t\tleaseSeconds: number,\n\t): Array<{ jobId: string; threadId: string; ownershipToken: string }> {\n\t\tconst token = randomUUID();\n\t\tconst expiresAt = new Date(Date.now() + leaseSeconds * 1000).toISOString();\n\n\t\tthis.db.run(\n\t\t\t`UPDATE jobs SET\n\t\t\t\tstatus = 'claimed',\n\t\t\t\tworker_id = ?,\n\t\t\t\townership_token = ?,\n\t\t\t\tlease_expires_at = ?,\n\t\t\t\tupdated_at = datetime('now')\n\t\t\tWHERE id IN (\n\t\t\t\tSELECT id FROM jobs\n\t\t\t\tWHERE phase = 'stage1'\n\t\t\t\t\tAND (status = 'pending' OR (status = 'claimed' AND lease_expires_at < datetime('now')))\n\t\t\t\tLIMIT ?\n\t\t\t)`,\n\t\t\t[workerId, token, expiresAt, limit],\n\t\t);\n\n\t\tconst rows = this.queryAll<{ id: string; thread_id: string }>(\n\t\t\t\"SELECT id, thread_id FROM jobs WHERE ownership_token = ? AND status = 'claimed'\",\n\t\t\t[token],\n\t\t);\n\n\t\tthis.schedulePersist();\n\n\t\treturn rows.map((r) => ({\n\t\t\tjobId: r.id,\n\t\t\tthreadId: r.thread_id,\n\t\t\townershipToken: token,\n\t\t}));\n\t}\n\n\t/**\n\t * Mark a stage1 job as complete and store the extraction output.\n\t */\n\tcompleteStage1Job(threadId: string, output: string): void {\n\t\tthis.db.run(\n\t\t\t\"UPDATE jobs SET status = 'done', updated_at = datetime('now') WHERE thread_id = ? AND phase = 'stage1' AND status = 'claimed'\",\n\t\t\t[threadId],\n\t\t);\n\t\tthis.db.run(\n\t\t\t\"INSERT OR REPLACE INTO stage1_outputs (thread_id, extraction_json, created_at) VALUES (?, ?, datetime('now'))\",\n\t\t\t[threadId, output],\n\t\t);\n\t\tthis.db.run(\n\t\t\t\"UPDATE threads SET status = 'done', updated_at = datetime('now') WHERE thread_id = ?\",\n\t\t\t[threadId],\n\t\t);\n\t\tthis.schedulePersist();\n\t}\n\n\t/**\n\t * Mark a stage1 job as errored.\n\t */\n\tfailStage1Job(threadId: string, errorMessage: string): void {\n\t\tthis.db.run(\n\t\t\t\"UPDATE jobs SET status = 'error', error_message = ?, updated_at = datetime('now') WHERE thread_id = ? AND phase = 'stage1' AND status = 'claimed'\",\n\t\t\t[errorMessage, threadId],\n\t\t);\n\t\tthis.db.run(\n\t\t\t\"UPDATE threads SET status = 'error', error_message = ?, updated_at = datetime('now') WHERE thread_id = ?\",\n\t\t\t[errorMessage, threadId],\n\t\t);\n\t\tthis.schedulePersist();\n\t}\n\n\t/**\n\t * Try to claim the global phase 2 consolidation job.\n\t * Only one worker can hold this at a time.\n\t */\n\ttryClaimGlobalPhase2Job(\n\t\tworkerId: string,\n\t\tleaseSeconds: number,\n\t): { jobId: string; ownershipToken: string } | null {\n\t\tconst token = randomUUID();\n\t\tconst expiresAt = new Date(Date.now() + leaseSeconds * 1000).toISOString();\n\n\t\tconst pendingStage1 = this.queryOne<{ cnt: number }>(\n\t\t\t\"SELECT COUNT(*) as cnt FROM jobs WHERE phase = 'stage1' AND status IN ('pending', 'claimed')\",\n\t\t);\n\n\t\tif (pendingStage1 && pendingStage1.cnt > 0) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst existingPhase2 = this.queryOne<{ id: string }>(\n\t\t\t\"SELECT id FROM jobs WHERE phase = 'stage2' AND status = 'claimed' AND lease_expires_at > datetime('now')\",\n\t\t);\n\n\t\tif (existingPhase2) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst outputCount = this.queryOne<{ cnt: number }>(\n\t\t\t\"SELECT COUNT(*) as cnt FROM stage1_outputs\",\n\t\t);\n\n\t\tif (!outputCount || outputCount.cnt === 0) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst jobId = randomUUID();\n\t\tthis.db.run(\n\t\t\t\"INSERT INTO jobs (id, phase, status, worker_id, ownership_token, lease_expires_at) VALUES (?, 'stage2', 'claimed', ?, ?, ?)\",\n\t\t\t[jobId, workerId, token, expiresAt],\n\t\t);\n\n\t\tthis.schedulePersist();\n\t\treturn { jobId, ownershipToken: token };\n\t}\n\n\t/**\n\t * Complete the phase 2 consolidation job.\n\t */\n\tcompletePhase2Job(jobId: string): void {\n\t\tthis.db.run(\n\t\t\t\"UPDATE jobs SET status = 'done', updated_at = datetime('now') WHERE id = ? AND phase = 'stage2'\",\n\t\t\t[jobId],\n\t\t);\n\t\tthis.schedulePersist();\n\t}\n\n\t/**\n\t * Get all stage1 extraction outputs.\n\t */\n\tgetStage1Outputs(): Array<{ threadId: string; extractionJson: string }> {\n\t\tconst rows = this.queryAll<{ thread_id: string; extraction_json: string }>(\n\t\t\t\"SELECT thread_id, extraction_json FROM stage1_outputs\",\n\t\t);\n\n\t\treturn rows.map((r) => ({\n\t\t\tthreadId: r.thread_id,\n\t\t\textractionJson: r.extraction_json,\n\t\t}));\n\t}\n\n\t/**\n\t * Get all stage1 outputs for a specific cwd.\n\t */\n\tgetStage1OutputsForCwd(cwd: string): Array<{ threadId: string; extractionJson: string }> {\n\t\tconst rows = this.queryAll<{ thread_id: string; extraction_json: string }>(\n\t\t\t`SELECT s.thread_id, s.extraction_json FROM stage1_outputs s\n\t\t\tINNER JOIN threads t ON t.thread_id = s.thread_id\n\t\t\tWHERE t.cwd = ?`,\n\t\t\t[cwd],\n\t\t);\n\n\t\treturn rows.map((r) => ({\n\t\t\tthreadId: r.thread_id,\n\t\t\textractionJson: r.extraction_json,\n\t\t}));\n\t}\n\n\t/**\n\t * Get thread info by ID.\n\t */\n\tgetThread(threadId: string): ThreadRow | undefined {\n\t\treturn this.queryOne<ThreadRow>(\n\t\t\t\"SELECT * FROM threads WHERE thread_id = ?\",\n\t\t\t[threadId],\n\t\t);\n\t}\n\n\t/**\n\t * Get pipeline statistics.\n\t */\n\tgetStats(): {\n\t\ttotalThreads: number;\n\t\tpendingThreads: number;\n\t\tdoneThreads: number;\n\t\terrorThreads: number;\n\t\ttotalStage1Outputs: number;\n\t\tpendingStage1Jobs: number;\n\t} {\n\t\tconst threads = this.queryOne<{ total: number; pending: number; done: number; errors: number }>(`\n\t\t\tSELECT\n\t\t\t\tCOUNT(*) as total,\n\t\t\t\tSUM(CASE WHEN status = 'pending' THEN 1 ELSE 0 END) as pending,\n\t\t\t\tSUM(CASE WHEN status = 'done' THEN 1 ELSE 0 END) as done,\n\t\t\t\tSUM(CASE WHEN status = 'error' THEN 1 ELSE 0 END) as errors\n\t\t\tFROM threads\n\t\t`)!;\n\n\t\tconst outputs = this.queryOne<{ cnt: number }>(\n\t\t\t\"SELECT COUNT(*) as cnt FROM stage1_outputs\",\n\t\t)!;\n\n\t\tconst pendingJobs = this.queryOne<{ cnt: number }>(\n\t\t\t\"SELECT COUNT(*) as cnt FROM jobs WHERE phase = 'stage1' AND status IN ('pending', 'claimed')\",\n\t\t)!;\n\n\t\treturn {\n\t\t\ttotalThreads: threads.total,\n\t\t\tpendingThreads: threads.pending,\n\t\t\tdoneThreads: threads.done,\n\t\t\terrorThreads: threads.errors,\n\t\t\ttotalStage1Outputs: outputs.cnt,\n\t\t\tpendingStage1Jobs: pendingJobs.cnt,\n\t\t};\n\t}\n\n\t/**\n\t * Clear all data (for /memory clear).\n\t */\n\tclearAll(): void {\n\t\tthis.db.run(\"DELETE FROM stage1_outputs\");\n\t\tthis.db.run(\"DELETE FROM jobs\");\n\t\tthis.db.run(\"DELETE FROM threads\");\n\t\tthis.schedulePersist();\n\t}\n\n\t/**\n\t * Clear data for a specific cwd (for /memory clear in project scope).\n\t */\n\tclearForCwd(cwd: string): void {\n\t\tthis.db.run(\n\t\t\t\"DELETE FROM stage1_outputs WHERE thread_id IN (SELECT thread_id FROM threads WHERE cwd = ?)\",\n\t\t\t[cwd],\n\t\t);\n\t\tthis.db.run(\n\t\t\t\"DELETE FROM jobs WHERE thread_id IN (SELECT thread_id FROM threads WHERE cwd = ?)\",\n\t\t\t[cwd],\n\t\t);\n\t\tthis.db.run(\"DELETE FROM threads WHERE cwd = ?\", [cwd]);\n\t\tthis.schedulePersist();\n\t}\n\n\t/**\n\t * Reset all threads to pending (for /memory rebuild).\n\t */\n\tresetAllForCwd(cwd: string): void {\n\t\tthis.db.run(\n\t\t\t\"DELETE FROM stage1_outputs WHERE thread_id IN (SELECT thread_id FROM threads WHERE cwd = ?)\",\n\t\t\t[cwd],\n\t\t);\n\t\tthis.db.run(\n\t\t\t\"DELETE FROM jobs WHERE thread_id IN (SELECT thread_id FROM threads WHERE cwd = ?)\",\n\t\t\t[cwd],\n\t\t);\n\t\tthis.db.run(\n\t\t\t\"UPDATE threads SET status = 'pending', updated_at = datetime('now') WHERE cwd = ?\",\n\t\t\t[cwd],\n\t\t);\n\n\t\tconst threads = this.queryAll<{ thread_id: string }>(\n\t\t\t\"SELECT thread_id FROM threads WHERE cwd = ?\",\n\t\t\t[cwd],\n\t\t);\n\n\t\tfor (const t of threads) {\n\t\t\tthis.db.run(\n\t\t\t\t\"INSERT INTO jobs (id, phase, thread_id, status) VALUES (?, 'stage1', ?, 'pending')\",\n\t\t\t\t[randomUUID(), t.thread_id],\n\t\t\t);\n\t\t}\n\t\tthis.schedulePersist();\n\t}\n\n\tclose(): void {\n\t\tif (this.persistTimer) {\n\t\t\tclearTimeout(this.persistTimer);\n\t\t\tthis.persistTimer = null;\n\t\t}\n\t\tthis.persist();\n\t\tthis.db.close();\n\t}\n}\n"]}
@@ -120,6 +120,7 @@ describe("#4243 — abort() must run before _disconnectFromAgent()", () => {
120
120
 
121
121
  it("newSession() invokes abort() before _disconnectFromAgent()", async () => {
122
122
  const session = await createSession();
123
+ (session as any).agent.state.isStreaming = true;
123
124
  const order = recordCallOrder(session as any, ["abort", "_disconnectFromAgent"]);
124
125
 
125
126
  const ok = await session.newSession();
@@ -138,6 +139,40 @@ describe("#4243 — abort() must run before _disconnectFromAgent()", () => {
138
139
  );
139
140
  });
140
141
 
142
+ it("newSession() waits instead of aborting when the prior turn is idle but not settled", async () => {
143
+ const session = await createSession();
144
+ const order: string[] = [];
145
+ let releaseIdle!: () => void;
146
+ const idle = new Promise<void>((resolve) => {
147
+ releaseIdle = resolve;
148
+ });
149
+
150
+ (session as any).agent.state.isStreaming = false;
151
+ (session as any).agent.waitForIdle = () => {
152
+ order.push("waitForIdle");
153
+ return idle;
154
+ };
155
+ (session as any).abort = async () => {
156
+ order.push("abort");
157
+ };
158
+ const originalDisconnect = (session as any)._disconnectFromAgent.bind(session);
159
+ (session as any)._disconnectFromAgent = () => {
160
+ order.push("_disconnectFromAgent");
161
+ originalDisconnect();
162
+ };
163
+
164
+ const pendingNewSession = session.newSession();
165
+ await Promise.resolve();
166
+ assert.deepEqual(order, ["waitForIdle"]);
167
+ assert.equal(order.includes("abort"), false);
168
+
169
+ releaseIdle();
170
+ const ok = await pendingNewSession;
171
+ assert.equal(ok, true);
172
+ assert.deepEqual(order, ["waitForIdle", "_disconnectFromAgent"]);
173
+ assert.equal(order.includes("abort"), false);
174
+ });
175
+
141
176
  it("newSession() waits instead of aborting while agent_end processing is still streaming", async () => {
142
177
  const session = await createSession();
143
178
  const order: string[] = [];
@@ -432,6 +467,7 @@ describe("#4243 — abort() must run before _disconnectFromAgent()", () => {
432
467
  const sessionFile = session.sessionFile;
433
468
  assert.ok(typeof sessionFile === "string" && sessionFile.length > 0, "need a session file to switch to");
434
469
 
470
+ (session as any).agent.state.isStreaming = true;
435
471
  const order = recordCallOrder(session as any, ["abort", "_disconnectFromAgent"]);
436
472
 
437
473
  const ok = await session.switchSession(sessionFile);
@@ -1,3 +1,4 @@
1
+ // GSD2 - Agent session workspace-root refresh regression tests
1
2
  // Regression test for #3616: newSession() must restore the full tool set
2
3
  // when cwd is unchanged.
3
4
  //
@@ -26,7 +27,7 @@ import { SettingsManager } from "./settings-manager.js";
26
27
 
27
28
  let testDir: string;
28
29
 
29
- async function createSession(): Promise<AgentSession> {
30
+ async function createSession(options: { workspaceRootRef?: { current: string } } = {}): Promise<AgentSession> {
30
31
  const agentDir = join(testDir, "agent-home");
31
32
  const authStorage = AuthStorage.inMemory({});
32
33
  const modelRegistry = new ModelRegistry(authStorage, join(agentDir, "models.json"));
@@ -48,6 +49,7 @@ async function createSession(): Promise<AgentSession> {
48
49
  cwd: testDir,
49
50
  resourceLoader,
50
51
  modelRegistry,
52
+ workspaceRootRef: options.workspaceRootRef,
51
53
  });
52
54
  }
53
55
 
@@ -130,4 +132,41 @@ describe("#3616 — newSession() restores narrowed tool set when cwd unchanged",
130
132
  "cwd-changed branch must rebuild with includeAllExtensionTools: true",
131
133
  );
132
134
  });
135
+
136
+ it("uses explicit workspaceRoot option instead of process.cwd() when rebuilding runtime", async () => {
137
+ const session = await createSession();
138
+ const explicitWorkspaceRoot = mkdtempSync(join(testDir, "explicit-workspace-"));
139
+ (session as any)._cwd = process.cwd();
140
+
141
+ let buildRuntimeCalled = false;
142
+ let capturedBuildOptions: { includeAllExtensionTools?: boolean } | undefined;
143
+ const originalBuild = (session as any)._buildRuntime.bind(session);
144
+ (session as any)._buildRuntime = (options?: { includeAllExtensionTools?: boolean }) => {
145
+ buildRuntimeCalled = true;
146
+ capturedBuildOptions = options;
147
+ return originalBuild(options);
148
+ };
149
+
150
+ const ok = await session.newSession({ workspaceRoot: explicitWorkspaceRoot });
151
+ assert.equal(ok, true);
152
+ assert.equal((session as any)._cwd, explicitWorkspaceRoot);
153
+ assert.ok(buildRuntimeCalled, "explicit workspace root differing from prior root must rebuild runtime");
154
+ assert.strictEqual(
155
+ capturedBuildOptions?.includeAllExtensionTools,
156
+ true,
157
+ "explicit workspaceRoot rebuild must pass includeAllExtensionTools: true",
158
+ );
159
+ });
160
+
161
+ it("updates provider workspace root ref when newSession uses explicit workspaceRoot", async () => {
162
+ const workspaceRootRef = { current: "" };
163
+ const session = await createSession({ workspaceRootRef });
164
+ const explicitWorkspaceRoot = mkdtempSync(join(testDir, "provider-workspace-"));
165
+
166
+ assert.equal(workspaceRootRef.current, testDir);
167
+
168
+ const ok = await session.newSession({ workspaceRoot: explicitWorkspaceRoot });
169
+ assert.equal(ok, true);
170
+ assert.equal(workspaceRootRef.current, explicitWorkspaceRoot);
171
+ });
133
172
  });
@@ -1,3 +1,4 @@
1
+ // GSD2 - Agent session lifecycle and workspace runtime coordination
1
2
  /**
2
3
  * AgentSession - Core abstraction for agent lifecycle and session management.
3
4
  *
@@ -167,6 +168,8 @@ export interface AgentSessionConfig {
167
168
  baseToolsOverride?: Record<string, AgentTool>;
168
169
  /** Mutable ref used by Agent to access the current ExtensionRunner */
169
170
  extensionRunnerRef?: { current?: ExtensionRunner };
171
+ /** Mutable ref used by providers to access the current workspace root. */
172
+ workspaceRootRef?: { current: string };
170
173
  /** Optional: check if the claude-code CLI provider is ready (installed + authed).
171
174
  * Passed through to RetryHandler for third-party block recovery (#3772). */
172
175
  isClaudeCodeReady?: () => boolean;
@@ -284,6 +287,7 @@ export class AgentSession {
284
287
  private _baseToolRegistry: Map<string, AgentTool> = new Map();
285
288
  private _cwd: string;
286
289
  private _extensionRunnerRef?: { current?: ExtensionRunner };
290
+ private _workspaceRootRef?: { current: string };
287
291
  private _initialActiveToolNames?: string[];
288
292
  private _baseToolsOverride?: Record<string, AgentTool>;
289
293
  private _extensionUIContext?: ExtensionUIContext;
@@ -305,6 +309,8 @@ export class AgentSession {
305
309
 
306
310
  // Base system prompt (without extension appends) - used to apply fresh appends each turn
307
311
  private _baseSystemPrompt = "";
312
+ // Optional prompt-only skill catalog filter. Skills remain loaded and invocable by name.
313
+ private _visibleSkillNames: Set<string> | undefined = undefined;
308
314
 
309
315
  constructor(config: AgentSessionConfig) {
310
316
  this.agent = config.agent;
@@ -321,6 +327,10 @@ export class AgentSession {
321
327
  this._modelRegistry,
322
328
  );
323
329
  this._extensionRunnerRef = config.extensionRunnerRef;
330
+ this._workspaceRootRef = config.workspaceRootRef;
331
+ if (this._workspaceRootRef) {
332
+ this._workspaceRootRef.current = this._cwd;
333
+ }
324
334
  this._initialActiveToolNames = config.initialActiveToolNames;
325
335
  this._baseToolsOverride = config.baseToolsOverride;
326
336
 
@@ -867,6 +877,25 @@ export class AgentSession {
867
877
  this.agent.setSystemPrompt(this._baseSystemPrompt);
868
878
  }
869
879
 
880
+ /**
881
+ * Set or clear a prompt-only filter for the <available_skills> catalog.
882
+ *
883
+ * This does not unload skills or disable the Skill tool. It only controls
884
+ * which loaded skills are advertised in the system prompt on rebuild.
885
+ */
886
+ setVisibleSkillsByName(skillNames: string[] | undefined): void {
887
+ this._visibleSkillNames = skillNames === undefined
888
+ ? undefined
889
+ : new Set(skillNames.map((name) => name.trim().toLowerCase()).filter(Boolean));
890
+ this._baseSystemPrompt = this._rebuildSystemPrompt(this.getActiveToolNames());
891
+ this.agent.setSystemPrompt(this._baseSystemPrompt);
892
+ }
893
+
894
+ /** Get the current prompt-only skill catalog filter, if one is active. */
895
+ getVisibleSkillNames(): string[] | undefined {
896
+ return this._visibleSkillNames ? [...this._visibleSkillNames] : undefined;
897
+ }
898
+
870
899
  /** Whether compaction or branch summarization is currently running */
871
900
  get isCompacting(): boolean {
872
901
  return this._compactionOrchestrator.isCompacting;
@@ -1045,6 +1074,9 @@ export class AgentSession {
1045
1074
  return buildSystemPrompt({
1046
1075
  cwd: this._cwd,
1047
1076
  skills: loadedSkills,
1077
+ skillFilter: this._visibleSkillNames
1078
+ ? (skill) => this._visibleSkillNames!.has(skill.name.trim().toLowerCase())
1079
+ : undefined,
1048
1080
  contextFiles: loadedContextFiles,
1049
1081
  customPrompt: loaderSystemPrompt,
1050
1082
  appendSystemPrompt,
@@ -1626,6 +1658,11 @@ export class AgentSession {
1626
1658
  // message_end/agent_end events fire while listeners are still connected.
1627
1659
  // During agent_end handling the turn is already ending; aborting there can
1628
1660
  // convert a successful auto-mode handoff into an aborted provider message.
1661
+ if (!this.agent.state.isStreaming) {
1662
+ this._retryHandler.abortRetry();
1663
+ await this.agent.waitForIdle();
1664
+ return;
1665
+ }
1629
1666
  await this.abort();
1630
1667
  }
1631
1668
 
@@ -1640,6 +1677,8 @@ export class AgentSession {
1640
1677
  async newSession(options?: {
1641
1678
  parentSession?: string;
1642
1679
  setup?: (sessionManager: SessionManager) => Promise<void>;
1680
+ /** Explicit workspace root for the new session/tool runtime. */
1681
+ workspaceRoot?: string;
1643
1682
  /** See ExtensionCommandContext.newSession for docs (#3731). */
1644
1683
  abortSignal?: AbortSignal;
1645
1684
  }): Promise<boolean> {
@@ -1661,10 +1700,10 @@ export class AgentSession {
1661
1700
  try {
1662
1701
  await this._settleCurrentTurnForSessionTransition();
1663
1702
 
1664
- // #3731: If the caller aborted (e.g. runUnit() timed out and restored cwd to
1665
- // project root), discard this session before capturing process.cwd() and
1666
- // rebuilding the tool runtime. Without this check, the late newSession()
1667
- // would rebuild tools with root cwd, breaking worktree isolation.
1703
+ // #3731: If the caller aborted (e.g. runUnit() timed out while the
1704
+ // worktree was being torn down), discard this session before rebuilding
1705
+ // the tool runtime. Without this check, the late newSession() could
1706
+ // rebuild tools with a stale workspace root.
1668
1707
  if (options?.abortSignal?.aborted) {
1669
1708
  return false;
1670
1709
  }
@@ -1674,15 +1713,21 @@ export class AgentSession {
1674
1713
  } finally {
1675
1714
  this._sessionSwitchPending = false;
1676
1715
  }
1677
- // Update cwd to current process directory auto-mode may have chdir'd
1678
- // into a worktree since the original session was created.
1716
+ // Update the workspace root for the new tool runtime. Auto-mode passes
1717
+ // this explicitly so session routing does not depend on global
1718
+ // process.cwd() after worktree merge/teardown. Other callers keep the
1719
+ // historical default.
1679
1720
  const previousCwd = this._cwd;
1680
- this._cwd = process.cwd();
1721
+ this._cwd = options?.workspaceRoot ?? process.cwd();
1722
+ if (this._workspaceRootRef) {
1723
+ this._workspaceRootRef.current = this._cwd;
1724
+ }
1681
1725
  this.sessionManager.newSession({ parentSession: options?.parentSession });
1682
1726
  this.agent.sessionId = this.sessionManager.getSessionId();
1683
1727
  this._steeringMessages = [];
1684
1728
  this._followUpMessages = [];
1685
1729
  this._pendingNextTurnMessages = [];
1730
+ this._visibleSkillNames = undefined;
1686
1731
 
1687
1732
  this.sessionManager.appendThinkingLevelChange(this.thinkingLevel);
1688
1733
 
@@ -2180,6 +2225,8 @@ export class AgentSession {
2180
2225
  getActiveTools: () => this.getActiveToolNames(),
2181
2226
  getAllTools: () => this.getAllTools(),
2182
2227
  setActiveTools: (toolNames) => this.setActiveToolsByName(toolNames),
2228
+ getVisibleSkills: () => this.getVisibleSkillNames(),
2229
+ setVisibleSkills: (skillNames) => this.setVisibleSkillsByName(skillNames),
2183
2230
  refreshTools: () => this._refreshToolRegistry(),
2184
2231
  getCommands,
2185
2232
  setModel: async (model, options) => {
@@ -2211,6 +2258,9 @@ export class AgentSession {
2211
2258
  })();
2212
2259
  },
2213
2260
  getSystemPrompt: () => this.systemPrompt,
2261
+ setCompactionThresholdOverride: (percent) => {
2262
+ this.settingsManager.setCompactionThresholdOverride(percent);
2263
+ },
2214
2264
  },
2215
2265
  );
2216
2266
  }
@@ -2345,6 +2395,7 @@ export class AgentSession {
2345
2395
  this.settingsManager.reload();
2346
2396
  resetApiProviders();
2347
2397
  await this._resourceLoader.reload();
2398
+ this._visibleSkillNames = undefined;
2348
2399
  this._buildRuntime({
2349
2400
  activeToolNames: this.getActiveToolNames(),
2350
2401
  flagValues: previousFlagValues,
@@ -2534,6 +2585,7 @@ export class AgentSession {
2534
2585
  this._steeringMessages = [];
2535
2586
  this._followUpMessages = [];
2536
2587
  this._pendingNextTurnMessages = [];
2588
+ this._visibleSkillNames = undefined;
2537
2589
 
2538
2590
  // Set new session
2539
2591
  this.sessionManager.setSessionFile(sessionPath);
@@ -1049,7 +1049,9 @@ test("chat-controller rolls up only contiguous low-signal tool runs on message_e
1049
1049
  assert.equal(host.chatContainer.children[1]?.constructor?.name, "AssistantMessageComponent");
1050
1050
  assert.equal(host.chatContainer.children[2]?.constructor?.name, "ToolPhaseSummaryComponent");
1051
1051
  assert.match(host.chatContainer.children[0].render(120).join("\n"), /Setup \/ shell 2 actions/);
1052
- assert.match(host.chatContainer.children[2].render(120).join("\n"), /Context reads 2 actions/);
1052
+ const readSummary = host.chatContainer.children[2].render(120).join("\n");
1053
+ assert.match(readSummary, /Context reads · 2 files/);
1054
+ assert.match(readSummary, /\/tmp\/a · \/tmp\/b/);
1053
1055
  assert.equal(host.chatContainer._prevRender, null, "summary reposition must invalidate the chat container render cache");
1054
1056
  });
1055
1057
 
@@ -1080,7 +1082,9 @@ test("chat-controller rolls up low-signal direct tool execution events on agent_
1080
1082
  } as any);
1081
1083
  }
1082
1084
 
1083
- assert.equal(host.chatContainer.children.length, 3, "direct tool events render as individual rows while running");
1085
+ assert.equal(host.chatContainer.children.length, 1, "direct tool events roll up as they finish");
1086
+ assert.equal(host.chatContainer.children[0]?.constructor?.name, "ToolPhaseSummaryComponent");
1087
+ assert.match(host.chatContainer.children[0].render(120).join("\n"), /Setup \/ shell 3 actions/);
1084
1088
 
1085
1089
  await handleAgentEvent(host, { type: "agent_end" } as any);
1086
1090
 
@@ -86,6 +86,13 @@ export interface CompactionSettings {
86
86
  enabled: boolean;
87
87
  reserveTokens: number;
88
88
  keepRecentTokens: number;
89
+ /**
90
+ * Optional percent-of-context-window threshold (0 < value < 1). When set,
91
+ * `shouldCompact()` fires once `contextTokens > contextWindow * thresholdPercent`,
92
+ * overriding the absolute `reserveTokens` calculation. Lets host integrations
93
+ * (e.g. GSD) express compaction policy as a fraction independent of model size.
94
+ */
95
+ thresholdPercent?: number;
89
96
  }
90
97
 
91
98
  export const DEFAULT_COMPACTION_SETTINGS: CompactionSettings = {
@@ -185,9 +192,20 @@ export function estimateContextTokens(messages: AgentMessage[]): ContextUsageEst
185
192
 
186
193
  /**
187
194
  * Check if compaction should trigger based on context usage.
195
+ *
196
+ * When `thresholdPercent` is set (and within (0, 1)), it overrides the absolute
197
+ * `reserveTokens` calculation: compaction fires at `contextWindow * thresholdPercent`.
198
+ * Otherwise the legacy `contextWindow - reserveTokens` headroom is used.
188
199
  */
189
200
  export function shouldCompact(contextTokens: number, contextWindow: number, settings: CompactionSettings): boolean {
190
201
  if (!settings.enabled) return false;
202
+ if (
203
+ settings.thresholdPercent !== undefined &&
204
+ settings.thresholdPercent > 0 &&
205
+ settings.thresholdPercent < 1
206
+ ) {
207
+ return contextTokens > contextWindow * settings.thresholdPercent;
208
+ }
191
209
  return contextTokens > contextWindow - settings.reserveTokens;
192
210
  }
193
211