commandmate 0.29.2 → 0.30.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (653) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-build-manifest.json +271 -264
  3. package/.next/app-path-routes-manifest.json +35 -34
  4. package/.next/build-manifest.json +2 -2
  5. package/.next/prerender-manifest.json +3 -3
  6. package/.next/required-server-files.json +1 -1
  7. package/.next/routes-manifest.json +8 -8
  8. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  9. package/.next/server/app/api/agents/update/route_client-reference-manifest.js +1 -1
  10. package/.next/server/app/api/agents/versions/route_client-reference-manifest.js +1 -1
  11. package/.next/server/app/api/app/update/route_client-reference-manifest.js +1 -1
  12. package/.next/server/app/api/app/update-check/route.js +1 -1
  13. package/.next/server/app/api/app/update-check/route_client-reference-manifest.js +1 -1
  14. package/.next/server/app/api/assistant/conversation/route.js +1 -1
  15. package/.next/server/app/api/assistant/conversation/route.js.nft.json +1 -1
  16. package/.next/server/app/api/assistant/conversation/route_client-reference-manifest.js +1 -1
  17. package/.next/server/app/api/assistant/current-output/route.js +1 -1
  18. package/.next/server/app/api/assistant/current-output/route.js.nft.json +1 -1
  19. package/.next/server/app/api/assistant/current-output/route_client-reference-manifest.js +1 -1
  20. package/.next/server/app/api/assistant/messages/route.js +1 -1
  21. package/.next/server/app/api/assistant/messages/route.js.nft.json +1 -1
  22. package/.next/server/app/api/assistant/messages/route_client-reference-manifest.js +1 -1
  23. package/.next/server/app/api/assistant/session/route.js +1 -1
  24. package/.next/server/app/api/assistant/session/route.js.nft.json +1 -1
  25. package/.next/server/app/api/assistant/session/route_client-reference-manifest.js +1 -1
  26. package/.next/server/app/api/assistant/start/route.js +18 -18
  27. package/.next/server/app/api/assistant/start/route.js.nft.json +1 -1
  28. package/.next/server/app/api/assistant/start/route_client-reference-manifest.js +1 -1
  29. package/.next/server/app/api/assistant/terminal/route.js +19 -19
  30. package/.next/server/app/api/assistant/terminal/route.js.nft.json +1 -1
  31. package/.next/server/app/api/assistant/terminal/route_client-reference-manifest.js +1 -1
  32. package/.next/server/app/api/assistant/tools/route.js +1 -1
  33. package/.next/server/app/api/assistant/tools/route.js.nft.json +1 -1
  34. package/.next/server/app/api/assistant/tools/route_client-reference-manifest.js +1 -1
  35. package/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
  36. package/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
  37. package/.next/server/app/api/auth/status/route_client-reference-manifest.js +1 -1
  38. package/.next/server/app/api/capabilities/route.js +1 -1
  39. package/.next/server/app/api/capabilities/route_client-reference-manifest.js +1 -1
  40. package/.next/server/app/api/daily-summary/route.js +1 -1
  41. package/.next/server/app/api/daily-summary/route_client-reference-manifest.js +1 -1
  42. package/.next/server/app/api/daily-summary/status/route_client-reference-manifest.js +1 -1
  43. package/.next/server/app/api/external-apps/[id]/health/route_client-reference-manifest.js +1 -1
  44. package/.next/server/app/api/external-apps/[id]/route_client-reference-manifest.js +1 -1
  45. package/.next/server/app/api/external-apps/route_client-reference-manifest.js +1 -1
  46. package/.next/server/app/api/fs/browse/route_client-reference-manifest.js +1 -1
  47. package/.next/server/app/api/fs/recent-paths/route_client-reference-manifest.js +1 -1
  48. package/.next/server/app/api/hooks/agent-event/route.js +1 -1
  49. package/.next/server/app/api/hooks/agent-event/route.js.nft.json +1 -1
  50. package/.next/server/app/api/hooks/agent-event/route_client-reference-manifest.js +1 -1
  51. package/.next/server/app/api/hooks/claude-done/route.js +2 -2
  52. package/.next/server/app/api/hooks/claude-done/route.js.nft.json +1 -1
  53. package/.next/server/app/api/hooks/claude-done/route_client-reference-manifest.js +1 -1
  54. package/.next/server/app/api/hooks/permission-request/route.js +1 -1
  55. package/.next/server/app/api/hooks/permission-request/route.js.nft.json +1 -1
  56. package/.next/server/app/api/hooks/permission-request/route_client-reference-manifest.js +1 -1
  57. package/.next/server/app/api/metrics/vibe/route_client-reference-manifest.js +1 -1
  58. package/.next/server/app/api/ollama/models/route_client-reference-manifest.js +1 -1
  59. package/.next/server/app/api/push/escalation/route.js +1 -1
  60. package/.next/server/app/api/push/escalation/route_client-reference-manifest.js +1 -1
  61. package/.next/server/app/api/push/subscriptions/route_client-reference-manifest.js +1 -1
  62. package/.next/server/app/api/push/vapid/route.js +1 -1
  63. package/.next/server/app/api/push/vapid/route_client-reference-manifest.js +1 -1
  64. package/.next/server/app/api/remote/pair/route_client-reference-manifest.js +1 -1
  65. package/.next/server/app/api/repositories/[id]/route_client-reference-manifest.js +1 -1
  66. package/.next/server/app/api/repositories/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
  67. package/.next/server/app/api/repositories/[id]/todos/route_client-reference-manifest.js +1 -1
  68. package/.next/server/app/api/repositories/clone/[jobId]/route.js +1 -1
  69. package/.next/server/app/api/repositories/clone/[jobId]/route.js.nft.json +1 -1
  70. package/.next/server/app/api/repositories/clone/[jobId]/route_client-reference-manifest.js +1 -1
  71. package/.next/server/app/api/repositories/clone/route.js +1 -1
  72. package/.next/server/app/api/repositories/clone/route.js.nft.json +1 -1
  73. package/.next/server/app/api/repositories/clone/route_client-reference-manifest.js +1 -1
  74. package/.next/server/app/api/repositories/excluded/route_client-reference-manifest.js +1 -1
  75. package/.next/server/app/api/repositories/restore/route.js +1 -1
  76. package/.next/server/app/api/repositories/restore/route.js.nft.json +1 -1
  77. package/.next/server/app/api/repositories/restore/route_client-reference-manifest.js +1 -1
  78. package/.next/server/app/api/repositories/route.js +1 -1
  79. package/.next/server/app/api/repositories/route.js.nft.json +1 -1
  80. package/.next/server/app/api/repositories/route_client-reference-manifest.js +1 -1
  81. package/.next/server/app/api/repositories/scan/route.js +1 -1
  82. package/.next/server/app/api/repositories/scan/route.js.nft.json +1 -1
  83. package/.next/server/app/api/repositories/scan/route_client-reference-manifest.js +1 -1
  84. package/.next/server/app/api/repositories/sync/route.js +1 -1
  85. package/.next/server/app/api/repositories/sync/route.js.nft.json +1 -1
  86. package/.next/server/app/api/repositories/sync/route_client-reference-manifest.js +1 -1
  87. package/.next/server/app/api/repositories/validate-path/route_client-reference-manifest.js +1 -1
  88. package/.next/server/app/api/settings/default-agents/route.js +1 -1
  89. package/.next/server/app/api/settings/default-agents/route.js.nft.json +1 -1
  90. package/.next/server/app/api/settings/default-agents/route_client-reference-manifest.js +1 -1
  91. package/.next/server/app/api/settings/default-surface-mode/route.js +1 -0
  92. package/.next/server/app/api/settings/default-surface-mode/route.js.nft.json +1 -0
  93. package/.next/server/app/api/settings/default-surface-mode/route_client-reference-manifest.js +1 -0
  94. package/.next/server/app/api/sidebar/group-order/route_client-reference-manifest.js +1 -1
  95. package/.next/server/app/api/skills/[id]/route_client-reference-manifest.js +1 -1
  96. package/.next/server/app/api/skills/installations/route_client-reference-manifest.js +1 -1
  97. package/.next/server/app/api/skills/operations/route_client-reference-manifest.js +1 -1
  98. package/.next/server/app/api/skills/reindex/route_client-reference-manifest.js +1 -1
  99. package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
  100. package/.next/server/app/api/slash-commands/route_client-reference-manifest.js +1 -1
  101. package/.next/server/app/api/tasks/[taskId]/cancel/route_client-reference-manifest.js +1 -1
  102. package/.next/server/app/api/tasks/[taskId]/route_client-reference-manifest.js +1 -1
  103. package/.next/server/app/api/templates/[id]/route_client-reference-manifest.js +1 -1
  104. package/.next/server/app/api/templates/route_client-reference-manifest.js +1 -1
  105. package/.next/server/app/api/todos/route_client-reference-manifest.js +1 -1
  106. package/.next/server/app/api/verification/runs/[runId]/route_client-reference-manifest.js +1 -1
  107. package/.next/server/app/api/verification/runs/route_client-reference-manifest.js +1 -1
  108. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js +1 -1
  109. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js.nft.json +1 -1
  110. package/.next/server/app/api/worktrees/[id]/auto-yes/route_client-reference-manifest.js +1 -1
  111. package/.next/server/app/api/worktrees/[id]/capture/route.js +1 -1
  112. package/.next/server/app/api/worktrees/[id]/capture/route.js.nft.json +1 -1
  113. package/.next/server/app/api/worktrees/[id]/capture/route_client-reference-manifest.js +1 -1
  114. package/.next/server/app/api/worktrees/[id]/clear-composer/route.js +1 -1
  115. package/.next/server/app/api/worktrees/[id]/clear-composer/route.js.nft.json +1 -1
  116. package/.next/server/app/api/worktrees/[id]/clear-composer/route_client-reference-manifest.js +1 -1
  117. package/.next/server/app/api/worktrees/[id]/cli-reference/route.js +1 -0
  118. package/.next/server/app/api/worktrees/[id]/cli-reference/route.js.nft.json +1 -0
  119. package/.next/server/app/api/worktrees/[id]/cli-reference/route_client-reference-manifest.js +1 -0
  120. package/.next/server/app/api/worktrees/[id]/cli-tool/route_client-reference-manifest.js +1 -1
  121. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route_client-reference-manifest.js +1 -1
  122. package/.next/server/app/api/worktrees/[id]/current-output/route.js +1 -1
  123. package/.next/server/app/api/worktrees/[id]/current-output/route.js.nft.json +1 -1
  124. package/.next/server/app/api/worktrees/[id]/current-output/route_client-reference-manifest.js +1 -1
  125. package/.next/server/app/api/worktrees/[id]/env/route_client-reference-manifest.js +1 -1
  126. package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route_client-reference-manifest.js +1 -1
  127. package/.next/server/app/api/worktrees/[id]/execution-logs/route_client-reference-manifest.js +1 -1
  128. package/.next/server/app/api/worktrees/[id]/files/[...path]/route_client-reference-manifest.js +1 -1
  129. package/.next/server/app/api/worktrees/[id]/git/branch/create/route_client-reference-manifest.js +1 -1
  130. package/.next/server/app/api/worktrees/[id]/git/branch/delete/route_client-reference-manifest.js +1 -1
  131. package/.next/server/app/api/worktrees/[id]/git/branches/route_client-reference-manifest.js +1 -1
  132. package/.next/server/app/api/worktrees/[id]/git/checkout/route_client-reference-manifest.js +1 -1
  133. package/.next/server/app/api/worktrees/[id]/git/commit/route_client-reference-manifest.js +1 -1
  134. package/.next/server/app/api/worktrees/[id]/git/diff/route_client-reference-manifest.js +1 -1
  135. package/.next/server/app/api/worktrees/[id]/git/fetch/route_client-reference-manifest.js +1 -1
  136. package/.next/server/app/api/worktrees/[id]/git/log/route_client-reference-manifest.js +1 -1
  137. package/.next/server/app/api/worktrees/[id]/git/pull/route_client-reference-manifest.js +1 -1
  138. package/.next/server/app/api/worktrees/[id]/git/push/route_client-reference-manifest.js +1 -1
  139. package/.next/server/app/api/worktrees/[id]/git/reset/route_client-reference-manifest.js +1 -1
  140. package/.next/server/app/api/worktrees/[id]/git/revert/route_client-reference-manifest.js +1 -1
  141. package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route_client-reference-manifest.js +1 -1
  142. package/.next/server/app/api/worktrees/[id]/git/stage/route_client-reference-manifest.js +1 -1
  143. package/.next/server/app/api/worktrees/[id]/git/staged/route_client-reference-manifest.js +1 -1
  144. package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route_client-reference-manifest.js +1 -1
  145. package/.next/server/app/api/worktrees/[id]/git/stash/apply/route_client-reference-manifest.js +1 -1
  146. package/.next/server/app/api/worktrees/[id]/git/stash/pop/route_client-reference-manifest.js +1 -1
  147. package/.next/server/app/api/worktrees/[id]/git/stash/push/route_client-reference-manifest.js +1 -1
  148. package/.next/server/app/api/worktrees/[id]/git/stash/route_client-reference-manifest.js +1 -1
  149. package/.next/server/app/api/worktrees/[id]/git/status/route_client-reference-manifest.js +1 -1
  150. package/.next/server/app/api/worktrees/[id]/git/unstage/route_client-reference-manifest.js +1 -1
  151. package/.next/server/app/api/worktrees/[id]/git/working-diff/route_client-reference-manifest.js +1 -1
  152. package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js +1 -1
  153. package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js.nft.json +1 -1
  154. package/.next/server/app/api/worktrees/[id]/instances/opencode/route_client-reference-manifest.js +1 -1
  155. package/.next/server/app/api/worktrees/[id]/interrupt/route.js +1 -1
  156. package/.next/server/app/api/worktrees/[id]/interrupt/route.js.nft.json +1 -1
  157. package/.next/server/app/api/worktrees/[id]/interrupt/route_client-reference-manifest.js +1 -1
  158. package/.next/server/app/api/worktrees/[id]/kill-session/route.js +1 -1
  159. package/.next/server/app/api/worktrees/[id]/kill-session/route.js.nft.json +1 -1
  160. package/.next/server/app/api/worktrees/[id]/kill-session/route_client-reference-manifest.js +1 -1
  161. package/.next/server/app/api/worktrees/[id]/logs/[filename]/route_client-reference-manifest.js +1 -1
  162. package/.next/server/app/api/worktrees/[id]/logs/route_client-reference-manifest.js +1 -1
  163. package/.next/server/app/api/worktrees/[id]/marp-render/route_client-reference-manifest.js +1 -1
  164. package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route_client-reference-manifest.js +1 -1
  165. package/.next/server/app/api/worktrees/[id]/memos/route_client-reference-manifest.js +1 -1
  166. package/.next/server/app/api/worktrees/[id]/messages/route_client-reference-manifest.js +1 -1
  167. package/.next/server/app/api/worktrees/[id]/opencode/diff/route_client-reference-manifest.js +1 -1
  168. package/.next/server/app/api/worktrees/[id]/opencode/session/route.js +1 -1
  169. package/.next/server/app/api/worktrees/[id]/opencode/session/route_client-reference-manifest.js +1 -1
  170. package/.next/server/app/api/worktrees/[id]/opencode/share/route.js +1 -1
  171. package/.next/server/app/api/worktrees/[id]/opencode/share/route_client-reference-manifest.js +1 -1
  172. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js +1 -1
  173. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js.nft.json +1 -1
  174. package/.next/server/app/api/worktrees/[id]/prompt-response/route_client-reference-manifest.js +1 -1
  175. package/.next/server/app/api/worktrees/[id]/resolve-target/route.js +1 -1
  176. package/.next/server/app/api/worktrees/[id]/resolve-target/route_client-reference-manifest.js +1 -1
  177. package/.next/server/app/api/worktrees/[id]/respond/route.js +1 -1
  178. package/.next/server/app/api/worktrees/[id]/respond/route.js.nft.json +1 -1
  179. package/.next/server/app/api/worktrees/[id]/respond/route_client-reference-manifest.js +1 -1
  180. package/.next/server/app/api/worktrees/[id]/route.js +1 -1
  181. package/.next/server/app/api/worktrees/[id]/route.js.nft.json +1 -1
  182. package/.next/server/app/api/worktrees/[id]/route_client-reference-manifest.js +1 -1
  183. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route_client-reference-manifest.js +1 -1
  184. package/.next/server/app/api/worktrees/[id]/schedules/active/route_client-reference-manifest.js +1 -1
  185. package/.next/server/app/api/worktrees/[id]/schedules/route_client-reference-manifest.js +1 -1
  186. package/.next/server/app/api/worktrees/[id]/search/route_client-reference-manifest.js +1 -1
  187. package/.next/server/app/api/worktrees/[id]/send/route.js +1 -1
  188. package/.next/server/app/api/worktrees/[id]/send/route.js.nft.json +1 -1
  189. package/.next/server/app/api/worktrees/[id]/send/route_client-reference-manifest.js +1 -1
  190. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js +1 -1
  191. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js.nft.json +1 -1
  192. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route_client-reference-manifest.js +1 -1
  193. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route_client-reference-manifest.js +1 -1
  194. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route_client-reference-manifest.js +1 -1
  195. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route_client-reference-manifest.js +1 -1
  196. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route_client-reference-manifest.js +1 -1
  197. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update/route_client-reference-manifest.js +1 -1
  198. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route_client-reference-manifest.js +1 -1
  199. package/.next/server/app/api/worktrees/[id]/skills/route_client-reference-manifest.js +1 -1
  200. package/.next/server/app/api/worktrees/[id]/slash-commands/route_client-reference-manifest.js +1 -1
  201. package/.next/server/app/api/worktrees/[id]/special-keys/route.js +1 -1
  202. package/.next/server/app/api/worktrees/[id]/special-keys/route.js.nft.json +1 -1
  203. package/.next/server/app/api/worktrees/[id]/special-keys/route_client-reference-manifest.js +1 -1
  204. package/.next/server/app/api/worktrees/[id]/tasks/route_client-reference-manifest.js +1 -1
  205. package/.next/server/app/api/worktrees/[id]/terminal/route.js +1 -1
  206. package/.next/server/app/api/worktrees/[id]/terminal/route.js.nft.json +1 -1
  207. package/.next/server/app/api/worktrees/[id]/terminal/route_client-reference-manifest.js +1 -1
  208. package/.next/server/app/api/worktrees/[id]/timers/history/route_client-reference-manifest.js +1 -1
  209. package/.next/server/app/api/worktrees/[id]/timers/route.js +1 -1
  210. package/.next/server/app/api/worktrees/[id]/timers/route.js.nft.json +1 -1
  211. package/.next/server/app/api/worktrees/[id]/timers/route_client-reference-manifest.js +1 -1
  212. package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
  213. package/.next/server/app/api/worktrees/[id]/todos/route_client-reference-manifest.js +1 -1
  214. package/.next/server/app/api/worktrees/[id]/tree/[...path]/route_client-reference-manifest.js +1 -1
  215. package/.next/server/app/api/worktrees/[id]/tree/route_client-reference-manifest.js +1 -1
  216. package/.next/server/app/api/worktrees/[id]/upload/[...path]/route_client-reference-manifest.js +1 -1
  217. package/.next/server/app/api/worktrees/[id]/verify/config/route_client-reference-manifest.js +1 -1
  218. package/.next/server/app/api/worktrees/[id]/verify/route_client-reference-manifest.js +1 -1
  219. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route_client-reference-manifest.js +1 -1
  220. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route_client-reference-manifest.js +1 -1
  221. package/.next/server/app/api/worktrees/[id]/verify/runs/route_client-reference-manifest.js +1 -1
  222. package/.next/server/app/api/worktrees/[id]/viewed/route_client-reference-manifest.js +1 -1
  223. package/.next/server/app/api/worktrees/apply-default-agents/route.js +1 -1
  224. package/.next/server/app/api/worktrees/apply-default-agents/route_client-reference-manifest.js +1 -1
  225. package/.next/server/app/api/worktrees/route.js +1 -1
  226. package/.next/server/app/api/worktrees/route.js.nft.json +1 -1
  227. package/.next/server/app/api/worktrees/route_client-reference-manifest.js +1 -1
  228. package/.next/server/app/chat/page_client-reference-manifest.js +1 -1
  229. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  230. package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
  231. package/.next/server/app/more/page.js +2 -2
  232. package/.next/server/app/more/page.js.nft.json +1 -1
  233. package/.next/server/app/more/page_client-reference-manifest.js +1 -1
  234. package/.next/server/app/offline/page_client-reference-manifest.js +1 -1
  235. package/.next/server/app/page_client-reference-manifest.js +1 -1
  236. package/.next/server/app/proxy/[...path]/route_client-reference-manifest.js +1 -1
  237. package/.next/server/app/repositories/page_client-reference-manifest.js +1 -1
  238. package/.next/server/app/review/page_client-reference-manifest.js +1 -1
  239. package/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  240. package/.next/server/app/skills/[skillId]/page_client-reference-manifest.js +1 -1
  241. package/.next/server/app/skills/installed/page_client-reference-manifest.js +1 -1
  242. package/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  243. package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -1
  244. package/.next/server/app/worktrees/[id]/page.js +11 -11
  245. package/.next/server/app/worktrees/[id]/page.js.nft.json +1 -1
  246. package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -1
  247. package/.next/server/app/worktrees/[id]/terminal/page.js +3 -3
  248. package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
  249. package/.next/server/app-paths-manifest.json +35 -34
  250. package/.next/server/chunks/1058.js +1 -1
  251. package/.next/server/chunks/1068.js +1 -1
  252. package/.next/server/chunks/1191.js +1 -1
  253. package/.next/server/chunks/1341.js +1 -1
  254. package/.next/server/chunks/1886.js +3 -3
  255. package/.next/server/chunks/2119.js +1 -1
  256. package/.next/server/chunks/2445.js +1 -1
  257. package/.next/server/chunks/261.js +1 -0
  258. package/.next/server/chunks/2739.js +1 -0
  259. package/.next/server/chunks/2816.js +1 -1
  260. package/.next/server/chunks/3099.js +5 -0
  261. package/.next/server/chunks/3123.js +1 -0
  262. package/.next/server/chunks/3241.js +1 -1
  263. package/.next/server/chunks/3543.js +1 -1
  264. package/.next/server/chunks/3945.js +1 -1
  265. package/.next/server/chunks/4325.js +1 -0
  266. package/.next/server/chunks/4390.js +1 -1
  267. package/.next/server/chunks/4393.js +1 -1
  268. package/.next/server/chunks/4443.js +6 -0
  269. package/.next/server/chunks/5017.js +1 -1
  270. package/.next/server/chunks/5043.js +1 -0
  271. package/.next/server/chunks/5120.js +1 -0
  272. package/.next/server/chunks/552.js +25 -0
  273. package/.next/server/chunks/6130.js +1 -1
  274. package/.next/server/chunks/6337.js +1 -1
  275. package/.next/server/chunks/663.js +1 -1
  276. package/.next/server/chunks/6894.js +8 -0
  277. package/.next/server/chunks/7685.js +1 -1
  278. package/.next/server/chunks/7836.js +1 -0
  279. package/.next/server/chunks/8356.js +1 -1
  280. package/.next/server/chunks/880.js +1 -1
  281. package/.next/server/chunks/8807.js +1 -1
  282. package/.next/server/chunks/9123.js +2 -2
  283. package/.next/server/chunks/9130.js +3 -3
  284. package/.next/server/chunks/9627.js +48 -26
  285. package/.next/server/chunks/9696.js +3 -0
  286. package/.next/server/chunks/9798.js +1 -1
  287. package/.next/server/middleware-manifest.json +5 -5
  288. package/.next/server/pages/500.html +1 -1
  289. package/.next/server/server-reference-manifest.json +1 -1
  290. package/.next/server/src/middleware.js +1 -1
  291. package/.next/server/src/middleware.js.map +1 -1
  292. package/.next/static/chunks/{4882-388e94fe0a03c2ba.js → 3916-0e929d089282dc5d.js} +1 -1
  293. package/.next/static/chunks/{5229-b2a81bb8fb5c19e9.js → 5229-6c89475b61bd2c8b.js} +1 -1
  294. package/.next/static/chunks/6022-7a7d1760fc9814c7.js +1 -0
  295. package/.next/static/chunks/6381-dbf04a99647f6018.js +1 -0
  296. package/.next/static/chunks/app/api/agents/update/route-ee11f7b8a34cba8c.js +1 -0
  297. package/.next/static/chunks/app/api/agents/versions/route-ee11f7b8a34cba8c.js +1 -0
  298. package/.next/static/chunks/app/api/app/update/route-ee11f7b8a34cba8c.js +1 -0
  299. package/.next/static/chunks/app/api/app/update-check/route-ee11f7b8a34cba8c.js +1 -0
  300. package/.next/static/chunks/app/api/assistant/conversation/route-ee11f7b8a34cba8c.js +1 -0
  301. package/.next/static/chunks/app/api/assistant/current-output/route-ee11f7b8a34cba8c.js +1 -0
  302. package/.next/static/chunks/app/api/assistant/messages/route-ee11f7b8a34cba8c.js +1 -0
  303. package/.next/static/chunks/app/api/assistant/session/route-ee11f7b8a34cba8c.js +1 -0
  304. package/.next/static/chunks/app/api/assistant/start/route-ee11f7b8a34cba8c.js +1 -0
  305. package/.next/static/chunks/app/api/assistant/terminal/route-ee11f7b8a34cba8c.js +1 -0
  306. package/.next/static/chunks/app/api/assistant/tools/route-ee11f7b8a34cba8c.js +1 -0
  307. package/.next/static/chunks/app/api/auth/login/route-ee11f7b8a34cba8c.js +1 -0
  308. package/.next/static/chunks/app/api/auth/logout/route-ee11f7b8a34cba8c.js +1 -0
  309. package/.next/static/chunks/app/api/auth/status/route-ee11f7b8a34cba8c.js +1 -0
  310. package/.next/static/chunks/app/api/capabilities/route-ee11f7b8a34cba8c.js +1 -0
  311. package/.next/static/chunks/app/api/daily-summary/route-ee11f7b8a34cba8c.js +1 -0
  312. package/.next/static/chunks/app/api/daily-summary/status/route-ee11f7b8a34cba8c.js +1 -0
  313. package/.next/static/chunks/app/api/external-apps/[id]/health/route-ee11f7b8a34cba8c.js +1 -0
  314. package/.next/static/chunks/app/api/external-apps/[id]/route-ee11f7b8a34cba8c.js +1 -0
  315. package/.next/static/chunks/app/api/external-apps/route-ee11f7b8a34cba8c.js +1 -0
  316. package/.next/static/chunks/app/api/fs/browse/route-ee11f7b8a34cba8c.js +1 -0
  317. package/.next/static/chunks/app/api/fs/recent-paths/route-ee11f7b8a34cba8c.js +1 -0
  318. package/.next/static/chunks/app/api/hooks/agent-event/route-ee11f7b8a34cba8c.js +1 -0
  319. package/.next/static/chunks/app/api/hooks/claude-done/route-ee11f7b8a34cba8c.js +1 -0
  320. package/.next/static/chunks/app/api/hooks/permission-request/route-ee11f7b8a34cba8c.js +1 -0
  321. package/.next/static/chunks/app/api/metrics/vibe/route-ee11f7b8a34cba8c.js +1 -0
  322. package/.next/static/chunks/app/api/ollama/models/route-ee11f7b8a34cba8c.js +1 -0
  323. package/.next/static/chunks/app/api/push/escalation/route-ee11f7b8a34cba8c.js +1 -0
  324. package/.next/static/chunks/app/api/push/subscriptions/route-ee11f7b8a34cba8c.js +1 -0
  325. package/.next/static/chunks/app/api/push/vapid/route-ee11f7b8a34cba8c.js +1 -0
  326. package/.next/static/chunks/app/api/remote/pair/route-ee11f7b8a34cba8c.js +1 -0
  327. package/.next/static/chunks/app/api/repositories/[id]/route-ee11f7b8a34cba8c.js +1 -0
  328. package/.next/static/chunks/app/api/repositories/[id]/todos/[todoId]/route-ee11f7b8a34cba8c.js +1 -0
  329. package/.next/static/chunks/app/api/repositories/[id]/todos/route-ee11f7b8a34cba8c.js +1 -0
  330. package/.next/static/chunks/app/api/repositories/clone/[jobId]/route-ee11f7b8a34cba8c.js +1 -0
  331. package/.next/static/chunks/app/api/repositories/clone/route-ee11f7b8a34cba8c.js +1 -0
  332. package/.next/static/chunks/app/api/repositories/excluded/route-ee11f7b8a34cba8c.js +1 -0
  333. package/.next/static/chunks/app/api/repositories/restore/route-ee11f7b8a34cba8c.js +1 -0
  334. package/.next/static/chunks/app/api/repositories/route-ee11f7b8a34cba8c.js +1 -0
  335. package/.next/static/chunks/app/api/repositories/scan/route-ee11f7b8a34cba8c.js +1 -0
  336. package/.next/static/chunks/app/api/repositories/sync/route-ee11f7b8a34cba8c.js +1 -0
  337. package/.next/static/chunks/app/api/repositories/validate-path/route-ee11f7b8a34cba8c.js +1 -0
  338. package/.next/static/chunks/app/api/settings/default-agents/route-ee11f7b8a34cba8c.js +1 -0
  339. package/.next/static/chunks/app/api/settings/default-surface-mode/route-ee11f7b8a34cba8c.js +1 -0
  340. package/.next/static/chunks/app/api/sidebar/group-order/route-ee11f7b8a34cba8c.js +1 -0
  341. package/.next/static/chunks/app/api/skills/[id]/route-ee11f7b8a34cba8c.js +1 -0
  342. package/.next/static/chunks/app/api/skills/installations/route-ee11f7b8a34cba8c.js +1 -0
  343. package/.next/static/chunks/app/api/skills/operations/route-ee11f7b8a34cba8c.js +1 -0
  344. package/.next/static/chunks/app/api/skills/reindex/route-ee11f7b8a34cba8c.js +1 -0
  345. package/.next/static/chunks/app/api/skills/route-ee11f7b8a34cba8c.js +1 -0
  346. package/.next/static/chunks/app/api/slash-commands/route-ee11f7b8a34cba8c.js +1 -0
  347. package/.next/static/chunks/app/api/tasks/[taskId]/cancel/route-ee11f7b8a34cba8c.js +1 -0
  348. package/.next/static/chunks/app/api/tasks/[taskId]/route-ee11f7b8a34cba8c.js +1 -0
  349. package/.next/static/chunks/app/api/templates/[id]/route-ee11f7b8a34cba8c.js +1 -0
  350. package/.next/static/chunks/app/api/templates/route-ee11f7b8a34cba8c.js +1 -0
  351. package/.next/static/chunks/app/api/todos/route-ee11f7b8a34cba8c.js +1 -0
  352. package/.next/static/chunks/app/api/verification/runs/[runId]/route-ee11f7b8a34cba8c.js +1 -0
  353. package/.next/static/chunks/app/api/verification/runs/route-ee11f7b8a34cba8c.js +1 -0
  354. package/.next/static/chunks/app/api/worktrees/[id]/auto-yes/route-ee11f7b8a34cba8c.js +1 -0
  355. package/.next/static/chunks/app/api/worktrees/[id]/capture/route-ee11f7b8a34cba8c.js +1 -0
  356. package/.next/static/chunks/app/api/worktrees/[id]/clear-composer/route-ee11f7b8a34cba8c.js +1 -0
  357. package/.next/static/chunks/app/api/worktrees/[id]/cli-reference/route-ee11f7b8a34cba8c.js +1 -0
  358. package/.next/static/chunks/app/api/worktrees/[id]/cli-tool/route-ee11f7b8a34cba8c.js +1 -0
  359. package/.next/static/chunks/app/api/worktrees/[id]/cmate/schedules/route-ee11f7b8a34cba8c.js +1 -0
  360. package/.next/static/chunks/app/api/worktrees/[id]/current-output/route-ee11f7b8a34cba8c.js +1 -0
  361. package/.next/static/chunks/app/api/worktrees/[id]/env/route-ee11f7b8a34cba8c.js +1 -0
  362. package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/[logId]/route-ee11f7b8a34cba8c.js +1 -0
  363. package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/route-ee11f7b8a34cba8c.js +1 -0
  364. package/.next/static/chunks/app/api/worktrees/[id]/files/[...path]/route-ee11f7b8a34cba8c.js +1 -0
  365. package/.next/static/chunks/app/api/worktrees/[id]/git/branch/create/route-ee11f7b8a34cba8c.js +1 -0
  366. package/.next/static/chunks/app/api/worktrees/[id]/git/branch/delete/route-ee11f7b8a34cba8c.js +1 -0
  367. package/.next/static/chunks/app/api/worktrees/[id]/git/branches/route-ee11f7b8a34cba8c.js +1 -0
  368. package/.next/static/chunks/app/api/worktrees/[id]/git/checkout/route-ee11f7b8a34cba8c.js +1 -0
  369. package/.next/static/chunks/app/api/worktrees/[id]/git/commit/route-ee11f7b8a34cba8c.js +1 -0
  370. package/.next/static/chunks/app/api/worktrees/[id]/git/diff/route-ee11f7b8a34cba8c.js +1 -0
  371. package/.next/static/chunks/app/api/worktrees/[id]/git/fetch/route-ee11f7b8a34cba8c.js +1 -0
  372. package/.next/static/chunks/app/api/worktrees/[id]/git/log/route-ee11f7b8a34cba8c.js +1 -0
  373. package/.next/static/chunks/app/api/worktrees/[id]/git/pull/route-ee11f7b8a34cba8c.js +1 -0
  374. package/.next/static/chunks/app/api/worktrees/[id]/git/push/route-ee11f7b8a34cba8c.js +1 -0
  375. package/.next/static/chunks/app/api/worktrees/[id]/git/reset/route-ee11f7b8a34cba8c.js +1 -0
  376. package/.next/static/chunks/app/api/worktrees/[id]/git/revert/route-ee11f7b8a34cba8c.js +1 -0
  377. package/.next/static/chunks/app/api/worktrees/[id]/git/show/[commitHash]/route-ee11f7b8a34cba8c.js +1 -0
  378. package/.next/static/chunks/app/api/worktrees/[id]/git/stage/route-ee11f7b8a34cba8c.js +1 -0
  379. package/.next/static/chunks/app/api/worktrees/[id]/git/staged/route-ee11f7b8a34cba8c.js +1 -0
  380. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/[index]/route-ee11f7b8a34cba8c.js +1 -0
  381. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/apply/route-ee11f7b8a34cba8c.js +1 -0
  382. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/pop/route-ee11f7b8a34cba8c.js +1 -0
  383. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/push/route-ee11f7b8a34cba8c.js +1 -0
  384. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/route-ee11f7b8a34cba8c.js +1 -0
  385. package/.next/static/chunks/app/api/worktrees/[id]/git/status/route-ee11f7b8a34cba8c.js +1 -0
  386. package/.next/static/chunks/app/api/worktrees/[id]/git/unstage/route-ee11f7b8a34cba8c.js +1 -0
  387. package/.next/static/chunks/app/api/worktrees/[id]/git/working-diff/route-ee11f7b8a34cba8c.js +1 -0
  388. package/.next/static/chunks/app/api/worktrees/[id]/instances/opencode/route-ee11f7b8a34cba8c.js +1 -0
  389. package/.next/static/chunks/app/api/worktrees/[id]/interrupt/route-ee11f7b8a34cba8c.js +1 -0
  390. package/.next/static/chunks/app/api/worktrees/[id]/kill-session/route-ee11f7b8a34cba8c.js +1 -0
  391. package/.next/static/chunks/app/api/worktrees/[id]/logs/[filename]/route-ee11f7b8a34cba8c.js +1 -0
  392. package/.next/static/chunks/app/api/worktrees/[id]/logs/route-ee11f7b8a34cba8c.js +1 -0
  393. package/.next/static/chunks/app/api/worktrees/[id]/marp-render/route-ee11f7b8a34cba8c.js +1 -0
  394. package/.next/static/chunks/app/api/worktrees/[id]/memos/[memoId]/route-ee11f7b8a34cba8c.js +1 -0
  395. package/.next/static/chunks/app/api/worktrees/[id]/memos/route-ee11f7b8a34cba8c.js +1 -0
  396. package/.next/static/chunks/app/api/worktrees/[id]/messages/route-ee11f7b8a34cba8c.js +1 -0
  397. package/.next/static/chunks/app/api/worktrees/[id]/opencode/diff/route-ee11f7b8a34cba8c.js +1 -0
  398. package/.next/static/chunks/app/api/worktrees/[id]/opencode/session/route-ee11f7b8a34cba8c.js +1 -0
  399. package/.next/static/chunks/app/api/worktrees/[id]/opencode/share/route-ee11f7b8a34cba8c.js +1 -0
  400. package/.next/static/chunks/app/api/worktrees/[id]/prompt-response/route-ee11f7b8a34cba8c.js +1 -0
  401. package/.next/static/chunks/app/api/worktrees/[id]/resolve-target/route-ee11f7b8a34cba8c.js +1 -0
  402. package/.next/static/chunks/app/api/worktrees/[id]/respond/route-ee11f7b8a34cba8c.js +1 -0
  403. package/.next/static/chunks/app/api/worktrees/[id]/route-ee11f7b8a34cba8c.js +1 -0
  404. package/.next/static/chunks/app/api/worktrees/[id]/schedules/[scheduleId]/route-ee11f7b8a34cba8c.js +1 -0
  405. package/.next/static/chunks/app/api/worktrees/[id]/schedules/active/route-ee11f7b8a34cba8c.js +1 -0
  406. package/.next/static/chunks/app/api/worktrees/[id]/schedules/route-ee11f7b8a34cba8c.js +1 -0
  407. package/.next/static/chunks/app/api/worktrees/[id]/search/route-ee11f7b8a34cba8c.js +1 -0
  408. package/.next/static/chunks/app/api/worktrees/[id]/send/route-ee11f7b8a34cba8c.js +1 -0
  409. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route-ee11f7b8a34cba8c.js +1 -0
  410. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/install/route-ee11f7b8a34cba8c.js +1 -0
  411. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/plan/route-ee11f7b8a34cba8c.js +1 -0
  412. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall/route-ee11f7b8a34cba8c.js +1 -0
  413. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route-ee11f7b8a34cba8c.js +1 -0
  414. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update/route-ee11f7b8a34cba8c.js +1 -0
  415. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update-plan/route-ee11f7b8a34cba8c.js +1 -0
  416. package/.next/static/chunks/app/api/worktrees/[id]/skills/route-ee11f7b8a34cba8c.js +1 -0
  417. package/.next/static/chunks/app/api/worktrees/[id]/slash-commands/route-ee11f7b8a34cba8c.js +1 -0
  418. package/.next/static/chunks/app/api/worktrees/[id]/special-keys/route-ee11f7b8a34cba8c.js +1 -0
  419. package/.next/static/chunks/app/api/worktrees/[id]/tasks/route-ee11f7b8a34cba8c.js +1 -0
  420. package/.next/static/chunks/app/api/worktrees/[id]/terminal/route-ee11f7b8a34cba8c.js +1 -0
  421. package/.next/static/chunks/app/api/worktrees/[id]/timers/history/route-ee11f7b8a34cba8c.js +1 -0
  422. package/.next/static/chunks/app/api/worktrees/[id]/timers/route-ee11f7b8a34cba8c.js +1 -0
  423. package/.next/static/chunks/app/api/worktrees/[id]/todos/[todoId]/route-ee11f7b8a34cba8c.js +1 -0
  424. package/.next/static/chunks/app/api/worktrees/[id]/todos/route-ee11f7b8a34cba8c.js +1 -0
  425. package/.next/static/chunks/app/api/worktrees/[id]/tree/[...path]/route-ee11f7b8a34cba8c.js +1 -0
  426. package/.next/static/chunks/app/api/worktrees/[id]/tree/route-ee11f7b8a34cba8c.js +1 -0
  427. package/.next/static/chunks/app/api/worktrees/[id]/upload/[...path]/route-ee11f7b8a34cba8c.js +1 -0
  428. package/.next/static/chunks/app/api/worktrees/[id]/verify/config/route-ee11f7b8a34cba8c.js +1 -0
  429. package/.next/static/chunks/app/api/worktrees/[id]/verify/route-ee11f7b8a34cba8c.js +1 -0
  430. package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route-ee11f7b8a34cba8c.js +1 -0
  431. package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/[runId]/route-ee11f7b8a34cba8c.js +1 -0
  432. package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/route-ee11f7b8a34cba8c.js +1 -0
  433. package/.next/static/chunks/app/api/worktrees/[id]/viewed/route-ee11f7b8a34cba8c.js +1 -0
  434. package/.next/static/chunks/app/api/worktrees/apply-default-agents/route-ee11f7b8a34cba8c.js +1 -0
  435. package/.next/static/chunks/app/api/worktrees/route-ee11f7b8a34cba8c.js +1 -0
  436. package/.next/static/chunks/app/manifest.webmanifest/route-ee11f7b8a34cba8c.js +1 -0
  437. package/.next/static/chunks/app/more/{page-75d3783da0d49a25.js → page-333bba1c8bbc9c11.js} +1 -1
  438. package/.next/static/chunks/app/proxy/[...path]/route-ee11f7b8a34cba8c.js +1 -0
  439. package/.next/static/chunks/app/worktrees/[id]/layout-ee11f7b8a34cba8c.js +1 -0
  440. package/.next/static/chunks/app/worktrees/[id]/page-aac399392ec8c273.js +1 -0
  441. package/.next/static/chunks/app/worktrees/[id]/terminal/page-2631bc5c4b0a9fb8.js +1 -0
  442. package/.next/static/css/23f9c40ecc458c77.css +1 -0
  443. package/.next/static/pcpB4K6KreMzu2qbhvuRY/_buildManifest.js +1 -0
  444. package/.next/trace +13 -13
  445. package/.next/types/app/api/settings/default-surface-mode/route.ts +347 -0
  446. package/.next/types/app/api/worktrees/[id]/{start-polling → cli-reference}/route.ts +3 -3
  447. package/.next/types/routes.d.ts +3 -2
  448. package/.next/types/validator.ts +18 -9
  449. package/dist/server/server.js +58 -0
  450. package/dist/server/src/lib/claude-output.js +1 -0
  451. package/dist/server/src/lib/db/app-settings-db.js +60 -0
  452. package/dist/server/src/lib/db/chat-db.js +120 -7
  453. package/dist/server/src/lib/detection/status-detector.js +3 -2
  454. package/dist/server/src/lib/env.js +122 -0
  455. package/dist/server/src/lib/git/worktrees.js +154 -0
  456. package/dist/server/src/lib/history/transcript-tail.js +80 -0
  457. package/dist/server/src/lib/history/user-turn-recorder.js +252 -0
  458. package/dist/server/src/lib/hooks/agent-event-service.js +40 -6
  459. package/dist/server/src/lib/hooks/permission-decision-service.js +85 -1
  460. package/dist/server/src/lib/hooks/sources/antigravity/history.js +607 -0
  461. package/dist/server/src/lib/hooks/sources/antigravity/source.js +7 -0
  462. package/dist/server/src/lib/hooks/sources/antigravity/transcript.js +407 -0
  463. package/dist/server/src/lib/hooks/sources/claude/history.js +797 -0
  464. package/dist/server/src/lib/hooks/sources/claude/source.js +4 -0
  465. package/dist/server/src/lib/hooks/sources/claude/transcript.js +518 -0
  466. package/dist/server/src/lib/hooks/sources/codex/history.js +663 -0
  467. package/dist/server/src/lib/hooks/sources/codex/source.js +4 -0
  468. package/dist/server/src/lib/hooks/sources/codex/transcript.js +448 -0
  469. package/dist/server/src/lib/hooks/sources/copilot/source.js +2 -0
  470. package/dist/server/src/lib/hooks/sources/gemini/source.js +2 -0
  471. package/dist/server/src/lib/hooks/sources/legacy-relay.js +3 -0
  472. package/dist/server/src/lib/hooks/sources/opencode/history.js +57 -0
  473. package/dist/server/src/lib/hooks/sources/opencode/source.js +4 -0
  474. package/dist/server/src/lib/hooks/sources/opencode/transcript.js +10 -28
  475. package/dist/server/src/lib/hooks/sources/turn-body.js +118 -0
  476. package/dist/server/src/lib/hooks/stop-history-capture.js +161 -0
  477. package/dist/server/src/lib/polling/prompt-dedup.js +2 -4
  478. package/dist/server/src/lib/polling/response-checker.js +87 -6
  479. package/dist/server/src/lib/polling/response-dedup.js +2 -4
  480. package/dist/server/src/lib/polling/response-poller-core.js +191 -29
  481. package/dist/server/src/lib/polling/structured-history-gate.js +272 -16
  482. package/dist/server/src/lib/push/push-sender.js +21 -1
  483. package/dist/server/src/lib/push/waiting-push-notifier.js +126 -8
  484. package/dist/server/src/lib/realtime/publisher-registry.js +171 -0
  485. package/dist/server/src/lib/realtime/terminal-broadcast.js +14 -1
  486. package/dist/server/src/lib/realtime/types.js +96 -1
  487. package/dist/server/src/lib/session/current-output-builder.js +365 -4
  488. package/dist/server/src/lib/session/send-user-message.js +90 -2
  489. package/dist/server/src/lib/tui-accumulator.js +2 -8
  490. package/dist/server/src/lib/ws-server.js +143 -6
  491. package/dist/server/src/types/agent-transcript.js +241 -5
  492. package/dist/server/src/types/ui-state.js +24 -1
  493. package/package.json +1 -1
  494. package/public/sw.js +15 -1
  495. package/.next/server/app/api/worktrees/[id]/start-polling/route.js +0 -1
  496. package/.next/server/app/api/worktrees/[id]/start-polling/route.js.nft.json +0 -1
  497. package/.next/server/app/api/worktrees/[id]/start-polling/route_client-reference-manifest.js +0 -1
  498. package/.next/server/chunks/1714.js +0 -7
  499. package/.next/server/chunks/2198.js +0 -1
  500. package/.next/server/chunks/221.js +0 -25
  501. package/.next/server/chunks/2759.js +0 -8
  502. package/.next/server/chunks/3558.js +0 -1
  503. package/.next/server/chunks/6781.js +0 -1
  504. package/.next/server/chunks/9508.js +0 -1
  505. package/.next/static/0YoRrahue4Vchxg1z83IQ/_buildManifest.js +0 -1
  506. package/.next/static/chunks/1379-af7af9e08f47c979.js +0 -1
  507. package/.next/static/chunks/6381-9ba5198c0a6ff197.js +0 -1
  508. package/.next/static/chunks/app/api/agents/update/route-1c30fb8d4d6fa6ef.js +0 -1
  509. package/.next/static/chunks/app/api/agents/versions/route-1c30fb8d4d6fa6ef.js +0 -1
  510. package/.next/static/chunks/app/api/app/update/route-1c30fb8d4d6fa6ef.js +0 -1
  511. package/.next/static/chunks/app/api/app/update-check/route-1c30fb8d4d6fa6ef.js +0 -1
  512. package/.next/static/chunks/app/api/assistant/conversation/route-1c30fb8d4d6fa6ef.js +0 -1
  513. package/.next/static/chunks/app/api/assistant/current-output/route-1c30fb8d4d6fa6ef.js +0 -1
  514. package/.next/static/chunks/app/api/assistant/messages/route-1c30fb8d4d6fa6ef.js +0 -1
  515. package/.next/static/chunks/app/api/assistant/session/route-1c30fb8d4d6fa6ef.js +0 -1
  516. package/.next/static/chunks/app/api/assistant/start/route-1c30fb8d4d6fa6ef.js +0 -1
  517. package/.next/static/chunks/app/api/assistant/terminal/route-1c30fb8d4d6fa6ef.js +0 -1
  518. package/.next/static/chunks/app/api/assistant/tools/route-1c30fb8d4d6fa6ef.js +0 -1
  519. package/.next/static/chunks/app/api/auth/login/route-1c30fb8d4d6fa6ef.js +0 -1
  520. package/.next/static/chunks/app/api/auth/logout/route-1c30fb8d4d6fa6ef.js +0 -1
  521. package/.next/static/chunks/app/api/auth/status/route-1c30fb8d4d6fa6ef.js +0 -1
  522. package/.next/static/chunks/app/api/capabilities/route-1c30fb8d4d6fa6ef.js +0 -1
  523. package/.next/static/chunks/app/api/daily-summary/route-1c30fb8d4d6fa6ef.js +0 -1
  524. package/.next/static/chunks/app/api/daily-summary/status/route-1c30fb8d4d6fa6ef.js +0 -1
  525. package/.next/static/chunks/app/api/external-apps/[id]/health/route-1c30fb8d4d6fa6ef.js +0 -1
  526. package/.next/static/chunks/app/api/external-apps/[id]/route-1c30fb8d4d6fa6ef.js +0 -1
  527. package/.next/static/chunks/app/api/external-apps/route-1c30fb8d4d6fa6ef.js +0 -1
  528. package/.next/static/chunks/app/api/fs/browse/route-1c30fb8d4d6fa6ef.js +0 -1
  529. package/.next/static/chunks/app/api/fs/recent-paths/route-1c30fb8d4d6fa6ef.js +0 -1
  530. package/.next/static/chunks/app/api/hooks/agent-event/route-1c30fb8d4d6fa6ef.js +0 -1
  531. package/.next/static/chunks/app/api/hooks/claude-done/route-1c30fb8d4d6fa6ef.js +0 -1
  532. package/.next/static/chunks/app/api/hooks/permission-request/route-1c30fb8d4d6fa6ef.js +0 -1
  533. package/.next/static/chunks/app/api/metrics/vibe/route-1c30fb8d4d6fa6ef.js +0 -1
  534. package/.next/static/chunks/app/api/ollama/models/route-1c30fb8d4d6fa6ef.js +0 -1
  535. package/.next/static/chunks/app/api/push/escalation/route-1c30fb8d4d6fa6ef.js +0 -1
  536. package/.next/static/chunks/app/api/push/subscriptions/route-1c30fb8d4d6fa6ef.js +0 -1
  537. package/.next/static/chunks/app/api/push/vapid/route-1c30fb8d4d6fa6ef.js +0 -1
  538. package/.next/static/chunks/app/api/remote/pair/route-1c30fb8d4d6fa6ef.js +0 -1
  539. package/.next/static/chunks/app/api/repositories/[id]/route-1c30fb8d4d6fa6ef.js +0 -1
  540. package/.next/static/chunks/app/api/repositories/[id]/todos/[todoId]/route-1c30fb8d4d6fa6ef.js +0 -1
  541. package/.next/static/chunks/app/api/repositories/[id]/todos/route-1c30fb8d4d6fa6ef.js +0 -1
  542. package/.next/static/chunks/app/api/repositories/clone/[jobId]/route-1c30fb8d4d6fa6ef.js +0 -1
  543. package/.next/static/chunks/app/api/repositories/clone/route-1c30fb8d4d6fa6ef.js +0 -1
  544. package/.next/static/chunks/app/api/repositories/excluded/route-1c30fb8d4d6fa6ef.js +0 -1
  545. package/.next/static/chunks/app/api/repositories/restore/route-1c30fb8d4d6fa6ef.js +0 -1
  546. package/.next/static/chunks/app/api/repositories/route-1c30fb8d4d6fa6ef.js +0 -1
  547. package/.next/static/chunks/app/api/repositories/scan/route-1c30fb8d4d6fa6ef.js +0 -1
  548. package/.next/static/chunks/app/api/repositories/sync/route-1c30fb8d4d6fa6ef.js +0 -1
  549. package/.next/static/chunks/app/api/repositories/validate-path/route-1c30fb8d4d6fa6ef.js +0 -1
  550. package/.next/static/chunks/app/api/settings/default-agents/route-1c30fb8d4d6fa6ef.js +0 -1
  551. package/.next/static/chunks/app/api/sidebar/group-order/route-1c30fb8d4d6fa6ef.js +0 -1
  552. package/.next/static/chunks/app/api/skills/[id]/route-1c30fb8d4d6fa6ef.js +0 -1
  553. package/.next/static/chunks/app/api/skills/installations/route-1c30fb8d4d6fa6ef.js +0 -1
  554. package/.next/static/chunks/app/api/skills/operations/route-1c30fb8d4d6fa6ef.js +0 -1
  555. package/.next/static/chunks/app/api/skills/reindex/route-1c30fb8d4d6fa6ef.js +0 -1
  556. package/.next/static/chunks/app/api/skills/route-1c30fb8d4d6fa6ef.js +0 -1
  557. package/.next/static/chunks/app/api/slash-commands/route-1c30fb8d4d6fa6ef.js +0 -1
  558. package/.next/static/chunks/app/api/tasks/[taskId]/cancel/route-1c30fb8d4d6fa6ef.js +0 -1
  559. package/.next/static/chunks/app/api/tasks/[taskId]/route-1c30fb8d4d6fa6ef.js +0 -1
  560. package/.next/static/chunks/app/api/templates/[id]/route-1c30fb8d4d6fa6ef.js +0 -1
  561. package/.next/static/chunks/app/api/templates/route-1c30fb8d4d6fa6ef.js +0 -1
  562. package/.next/static/chunks/app/api/todos/route-1c30fb8d4d6fa6ef.js +0 -1
  563. package/.next/static/chunks/app/api/verification/runs/[runId]/route-1c30fb8d4d6fa6ef.js +0 -1
  564. package/.next/static/chunks/app/api/verification/runs/route-1c30fb8d4d6fa6ef.js +0 -1
  565. package/.next/static/chunks/app/api/worktrees/[id]/auto-yes/route-1c30fb8d4d6fa6ef.js +0 -1
  566. package/.next/static/chunks/app/api/worktrees/[id]/capture/route-1c30fb8d4d6fa6ef.js +0 -1
  567. package/.next/static/chunks/app/api/worktrees/[id]/clear-composer/route-1c30fb8d4d6fa6ef.js +0 -1
  568. package/.next/static/chunks/app/api/worktrees/[id]/cli-tool/route-1c30fb8d4d6fa6ef.js +0 -1
  569. package/.next/static/chunks/app/api/worktrees/[id]/cmate/schedules/route-1c30fb8d4d6fa6ef.js +0 -1
  570. package/.next/static/chunks/app/api/worktrees/[id]/current-output/route-1c30fb8d4d6fa6ef.js +0 -1
  571. package/.next/static/chunks/app/api/worktrees/[id]/env/route-1c30fb8d4d6fa6ef.js +0 -1
  572. package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/[logId]/route-1c30fb8d4d6fa6ef.js +0 -1
  573. package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/route-1c30fb8d4d6fa6ef.js +0 -1
  574. package/.next/static/chunks/app/api/worktrees/[id]/files/[...path]/route-1c30fb8d4d6fa6ef.js +0 -1
  575. package/.next/static/chunks/app/api/worktrees/[id]/git/branch/create/route-1c30fb8d4d6fa6ef.js +0 -1
  576. package/.next/static/chunks/app/api/worktrees/[id]/git/branch/delete/route-1c30fb8d4d6fa6ef.js +0 -1
  577. package/.next/static/chunks/app/api/worktrees/[id]/git/branches/route-1c30fb8d4d6fa6ef.js +0 -1
  578. package/.next/static/chunks/app/api/worktrees/[id]/git/checkout/route-1c30fb8d4d6fa6ef.js +0 -1
  579. package/.next/static/chunks/app/api/worktrees/[id]/git/commit/route-1c30fb8d4d6fa6ef.js +0 -1
  580. package/.next/static/chunks/app/api/worktrees/[id]/git/diff/route-1c30fb8d4d6fa6ef.js +0 -1
  581. package/.next/static/chunks/app/api/worktrees/[id]/git/fetch/route-1c30fb8d4d6fa6ef.js +0 -1
  582. package/.next/static/chunks/app/api/worktrees/[id]/git/log/route-1c30fb8d4d6fa6ef.js +0 -1
  583. package/.next/static/chunks/app/api/worktrees/[id]/git/pull/route-1c30fb8d4d6fa6ef.js +0 -1
  584. package/.next/static/chunks/app/api/worktrees/[id]/git/push/route-1c30fb8d4d6fa6ef.js +0 -1
  585. package/.next/static/chunks/app/api/worktrees/[id]/git/reset/route-1c30fb8d4d6fa6ef.js +0 -1
  586. package/.next/static/chunks/app/api/worktrees/[id]/git/revert/route-1c30fb8d4d6fa6ef.js +0 -1
  587. package/.next/static/chunks/app/api/worktrees/[id]/git/show/[commitHash]/route-1c30fb8d4d6fa6ef.js +0 -1
  588. package/.next/static/chunks/app/api/worktrees/[id]/git/stage/route-1c30fb8d4d6fa6ef.js +0 -1
  589. package/.next/static/chunks/app/api/worktrees/[id]/git/staged/route-1c30fb8d4d6fa6ef.js +0 -1
  590. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/[index]/route-1c30fb8d4d6fa6ef.js +0 -1
  591. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/apply/route-1c30fb8d4d6fa6ef.js +0 -1
  592. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/pop/route-1c30fb8d4d6fa6ef.js +0 -1
  593. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/push/route-1c30fb8d4d6fa6ef.js +0 -1
  594. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/route-1c30fb8d4d6fa6ef.js +0 -1
  595. package/.next/static/chunks/app/api/worktrees/[id]/git/status/route-1c30fb8d4d6fa6ef.js +0 -1
  596. package/.next/static/chunks/app/api/worktrees/[id]/git/unstage/route-1c30fb8d4d6fa6ef.js +0 -1
  597. package/.next/static/chunks/app/api/worktrees/[id]/git/working-diff/route-1c30fb8d4d6fa6ef.js +0 -1
  598. package/.next/static/chunks/app/api/worktrees/[id]/instances/opencode/route-1c30fb8d4d6fa6ef.js +0 -1
  599. package/.next/static/chunks/app/api/worktrees/[id]/interrupt/route-1c30fb8d4d6fa6ef.js +0 -1
  600. package/.next/static/chunks/app/api/worktrees/[id]/kill-session/route-1c30fb8d4d6fa6ef.js +0 -1
  601. package/.next/static/chunks/app/api/worktrees/[id]/logs/[filename]/route-1c30fb8d4d6fa6ef.js +0 -1
  602. package/.next/static/chunks/app/api/worktrees/[id]/logs/route-1c30fb8d4d6fa6ef.js +0 -1
  603. package/.next/static/chunks/app/api/worktrees/[id]/marp-render/route-1c30fb8d4d6fa6ef.js +0 -1
  604. package/.next/static/chunks/app/api/worktrees/[id]/memos/[memoId]/route-1c30fb8d4d6fa6ef.js +0 -1
  605. package/.next/static/chunks/app/api/worktrees/[id]/memos/route-1c30fb8d4d6fa6ef.js +0 -1
  606. package/.next/static/chunks/app/api/worktrees/[id]/messages/route-1c30fb8d4d6fa6ef.js +0 -1
  607. package/.next/static/chunks/app/api/worktrees/[id]/opencode/diff/route-1c30fb8d4d6fa6ef.js +0 -1
  608. package/.next/static/chunks/app/api/worktrees/[id]/opencode/session/route-1c30fb8d4d6fa6ef.js +0 -1
  609. package/.next/static/chunks/app/api/worktrees/[id]/opencode/share/route-1c30fb8d4d6fa6ef.js +0 -1
  610. package/.next/static/chunks/app/api/worktrees/[id]/prompt-response/route-1c30fb8d4d6fa6ef.js +0 -1
  611. package/.next/static/chunks/app/api/worktrees/[id]/resolve-target/route-1c30fb8d4d6fa6ef.js +0 -1
  612. package/.next/static/chunks/app/api/worktrees/[id]/respond/route-1c30fb8d4d6fa6ef.js +0 -1
  613. package/.next/static/chunks/app/api/worktrees/[id]/route-1c30fb8d4d6fa6ef.js +0 -1
  614. package/.next/static/chunks/app/api/worktrees/[id]/schedules/[scheduleId]/route-1c30fb8d4d6fa6ef.js +0 -1
  615. package/.next/static/chunks/app/api/worktrees/[id]/schedules/active/route-1c30fb8d4d6fa6ef.js +0 -1
  616. package/.next/static/chunks/app/api/worktrees/[id]/schedules/route-1c30fb8d4d6fa6ef.js +0 -1
  617. package/.next/static/chunks/app/api/worktrees/[id]/search/route-1c30fb8d4d6fa6ef.js +0 -1
  618. package/.next/static/chunks/app/api/worktrees/[id]/send/route-1c30fb8d4d6fa6ef.js +0 -1
  619. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route-1c30fb8d4d6fa6ef.js +0 -1
  620. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/install/route-1c30fb8d4d6fa6ef.js +0 -1
  621. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/plan/route-1c30fb8d4d6fa6ef.js +0 -1
  622. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall/route-1c30fb8d4d6fa6ef.js +0 -1
  623. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route-1c30fb8d4d6fa6ef.js +0 -1
  624. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update/route-1c30fb8d4d6fa6ef.js +0 -1
  625. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update-plan/route-1c30fb8d4d6fa6ef.js +0 -1
  626. package/.next/static/chunks/app/api/worktrees/[id]/skills/route-1c30fb8d4d6fa6ef.js +0 -1
  627. package/.next/static/chunks/app/api/worktrees/[id]/slash-commands/route-1c30fb8d4d6fa6ef.js +0 -1
  628. package/.next/static/chunks/app/api/worktrees/[id]/special-keys/route-1c30fb8d4d6fa6ef.js +0 -1
  629. package/.next/static/chunks/app/api/worktrees/[id]/start-polling/route-1c30fb8d4d6fa6ef.js +0 -1
  630. package/.next/static/chunks/app/api/worktrees/[id]/tasks/route-1c30fb8d4d6fa6ef.js +0 -1
  631. package/.next/static/chunks/app/api/worktrees/[id]/terminal/route-1c30fb8d4d6fa6ef.js +0 -1
  632. package/.next/static/chunks/app/api/worktrees/[id]/timers/history/route-1c30fb8d4d6fa6ef.js +0 -1
  633. package/.next/static/chunks/app/api/worktrees/[id]/timers/route-1c30fb8d4d6fa6ef.js +0 -1
  634. package/.next/static/chunks/app/api/worktrees/[id]/todos/[todoId]/route-1c30fb8d4d6fa6ef.js +0 -1
  635. package/.next/static/chunks/app/api/worktrees/[id]/todos/route-1c30fb8d4d6fa6ef.js +0 -1
  636. package/.next/static/chunks/app/api/worktrees/[id]/tree/[...path]/route-1c30fb8d4d6fa6ef.js +0 -1
  637. package/.next/static/chunks/app/api/worktrees/[id]/tree/route-1c30fb8d4d6fa6ef.js +0 -1
  638. package/.next/static/chunks/app/api/worktrees/[id]/upload/[...path]/route-1c30fb8d4d6fa6ef.js +0 -1
  639. package/.next/static/chunks/app/api/worktrees/[id]/verify/config/route-1c30fb8d4d6fa6ef.js +0 -1
  640. package/.next/static/chunks/app/api/worktrees/[id]/verify/route-1c30fb8d4d6fa6ef.js +0 -1
  641. package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route-1c30fb8d4d6fa6ef.js +0 -1
  642. package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/[runId]/route-1c30fb8d4d6fa6ef.js +0 -1
  643. package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/route-1c30fb8d4d6fa6ef.js +0 -1
  644. package/.next/static/chunks/app/api/worktrees/[id]/viewed/route-1c30fb8d4d6fa6ef.js +0 -1
  645. package/.next/static/chunks/app/api/worktrees/apply-default-agents/route-1c30fb8d4d6fa6ef.js +0 -1
  646. package/.next/static/chunks/app/api/worktrees/route-1c30fb8d4d6fa6ef.js +0 -1
  647. package/.next/static/chunks/app/manifest.webmanifest/route-1c30fb8d4d6fa6ef.js +0 -1
  648. package/.next/static/chunks/app/proxy/[...path]/route-1c30fb8d4d6fa6ef.js +0 -1
  649. package/.next/static/chunks/app/worktrees/[id]/layout-1c30fb8d4d6fa6ef.js +0 -1
  650. package/.next/static/chunks/app/worktrees/[id]/page-ce6279d581d1df95.js +0 -1
  651. package/.next/static/chunks/app/worktrees/[id]/terminal/page-00ad5d9a62a71cab.js +0 -1
  652. package/.next/static/css/b326c8a734e1928e.css +0 -1
  653. /package/.next/static/{0YoRrahue4Vchxg1z83IQ → pcpB4K6KreMzu2qbhvuRY}/_ssgManifest.js +0 -0
@@ -1,32 +1,62 @@
1
1
  "use strict";
2
2
  /**
3
- * Whether somebody better-informed is already recording this turn (Issue #2041).
3
+ * Whether somebody better-informed is already recording this turn (Issue #2041,
4
+ * extended for Claude Code in #2121, codex in #2197 and antigravity in #2198).
4
5
  *
5
6
  * The poller's job has always been to be the only writer of conversation
6
- * history, because for five of the six tools the terminal is the only place the
7
- * reply exists. opencode is the exception: since #1763 CommandMate holds an SSE
8
- * connection to the agent's own server, and since this Issue that connection
9
- * carries the reply's Markdown source. Two writers for one turn would put the
10
- * same answer in History twice once as the agent wrote it and once as its TUI
11
- * drew it — so one of them has to stand down, and it is the one reading the
12
- * screen.
7
+ * history, because for most of the six tools the terminal is the only place the
8
+ * reply exists. Four of them now have a second writer: opencode publishes its
9
+ * replies over the SSE stream CommandMate subscribes to (#1763/#2041), and
10
+ * claude, codex and antigravity each keep their own transcript file on disk.
11
+ * Two writers for one turn would put the same answer in History twice — once as
12
+ * the agent wrote it and once as its TUI drew it — so one of them has to stand
13
+ * down, and it is the one reading the screen.
13
14
  *
14
15
  * ## Why this is a module and not an `if`
15
16
  *
16
17
  * Two reasons, and the second is the one that matters. The obvious one is that
17
18
  * `response-checker` is 1,000 lines with a single tool-agnostic spine, and a
18
19
  * `cliToolId === 'opencode' && …` in the middle of the save path is exactly the
19
- * kind of branch that gets copied to the next tool that grows a server. The
20
- * real one is the import: `@/lib/hooks/sources/opencode/subscription` reaches
21
- * the whole opencode client through its module graph, and the poller's tests
22
- * replace that graph wholesale. One named seam is one thing to stub.
20
+ * kind of branch that gets copied to the next tool that grows a reader. The real
21
+ * one is the import: `@/lib/hooks/sources/opencode/subscription` reaches the
22
+ * whole opencode client through its module graph, and the poller's tests replace
23
+ * that graph wholesale. One named seam is one thing to stub.
24
+ *
25
+ * ## The tool names are gone (Issue #2197)
26
+ *
27
+ * Until this Issue the two functions below opened with `if (cliToolId !==
28
+ * 'opencode')` and `if (cliToolId !== CLAUDE_CLI_TOOL_ID)`, which is the branch
29
+ * the module comment above says it exists to prevent — the third tool arrived
30
+ * and the third `!==` was about to be written. What replaces them is a value the
31
+ * source declares about itself:
32
+ * `AgentSourceCapabilities.transcriptHistory` (`'pull' | 'push' | null`, see
33
+ * `lib/hooks/agent-event-types`). A tool with no second writer says `null` and
34
+ * both questions below answer false for it without naming it — which is what let
35
+ * #2198 add antigravity by editing its own `source.ts` and this file's reader
36
+ * table and nothing else, and what leaves gemini and copilot on the scraper
37
+ * without a line of code mentioning them.
38
+ *
39
+ * The word has three values rather than two because the two shapes are asked
40
+ * *different questions*:
41
+ *
42
+ * - **push** — a subscription is already receiving the reply, so the only thing
43
+ * to ask is whether that connection is live
44
+ * ({@link isStructuredHistoryWriterLive}).
45
+ * - **pull** — there is no connection, only a file, and nothing reads it until
46
+ * something asks. So the question is not "is anyone recording?" but "record
47
+ * it now, and tell me whether you did"
48
+ * ({@link captureStructuredHistoryTurn}). The call has to be here rather than
49
+ * in the hook receiver for a reason beyond tidiness: a hook post is answered
50
+ * and forgotten, so the only moment CommandMate knows a turn is *finished and
51
+ * about to be written* is this one, and doing the handover at the point of
52
+ * the write is what makes it impossible for both writers to run.
23
53
  *
24
54
  * ## What is NOT gated
25
55
  *
26
56
  * Only the two calls that *record the reply* — the `chat_messages` row and the
27
57
  * Markdown conversation log. Prompt rows, Auto-Yes, the waiting-episode edges,
28
58
  * push notifications, task events and the session-state cursor all stay on the
29
- * scraper, because none of them are things the event stream duplicates: a
59
+ * scraper, because none of them are things the second writer duplicates: a
30
60
  * `permission.asked` becomes a pending decision, never a history row, and the
31
61
  * push fan-out has no second producer at all. Gating them would trade a
32
62
  * duplicated reply for a silent notification, which is the worse failure.
@@ -34,15 +64,147 @@
34
64
  * @module lib/polling/structured-history-gate
35
65
  */
36
66
  Object.defineProperty(exports, "__esModule", { value: true });
67
+ exports.resetStructuredHistoryCaptureQueue = resetStructuredHistoryCaptureQueue;
68
+ exports.isPullTranscriptHistory = isPullTranscriptHistory;
37
69
  exports.isStructuredHistoryWriterLive = isStructuredHistoryWriterLive;
70
+ exports.captureStructuredHistoryTurn = captureStructuredHistoryTurn;
71
+ exports.hasStructuredHistoryTranscript = hasStructuredHistoryTranscript;
38
72
  const logger_1 = require("../../lib/logger");
39
73
  const subscription_1 = require("../../lib/hooks/sources/opencode/subscription");
74
+ const history_1 = require("../../lib/hooks/sources/claude/history");
75
+ const history_2 = require("../../lib/hooks/sources/codex/history");
76
+ const history_3 = require("../../lib/hooks/sources/antigravity/history");
77
+ const tool_id_1 = require("../../lib/hooks/sources/claude/tool-id");
78
+ const tool_id_2 = require("../../lib/hooks/sources/codex/tool-id");
79
+ const tool_id_3 = require("../../lib/hooks/sources/antigravity/tool-id");
80
+ const registry_1 = require("../../lib/hooks/sources/registry");
40
81
  const logger = (0, logger_1.createLogger)('lib/polling/structured-history-gate');
82
+ /**
83
+ * One in-flight capture per instance (Issue #2246).
84
+ *
85
+ * Until this Issue there was one caller — the poller's save path, whose ticks do
86
+ * not overlap — and the Stop hook receiver is now a second one, arriving at
87
+ * exactly the moment the poller is most likely to be inside the same turn. Two
88
+ * things follow, and it is worth separating them because #2246's own text runs
89
+ * them together.
90
+ *
91
+ * **The duplicate-row race it describes is not open today, and this is what
92
+ * keeps it shut.** The readers are idempotent through `findMessageByRequestId`,
93
+ * which is a check-then-write over a *non-unique* index — but the check and the
94
+ * write are adjacent and synchronous (`better-sqlite3` is), and the only `await`
95
+ * in that stretch is the dynamic import *before* the check. So there is no point
96
+ * for a second caller to interleave at, and two concurrent captures of one turn
97
+ * already end in one row. That is a property of two adjacent statements, which
98
+ * is exactly the kind of property a later refactor removes without noticing: an
99
+ * `await` inserted between them re-opens the window silently, and the row it
100
+ * costs is a duplicated reply nobody sees until an operator reports it.
101
+ *
102
+ * **What it saves today is the work.** Both triggers otherwise read, parse and
103
+ * render the same 4 MiB tail at the same time, and the second one throws all of
104
+ * it away.
105
+ *
106
+ * A queue rather than a shared result: the second caller runs the read again
107
+ * after the first finishes, because it may be asking about a newer turn and
108
+ * because the answer it needs is about the file as it is *now*. Re-running is
109
+ * cheap and, after the first call, finds the row and answers true.
110
+ *
111
+ * On `globalThis` for the reason every shared map in this subsystem is (#1736):
112
+ * under `next dev` the poller's bundle and the hook receiver's bundle would each
113
+ * get a private copy of a module-scoped map, and a lock only one of two bundles
114
+ * can see is not a lock.
115
+ */
116
+ const captureQueue = (globalThis.__structuredHistoryCaptureQueue ??= new Map());
117
+ /** Forget every instance's in-flight capture. Test seam. */
118
+ function resetStructuredHistoryCaptureQueue() {
119
+ captureQueue.clear();
120
+ }
121
+ /** The queue key; the same triple `buildCompositeKey` spells everywhere else. */
122
+ function captureKeyOf(worktreeId, cliToolId, instanceId) {
123
+ return `${worktreeId}\u0000${cliToolId}\u0000${instanceId}`;
124
+ }
125
+ /**
126
+ * Run `work` after whatever is already running for this instance.
127
+ *
128
+ * The stored promise is a settled-only shadow of the real one, so a caller that
129
+ * throws cannot reject the next caller's chain, and the entry is removed only by
130
+ * whoever put it there — a later call that has already replaced it must not have
131
+ * its own lock deleted underneath it.
132
+ */
133
+ function serializePerInstance(key, work) {
134
+ const previous = captureQueue.get(key) ?? Promise.resolve();
135
+ const result = previous.then(work, work);
136
+ const settled = result.then(() => undefined, () => undefined);
137
+ captureQueue.set(key, settled);
138
+ void settled.then(() => {
139
+ if (captureQueue.get(key) === settled)
140
+ captureQueue.delete(key);
141
+ });
142
+ return result;
143
+ }
144
+ /**
145
+ * Which reader answers for which tool.
146
+ *
147
+ * The one place a tool id still appears, and it is a dispatch table rather than
148
+ * a decision: *whether* to ask is
149
+ * `AgentSourceCapabilities.transcriptHistory === 'pull'`, and this only says who
150
+ * to ask. It cannot be folded into the capability itself because #1921 D3
151
+ * requires every declared capability to be JSON-serialisable — the block is
152
+ * copied onto the wire in `structuredEvents.source`, so a capability that were a
153
+ * function would vanish silently on the way out.
154
+ *
155
+ * A tool that declares `'pull'` and is missing here is a bug, and a loud one:
156
+ * {@link captureStructuredHistoryTurn} logs it and falls back to the scraper.
157
+ */
158
+ const PULL_TRANSCRIPT_READERS = {
159
+ [tool_id_1.CLAUDE_CLI_TOOL_ID]: {
160
+ capture: (target, capture) => (0, history_1.captureClaudeTranscriptTurn)(target, capture),
161
+ locate: (target, capture) => (0, history_1.resolveClaudeTranscriptPath)(target, capture),
162
+ },
163
+ [tool_id_2.CODEX_CLI_TOOL_ID]: {
164
+ capture: (target, capture) => (0, history_2.captureCodexTranscriptTurn)(target, capture),
165
+ locate: (target, capture) => (0, history_2.resolveCodexTranscriptPath)(target, capture),
166
+ },
167
+ [tool_id_3.ANTIGRAVITY_CLI_TOOL_ID]: {
168
+ capture: (target, capture) => (0, history_3.captureAntigravityTranscriptTurn)(target, capture),
169
+ locate: (target, capture) => (0, history_3.resolveAntigravityTranscriptPath)(target, capture),
170
+ },
171
+ };
172
+ /**
173
+ * What this tool's source says about who records its replies.
174
+ *
175
+ * Never throws: a registry that cannot be reached is one that declares nothing,
176
+ * and nothing means the scraper keeps writing — the safe direction, as
177
+ * everywhere else in this module.
178
+ */
179
+ function transcriptHistoryModeOf(cliToolId) {
180
+ try {
181
+ return (0, registry_1.getAgentEventSource)(cliToolId).capabilities.transcriptHistory ?? null;
182
+ }
183
+ catch (error) {
184
+ logger.warn('structured-history-capability-unavailable', {
185
+ cliToolId,
186
+ error: error instanceof Error ? error.message : String(error),
187
+ });
188
+ return null;
189
+ }
190
+ }
191
+ /**
192
+ * Whether this tool keeps a transcript a reader can be asked to pull from.
193
+ *
194
+ * Exported for the Stop receiver (Issue #2246), which has to decide whether the
195
+ * *retry* below is worth waiting for before it answers the agent's hook. It is
196
+ * the same question {@link captureStructuredHistoryTurn} opens with, asked
197
+ * without doing the read — never a tool id comparison, here or there.
198
+ */
199
+ function isPullTranscriptHistory(cliToolId) {
200
+ return transcriptHistoryModeOf(cliToolId) === 'pull';
201
+ }
41
202
  /**
42
203
  * Whether the agent's own server is recording this instance's replies.
43
204
  *
44
- * False for every tool but opencode, and false for an opencode instance whose
45
- * subscription is anything other than `live`see
205
+ * False for every tool whose source does not declare `transcriptHistory: 'push'`
206
+ * today that is all of them but opencode and false for an opencode instance
207
+ * whose subscription is anything other than `live`; see
46
208
  * {@link isOpencodeStructuredHistoryLive} for why `lost` counts as "nobody is
47
209
  * writing this down" rather than as "somebody will". The fallback direction is
48
210
  * the safe one: two writers duplicate a reply, no writer loses it.
@@ -54,9 +216,12 @@ const logger = (0, logger_1.createLogger)('lib/polling/structured-history-gate')
54
216
  * @param instanceId - The agent instance; defaults to the primary
55
217
  */
56
218
  function isStructuredHistoryWriterLive(worktreeId, cliToolId, instanceId) {
57
- if (cliToolId !== 'opencode')
219
+ if (transcriptHistoryModeOf(cliToolId) !== 'push')
58
220
  return false;
59
221
  try {
222
+ // One probe, because there is one push source. A second one adds a table
223
+ // here of the shape `PULL_TRANSCRIPT_READERS` already has; it does not add
224
+ // another `cliToolId ===`.
60
225
  return (0, subscription_1.isOpencodeStructuredHistoryLive)({
61
226
  worktreeId,
62
227
  cliToolId,
@@ -73,3 +238,94 @@ function isStructuredHistoryWriterLive(worktreeId, cliToolId, instanceId) {
73
238
  return false;
74
239
  }
75
240
  }
241
+ /**
242
+ * Ask the pull-mode structured writer to record this turn now (#2121, #2197).
243
+ *
244
+ * The file-backed half of the stand-down. Returns true when `chat_messages`
245
+ * holds this turn as the agent's own Markdown — because this call wrote it, or
246
+ * because an earlier poll of the same finished turn already did — and the caller
247
+ * must therefore drop the scraped copy.
248
+ *
249
+ * False for every tool that does not declare `transcriptHistory: 'pull'`, and
250
+ * false for one that does whenever anything at all prevented the write: no
251
+ * session pointer (a pane started without hooks, or with hooks codex has not
252
+ * been told to trust), no transcript file, an unreadable one, a window with no
253
+ * prompt in it, or a turn the agent has not finished writing. That is the
254
+ * fail-open every one of these Issues' acceptance criteria asks for in as many
255
+ * words — 転写ファイルが無い / 読めない場合は従来のスクレイプ経路にフォール
256
+ * バックする. Two writers duplicate a reply; no writer loses one.
257
+ *
258
+ * Never throws, for the same reason {@link isStructuredHistoryWriterLive} does
259
+ * not: this runs inside the poller's save path, and an exception here would cost
260
+ * the scraped reply as well as the structured one.
261
+ *
262
+ * @param worktreeId - The worktree
263
+ * @param cliToolId - The tool driving the pane
264
+ * @param instanceId - The agent instance; defaults to the primary
265
+ * @param capture - Where to look; see {@link StructuredHistoryCapture}
266
+ */
267
+ async function captureStructuredHistoryTurn(worktreeId, cliToolId, instanceId, capture) {
268
+ if (!isPullTranscriptHistory(cliToolId))
269
+ return false;
270
+ const reader = PULL_TRANSCRIPT_READERS[cliToolId];
271
+ if (!reader) {
272
+ logger.warn('structured-history-reader-missing', {
273
+ worktreeId,
274
+ cliToolId,
275
+ instanceId: instanceId ?? cliToolId,
276
+ });
277
+ return false;
278
+ }
279
+ const resolvedInstanceId = instanceId ?? cliToolId;
280
+ return serializePerInstance(captureKeyOf(worktreeId, cliToolId, resolvedInstanceId), async () => {
281
+ try {
282
+ return await reader.capture({ worktreeId, cliToolId, instanceId: resolvedInstanceId }, capture);
283
+ }
284
+ catch (error) {
285
+ logger.warn('structured-history-capture-unavailable', {
286
+ worktreeId,
287
+ cliToolId,
288
+ instanceId: resolvedInstanceId,
289
+ error: error instanceof Error ? error.message : String(error),
290
+ });
291
+ return false;
292
+ }
293
+ });
294
+ }
295
+ /**
296
+ * Whether a pull reader can name a transcript for this instance (Issue #2246).
297
+ *
298
+ * Not "is there a turn to write" and not "did anything get written" — only
299
+ * whether the file the reader would open exists right now. The one caller is
300
+ * `lib/hooks/stop-history-capture`, which asks it after a capture answered
301
+ * false, to decide whether waiting half a second and asking again could help.
302
+ * An instance with no transcript will not have one in half a second, and the
303
+ * delay would be paid on every `stop` of every session without hooks.
304
+ *
305
+ * False for every tool that does not declare `transcriptHistory: 'pull'`, and
306
+ * never throws — an unanswerable question is one whose answer is "no file",
307
+ * which costs the retry and nothing else.
308
+ *
309
+ * @param worktreeId - The worktree
310
+ * @param cliToolId - The tool driving the pane
311
+ * @param instanceId - The agent instance; defaults to the primary
312
+ * @param capture - Where to look; see {@link StructuredHistoryCapture}
313
+ */
314
+ async function hasStructuredHistoryTranscript(worktreeId, cliToolId, instanceId, capture) {
315
+ const reader = isPullTranscriptHistory(cliToolId) ? PULL_TRANSCRIPT_READERS[cliToolId] : undefined;
316
+ if (!reader)
317
+ return false;
318
+ try {
319
+ const path = await reader.locate({ worktreeId, cliToolId, instanceId: instanceId ?? cliToolId }, capture);
320
+ return path !== null;
321
+ }
322
+ catch (error) {
323
+ logger.warn('structured-history-locate-unavailable', {
324
+ worktreeId,
325
+ cliToolId,
326
+ instanceId: instanceId ?? cliToolId,
327
+ error: error instanceof Error ? error.message : String(error),
328
+ });
329
+ return false;
330
+ }
331
+ }
@@ -317,9 +317,29 @@ async function notifyPushSubscribers(event, now = Date.now()) {
317
317
  // from one that was never attempted — `push-send-failed` is per device and
318
318
  // sits below the default log level's attention, and success said nothing at
319
319
  // all. One line per fan-out names both halves, and no endpoint.
320
+ //
321
+ // Issue #2133: it also names *whose* fan-out it was. Without the subject,
322
+ // two worktrees notifying in the same second print two identical lines, so
323
+ // the UAT steps that pass by counting zero notifications
324
+ // (`docs/qa/2001-cross-device-dismissal-uat.md` T-4 / T-6 / T-7) read a
325
+ // neighbour's push as their own — which is what the Epic #2002 run hit on
326
+ // 2026-08-29, and only the co-timed `resolution-push-sent` (which does carry
327
+ // `worktreeId`) rescued the reading. A waiting push has no such partner.
328
+ //
329
+ // The key names match `resolution-push-notifier`'s context on purpose, so
330
+ // both halves of one episode grep together. `instanceId` resolves exactly as
331
+ // the episode dedup key above does, and is left absent — `JSON.stringify`
332
+ // drops `undefined` — rather than logged as an empty string when no producer
333
+ // named an instance.
320
334
  const delivered = outcomes.filter(Boolean).length;
321
335
  const failed = outcomes.length - delivered;
322
- logger.info('push-fanout-complete', { kind: event.kind, delivered, failed });
336
+ logger.info('push-fanout-complete', {
337
+ kind: event.kind,
338
+ worktreeId: event.worktreeId,
339
+ instanceId: event.instanceId ?? event.agentName,
340
+ delivered,
341
+ failed,
342
+ });
323
343
  }
324
344
  catch (err) {
325
345
  logger.warn('push-fanout-error', {
@@ -39,19 +39,31 @@
39
39
  * closes — so an install with nothing waiting has no timer, and one that never
40
40
  * configured VAPID never even gets that far.
41
41
  *
42
+ * ## Holding a wait that has not named itself
43
+ *
44
+ * The edge fires once, and for a dialog drawn between two probes it fires
45
+ * before anything on the pane can be classified — so #2156's `AskUserQuestion`
46
+ * arrived here as `unclassified` and was announced as "check the terminal"
47
+ * although the app could answer it. The kind is refreshed in place afterwards
48
+ * and that refresh is deliberately not an edge, so the fix is on this side:
49
+ * an unnamed wait is held for {@link CLASSIFICATION_GRACE_MS} and then sent
50
+ * under whatever the episode is called at that point. One notification either
51
+ * way — no correction push, and nothing at all if the wait ended meanwhile.
52
+ *
42
53
  * Everything here is advisory: a failure must not disturb the status read that
43
54
  * observed the edge (`emit` contains listener throws) nor the poller.
44
55
  *
45
56
  * @module lib/push/waiting-push-notifier
46
57
  */
47
58
  Object.defineProperty(exports, "__esModule", { value: true });
48
- exports.ESCALATION_TICK_MS = void 0;
59
+ exports.CLASSIFICATION_GRACE_MS = exports.ESCALATION_TICK_MS = void 0;
49
60
  exports.handleWaitingTransition = handleWaitingTransition;
50
61
  exports.runEscalationTick = runEscalationTick;
51
62
  exports.startWaitingPushNotifier = startWaitingPushNotifier;
52
63
  exports.stopWaitingPushNotifier = stopWaitingPushNotifier;
53
64
  exports.isWaitingPushNotifierActive = isWaitingPushNotifierActive;
54
65
  exports.pendingEscalationCount = pendingEscalationCount;
66
+ exports.heldWaitCount = heldWaitCount;
55
67
  const auto_yes_state_1 = require("../../lib/auto-yes-state");
56
68
  const db_instance_1 = require("../../lib/db/db-instance");
57
69
  const worktree_db_1 = require("../../lib/db/worktree-db");
@@ -65,8 +77,33 @@ const vapid_1 = require("./vapid");
65
77
  const logger = (0, logger_1.createLogger)('push/waiting-notifier');
66
78
  /** How often outstanding waits are re-checked. Minute granularity is enough. */
67
79
  exports.ESCALATION_TICK_MS = 60_000;
80
+ /**
81
+ * How long a wait that has not named itself yet is held before it notifies
82
+ * (Issue #2156).
83
+ *
84
+ * `AskUserQuestion` opens the episode before the pane carries anything the
85
+ * screen scraper can read, so the *first* classification of that wait is
86
+ * `unclassified` and the body would say "check the terminal" about a dialog the
87
+ * app can answer. `waiting-episode-state` refreshes the kind in place on the
88
+ * next probe and deliberately emits nothing for it (a wait that changes
89
+ * character is still one wait), so the notifier only ever saw the provisional
90
+ * verdict.
91
+ *
92
+ * Measured on the session in the Issue: the edge opened at 00:08:38.837 with no
93
+ * usable classification and the next status probe refined it to `prompt` at
94
+ * 00:08:44.863 — 6.03 s later; 8 s is that measurement plus one probe's jitter
95
+ * and nothing more, because the hold is silence on the phone and it is meant to
96
+ * buy exactly one reclassification.
97
+ *
98
+ * Only an unnamed wait pays it: `prompt` and `menu` are positive verdicts and
99
+ * still notify on the edge itself.
100
+ */
101
+ exports.CLASSIFICATION_GRACE_MS = 8_000;
68
102
  const pending = globalThis.__waitingPushPending ??
69
103
  (globalThis.__waitingPushPending = new Map());
104
+ /** Composite key -> the timer holding that wait's first notification (#2156). */
105
+ const graceTimers = globalThis.__waitingPushGraceTimers ??
106
+ (globalThis.__waitingPushGraceTimers = new Map());
70
107
  /**
71
108
  * The worktree's display name, for the notification title.
72
109
  *
@@ -109,6 +146,73 @@ async function sendWaitingPush(wait, escalated, now) {
109
146
  });
110
147
  }
111
148
  }
149
+ /**
150
+ * Whether this classification is still provisional (Issue #2156).
151
+ *
152
+ * `unclassified` is what `deriveWaitingKind` returns for a frame the scraper
153
+ * could not read at all, and a null kind is the same admission from a producer
154
+ * that passed none — both mean "waiting, but nobody has said what for" and both
155
+ * are the verdict that arrives first when a dialog is drawn between two probes.
156
+ * `prompt` and `menu` are positive readings of the pane and are taken at once.
157
+ */
158
+ function isUnnamedWait(kind) {
159
+ return kind === null || kind === undefined || kind === 'unclassified';
160
+ }
161
+ /** Drop the hold on this wait without sending anything. */
162
+ function cancelGrace(key) {
163
+ const timer = graceTimers.get(key);
164
+ if (timer === undefined)
165
+ return;
166
+ clearTimeout(timer);
167
+ graceTimers.delete(key);
168
+ }
169
+ /**
170
+ * The Auto-Yes gate, then the fan-out.
171
+ *
172
+ * In that order because `shouldSendWaitingPush` records the episode at the
173
+ * moment it decides to send, so a notification dropped after the fan-out began
174
+ * would still consume the episode's one slot — see `prompt-push-gate`.
175
+ */
176
+ function gateAndSend(wait, now) {
177
+ if ((0, prompt_push_gate_1.isPromptPushSuppressed)({
178
+ worktreeId: wait.worktreeId,
179
+ cliToolId: wait.cliToolId,
180
+ instanceId: wait.instanceId,
181
+ waitingSince: wait.since,
182
+ })) {
183
+ return;
184
+ }
185
+ void sendWaitingPush(wait, false, now);
186
+ }
187
+ /**
188
+ * The grace elapsed: send the held wait with whatever it is called *now*
189
+ * (Issue #2156).
190
+ *
191
+ * The episode store is the authority here for the same reason it is in
192
+ * {@link runEscalationTick}: it carries the classification every later probe
193
+ * refined, and its absence is the wait having ended. Nothing is sent in that
194
+ * case — a wait answered inside the grace never needed a notification, and
195
+ * dropping it is the direction #1999/#2000 asked for rather than a correction
196
+ * push chasing one that was already wrong.
197
+ */
198
+ function releaseHeldWait(key) {
199
+ graceTimers.delete(key);
200
+ const held = pending.get(key);
201
+ // Gone means the closing edge dropped it, or a reminder already claimed it.
202
+ if (held === undefined)
203
+ return;
204
+ const episode = (0, waiting_episode_state_1.getWaitingEpisode)(held.worktreeId, held.cliToolId, held.instanceId);
205
+ if (episode === null || episode.since !== held.since) {
206
+ pending.delete(key);
207
+ stopEscalationTimerIfIdle();
208
+ return;
209
+ }
210
+ // Written back so the reminder quotes the settled kind even if the episode is
211
+ // gone by the time it runs.
212
+ const settled = { ...held, kind: episode.kind };
213
+ pending.set(key, settled);
214
+ gateAndSend(settled, Date.now());
215
+ }
112
216
  function startEscalationTimer() {
113
217
  if (globalThis.__waitingPushEscalationTimer !== undefined)
114
218
  return;
@@ -143,6 +247,8 @@ function handleWaitingTransition(transition) {
143
247
  return;
144
248
  const key = (0, auto_yes_state_1.buildCompositeKey)(transition.worktreeId, transition.cliToolId, transition.instanceId);
145
249
  if (!transition.waiting || transition.since === null) {
250
+ // Issue #2156: a wait still inside its grace is answered, not notified.
251
+ cancelGrace(key);
146
252
  pending.delete(key);
147
253
  stopEscalationTimerIfIdle();
148
254
  // Issue #2001: this is the moment the notification on every *other* device
@@ -180,15 +286,20 @@ function handleWaitingTransition(transition) {
180
286
  // episode at the moment it decides to send.
181
287
  pending.set(key, wait);
182
288
  startEscalationTimer();
183
- if ((0, prompt_push_gate_1.isPromptPushSuppressed)({
184
- worktreeId: wait.worktreeId,
185
- cliToolId: wait.cliToolId,
186
- instanceId: wait.instanceId,
187
- waitingSince: wait.since,
188
- })) {
289
+ // Issue #2156: a wait nobody has named yet is held for one probe interval so
290
+ // it can notify under the kind it turns out to be, rather than under the
291
+ // placeholder it opened with. A named wait notifies on the edge, as before.
292
+ if (isUnnamedWait(wait.kind)) {
293
+ cancelGrace(key);
294
+ const timer = setTimeout(() => {
295
+ releaseHeldWait(key);
296
+ }, exports.CLASSIFICATION_GRACE_MS);
297
+ // Same reasoning as the escalation interval: never hold the process open.
298
+ timer.unref?.();
299
+ graceTimers.set(key, timer);
189
300
  return;
190
301
  }
191
- void sendWaitingPush(wait, false, transition.at);
302
+ gateAndSend(wait, transition.at);
192
303
  }
193
304
  /**
194
305
  * Re-notify every wait that has outlived the threshold, once each.
@@ -267,6 +378,9 @@ function stopWaitingPushNotifier() {
267
378
  existing();
268
379
  globalThis.__waitingPushUnsubscribe = undefined;
269
380
  }
381
+ for (const timer of graceTimers.values())
382
+ clearTimeout(timer);
383
+ graceTimers.clear();
270
384
  pending.clear();
271
385
  stopEscalationTimerIfIdle();
272
386
  }
@@ -278,3 +392,7 @@ function isWaitingPushNotifierActive() {
278
392
  function pendingEscalationCount() {
279
393
  return pending.size;
280
394
  }
395
+ /** How many waits are held waiting to be classified (#2156). Test seam. */
396
+ function heldWaitCount() {
397
+ return graceTimers.size;
398
+ }