commandmate 0.23.0 → 0.25.0

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 (688) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-build-manifest.json +415 -406
  3. package/.next/app-path-routes-manifest.json +27 -26
  4. package/.next/build-manifest.json +5 -5
  5. package/.next/prerender-manifest.json +9 -9
  6. package/.next/react-loadable-manifest.json +4 -4
  7. package/.next/required-server-files.json +1 -1
  8. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  9. package/.next/server/app/api/app/update/route_client-reference-manifest.js +1 -1
  10. package/.next/server/app/api/app/update-check/route.js +1 -1
  11. package/.next/server/app/api/app/update-check/route_client-reference-manifest.js +1 -1
  12. package/.next/server/app/api/assistant/conversation/route.js +1 -1
  13. package/.next/server/app/api/assistant/conversation/route.js.nft.json +1 -1
  14. package/.next/server/app/api/assistant/conversation/route_client-reference-manifest.js +1 -1
  15. package/.next/server/app/api/assistant/current-output/route.js +1 -1
  16. package/.next/server/app/api/assistant/current-output/route.js.nft.json +1 -1
  17. package/.next/server/app/api/assistant/current-output/route_client-reference-manifest.js +1 -1
  18. package/.next/server/app/api/assistant/messages/route.js +1 -1
  19. package/.next/server/app/api/assistant/messages/route.js.nft.json +1 -1
  20. package/.next/server/app/api/assistant/messages/route_client-reference-manifest.js +1 -1
  21. package/.next/server/app/api/assistant/session/route.js +1 -1
  22. package/.next/server/app/api/assistant/session/route.js.nft.json +1 -1
  23. package/.next/server/app/api/assistant/session/route_client-reference-manifest.js +1 -1
  24. package/.next/server/app/api/assistant/start/route.js +1 -1
  25. package/.next/server/app/api/assistant/start/route.js.nft.json +1 -1
  26. package/.next/server/app/api/assistant/start/route_client-reference-manifest.js +1 -1
  27. package/.next/server/app/api/assistant/terminal/route.js +2 -2
  28. package/.next/server/app/api/assistant/terminal/route.js.nft.json +1 -1
  29. package/.next/server/app/api/assistant/terminal/route_client-reference-manifest.js +1 -1
  30. package/.next/server/app/api/assistant/tools/route.js +1 -1
  31. package/.next/server/app/api/assistant/tools/route.js.nft.json +1 -1
  32. package/.next/server/app/api/assistant/tools/route_client-reference-manifest.js +1 -1
  33. package/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
  34. package/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
  35. package/.next/server/app/api/auth/status/route_client-reference-manifest.js +1 -1
  36. package/.next/server/app/api/daily-summary/route.js +1 -1
  37. package/.next/server/app/api/daily-summary/route.js.nft.json +1 -1
  38. package/.next/server/app/api/daily-summary/route_client-reference-manifest.js +1 -1
  39. package/.next/server/app/api/daily-summary/status/route.js +1 -1
  40. package/.next/server/app/api/daily-summary/status/route.js.nft.json +1 -1
  41. package/.next/server/app/api/daily-summary/status/route_client-reference-manifest.js +1 -1
  42. package/.next/server/app/api/external-apps/[id]/health/route_client-reference-manifest.js +1 -1
  43. package/.next/server/app/api/external-apps/[id]/route_client-reference-manifest.js +1 -1
  44. package/.next/server/app/api/external-apps/route_client-reference-manifest.js +1 -1
  45. package/.next/server/app/api/fs/browse/route_client-reference-manifest.js +1 -1
  46. package/.next/server/app/api/fs/recent-paths/route_client-reference-manifest.js +1 -1
  47. package/.next/server/app/api/hooks/agent-event/route.js +1 -1
  48. package/.next/server/app/api/hooks/agent-event/route.js.nft.json +1 -1
  49. package/.next/server/app/api/hooks/agent-event/route_client-reference-manifest.js +1 -1
  50. package/.next/server/app/api/hooks/claude-done/route.js +1 -1
  51. package/.next/server/app/api/hooks/claude-done/route.js.nft.json +1 -1
  52. package/.next/server/app/api/hooks/claude-done/route_client-reference-manifest.js +1 -1
  53. package/.next/server/app/api/hooks/permission-request/route.js +1 -1
  54. package/.next/server/app/api/hooks/permission-request/route.js.nft.json +1 -1
  55. package/.next/server/app/api/hooks/permission-request/route_client-reference-manifest.js +1 -1
  56. package/.next/server/app/api/metrics/vibe/route_client-reference-manifest.js +1 -1
  57. package/.next/server/app/api/ollama/models/route_client-reference-manifest.js +1 -1
  58. package/.next/server/app/api/push/escalation/route.js +1 -0
  59. package/.next/server/app/api/push/escalation/route.js.nft.json +1 -0
  60. package/.next/server/app/api/push/escalation/route_client-reference-manifest.js +1 -0
  61. package/.next/server/app/api/push/subscriptions/route.js +1 -1
  62. package/.next/server/app/api/push/subscriptions/route_client-reference-manifest.js +1 -1
  63. package/.next/server/app/api/push/vapid/route.js +1 -1
  64. package/.next/server/app/api/push/vapid/route.js.nft.json +1 -1
  65. package/.next/server/app/api/push/vapid/route_client-reference-manifest.js +1 -1
  66. package/.next/server/app/api/repositories/[id]/route_client-reference-manifest.js +1 -1
  67. package/.next/server/app/api/repositories/[id]/todos/[todoId]/route.js +1 -1
  68. package/.next/server/app/api/repositories/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
  69. package/.next/server/app/api/repositories/[id]/todos/route.js +1 -1
  70. package/.next/server/app/api/repositories/[id]/todos/route_client-reference-manifest.js +1 -1
  71. package/.next/server/app/api/repositories/clone/[jobId]/route.js +1 -1
  72. package/.next/server/app/api/repositories/clone/[jobId]/route.js.nft.json +1 -1
  73. package/.next/server/app/api/repositories/clone/[jobId]/route_client-reference-manifest.js +1 -1
  74. package/.next/server/app/api/repositories/clone/route.js +1 -1
  75. package/.next/server/app/api/repositories/clone/route.js.nft.json +1 -1
  76. package/.next/server/app/api/repositories/clone/route_client-reference-manifest.js +1 -1
  77. package/.next/server/app/api/repositories/excluded/route_client-reference-manifest.js +1 -1
  78. package/.next/server/app/api/repositories/restore/route.js +1 -1
  79. package/.next/server/app/api/repositories/restore/route.js.nft.json +1 -1
  80. package/.next/server/app/api/repositories/restore/route_client-reference-manifest.js +1 -1
  81. package/.next/server/app/api/repositories/route.js +1 -1
  82. package/.next/server/app/api/repositories/route.js.nft.json +1 -1
  83. package/.next/server/app/api/repositories/route_client-reference-manifest.js +1 -1
  84. package/.next/server/app/api/repositories/scan/route.js +1 -1
  85. package/.next/server/app/api/repositories/scan/route.js.nft.json +1 -1
  86. package/.next/server/app/api/repositories/scan/route_client-reference-manifest.js +1 -1
  87. package/.next/server/app/api/repositories/sync/route.js +1 -1
  88. package/.next/server/app/api/repositories/sync/route.js.nft.json +1 -1
  89. package/.next/server/app/api/repositories/sync/route_client-reference-manifest.js +1 -1
  90. package/.next/server/app/api/repositories/validate-path/route_client-reference-manifest.js +1 -1
  91. package/.next/server/app/api/sidebar/group-order/route_client-reference-manifest.js +1 -1
  92. package/.next/server/app/api/skills/[id]/route_client-reference-manifest.js +1 -1
  93. package/.next/server/app/api/skills/installations/route_client-reference-manifest.js +1 -1
  94. package/.next/server/app/api/skills/operations/route_client-reference-manifest.js +1 -1
  95. package/.next/server/app/api/skills/reindex/route_client-reference-manifest.js +1 -1
  96. package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
  97. package/.next/server/app/api/slash-commands/route_client-reference-manifest.js +1 -1
  98. package/.next/server/app/api/tasks/[taskId]/cancel/route_client-reference-manifest.js +1 -1
  99. package/.next/server/app/api/tasks/[taskId]/route.js +1 -1
  100. package/.next/server/app/api/tasks/[taskId]/route_client-reference-manifest.js +1 -1
  101. package/.next/server/app/api/templates/[id]/route_client-reference-manifest.js +1 -1
  102. package/.next/server/app/api/templates/route_client-reference-manifest.js +1 -1
  103. package/.next/server/app/api/todos/route.js +1 -1
  104. package/.next/server/app/api/todos/route_client-reference-manifest.js +1 -1
  105. package/.next/server/app/api/verification/runs/[runId]/route.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.js +1 -1
  108. package/.next/server/app/api/verification/runs/route_client-reference-manifest.js +1 -1
  109. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js +1 -1
  110. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js.nft.json +1 -1
  111. package/.next/server/app/api/worktrees/[id]/auto-yes/route_client-reference-manifest.js +1 -1
  112. package/.next/server/app/api/worktrees/[id]/capture/route.js +1 -1
  113. package/.next/server/app/api/worktrees/[id]/capture/route.js.nft.json +1 -1
  114. package/.next/server/app/api/worktrees/[id]/capture/route_client-reference-manifest.js +1 -1
  115. package/.next/server/app/api/worktrees/[id]/cli-tool/route.js +1 -1
  116. package/.next/server/app/api/worktrees/[id]/cli-tool/route_client-reference-manifest.js +1 -1
  117. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route.js +1 -1
  118. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route.js.nft.json +1 -1
  119. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route_client-reference-manifest.js +1 -1
  120. package/.next/server/app/api/worktrees/[id]/current-output/route.js +1 -1
  121. package/.next/server/app/api/worktrees/[id]/current-output/route.js.nft.json +1 -1
  122. package/.next/server/app/api/worktrees/[id]/current-output/route_client-reference-manifest.js +1 -1
  123. package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route.js +1 -1
  124. package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route_client-reference-manifest.js +1 -1
  125. package/.next/server/app/api/worktrees/[id]/execution-logs/route.js +1 -1
  126. package/.next/server/app/api/worktrees/[id]/execution-logs/route_client-reference-manifest.js +1 -1
  127. package/.next/server/app/api/worktrees/[id]/files/[...path]/route_client-reference-manifest.js +1 -1
  128. package/.next/server/app/api/worktrees/[id]/git/branch/create/route_client-reference-manifest.js +1 -1
  129. package/.next/server/app/api/worktrees/[id]/git/branch/delete/route_client-reference-manifest.js +1 -1
  130. package/.next/server/app/api/worktrees/[id]/git/branches/route.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.js +1 -1
  134. package/.next/server/app/api/worktrees/[id]/git/commit/route_client-reference-manifest.js +1 -1
  135. package/.next/server/app/api/worktrees/[id]/git/diff/route_client-reference-manifest.js +1 -1
  136. package/.next/server/app/api/worktrees/[id]/git/fetch/route_client-reference-manifest.js +1 -1
  137. package/.next/server/app/api/worktrees/[id]/git/log/route.js +1 -1
  138. package/.next/server/app/api/worktrees/[id]/git/log/route_client-reference-manifest.js +1 -1
  139. package/.next/server/app/api/worktrees/[id]/git/pull/route_client-reference-manifest.js +1 -1
  140. package/.next/server/app/api/worktrees/[id]/git/push/route_client-reference-manifest.js +1 -1
  141. package/.next/server/app/api/worktrees/[id]/git/reset/route_client-reference-manifest.js +1 -1
  142. package/.next/server/app/api/worktrees/[id]/git/revert/route_client-reference-manifest.js +1 -1
  143. package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route_client-reference-manifest.js +1 -1
  144. package/.next/server/app/api/worktrees/[id]/git/stage/route_client-reference-manifest.js +1 -1
  145. package/.next/server/app/api/worktrees/[id]/git/staged/route.js +1 -1
  146. package/.next/server/app/api/worktrees/[id]/git/staged/route_client-reference-manifest.js +1 -1
  147. package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route_client-reference-manifest.js +1 -1
  148. package/.next/server/app/api/worktrees/[id]/git/stash/apply/route_client-reference-manifest.js +1 -1
  149. package/.next/server/app/api/worktrees/[id]/git/stash/pop/route_client-reference-manifest.js +1 -1
  150. package/.next/server/app/api/worktrees/[id]/git/stash/push/route.js +1 -1
  151. package/.next/server/app/api/worktrees/[id]/git/stash/push/route_client-reference-manifest.js +1 -1
  152. package/.next/server/app/api/worktrees/[id]/git/stash/route.js +1 -1
  153. package/.next/server/app/api/worktrees/[id]/git/stash/route_client-reference-manifest.js +1 -1
  154. package/.next/server/app/api/worktrees/[id]/git/status/route.js +1 -1
  155. package/.next/server/app/api/worktrees/[id]/git/status/route_client-reference-manifest.js +1 -1
  156. package/.next/server/app/api/worktrees/[id]/git/unstage/route_client-reference-manifest.js +1 -1
  157. package/.next/server/app/api/worktrees/[id]/git/working-diff/route.js +1 -1
  158. package/.next/server/app/api/worktrees/[id]/git/working-diff/route_client-reference-manifest.js +1 -1
  159. package/.next/server/app/api/worktrees/[id]/interrupt/route.js +1 -1
  160. package/.next/server/app/api/worktrees/[id]/interrupt/route.js.nft.json +1 -1
  161. package/.next/server/app/api/worktrees/[id]/interrupt/route_client-reference-manifest.js +1 -1
  162. package/.next/server/app/api/worktrees/[id]/kill-session/route.js +1 -1
  163. package/.next/server/app/api/worktrees/[id]/kill-session/route.js.nft.json +1 -1
  164. package/.next/server/app/api/worktrees/[id]/kill-session/route_client-reference-manifest.js +1 -1
  165. package/.next/server/app/api/worktrees/[id]/logs/[filename]/route_client-reference-manifest.js +1 -1
  166. package/.next/server/app/api/worktrees/[id]/logs/route_client-reference-manifest.js +1 -1
  167. package/.next/server/app/api/worktrees/[id]/marp-render/route.js +5 -5
  168. package/.next/server/app/api/worktrees/[id]/marp-render/route_client-reference-manifest.js +1 -1
  169. package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route.js +1 -1
  170. package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route_client-reference-manifest.js +1 -1
  171. package/.next/server/app/api/worktrees/[id]/memos/route.js +1 -1
  172. package/.next/server/app/api/worktrees/[id]/memos/route_client-reference-manifest.js +1 -1
  173. package/.next/server/app/api/worktrees/[id]/messages/route.js +1 -1
  174. package/.next/server/app/api/worktrees/[id]/messages/route_client-reference-manifest.js +1 -1
  175. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js +1 -1
  176. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js.nft.json +1 -1
  177. package/.next/server/app/api/worktrees/[id]/prompt-response/route_client-reference-manifest.js +1 -1
  178. package/.next/server/app/api/worktrees/[id]/respond/route.js +1 -1
  179. package/.next/server/app/api/worktrees/[id]/respond/route.js.nft.json +1 -1
  180. package/.next/server/app/api/worktrees/[id]/respond/route_client-reference-manifest.js +1 -1
  181. package/.next/server/app/api/worktrees/[id]/route.js +1 -1
  182. package/.next/server/app/api/worktrees/[id]/route.js.nft.json +1 -1
  183. package/.next/server/app/api/worktrees/[id]/route_client-reference-manifest.js +1 -1
  184. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route.js +2 -2
  185. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route.js.nft.json +1 -1
  186. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route_client-reference-manifest.js +1 -1
  187. package/.next/server/app/api/worktrees/[id]/schedules/active/route.js +1 -1
  188. package/.next/server/app/api/worktrees/[id]/schedules/active/route.js.nft.json +1 -1
  189. package/.next/server/app/api/worktrees/[id]/schedules/active/route_client-reference-manifest.js +1 -1
  190. package/.next/server/app/api/worktrees/[id]/schedules/route.js +3 -3
  191. package/.next/server/app/api/worktrees/[id]/schedules/route.js.nft.json +1 -1
  192. package/.next/server/app/api/worktrees/[id]/schedules/route_client-reference-manifest.js +1 -1
  193. package/.next/server/app/api/worktrees/[id]/search/route_client-reference-manifest.js +1 -1
  194. package/.next/server/app/api/worktrees/[id]/send/route.js +1 -1
  195. package/.next/server/app/api/worktrees/[id]/send/route.js.nft.json +1 -1
  196. package/.next/server/app/api/worktrees/[id]/send/route_client-reference-manifest.js +1 -1
  197. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js +1 -1
  198. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js.nft.json +1 -1
  199. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route_client-reference-manifest.js +1 -1
  200. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route_client-reference-manifest.js +1 -1
  201. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route_client-reference-manifest.js +1 -1
  202. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route_client-reference-manifest.js +1 -1
  203. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route_client-reference-manifest.js +1 -1
  204. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update/route_client-reference-manifest.js +1 -1
  205. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route_client-reference-manifest.js +1 -1
  206. package/.next/server/app/api/worktrees/[id]/skills/route.js +1 -1
  207. package/.next/server/app/api/worktrees/[id]/skills/route_client-reference-manifest.js +1 -1
  208. package/.next/server/app/api/worktrees/[id]/slash-commands/route.js +1 -1
  209. package/.next/server/app/api/worktrees/[id]/slash-commands/route_client-reference-manifest.js +1 -1
  210. package/.next/server/app/api/worktrees/[id]/special-keys/route.js +1 -1
  211. package/.next/server/app/api/worktrees/[id]/special-keys/route.js.nft.json +1 -1
  212. package/.next/server/app/api/worktrees/[id]/special-keys/route_client-reference-manifest.js +1 -1
  213. package/.next/server/app/api/worktrees/[id]/start-polling/route.js +1 -1
  214. package/.next/server/app/api/worktrees/[id]/start-polling/route.js.nft.json +1 -1
  215. package/.next/server/app/api/worktrees/[id]/start-polling/route_client-reference-manifest.js +1 -1
  216. package/.next/server/app/api/worktrees/[id]/tasks/route.js +2 -2
  217. package/.next/server/app/api/worktrees/[id]/tasks/route_client-reference-manifest.js +1 -1
  218. package/.next/server/app/api/worktrees/[id]/terminal/route.js +1 -1
  219. package/.next/server/app/api/worktrees/[id]/terminal/route.js.nft.json +1 -1
  220. package/.next/server/app/api/worktrees/[id]/terminal/route_client-reference-manifest.js +1 -1
  221. package/.next/server/app/api/worktrees/[id]/timers/history/route.js +1 -1
  222. package/.next/server/app/api/worktrees/[id]/timers/history/route_client-reference-manifest.js +1 -1
  223. package/.next/server/app/api/worktrees/[id]/timers/route.js +1 -1
  224. package/.next/server/app/api/worktrees/[id]/timers/route.js.nft.json +1 -1
  225. package/.next/server/app/api/worktrees/[id]/timers/route_client-reference-manifest.js +1 -1
  226. package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route.js +1 -1
  227. package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
  228. package/.next/server/app/api/worktrees/[id]/todos/route.js +1 -1
  229. package/.next/server/app/api/worktrees/[id]/todos/route_client-reference-manifest.js +1 -1
  230. package/.next/server/app/api/worktrees/[id]/tree/[...path]/route.js +1 -1
  231. package/.next/server/app/api/worktrees/[id]/tree/[...path]/route_client-reference-manifest.js +1 -1
  232. package/.next/server/app/api/worktrees/[id]/tree/route.js +1 -1
  233. package/.next/server/app/api/worktrees/[id]/tree/route_client-reference-manifest.js +1 -1
  234. package/.next/server/app/api/worktrees/[id]/upload/[...path]/route_client-reference-manifest.js +1 -1
  235. package/.next/server/app/api/worktrees/[id]/verify/route.js +1 -1
  236. package/.next/server/app/api/worktrees/[id]/verify/route_client-reference-manifest.js +1 -1
  237. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route.js +1 -1
  238. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route_client-reference-manifest.js +1 -1
  239. package/.next/server/app/api/worktrees/[id]/verify/runs/route.js +1 -1
  240. package/.next/server/app/api/worktrees/[id]/verify/runs/route_client-reference-manifest.js +1 -1
  241. package/.next/server/app/api/worktrees/[id]/viewed/route.js +1 -1
  242. package/.next/server/app/api/worktrees/[id]/viewed/route_client-reference-manifest.js +1 -1
  243. package/.next/server/app/api/worktrees/route.js +1 -1
  244. package/.next/server/app/api/worktrees/route.js.nft.json +1 -1
  245. package/.next/server/app/api/worktrees/route_client-reference-manifest.js +1 -1
  246. package/.next/server/app/chat/page.js +2 -2
  247. package/.next/server/app/chat/page.js.nft.json +1 -1
  248. package/.next/server/app/chat/page_client-reference-manifest.js +1 -1
  249. package/.next/server/app/login/page.js +2 -2
  250. package/.next/server/app/login/page.js.nft.json +1 -1
  251. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  252. package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
  253. package/.next/server/app/more/page.js +2 -2
  254. package/.next/server/app/more/page.js.nft.json +1 -1
  255. package/.next/server/app/more/page_client-reference-manifest.js +1 -1
  256. package/.next/server/app/offline/page_client-reference-manifest.js +1 -1
  257. package/.next/server/app/page.js +1 -1
  258. package/.next/server/app/page.js.nft.json +1 -1
  259. package/.next/server/app/page_client-reference-manifest.js +1 -1
  260. package/.next/server/app/proxy/[...path]/route.js +1 -1
  261. package/.next/server/app/proxy/[...path]/route_client-reference-manifest.js +1 -1
  262. package/.next/server/app/repositories/page.js +2 -2
  263. package/.next/server/app/repositories/page.js.nft.json +1 -1
  264. package/.next/server/app/repositories/page_client-reference-manifest.js +1 -1
  265. package/.next/server/app/review/page.js +1 -1
  266. package/.next/server/app/review/page.js.nft.json +1 -1
  267. package/.next/server/app/review/page_client-reference-manifest.js +1 -1
  268. package/.next/server/app/sessions/page.js +1 -1
  269. package/.next/server/app/sessions/page.js.nft.json +1 -1
  270. package/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  271. package/.next/server/app/skills/[skillId]/page.js +2 -2
  272. package/.next/server/app/skills/[skillId]/page.js.nft.json +1 -1
  273. package/.next/server/app/skills/[skillId]/page_client-reference-manifest.js +1 -1
  274. package/.next/server/app/skills/installed/page.js +2 -2
  275. package/.next/server/app/skills/installed/page.js.nft.json +1 -1
  276. package/.next/server/app/skills/installed/page_client-reference-manifest.js +1 -1
  277. package/.next/server/app/skills/page.js +2 -2
  278. package/.next/server/app/skills/page.js.nft.json +1 -1
  279. package/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  280. package/.next/server/app/worktrees/[id]/files/[...path]/page.js +2 -2
  281. package/.next/server/app/worktrees/[id]/files/[...path]/page.js.nft.json +1 -1
  282. package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -1
  283. package/.next/server/app/worktrees/[id]/page.js +7 -7
  284. package/.next/server/app/worktrees/[id]/page.js.nft.json +1 -1
  285. package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -1
  286. package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
  287. package/.next/server/app-paths-manifest.json +27 -26
  288. package/.next/server/chunks/1029.js +1 -1
  289. package/.next/server/chunks/1296.js +1 -1
  290. package/.next/server/chunks/1366.js +1 -1
  291. package/.next/server/chunks/1601.js +7 -0
  292. package/.next/server/chunks/1825.js +1 -1
  293. package/.next/server/chunks/2119.js +1 -1
  294. package/.next/server/chunks/2404.js +1 -1
  295. package/.next/server/chunks/2445.js +1 -1
  296. package/.next/server/chunks/2546.js +1 -1
  297. package/.next/server/chunks/3346.js +1 -1
  298. package/.next/server/chunks/3417.js +1 -1
  299. package/.next/server/chunks/3480.js +1 -1
  300. package/.next/server/chunks/3543.js +1 -1
  301. package/.next/server/chunks/3945.js +1 -1
  302. package/.next/server/chunks/4393.js +1 -0
  303. package/.next/server/chunks/4444.js +1 -1
  304. package/.next/server/chunks/4455.js +1 -0
  305. package/.next/server/chunks/5164.js +1 -0
  306. package/.next/server/chunks/5571.js +1 -1
  307. package/.next/server/chunks/5959.js +5 -5
  308. package/.next/server/chunks/5998.js +1 -1
  309. package/.next/server/chunks/6130.js +1 -1
  310. package/.next/server/chunks/6159.js +1 -1
  311. package/.next/server/chunks/6274.js +2 -2
  312. package/.next/server/chunks/6285.js +1 -1
  313. package/.next/server/chunks/6401.js +1 -1
  314. package/.next/server/chunks/7458.js +5 -5
  315. package/.next/server/chunks/848.js +1 -1
  316. package/.next/server/chunks/8536.js +1 -1
  317. package/.next/server/chunks/8730.js +1 -0
  318. package/.next/server/chunks/880.js +21 -0
  319. package/.next/server/chunks/8807.js +134 -129
  320. package/.next/server/chunks/9058.js +1 -1
  321. package/.next/server/chunks/9123.js +8 -8
  322. package/.next/server/chunks/9328.js +1 -1
  323. package/.next/server/chunks/9358.js +1 -1
  324. package/.next/server/chunks/9373.js +3 -3
  325. package/.next/server/chunks/9687.js +1 -1
  326. package/.next/server/middleware-build-manifest.js +1 -1
  327. package/.next/server/middleware-manifest.json +5 -5
  328. package/.next/server/middleware-react-loadable-manifest.js +1 -1
  329. package/.next/server/pages/500.html +1 -1
  330. package/.next/server/pages-manifest.json +1 -1
  331. package/.next/server/server-reference-manifest.json +1 -1
  332. package/.next/static/chunks/2053-dfac2d49227cc942.js +1 -0
  333. package/.next/static/chunks/3898-ef488bfa804507d9.js +1 -0
  334. package/.next/static/chunks/4322-dfd5a7119b5ba4fc.js +1 -0
  335. package/.next/static/chunks/{4974-eaf66770bfa9dea0.js → 4974-35592ec312322124.js} +1 -1
  336. package/.next/static/chunks/5229-35f9acab97a553c5.js +1 -0
  337. package/.next/static/chunks/6381-51f9c4a128aadc0b.js +1 -0
  338. package/.next/static/chunks/7229.7f0f5a7032b612b4.js +1 -0
  339. package/.next/static/chunks/{9599-d29d2f8eeaf7c249.js → 8649-f551b0010dba4986.js} +1 -1
  340. package/.next/static/chunks/9263.f2034ec525abcf72.js +1 -0
  341. package/.next/static/chunks/app/api/app/update/{route-973ec48531555712.js → route-fae89f8d4cc3ff97.js} +1 -1
  342. package/.next/static/chunks/app/api/app/update-check/{route-973ec48531555712.js → route-fae89f8d4cc3ff97.js} +1 -1
  343. package/.next/static/chunks/app/api/assistant/conversation/{route-973ec48531555712.js → route-fae89f8d4cc3ff97.js} +1 -1
  344. package/.next/static/chunks/app/api/assistant/current-output/{route-973ec48531555712.js → route-fae89f8d4cc3ff97.js} +1 -1
  345. package/.next/static/chunks/app/api/assistant/messages/route-fae89f8d4cc3ff97.js +1 -0
  346. package/.next/static/chunks/app/api/assistant/session/route-fae89f8d4cc3ff97.js +1 -0
  347. package/.next/static/chunks/app/api/assistant/start/route-fae89f8d4cc3ff97.js +1 -0
  348. package/.next/static/chunks/app/api/assistant/terminal/route-fae89f8d4cc3ff97.js +1 -0
  349. package/.next/static/chunks/app/api/assistant/tools/route-fae89f8d4cc3ff97.js +1 -0
  350. package/.next/static/chunks/app/api/auth/login/route-fae89f8d4cc3ff97.js +1 -0
  351. package/.next/static/chunks/app/api/auth/logout/route-fae89f8d4cc3ff97.js +1 -0
  352. package/.next/static/chunks/app/api/auth/status/route-fae89f8d4cc3ff97.js +1 -0
  353. package/.next/static/chunks/app/api/daily-summary/route-fae89f8d4cc3ff97.js +1 -0
  354. package/.next/static/chunks/app/api/daily-summary/status/route-fae89f8d4cc3ff97.js +1 -0
  355. package/.next/static/chunks/app/api/external-apps/[id]/health/route-fae89f8d4cc3ff97.js +1 -0
  356. package/.next/static/chunks/app/api/external-apps/[id]/route-fae89f8d4cc3ff97.js +1 -0
  357. package/.next/static/chunks/app/api/external-apps/route-fae89f8d4cc3ff97.js +1 -0
  358. package/.next/static/chunks/app/api/fs/browse/route-fae89f8d4cc3ff97.js +1 -0
  359. package/.next/static/chunks/app/api/fs/recent-paths/route-fae89f8d4cc3ff97.js +1 -0
  360. package/.next/static/chunks/app/api/hooks/agent-event/route-fae89f8d4cc3ff97.js +1 -0
  361. package/.next/static/chunks/app/api/hooks/claude-done/route-fae89f8d4cc3ff97.js +1 -0
  362. package/.next/static/chunks/app/api/hooks/permission-request/route-fae89f8d4cc3ff97.js +1 -0
  363. package/.next/static/chunks/app/api/metrics/vibe/route-fae89f8d4cc3ff97.js +1 -0
  364. package/.next/static/chunks/app/api/ollama/models/route-fae89f8d4cc3ff97.js +1 -0
  365. package/.next/static/chunks/app/api/push/escalation/route-fae89f8d4cc3ff97.js +1 -0
  366. package/.next/static/chunks/app/api/push/subscriptions/route-fae89f8d4cc3ff97.js +1 -0
  367. package/.next/static/chunks/app/api/push/vapid/route-fae89f8d4cc3ff97.js +1 -0
  368. package/.next/static/chunks/app/api/repositories/[id]/route-fae89f8d4cc3ff97.js +1 -0
  369. package/.next/static/chunks/app/api/repositories/[id]/todos/[todoId]/route-fae89f8d4cc3ff97.js +1 -0
  370. package/.next/static/chunks/app/api/repositories/[id]/todos/route-fae89f8d4cc3ff97.js +1 -0
  371. package/.next/static/chunks/app/api/repositories/clone/[jobId]/route-fae89f8d4cc3ff97.js +1 -0
  372. package/.next/static/chunks/app/api/repositories/clone/route-fae89f8d4cc3ff97.js +1 -0
  373. package/.next/static/chunks/app/api/repositories/excluded/route-fae89f8d4cc3ff97.js +1 -0
  374. package/.next/static/chunks/app/api/repositories/restore/route-fae89f8d4cc3ff97.js +1 -0
  375. package/.next/static/chunks/app/api/repositories/route-fae89f8d4cc3ff97.js +1 -0
  376. package/.next/static/chunks/app/api/repositories/scan/route-fae89f8d4cc3ff97.js +1 -0
  377. package/.next/static/chunks/app/api/repositories/sync/route-fae89f8d4cc3ff97.js +1 -0
  378. package/.next/static/chunks/app/api/repositories/validate-path/route-fae89f8d4cc3ff97.js +1 -0
  379. package/.next/static/chunks/app/api/sidebar/group-order/route-fae89f8d4cc3ff97.js +1 -0
  380. package/.next/static/chunks/app/api/skills/[id]/route-fae89f8d4cc3ff97.js +1 -0
  381. package/.next/static/chunks/app/api/skills/installations/route-fae89f8d4cc3ff97.js +1 -0
  382. package/.next/static/chunks/app/api/skills/operations/route-fae89f8d4cc3ff97.js +1 -0
  383. package/.next/static/chunks/app/api/skills/reindex/route-fae89f8d4cc3ff97.js +1 -0
  384. package/.next/static/chunks/app/api/skills/route-fae89f8d4cc3ff97.js +1 -0
  385. package/.next/static/chunks/app/api/slash-commands/route-fae89f8d4cc3ff97.js +1 -0
  386. package/.next/static/chunks/app/api/tasks/[taskId]/cancel/route-fae89f8d4cc3ff97.js +1 -0
  387. package/.next/static/chunks/app/api/tasks/[taskId]/route-fae89f8d4cc3ff97.js +1 -0
  388. package/.next/static/chunks/app/api/templates/[id]/route-fae89f8d4cc3ff97.js +1 -0
  389. package/.next/static/chunks/app/api/templates/route-fae89f8d4cc3ff97.js +1 -0
  390. package/.next/static/chunks/app/api/todos/route-fae89f8d4cc3ff97.js +1 -0
  391. package/.next/static/chunks/app/api/verification/runs/[runId]/route-fae89f8d4cc3ff97.js +1 -0
  392. package/.next/static/chunks/app/api/verification/runs/route-fae89f8d4cc3ff97.js +1 -0
  393. package/.next/static/chunks/app/api/worktrees/[id]/auto-yes/route-fae89f8d4cc3ff97.js +1 -0
  394. package/.next/static/chunks/app/api/worktrees/[id]/capture/route-fae89f8d4cc3ff97.js +1 -0
  395. package/.next/static/chunks/app/api/worktrees/[id]/cli-tool/route-fae89f8d4cc3ff97.js +1 -0
  396. package/.next/static/chunks/app/api/worktrees/[id]/cmate/schedules/route-fae89f8d4cc3ff97.js +1 -0
  397. package/.next/static/chunks/app/api/worktrees/[id]/current-output/route-fae89f8d4cc3ff97.js +1 -0
  398. package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/[logId]/route-fae89f8d4cc3ff97.js +1 -0
  399. package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/route-fae89f8d4cc3ff97.js +1 -0
  400. package/.next/static/chunks/app/api/worktrees/[id]/files/[...path]/route-fae89f8d4cc3ff97.js +1 -0
  401. package/.next/static/chunks/app/api/worktrees/[id]/git/branch/create/route-fae89f8d4cc3ff97.js +1 -0
  402. package/.next/static/chunks/app/api/worktrees/[id]/git/branch/delete/route-fae89f8d4cc3ff97.js +1 -0
  403. package/.next/static/chunks/app/api/worktrees/[id]/git/branches/route-fae89f8d4cc3ff97.js +1 -0
  404. package/.next/static/chunks/app/api/worktrees/[id]/git/checkout/route-fae89f8d4cc3ff97.js +1 -0
  405. package/.next/static/chunks/app/api/worktrees/[id]/git/commit/route-fae89f8d4cc3ff97.js +1 -0
  406. package/.next/static/chunks/app/api/worktrees/[id]/git/diff/route-fae89f8d4cc3ff97.js +1 -0
  407. package/.next/static/chunks/app/api/worktrees/[id]/git/fetch/route-fae89f8d4cc3ff97.js +1 -0
  408. package/.next/static/chunks/app/api/worktrees/[id]/git/log/route-fae89f8d4cc3ff97.js +1 -0
  409. package/.next/static/chunks/app/api/worktrees/[id]/git/pull/route-fae89f8d4cc3ff97.js +1 -0
  410. package/.next/static/chunks/app/api/worktrees/[id]/git/push/route-fae89f8d4cc3ff97.js +1 -0
  411. package/.next/static/chunks/app/api/worktrees/[id]/git/reset/route-fae89f8d4cc3ff97.js +1 -0
  412. package/.next/static/chunks/app/api/worktrees/[id]/git/revert/route-fae89f8d4cc3ff97.js +1 -0
  413. package/.next/static/chunks/app/api/worktrees/[id]/git/show/[commitHash]/route-fae89f8d4cc3ff97.js +1 -0
  414. package/.next/static/chunks/app/api/worktrees/[id]/git/stage/route-fae89f8d4cc3ff97.js +1 -0
  415. package/.next/static/chunks/app/api/worktrees/[id]/git/staged/route-fae89f8d4cc3ff97.js +1 -0
  416. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/[index]/route-fae89f8d4cc3ff97.js +1 -0
  417. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/apply/route-fae89f8d4cc3ff97.js +1 -0
  418. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/pop/route-fae89f8d4cc3ff97.js +1 -0
  419. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/push/route-fae89f8d4cc3ff97.js +1 -0
  420. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/route-fae89f8d4cc3ff97.js +1 -0
  421. package/.next/static/chunks/app/api/worktrees/[id]/git/status/route-fae89f8d4cc3ff97.js +1 -0
  422. package/.next/static/chunks/app/api/worktrees/[id]/git/unstage/route-fae89f8d4cc3ff97.js +1 -0
  423. package/.next/static/chunks/app/api/worktrees/[id]/git/working-diff/route-fae89f8d4cc3ff97.js +1 -0
  424. package/.next/static/chunks/app/api/worktrees/[id]/interrupt/route-fae89f8d4cc3ff97.js +1 -0
  425. package/.next/static/chunks/app/api/worktrees/[id]/kill-session/route-fae89f8d4cc3ff97.js +1 -0
  426. package/.next/static/chunks/app/api/worktrees/[id]/logs/[filename]/route-fae89f8d4cc3ff97.js +1 -0
  427. package/.next/static/chunks/app/api/worktrees/[id]/logs/route-fae89f8d4cc3ff97.js +1 -0
  428. package/.next/static/chunks/app/api/worktrees/[id]/marp-render/route-fae89f8d4cc3ff97.js +1 -0
  429. package/.next/static/chunks/app/api/worktrees/[id]/memos/[memoId]/route-fae89f8d4cc3ff97.js +1 -0
  430. package/.next/static/chunks/app/api/worktrees/[id]/memos/route-fae89f8d4cc3ff97.js +1 -0
  431. package/.next/static/chunks/app/api/worktrees/[id]/messages/route-fae89f8d4cc3ff97.js +1 -0
  432. package/.next/static/chunks/app/api/worktrees/[id]/prompt-response/route-fae89f8d4cc3ff97.js +1 -0
  433. package/.next/static/chunks/app/api/worktrees/[id]/respond/route-fae89f8d4cc3ff97.js +1 -0
  434. package/.next/static/chunks/app/api/worktrees/[id]/route-fae89f8d4cc3ff97.js +1 -0
  435. package/.next/static/chunks/app/api/worktrees/[id]/schedules/[scheduleId]/route-fae89f8d4cc3ff97.js +1 -0
  436. package/.next/static/chunks/app/api/worktrees/[id]/schedules/active/route-fae89f8d4cc3ff97.js +1 -0
  437. package/.next/static/chunks/app/api/worktrees/[id]/schedules/route-fae89f8d4cc3ff97.js +1 -0
  438. package/.next/static/chunks/app/api/worktrees/[id]/search/route-fae89f8d4cc3ff97.js +1 -0
  439. package/.next/static/chunks/app/api/worktrees/[id]/send/route-fae89f8d4cc3ff97.js +1 -0
  440. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route-fae89f8d4cc3ff97.js +1 -0
  441. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/install/route-fae89f8d4cc3ff97.js +1 -0
  442. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/plan/route-fae89f8d4cc3ff97.js +1 -0
  443. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall/route-fae89f8d4cc3ff97.js +1 -0
  444. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route-fae89f8d4cc3ff97.js +1 -0
  445. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update/route-fae89f8d4cc3ff97.js +1 -0
  446. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update-plan/route-fae89f8d4cc3ff97.js +1 -0
  447. package/.next/static/chunks/app/api/worktrees/[id]/skills/route-fae89f8d4cc3ff97.js +1 -0
  448. package/.next/static/chunks/app/api/worktrees/[id]/slash-commands/route-fae89f8d4cc3ff97.js +1 -0
  449. package/.next/static/chunks/app/api/worktrees/[id]/special-keys/route-fae89f8d4cc3ff97.js +1 -0
  450. package/.next/static/chunks/app/api/worktrees/[id]/start-polling/route-fae89f8d4cc3ff97.js +1 -0
  451. package/.next/static/chunks/app/api/worktrees/[id]/tasks/route-fae89f8d4cc3ff97.js +1 -0
  452. package/.next/static/chunks/app/api/worktrees/[id]/terminal/route-fae89f8d4cc3ff97.js +1 -0
  453. package/.next/static/chunks/app/api/worktrees/[id]/timers/history/route-fae89f8d4cc3ff97.js +1 -0
  454. package/.next/static/chunks/app/api/worktrees/[id]/timers/route-fae89f8d4cc3ff97.js +1 -0
  455. package/.next/static/chunks/app/api/worktrees/[id]/todos/[todoId]/route-fae89f8d4cc3ff97.js +1 -0
  456. package/.next/static/chunks/app/api/worktrees/[id]/todos/route-fae89f8d4cc3ff97.js +1 -0
  457. package/.next/static/chunks/app/api/worktrees/[id]/tree/[...path]/route-fae89f8d4cc3ff97.js +1 -0
  458. package/.next/static/chunks/app/api/worktrees/[id]/tree/route-fae89f8d4cc3ff97.js +1 -0
  459. package/.next/static/chunks/app/api/worktrees/[id]/upload/[...path]/route-fae89f8d4cc3ff97.js +1 -0
  460. package/.next/static/chunks/app/api/worktrees/[id]/verify/route-fae89f8d4cc3ff97.js +1 -0
  461. package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/[runId]/route-fae89f8d4cc3ff97.js +1 -0
  462. package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/route-fae89f8d4cc3ff97.js +1 -0
  463. package/.next/static/chunks/app/api/worktrees/[id]/viewed/route-fae89f8d4cc3ff97.js +1 -0
  464. package/.next/static/chunks/app/api/worktrees/route-fae89f8d4cc3ff97.js +1 -0
  465. package/.next/static/chunks/app/chat/page-439b35c9cb90dbe0.js +1 -0
  466. package/.next/static/chunks/app/layout-6a26ea22d5cf03dc.js +1 -0
  467. package/.next/static/chunks/app/login/page-eefd515d8c37e5ee.js +1 -0
  468. package/.next/static/chunks/app/manifest.webmanifest/route-fae89f8d4cc3ff97.js +1 -0
  469. package/.next/static/chunks/app/more/page-889b7546a8a553dc.js +1 -0
  470. package/.next/static/chunks/app/page-a8d04ac0e3e4c9fc.js +1 -0
  471. package/.next/static/chunks/app/proxy/[...path]/route-fae89f8d4cc3ff97.js +1 -0
  472. package/.next/static/chunks/app/repositories/page-f3c4d8839b1ca203.js +1 -0
  473. package/.next/static/chunks/app/review/page-6dc88649fe88ac16.js +1 -0
  474. package/.next/static/chunks/app/sessions/page-2c9ed9e969097688.js +1 -0
  475. package/.next/static/chunks/app/skills/[skillId]/page-19beef6121c4c982.js +1 -0
  476. package/.next/static/chunks/app/skills/installed/page-d5b9cef6d21fabda.js +1 -0
  477. package/.next/static/chunks/app/skills/page-06ef637e07dd9377.js +1 -0
  478. package/.next/static/chunks/app/worktrees/[id]/files/[...path]/page-5fed3984fafcd910.js +1 -0
  479. package/.next/static/chunks/app/worktrees/[id]/layout-fae89f8d4cc3ff97.js +1 -0
  480. package/.next/static/chunks/app/worktrees/[id]/page-207c69540fd856ef.js +1 -0
  481. package/.next/static/chunks/{webpack-180bebdee221b6f4.js → webpack-9d892a9ff07c289d.js} +1 -1
  482. package/.next/static/css/e865c4979a41aa03.css +1 -0
  483. package/.next/static/ehkNc5xDMDkXlua08Bwq0/_buildManifest.js +1 -0
  484. package/.next/trace +12 -12
  485. package/.next/types/app/api/push/escalation/route.ts +347 -0
  486. package/.next/types/routes.d.ts +2 -1
  487. package/.next/types/validator.ts +9 -0
  488. package/README.md +96 -45
  489. package/dist/cli/commands/capture.d.ts.map +1 -1
  490. package/dist/cli/commands/capture.js +6 -0
  491. package/dist/cli/commands/instances.d.ts.map +1 -1
  492. package/dist/cli/commands/instances.js +19 -1
  493. package/dist/cli/commands/task.d.ts.map +1 -1
  494. package/dist/cli/commands/task.js +6 -0
  495. package/dist/cli/commands/verify.js +6 -1
  496. package/dist/cli/types/api-responses.d.ts +46 -0
  497. package/dist/cli/types/api-responses.d.ts.map +1 -1
  498. package/dist/cli/utils/verify-runner.d.ts.map +1 -1
  499. package/dist/cli/utils/verify-runner.js +17 -1
  500. package/dist/server/locales/en/notifications.json +20 -1
  501. package/dist/server/locales/ja/notifications.json +20 -1
  502. package/dist/server/server.js +23 -0
  503. package/dist/server/src/config/activity-bar-config.js +5 -1
  504. package/dist/server/src/lib/auto-yes-poller.js +40 -4
  505. package/dist/server/src/lib/cli-tools/codex.js +58 -29
  506. package/dist/server/src/lib/db/db.js +2 -1
  507. package/dist/server/src/lib/db/migrations/index.js +2 -0
  508. package/dist/server/src/lib/db/migrations/runner.js +1 -1
  509. package/dist/server/src/lib/db/migrations/v56-gate-result-source.js +58 -0
  510. package/dist/server/src/lib/db/verification-db.js +26 -6
  511. package/dist/server/src/lib/detection/cli-patterns.js +148 -6
  512. package/dist/server/src/lib/detection/model-info-extractor.js +384 -0
  513. package/dist/server/src/lib/detection/status-detector.js +28 -0
  514. package/dist/server/src/lib/hooks/sources/antigravity/source.js +4 -0
  515. package/dist/server/src/lib/hooks/sources/claude/source.js +7 -0
  516. package/dist/server/src/lib/hooks/sources/codex/source.js +5 -0
  517. package/dist/server/src/lib/hooks/sources/define-source.js +8 -0
  518. package/dist/server/src/lib/hooks/sources/event-mapper.js +20 -0
  519. package/dist/server/src/lib/hooks/sources/opencode/ingest.js +6 -0
  520. package/dist/server/src/lib/hooks/sources/opencode/mappers.js +22 -0
  521. package/dist/server/src/lib/hooks/sources/opencode/source.js +3 -0
  522. package/dist/server/src/lib/polling/response-checker.js +47 -0
  523. package/dist/server/src/lib/push/escalation-settings.js +114 -0
  524. package/dist/server/src/lib/push/index.js +21 -1
  525. package/dist/server/src/lib/push/notification-dedup.js +35 -0
  526. package/dist/server/src/lib/push/push-sender.js +66 -7
  527. package/dist/server/src/lib/push/waiting-push-notifier.js +231 -0
  528. package/dist/server/src/lib/realtime/waiting-broadcast.js +93 -0
  529. package/dist/server/src/lib/session/agent-event-state.js +260 -0
  530. package/dist/server/src/lib/session/current-output-builder.js +24 -0
  531. package/dist/server/src/lib/session/next-action-helper.js +93 -0
  532. package/dist/server/src/lib/session/prompt-waiting-composition.js +38 -0
  533. package/dist/server/src/lib/session/waiting-episode-state.js +136 -0
  534. package/dist/server/src/lib/session/waiting-kind.js +59 -0
  535. package/dist/server/src/lib/tasks/contract-message.js +64 -21
  536. package/dist/server/src/lib/tasks/contract-parser.js +58 -12
  537. package/dist/server/src/lib/verification/gate-runner.js +64 -22
  538. package/dist/server/src/lib/verification/verify-config.js +84 -51
  539. package/dist/server/src/lib/ws-server.js +9 -0
  540. package/dist/server/src/types/sidebar.js +68 -0
  541. package/package.json +1 -1
  542. package/.next/server/chunks/3451.js +0 -1
  543. package/.next/server/chunks/6283.js +0 -1
  544. package/.next/server/chunks/646.js +0 -21
  545. package/.next/static/chunks/2053-52d3c82014e1cd54.js +0 -1
  546. package/.next/static/chunks/4560-0917ae2e6a0e5400.js +0 -1
  547. package/.next/static/chunks/6488-95ba9d24a76f0cc5.js +0 -1
  548. package/.next/static/chunks/7229.edb331fb9fbafa27.js +0 -1
  549. package/.next/static/chunks/744-fa8c0ae444c8338c.js +0 -1
  550. package/.next/static/chunks/9263.5259f73f89220d64.js +0 -1
  551. package/.next/static/chunks/app/api/assistant/messages/route-973ec48531555712.js +0 -1
  552. package/.next/static/chunks/app/api/assistant/session/route-973ec48531555712.js +0 -1
  553. package/.next/static/chunks/app/api/assistant/start/route-973ec48531555712.js +0 -1
  554. package/.next/static/chunks/app/api/assistant/terminal/route-973ec48531555712.js +0 -1
  555. package/.next/static/chunks/app/api/assistant/tools/route-973ec48531555712.js +0 -1
  556. package/.next/static/chunks/app/api/auth/login/route-973ec48531555712.js +0 -1
  557. package/.next/static/chunks/app/api/auth/logout/route-973ec48531555712.js +0 -1
  558. package/.next/static/chunks/app/api/auth/status/route-973ec48531555712.js +0 -1
  559. package/.next/static/chunks/app/api/daily-summary/route-973ec48531555712.js +0 -1
  560. package/.next/static/chunks/app/api/daily-summary/status/route-973ec48531555712.js +0 -1
  561. package/.next/static/chunks/app/api/external-apps/[id]/health/route-973ec48531555712.js +0 -1
  562. package/.next/static/chunks/app/api/external-apps/[id]/route-973ec48531555712.js +0 -1
  563. package/.next/static/chunks/app/api/external-apps/route-973ec48531555712.js +0 -1
  564. package/.next/static/chunks/app/api/fs/browse/route-973ec48531555712.js +0 -1
  565. package/.next/static/chunks/app/api/fs/recent-paths/route-973ec48531555712.js +0 -1
  566. package/.next/static/chunks/app/api/hooks/agent-event/route-973ec48531555712.js +0 -1
  567. package/.next/static/chunks/app/api/hooks/claude-done/route-973ec48531555712.js +0 -1
  568. package/.next/static/chunks/app/api/hooks/permission-request/route-973ec48531555712.js +0 -1
  569. package/.next/static/chunks/app/api/metrics/vibe/route-973ec48531555712.js +0 -1
  570. package/.next/static/chunks/app/api/ollama/models/route-973ec48531555712.js +0 -1
  571. package/.next/static/chunks/app/api/push/subscriptions/route-973ec48531555712.js +0 -1
  572. package/.next/static/chunks/app/api/push/vapid/route-973ec48531555712.js +0 -1
  573. package/.next/static/chunks/app/api/repositories/[id]/route-973ec48531555712.js +0 -1
  574. package/.next/static/chunks/app/api/repositories/[id]/todos/[todoId]/route-973ec48531555712.js +0 -1
  575. package/.next/static/chunks/app/api/repositories/[id]/todos/route-973ec48531555712.js +0 -1
  576. package/.next/static/chunks/app/api/repositories/clone/[jobId]/route-973ec48531555712.js +0 -1
  577. package/.next/static/chunks/app/api/repositories/clone/route-973ec48531555712.js +0 -1
  578. package/.next/static/chunks/app/api/repositories/excluded/route-973ec48531555712.js +0 -1
  579. package/.next/static/chunks/app/api/repositories/restore/route-973ec48531555712.js +0 -1
  580. package/.next/static/chunks/app/api/repositories/route-973ec48531555712.js +0 -1
  581. package/.next/static/chunks/app/api/repositories/scan/route-973ec48531555712.js +0 -1
  582. package/.next/static/chunks/app/api/repositories/sync/route-973ec48531555712.js +0 -1
  583. package/.next/static/chunks/app/api/repositories/validate-path/route-973ec48531555712.js +0 -1
  584. package/.next/static/chunks/app/api/sidebar/group-order/route-973ec48531555712.js +0 -1
  585. package/.next/static/chunks/app/api/skills/[id]/route-973ec48531555712.js +0 -1
  586. package/.next/static/chunks/app/api/skills/installations/route-973ec48531555712.js +0 -1
  587. package/.next/static/chunks/app/api/skills/operations/route-973ec48531555712.js +0 -1
  588. package/.next/static/chunks/app/api/skills/reindex/route-973ec48531555712.js +0 -1
  589. package/.next/static/chunks/app/api/skills/route-973ec48531555712.js +0 -1
  590. package/.next/static/chunks/app/api/slash-commands/route-973ec48531555712.js +0 -1
  591. package/.next/static/chunks/app/api/tasks/[taskId]/cancel/route-973ec48531555712.js +0 -1
  592. package/.next/static/chunks/app/api/tasks/[taskId]/route-973ec48531555712.js +0 -1
  593. package/.next/static/chunks/app/api/templates/[id]/route-973ec48531555712.js +0 -1
  594. package/.next/static/chunks/app/api/templates/route-973ec48531555712.js +0 -1
  595. package/.next/static/chunks/app/api/todos/route-973ec48531555712.js +0 -1
  596. package/.next/static/chunks/app/api/verification/runs/[runId]/route-973ec48531555712.js +0 -1
  597. package/.next/static/chunks/app/api/verification/runs/route-973ec48531555712.js +0 -1
  598. package/.next/static/chunks/app/api/worktrees/[id]/auto-yes/route-973ec48531555712.js +0 -1
  599. package/.next/static/chunks/app/api/worktrees/[id]/capture/route-973ec48531555712.js +0 -1
  600. package/.next/static/chunks/app/api/worktrees/[id]/cli-tool/route-973ec48531555712.js +0 -1
  601. package/.next/static/chunks/app/api/worktrees/[id]/cmate/schedules/route-973ec48531555712.js +0 -1
  602. package/.next/static/chunks/app/api/worktrees/[id]/current-output/route-973ec48531555712.js +0 -1
  603. package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/[logId]/route-973ec48531555712.js +0 -1
  604. package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/route-973ec48531555712.js +0 -1
  605. package/.next/static/chunks/app/api/worktrees/[id]/files/[...path]/route-973ec48531555712.js +0 -1
  606. package/.next/static/chunks/app/api/worktrees/[id]/git/branch/create/route-973ec48531555712.js +0 -1
  607. package/.next/static/chunks/app/api/worktrees/[id]/git/branch/delete/route-973ec48531555712.js +0 -1
  608. package/.next/static/chunks/app/api/worktrees/[id]/git/branches/route-973ec48531555712.js +0 -1
  609. package/.next/static/chunks/app/api/worktrees/[id]/git/checkout/route-973ec48531555712.js +0 -1
  610. package/.next/static/chunks/app/api/worktrees/[id]/git/commit/route-973ec48531555712.js +0 -1
  611. package/.next/static/chunks/app/api/worktrees/[id]/git/diff/route-973ec48531555712.js +0 -1
  612. package/.next/static/chunks/app/api/worktrees/[id]/git/fetch/route-973ec48531555712.js +0 -1
  613. package/.next/static/chunks/app/api/worktrees/[id]/git/log/route-973ec48531555712.js +0 -1
  614. package/.next/static/chunks/app/api/worktrees/[id]/git/pull/route-973ec48531555712.js +0 -1
  615. package/.next/static/chunks/app/api/worktrees/[id]/git/push/route-973ec48531555712.js +0 -1
  616. package/.next/static/chunks/app/api/worktrees/[id]/git/reset/route-973ec48531555712.js +0 -1
  617. package/.next/static/chunks/app/api/worktrees/[id]/git/revert/route-973ec48531555712.js +0 -1
  618. package/.next/static/chunks/app/api/worktrees/[id]/git/show/[commitHash]/route-973ec48531555712.js +0 -1
  619. package/.next/static/chunks/app/api/worktrees/[id]/git/stage/route-973ec48531555712.js +0 -1
  620. package/.next/static/chunks/app/api/worktrees/[id]/git/staged/route-973ec48531555712.js +0 -1
  621. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/[index]/route-973ec48531555712.js +0 -1
  622. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/apply/route-973ec48531555712.js +0 -1
  623. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/pop/route-973ec48531555712.js +0 -1
  624. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/push/route-973ec48531555712.js +0 -1
  625. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/route-973ec48531555712.js +0 -1
  626. package/.next/static/chunks/app/api/worktrees/[id]/git/status/route-973ec48531555712.js +0 -1
  627. package/.next/static/chunks/app/api/worktrees/[id]/git/unstage/route-973ec48531555712.js +0 -1
  628. package/.next/static/chunks/app/api/worktrees/[id]/git/working-diff/route-973ec48531555712.js +0 -1
  629. package/.next/static/chunks/app/api/worktrees/[id]/interrupt/route-973ec48531555712.js +0 -1
  630. package/.next/static/chunks/app/api/worktrees/[id]/kill-session/route-973ec48531555712.js +0 -1
  631. package/.next/static/chunks/app/api/worktrees/[id]/logs/[filename]/route-973ec48531555712.js +0 -1
  632. package/.next/static/chunks/app/api/worktrees/[id]/logs/route-973ec48531555712.js +0 -1
  633. package/.next/static/chunks/app/api/worktrees/[id]/marp-render/route-973ec48531555712.js +0 -1
  634. package/.next/static/chunks/app/api/worktrees/[id]/memos/[memoId]/route-973ec48531555712.js +0 -1
  635. package/.next/static/chunks/app/api/worktrees/[id]/memos/route-973ec48531555712.js +0 -1
  636. package/.next/static/chunks/app/api/worktrees/[id]/messages/route-973ec48531555712.js +0 -1
  637. package/.next/static/chunks/app/api/worktrees/[id]/prompt-response/route-973ec48531555712.js +0 -1
  638. package/.next/static/chunks/app/api/worktrees/[id]/respond/route-973ec48531555712.js +0 -1
  639. package/.next/static/chunks/app/api/worktrees/[id]/route-973ec48531555712.js +0 -1
  640. package/.next/static/chunks/app/api/worktrees/[id]/schedules/[scheduleId]/route-973ec48531555712.js +0 -1
  641. package/.next/static/chunks/app/api/worktrees/[id]/schedules/active/route-973ec48531555712.js +0 -1
  642. package/.next/static/chunks/app/api/worktrees/[id]/schedules/route-973ec48531555712.js +0 -1
  643. package/.next/static/chunks/app/api/worktrees/[id]/search/route-973ec48531555712.js +0 -1
  644. package/.next/static/chunks/app/api/worktrees/[id]/send/route-973ec48531555712.js +0 -1
  645. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route-973ec48531555712.js +0 -1
  646. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/install/route-973ec48531555712.js +0 -1
  647. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/plan/route-973ec48531555712.js +0 -1
  648. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall/route-973ec48531555712.js +0 -1
  649. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route-973ec48531555712.js +0 -1
  650. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update/route-973ec48531555712.js +0 -1
  651. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update-plan/route-973ec48531555712.js +0 -1
  652. package/.next/static/chunks/app/api/worktrees/[id]/skills/route-973ec48531555712.js +0 -1
  653. package/.next/static/chunks/app/api/worktrees/[id]/slash-commands/route-973ec48531555712.js +0 -1
  654. package/.next/static/chunks/app/api/worktrees/[id]/special-keys/route-973ec48531555712.js +0 -1
  655. package/.next/static/chunks/app/api/worktrees/[id]/start-polling/route-973ec48531555712.js +0 -1
  656. package/.next/static/chunks/app/api/worktrees/[id]/tasks/route-973ec48531555712.js +0 -1
  657. package/.next/static/chunks/app/api/worktrees/[id]/terminal/route-973ec48531555712.js +0 -1
  658. package/.next/static/chunks/app/api/worktrees/[id]/timers/history/route-973ec48531555712.js +0 -1
  659. package/.next/static/chunks/app/api/worktrees/[id]/timers/route-973ec48531555712.js +0 -1
  660. package/.next/static/chunks/app/api/worktrees/[id]/todos/[todoId]/route-973ec48531555712.js +0 -1
  661. package/.next/static/chunks/app/api/worktrees/[id]/todos/route-973ec48531555712.js +0 -1
  662. package/.next/static/chunks/app/api/worktrees/[id]/tree/[...path]/route-973ec48531555712.js +0 -1
  663. package/.next/static/chunks/app/api/worktrees/[id]/tree/route-973ec48531555712.js +0 -1
  664. package/.next/static/chunks/app/api/worktrees/[id]/upload/[...path]/route-973ec48531555712.js +0 -1
  665. package/.next/static/chunks/app/api/worktrees/[id]/verify/route-973ec48531555712.js +0 -1
  666. package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/[runId]/route-973ec48531555712.js +0 -1
  667. package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/route-973ec48531555712.js +0 -1
  668. package/.next/static/chunks/app/api/worktrees/[id]/viewed/route-973ec48531555712.js +0 -1
  669. package/.next/static/chunks/app/api/worktrees/route-973ec48531555712.js +0 -1
  670. package/.next/static/chunks/app/chat/page-83a2238ab453afaa.js +0 -1
  671. package/.next/static/chunks/app/layout-86574192bd3c0e6b.js +0 -1
  672. package/.next/static/chunks/app/login/page-0247a3fb569bb22b.js +0 -1
  673. package/.next/static/chunks/app/manifest.webmanifest/route-973ec48531555712.js +0 -1
  674. package/.next/static/chunks/app/more/page-1619018cac999bbc.js +0 -1
  675. package/.next/static/chunks/app/page-a34d26812f085b6c.js +0 -1
  676. package/.next/static/chunks/app/proxy/[...path]/route-973ec48531555712.js +0 -1
  677. package/.next/static/chunks/app/repositories/page-202680fe6ec169c8.js +0 -1
  678. package/.next/static/chunks/app/review/page-b559bfb11c46931b.js +0 -1
  679. package/.next/static/chunks/app/sessions/page-3fa7e767d0ab3889.js +0 -1
  680. package/.next/static/chunks/app/skills/[skillId]/page-10d6f983e5f06ffb.js +0 -1
  681. package/.next/static/chunks/app/skills/installed/page-6641f95e6a6e5f9d.js +0 -1
  682. package/.next/static/chunks/app/skills/page-184f8e23e31a3667.js +0 -1
  683. package/.next/static/chunks/app/worktrees/[id]/files/[...path]/page-6041d3c3db326317.js +0 -1
  684. package/.next/static/chunks/app/worktrees/[id]/layout-973ec48531555712.js +0 -1
  685. package/.next/static/chunks/app/worktrees/[id]/page-966a451ae7b0903a.js +0 -1
  686. package/.next/static/css/d3453a6876553d32.css +0 -1
  687. package/.next/static/wH6K6QNPHSdATFkVoIcy3/_buildManifest.js +0 -1
  688. /package/.next/static/{wH6K6QNPHSdATFkVoIcy3 → ehkNc5xDMDkXlua08Bwq0}/_ssgManifest.js +0 -0
@@ -28,7 +28,20 @@ const prompt_dedup_1 = require("./prompt-dedup");
28
28
  const response_dedup_1 = require("./response-dedup");
29
29
  const response_poller_core_1 = require("./response-poller-core");
30
30
  const push_1 = require("../../lib/push");
31
+ // Issue #1790: imported by deep path, not through `@/lib/push`. Suites that
32
+ // replace the barrel to count notifications (e.g. the #1547 escalation test)
33
+ // would otherwise get `undefined` here and take down module evaluation.
34
+ const waiting_push_notifier_1 = require("../../lib/push/waiting-push-notifier");
35
+ const waiting_episode_state_1 = require("../../lib/session/waiting-episode-state");
31
36
  const task_transition_service_1 = require("../../lib/tasks/task-transition-service");
37
+ // Issue #1790: arm the waiting-edge push subscription.
38
+ //
39
+ // It has to exist before the first edge, and `server.ts` reaches this module at
40
+ // boot (it imports `polling/response-poller` for `stopAllPolling`, which pulls
41
+ // in `response-poller-core` and then this file), so this is the earliest hook
42
+ // the notification path owns. Idempotent by replacement, and it starts no timer
43
+ // and touches no database until a wait actually opens.
44
+ (0, waiting_push_notifier_1.startWaitingPushNotifier)();
32
45
  /**
33
46
  * Creates an incomplete extraction result with empty response.
34
47
  * Centralizes the repeated pattern of returning an in-progress/incomplete state.
@@ -465,13 +478,39 @@ async function checkForResponse(worktreeId, cliToolId, instanceId) {
465
478
  });
466
479
  // Web Push fan-out (Issue #1125): agent is now waiting for a prompt reply.
467
480
  // Fire-and-forget — push is advisory and must never block/break the poller.
481
+ //
482
+ // Issue #1790: the wait is now named by #1786's episode rather than by the
483
+ // prompt text. The two lines below are ordered, not incidental:
484
+ //
485
+ // 1. the notification is raised first, while it still has the prompt's
486
+ // own question to quote — it records the episode in the dedup, so
487
+ // whichever path reports the wait second says nothing;
488
+ // 2. `observeWaitingEdge` then opens that same episode, which is what
489
+ // lets the edge listener (and #1788's WebSocket frame) agree with this
490
+ // call about *which* wait this is instead of raising a second one.
491
+ //
492
+ // Both use one timestamp so the episode the notification claims and the
493
+ // episode the store opens are the same number.
494
+ const promptObservedAt = Date.now();
495
+ const promptWaitingSince = (0, waiting_episode_state_1.getWaitingEpisode)(worktreeId, cliToolId, instanceId)?.since ?? promptObservedAt;
468
496
  void (0, push_1.notifyPushSubscribers)({
469
497
  worktreeId,
470
498
  worktreeName: worktree.name,
471
499
  kind: 'prompt',
472
500
  agentName: resolvedInstanceId,
501
+ instanceId: resolvedInstanceId,
502
+ waitingKind: 'prompt',
503
+ waitingSince: promptWaitingSince,
473
504
  excerpt: promptDetection.promptData?.question ?? promptSaveContent,
474
505
  }).catch(() => { });
506
+ (0, waiting_episode_state_1.observeWaitingEdge)({
507
+ worktreeId,
508
+ cliToolId,
509
+ instanceId,
510
+ waiting: true,
511
+ kind: 'prompt',
512
+ now: promptObservedAt,
513
+ });
475
514
  if (!isFullScreenTui) {
476
515
  (0, response_poller_core_1.stopPolling)(worktreeId, cliToolId, instanceId);
477
516
  }
@@ -562,6 +601,14 @@ async function checkForResponse(worktreeId, cliToolId, instanceId) {
562
601
  });
563
602
  // Broadcast message to WebSocket clients
564
603
  (0, ws_server_1.broadcastMessage)('message', { worktreeId, message });
604
+ // Issue #1790: the agent has just produced a reply, so whatever it was
605
+ // waiting for is over. Closing the episode here is what makes a *second*
606
+ // prompt in the same session notify again: without it a wait opened by the
607
+ // prompt branch above could stay open until a browser next probes the status
608
+ // API, and every later prompt would be folded into that stale episode and
609
+ // silently deduped. Nothing to close is a no-op, and no notification is
610
+ // raised for a closing edge.
611
+ (0, waiting_episode_state_1.observeWaitingEdge)({ worktreeId, cliToolId, instanceId, waiting: false });
565
612
  // Web Push fan-out (Issue #1125): session completed (running → idle).
566
613
  // Fire-and-forget — push is advisory and must never block/break the poller.
567
614
  void (0, push_1.notifyPushSubscribers)({
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ /**
3
+ * The "still waiting" reminder setting (Issue #1790).
4
+ *
5
+ * A wait that nobody answers is the case push notifications exist for, and one
6
+ * notification is easy to miss — so after a threshold the server sends exactly
7
+ * one more. How long to wait, and whether to do it at all, is a user decision,
8
+ * and it is a *server-side* one: the check runs in the background with no
9
+ * request and no browser attached, so it cannot read a device's localStorage the
10
+ * way #1788's in-app toggle does. It is therefore stored once for the install
11
+ * and applies to every subscribed device.
12
+ *
13
+ * ## Why the SQL lives here
14
+ *
15
+ * `app_settings` (migration v27) is the generic key-value store this rides on,
16
+ * so no migration is added. Its typed helpers live in `db/app-settings-db`, but
17
+ * both existing ones are `string[]`-shaped and this value is an object with two
18
+ * fields of different types; a third helper there would be a fourth reader of
19
+ * the same table with no shared logic to gain. Keeping the accessor beside its
20
+ * only consumer also keeps the defaults — which the escalation tick applies on
21
+ * every failure path — in one file.
22
+ *
23
+ * Every read is total: a missing row, malformed JSON, an out-of-range threshold
24
+ * or an unopenable database all resolve to {@link DEFAULT_ESCALATION_SETTINGS}
25
+ * rather than throwing. The caller is a background timer whose failure mode
26
+ * must be "no reminder", never "the server logs an exception every minute".
27
+ *
28
+ * @module lib/push/escalation-settings
29
+ */
30
+ Object.defineProperty(exports, "__esModule", { value: true });
31
+ exports.MAX_ESCALATION_THRESHOLD_MINUTES = exports.MIN_ESCALATION_THRESHOLD_MINUTES = exports.ESCALATION_THRESHOLD_CHOICES = exports.DEFAULT_ESCALATION_SETTINGS = exports.ESCALATION_SETTINGS_KEY = void 0;
32
+ exports.normalizeEscalationSettings = normalizeEscalationSettings;
33
+ exports.getPushEscalationSettings = getPushEscalationSettings;
34
+ exports.setPushEscalationSettings = setPushEscalationSettings;
35
+ const db_instance_1 = require("../../lib/db/db-instance");
36
+ const logger_1 = require("../../lib/logger");
37
+ const logger = (0, logger_1.createLogger)('push/escalation-settings');
38
+ /** `app_settings.key` this setting is stored under. */
39
+ exports.ESCALATION_SETTINGS_KEY = 'push_escalation';
40
+ /**
41
+ * On by default at ten minutes, per the Issue.
42
+ *
43
+ * Defaulting to *on* is the same call #1788 made for the in-app toast: a user
44
+ * who never opened the settings screen is the one most likely to walk away from
45
+ * a waiting agent, and the cost of being wrong is one extra notification per
46
+ * unanswered wait — bounded, because there is only ever one.
47
+ */
48
+ exports.DEFAULT_ESCALATION_SETTINGS = {
49
+ enabled: true,
50
+ thresholdMinutes: 10,
51
+ };
52
+ /** The thresholds the settings UI offers, in minutes. */
53
+ exports.ESCALATION_THRESHOLD_CHOICES = [5, 10, 30, 60];
54
+ /** Guard rails for a hand-written value: at least a minute, at most a day. */
55
+ exports.MIN_ESCALATION_THRESHOLD_MINUTES = 1;
56
+ exports.MAX_ESCALATION_THRESHOLD_MINUTES = 1440;
57
+ /**
58
+ * Narrow arbitrary input to a usable setting, filling each field independently.
59
+ *
60
+ * Field-by-field rather than all-or-nothing so that a bad threshold does not
61
+ * silently switch the reminder back on (or off): the half the user did set is
62
+ * the half that is honoured.
63
+ */
64
+ function normalizeEscalationSettings(value) {
65
+ if (typeof value !== 'object' || value === null)
66
+ return { ...exports.DEFAULT_ESCALATION_SETTINGS };
67
+ const record = value;
68
+ const enabled = typeof record.enabled === 'boolean' ? record.enabled : exports.DEFAULT_ESCALATION_SETTINGS.enabled;
69
+ const raw = record.thresholdMinutes;
70
+ const thresholdMinutes = typeof raw === 'number' &&
71
+ Number.isFinite(raw) &&
72
+ raw >= exports.MIN_ESCALATION_THRESHOLD_MINUTES &&
73
+ raw <= exports.MAX_ESCALATION_THRESHOLD_MINUTES
74
+ ? Math.round(raw)
75
+ : exports.DEFAULT_ESCALATION_SETTINGS.thresholdMinutes;
76
+ return { enabled, thresholdMinutes };
77
+ }
78
+ /** Read the setting. Never throws — see the module docblock. */
79
+ function getPushEscalationSettings() {
80
+ try {
81
+ const row = (0, db_instance_1.getDbInstance)()
82
+ .prepare('SELECT value FROM app_settings WHERE key = ?')
83
+ .get(exports.ESCALATION_SETTINGS_KEY);
84
+ if (!row)
85
+ return { ...exports.DEFAULT_ESCALATION_SETTINGS };
86
+ return normalizeEscalationSettings(JSON.parse(row.value));
87
+ }
88
+ catch (error) {
89
+ logger.warn('escalation-settings-read-failed', {
90
+ error: error instanceof Error ? error.message : String(error),
91
+ });
92
+ return { ...exports.DEFAULT_ESCALATION_SETTINGS };
93
+ }
94
+ }
95
+ /**
96
+ * Persist the setting, normalizing first so a malformed request cannot store a
97
+ * value later reads would have to reject anyway.
98
+ *
99
+ * @returns What was actually written.
100
+ */
101
+ function setPushEscalationSettings(value) {
102
+ const settings = normalizeEscalationSettings(value);
103
+ const now = Date.now();
104
+ (0, db_instance_1.getDbInstance)()
105
+ .prepare(`
106
+ INSERT INTO app_settings (key, value, created_at, updated_at)
107
+ VALUES (?, ?, ?, ?)
108
+ ON CONFLICT(key) DO UPDATE SET
109
+ value = excluded.value,
110
+ updated_at = excluded.updated_at
111
+ `)
112
+ .run(exports.ESCALATION_SETTINGS_KEY, JSON.stringify(settings), now, now);
113
+ return settings;
114
+ }
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  /** Web Push module barrel (Issue #1125). */
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.DEFAULT_DEDUP_WINDOW_MS = exports.resetNotificationDedup = exports.shouldSendNotification = exports.resolvePushLocale = exports.buildExcerpt = exports.buildPushPayload = exports.notifyPushSubscribers = exports.getVapidPublicKey = exports.isPushConfigured = exports.getVapidConfig = void 0;
4
+ exports.MAX_ESCALATION_THRESHOLD_MINUTES = exports.MIN_ESCALATION_THRESHOLD_MINUTES = exports.ESCALATION_SETTINGS_KEY = exports.ESCALATION_THRESHOLD_CHOICES = exports.DEFAULT_ESCALATION_SETTINGS = exports.normalizeEscalationSettings = exports.setPushEscalationSettings = exports.getPushEscalationSettings = exports.ESCALATION_TICK_MS = exports.pendingEscalationCount = exports.runEscalationTick = exports.handleWaitingTransition = exports.isWaitingPushNotifierActive = exports.stopWaitingPushNotifier = exports.startWaitingPushNotifier = exports.resetWaitingPushDedup = exports.shouldSendWaitingPush = exports.DEFAULT_DEDUP_WINDOW_MS = exports.resetNotificationDedup = exports.shouldSendNotification = exports.resolvePushLocale = exports.buildExcerpt = exports.buildPushPayload = exports.notifyPushSubscribers = exports.getVapidPublicKey = exports.isPushConfigured = exports.getVapidConfig = void 0;
5
5
  var vapid_1 = require("./vapid");
6
6
  Object.defineProperty(exports, "getVapidConfig", { enumerable: true, get: function () { return vapid_1.getVapidConfig; } });
7
7
  Object.defineProperty(exports, "isPushConfigured", { enumerable: true, get: function () { return vapid_1.isPushConfigured; } });
@@ -15,3 +15,23 @@ var notification_dedup_1 = require("./notification-dedup");
15
15
  Object.defineProperty(exports, "shouldSendNotification", { enumerable: true, get: function () { return notification_dedup_1.shouldSendNotification; } });
16
16
  Object.defineProperty(exports, "resetNotificationDedup", { enumerable: true, get: function () { return notification_dedup_1.resetNotificationDedup; } });
17
17
  Object.defineProperty(exports, "DEFAULT_DEDUP_WINDOW_MS", { enumerable: true, get: function () { return notification_dedup_1.DEFAULT_DEDUP_WINDOW_MS; } });
18
+ Object.defineProperty(exports, "shouldSendWaitingPush", { enumerable: true, get: function () { return notification_dedup_1.shouldSendWaitingPush; } });
19
+ Object.defineProperty(exports, "resetWaitingPushDedup", { enumerable: true, get: function () { return notification_dedup_1.resetWaitingPushDedup; } });
20
+ // Waiting-edge driven notifications (Issue #1790).
21
+ var waiting_push_notifier_1 = require("./waiting-push-notifier");
22
+ Object.defineProperty(exports, "startWaitingPushNotifier", { enumerable: true, get: function () { return waiting_push_notifier_1.startWaitingPushNotifier; } });
23
+ Object.defineProperty(exports, "stopWaitingPushNotifier", { enumerable: true, get: function () { return waiting_push_notifier_1.stopWaitingPushNotifier; } });
24
+ Object.defineProperty(exports, "isWaitingPushNotifierActive", { enumerable: true, get: function () { return waiting_push_notifier_1.isWaitingPushNotifierActive; } });
25
+ Object.defineProperty(exports, "handleWaitingTransition", { enumerable: true, get: function () { return waiting_push_notifier_1.handleWaitingTransition; } });
26
+ Object.defineProperty(exports, "runEscalationTick", { enumerable: true, get: function () { return waiting_push_notifier_1.runEscalationTick; } });
27
+ Object.defineProperty(exports, "pendingEscalationCount", { enumerable: true, get: function () { return waiting_push_notifier_1.pendingEscalationCount; } });
28
+ Object.defineProperty(exports, "ESCALATION_TICK_MS", { enumerable: true, get: function () { return waiting_push_notifier_1.ESCALATION_TICK_MS; } });
29
+ var escalation_settings_1 = require("./escalation-settings");
30
+ Object.defineProperty(exports, "getPushEscalationSettings", { enumerable: true, get: function () { return escalation_settings_1.getPushEscalationSettings; } });
31
+ Object.defineProperty(exports, "setPushEscalationSettings", { enumerable: true, get: function () { return escalation_settings_1.setPushEscalationSettings; } });
32
+ Object.defineProperty(exports, "normalizeEscalationSettings", { enumerable: true, get: function () { return escalation_settings_1.normalizeEscalationSettings; } });
33
+ Object.defineProperty(exports, "DEFAULT_ESCALATION_SETTINGS", { enumerable: true, get: function () { return escalation_settings_1.DEFAULT_ESCALATION_SETTINGS; } });
34
+ Object.defineProperty(exports, "ESCALATION_THRESHOLD_CHOICES", { enumerable: true, get: function () { return escalation_settings_1.ESCALATION_THRESHOLD_CHOICES; } });
35
+ Object.defineProperty(exports, "ESCALATION_SETTINGS_KEY", { enumerable: true, get: function () { return escalation_settings_1.ESCALATION_SETTINGS_KEY; } });
36
+ Object.defineProperty(exports, "MIN_ESCALATION_THRESHOLD_MINUTES", { enumerable: true, get: function () { return escalation_settings_1.MIN_ESCALATION_THRESHOLD_MINUTES; } });
37
+ Object.defineProperty(exports, "MAX_ESCALATION_THRESHOLD_MINUTES", { enumerable: true, get: function () { return escalation_settings_1.MAX_ESCALATION_THRESHOLD_MINUTES; } });
@@ -15,6 +15,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.DEFAULT_DEDUP_WINDOW_MS = void 0;
16
16
  exports.shouldSendNotification = shouldSendNotification;
17
17
  exports.resetNotificationDedup = resetNotificationDedup;
18
+ exports.shouldSendWaitingPush = shouldSendWaitingPush;
19
+ exports.resetWaitingPushDedup = resetWaitingPushDedup;
18
20
  const crypto_1 = require("crypto");
19
21
  /** Default suppression window: repeats of identical content within this are dropped. */
20
22
  exports.DEFAULT_DEDUP_WINDOW_MS = 30_000;
@@ -40,3 +42,36 @@ function shouldSendNotification(event, now = Date.now(), windowMs = exports.DEFA
40
42
  function resetNotificationDedup() {
41
43
  lastSent.clear();
42
44
  }
45
+ const waitingSent = globalThis.__waitingPushDedup ??
46
+ (globalThis.__waitingPushDedup = new Map());
47
+ /**
48
+ * Whether this waiting notification should be sent, recording it if so.
49
+ *
50
+ * Replaces the content hash for the waiting path (Issue #1790). Content was
51
+ * never the right key here: two identical `Do you want to proceed?` prompts
52
+ * seconds apart are two separate waits a human has to answer twice, and the
53
+ * 30 s window dropped the second one — while a single wait that outlives the
54
+ * window could be notified again for the same question. The episode's `since`
55
+ * is the wait's identity, so "one notification per wait" becomes exact:
56
+ *
57
+ * - first notification of an episode → sent, recorded;
58
+ * - any repeat for the same `since` → suppressed, however it arrived (the
59
+ * poller and the edge listener both report the same wait);
60
+ * - the escalation → allowed exactly once per episode;
61
+ * - a new episode (the wait ended and another began) → sent again, even if the
62
+ * prompt text and the elapsed time are identical.
63
+ */
64
+ function shouldSendWaitingPush(event) {
65
+ const key = `${event.worktreeId}::${event.instanceId}`;
66
+ const escalated = event.escalated === true;
67
+ const prev = waitingSent.get(key);
68
+ if (prev && prev.since === event.since && (prev.escalated || !escalated)) {
69
+ return false;
70
+ }
71
+ waitingSent.set(key, { since: event.since, escalated });
72
+ return true;
73
+ }
74
+ /** Clear the episode-scoped state (for tests). */
75
+ function resetWaitingPushDedup() {
76
+ waitingSent.clear();
77
+ }
@@ -64,6 +64,36 @@ function buildExcerpt(text, maxLength = MAX_EXCERPT_LENGTH) {
64
64
  return collapsed;
65
65
  return collapsed.slice(0, maxLength - 1).trimEnd() + '…';
66
66
  }
67
+ /**
68
+ * Whether this wait can only be dealt with at the terminal (Issue #1790).
69
+ *
70
+ * A `menu` (selection list / pager) and an `unclassified` wait share the one
71
+ * fact the reader acts on: tapping the notification will not present anything
72
+ * to answer. `prompt` — and an absent kind, which is every pre-#1790 caller —
73
+ * keeps the original "waiting for your reply" wording.
74
+ */
75
+ function needsTerminal(waitingKind) {
76
+ return waitingKind === 'menu' || waitingKind === 'unclassified';
77
+ }
78
+ /** The body for a waiting notification, in the reader's language. */
79
+ function buildWaitingBody(event, messages, excerpt, now) {
80
+ const terminal = needsTerminal(event.waitingKind);
81
+ if (event.escalated) {
82
+ // The excerpt is dropped on purpose: after ten minutes the question is no
83
+ // longer news, the elapsed time is.
84
+ const elapsedMs = now - (event.waitingSince ?? now);
85
+ const minutes = String(Math.max(1, Math.floor(elapsedMs / 60_000)));
86
+ return (terminal ? messages.stillWaitingTerminal : messages.stillWaitingPrompt).replace('{minutes}', minutes);
87
+ }
88
+ if (terminal) {
89
+ return excerpt
90
+ ? messages.terminalAttentionWithExcerpt.replace('{excerpt}', excerpt)
91
+ : messages.terminalAttention;
92
+ }
93
+ return excerpt
94
+ ? messages.promptWaitingWithExcerpt.replace('{excerpt}', excerpt)
95
+ : messages.promptWaiting;
96
+ }
67
97
  /** Build the minimal notification payload for an event, in the reader's language. */
68
98
  function buildPushPayload(event, locale = i18n_config_1.DEFAULT_LOCALE, now = Date.now()) {
69
99
  const excerpt = buildExcerpt(event.excerpt);
@@ -71,9 +101,7 @@ function buildPushPayload(event, locale = i18n_config_1.DEFAULT_LOCALE, now = Da
71
101
  const title = `${event.worktreeName}${agentSuffix}`;
72
102
  const messages = PUSH_MESSAGES[resolvePushLocale(locale)];
73
103
  const body = event.kind === 'prompt'
74
- ? excerpt
75
- ? messages.promptWaitingWithExcerpt.replace('{excerpt}', excerpt)
76
- : messages.promptWaiting
104
+ ? buildWaitingBody(event, messages, excerpt, now)
77
105
  : excerpt
78
106
  ? messages.completionWithExcerpt.replace('{excerpt}', excerpt)
79
107
  : messages.completion;
@@ -83,8 +111,12 @@ function buildPushPayload(event, locale = i18n_config_1.DEFAULT_LOCALE, now = Da
83
111
  body,
84
112
  worktreeId: event.worktreeId,
85
113
  url: `/worktrees/${event.worktreeId}`,
114
+ // Unchanged by #1790, and deliberately: the escalation carries the same tag
115
+ // as the notification it follows up, so the Service Worker replaces the
116
+ // stale one instead of stacking a second card for the same wait.
86
117
  tag: `${event.worktreeId}:${event.kind}`,
87
118
  timestamp: now,
119
+ ...(event.waitingKind ? { waitingKind: event.waitingKind } : {}),
88
120
  };
89
121
  }
90
122
  async function sendToOne(sub, payload) {
@@ -102,19 +134,46 @@ async function sendToOne(sub, payload) {
102
134
  logger.warn('push-send-failed', { statusCode: statusCode ?? 'unknown' });
103
135
  }
104
136
  }
137
+ /**
138
+ * Which guard applies to this event (Issue #1790).
139
+ *
140
+ * An episode-scoped waiting notification is deduped by the wait it belongs to;
141
+ * everything else — every completion, and any prompt event that predates the
142
+ * episode store — keeps the content hash and its 30 s window. Both record as
143
+ * they decide, so this must be called exactly once per event.
144
+ */
145
+ function passesDedup(event) {
146
+ if (event.kind === 'prompt' && typeof event.waitingSince === 'number') {
147
+ return (0, notification_dedup_1.shouldSendWaitingPush)({
148
+ worktreeId: event.worktreeId,
149
+ instanceId: event.instanceId ?? event.agentName ?? '',
150
+ since: event.waitingSince,
151
+ escalated: event.escalated,
152
+ });
153
+ }
154
+ return (0, notification_dedup_1.shouldSendNotification)({
155
+ worktreeId: event.worktreeId,
156
+ kind: event.kind,
157
+ content: event.excerpt,
158
+ });
159
+ }
105
160
  /**
106
161
  * Fan out a notification to all subscriptions opted into this event's kind.
107
162
  * Never throws — push is advisory and must not disrupt the poller. No-op when
108
163
  * push is unconfigured, deduped, or there are no matching subscriptions.
164
+ *
165
+ * `now` is injectable because the escalation body quotes how long the wait has
166
+ * lasted (Issue #1790): the reminder is raised from a periodic check that knows
167
+ * the tick's time, and reading the clock again here would report a different
168
+ * elapsed time from the one that decided to send.
109
169
  */
110
- async function notifyPushSubscribers(event) {
170
+ async function notifyPushSubscribers(event, now = Date.now()) {
111
171
  try {
112
172
  const config = (0, vapid_1.getVapidConfig)();
113
173
  if (!config)
114
174
  return;
115
- if (!(0, notification_dedup_1.shouldSendNotification)({ worktreeId: event.worktreeId, kind: event.kind, content: event.excerpt })) {
175
+ if (!passesDedup(event))
116
176
  return;
117
- }
118
177
  const db = (0, db_instance_1.getDbInstance)();
119
178
  const subscriptions = (0, push_subscriptions_db_1.getPushSubscriptionsForKind)(db, event.kind);
120
179
  if (subscriptions.length === 0)
@@ -132,7 +191,7 @@ async function notifyPushSubscribers(event) {
132
191
  byLocale.set(locale, [sub]);
133
192
  }
134
193
  await Promise.all(Array.from(byLocale, ([locale, subs]) => {
135
- const payload = JSON.stringify(buildPushPayload(event, locale));
194
+ const payload = JSON.stringify(buildPushPayload(event, locale, now));
136
195
  return Promise.all(subs.map((sub) => sendToOne(sub, payload)));
137
196
  }));
138
197
  }
@@ -0,0 +1,231 @@
1
+ "use strict";
2
+ /**
3
+ * Send a push notification when an agent starts waiting, and one reminder if it
4
+ * is still waiting later (Issue #1790).
5
+ *
6
+ * ## Why this subscribes rather than detects
7
+ *
8
+ * The prompt notification used to be raised from one line inside the response
9
+ * poller, which made it inherit every one of that poller's boundaries: it only
10
+ * runs when a send-family API or Auto-Yes started it, it stops itself on the
11
+ * first prompt of a turn, it gives up after `MAX_POLLING_DURATION`, and it can
12
+ * only see waits the screen scraper classified as `isPrompt`. A wait that began
13
+ * after a `tmux` keystroke, a second prompt in the same turn, a wait that only
14
+ * the agent's own hook events reported, and a selection list were all silently
15
+ * unnotifiable.
16
+ *
17
+ * #1786 made the waiting edge observable exactly once, in
18
+ * `waiting-episode-state`, and #1788 already subscribes to it for the WebSocket
19
+ * frame. This module is the same subscription for push — it captures no pane,
20
+ * runs no detector, and keeps no "was it waiting last time?" of its own.
21
+ *
22
+ * ## The poller still notifies, and that is deliberate
23
+ *
24
+ * Contrary to the Issue's premise, the edge is *not* observed by a background
25
+ * process: `observeWaitingEdge`'s only caller is `worktree-status-helper`, on
26
+ * the worktree list / detail API probe. So the edge fires when a client is
27
+ * looking, and moving push onto it *alone* would have swapped one blind spot
28
+ * (no poller) for a worse one (nobody has the app open — the very situation a
29
+ * phone notification is for). The poller therefore keeps its call, and
30
+ * `response-checker` opens the same episode through `observeWaitingEdge` so both
31
+ * producers name the wait identically; `shouldSendWaitingPush` then collapses
32
+ * them to one notification. See the commit message for the measurement.
33
+ *
34
+ * ## Escalation
35
+ *
36
+ * There is no existing server-side sweep over waiting sessions to ride on, so
37
+ * this keeps a small interval of its own. It exists only while some wait is
38
+ * outstanding — created on the first open episode, cleared when the last one
39
+ * closes — so an install with nothing waiting has no timer, and one that never
40
+ * configured VAPID never even gets that far.
41
+ *
42
+ * Everything here is advisory: a failure must not disturb the status read that
43
+ * observed the edge (`emit` contains listener throws) nor the poller.
44
+ *
45
+ * @module lib/push/waiting-push-notifier
46
+ */
47
+ Object.defineProperty(exports, "__esModule", { value: true });
48
+ exports.ESCALATION_TICK_MS = void 0;
49
+ exports.handleWaitingTransition = handleWaitingTransition;
50
+ exports.runEscalationTick = runEscalationTick;
51
+ exports.startWaitingPushNotifier = startWaitingPushNotifier;
52
+ exports.stopWaitingPushNotifier = stopWaitingPushNotifier;
53
+ exports.isWaitingPushNotifierActive = isWaitingPushNotifierActive;
54
+ exports.pendingEscalationCount = pendingEscalationCount;
55
+ const auto_yes_state_1 = require("../../lib/auto-yes-state");
56
+ const db_instance_1 = require("../../lib/db/db-instance");
57
+ const worktree_db_1 = require("../../lib/db/worktree-db");
58
+ const logger_1 = require("../../lib/logger");
59
+ const waiting_episode_state_1 = require("../../lib/session/waiting-episode-state");
60
+ const escalation_settings_1 = require("./escalation-settings");
61
+ const push_sender_1 = require("./push-sender");
62
+ const vapid_1 = require("./vapid");
63
+ const logger = (0, logger_1.createLogger)('push/waiting-notifier');
64
+ /** How often outstanding waits are re-checked. Minute granularity is enough. */
65
+ exports.ESCALATION_TICK_MS = 60_000;
66
+ const pending = globalThis.__waitingPushPending ??
67
+ (globalThis.__waitingPushPending = new Map());
68
+ /**
69
+ * The worktree's display name, for the notification title.
70
+ *
71
+ * Falls back to the id rather than dropping the notification: a database that
72
+ * cannot answer is a reason to send a less readable title, not a reason to
73
+ * leave the user waiting in silence.
74
+ */
75
+ function resolveWorktreeName(worktreeId) {
76
+ try {
77
+ return (0, worktree_db_1.getWorktreeById)((0, db_instance_1.getDbInstance)(), worktreeId)?.name ?? worktreeId;
78
+ }
79
+ catch {
80
+ return worktreeId;
81
+ }
82
+ }
83
+ /** Fan one waiting notification out. Never throws. */
84
+ async function sendWaitingPush(wait, escalated, now) {
85
+ const instanceId = wait.instanceId ?? wait.cliToolId;
86
+ try {
87
+ await (0, push_sender_1.notifyPushSubscribers)({
88
+ worktreeId: wait.worktreeId,
89
+ worktreeName: resolveWorktreeName(wait.worktreeId),
90
+ kind: 'prompt',
91
+ agentName: instanceId,
92
+ instanceId,
93
+ waitingKind: wait.kind,
94
+ waitingSince: wait.since,
95
+ escalated,
96
+ },
97
+ // The deciding tick's clock, not a fresh reading: the reminder's body
98
+ // quotes the elapsed time this call was made on.
99
+ now);
100
+ }
101
+ catch (error) {
102
+ logger.warn('waiting-push-failed', {
103
+ worktreeId: wait.worktreeId,
104
+ instanceId,
105
+ escalated,
106
+ error: error instanceof Error ? error.message : String(error),
107
+ });
108
+ }
109
+ }
110
+ function startEscalationTimer() {
111
+ if (globalThis.__waitingPushEscalationTimer !== undefined)
112
+ return;
113
+ const timer = setInterval(() => {
114
+ runEscalationTick();
115
+ }, exports.ESCALATION_TICK_MS);
116
+ // Never hold the process open for a reminder; the server exiting is a far
117
+ // stronger signal than "someone might still be waiting".
118
+ timer.unref?.();
119
+ globalThis.__waitingPushEscalationTimer = timer;
120
+ }
121
+ function stopEscalationTimerIfIdle() {
122
+ if (pending.size > 0)
123
+ return;
124
+ const timer = globalThis.__waitingPushEscalationTimer;
125
+ if (timer !== undefined) {
126
+ clearInterval(timer);
127
+ globalThis.__waitingPushEscalationTimer = undefined;
128
+ }
129
+ }
130
+ /**
131
+ * Handle one crossing of the waiting edge.
132
+ *
133
+ * Exported for tests, which drive it directly rather than through the
134
+ * subscription so a failure points at this function and not at #1786's store.
135
+ */
136
+ function handleWaitingTransition(transition) {
137
+ // Nothing downstream can do anything without VAPID keys, so an install
138
+ // without push does not track waits, does not read the database and does not
139
+ // start a timer — it is inert rather than merely quiet.
140
+ if (!(0, vapid_1.isPushConfigured)())
141
+ return;
142
+ const key = (0, auto_yes_state_1.buildCompositeKey)(transition.worktreeId, transition.cliToolId, transition.instanceId);
143
+ if (!transition.waiting || transition.since === null) {
144
+ pending.delete(key);
145
+ stopEscalationTimerIfIdle();
146
+ return;
147
+ }
148
+ const wait = {
149
+ worktreeId: transition.worktreeId,
150
+ cliToolId: transition.cliToolId,
151
+ instanceId: transition.instanceId,
152
+ since: transition.since,
153
+ kind: transition.kind,
154
+ };
155
+ pending.set(key, wait);
156
+ startEscalationTimer();
157
+ void sendWaitingPush(wait, false, transition.at);
158
+ }
159
+ /**
160
+ * Re-notify every wait that has outlived the threshold, once each.
161
+ *
162
+ * Exported so tests can advance a fake clock instead of a real minute.
163
+ */
164
+ function runEscalationTick(now = Date.now()) {
165
+ if (pending.size === 0) {
166
+ stopEscalationTimerIfIdle();
167
+ return;
168
+ }
169
+ const settings = (0, escalation_settings_1.getPushEscalationSettings)();
170
+ const thresholdMs = settings.thresholdMinutes * 60_000;
171
+ for (const [key, wait] of Array.from(pending)) {
172
+ // The episode store, not this map, is the authority on whether the wait is
173
+ // still going: it is written by the status probe, so an answer given in
174
+ // another tab — or a wait whose closing edge this module never saw — is
175
+ // caught here even when `pending` still lists it.
176
+ const episode = (0, waiting_episode_state_1.getWaitingEpisode)(wait.worktreeId, wait.cliToolId, wait.instanceId);
177
+ if (episode === null || episode.since !== wait.since) {
178
+ pending.delete(key);
179
+ continue;
180
+ }
181
+ if (!settings.enabled)
182
+ continue;
183
+ if (now - wait.since < thresholdMs)
184
+ continue;
185
+ // Dropped before sending, not after: the reminder is once per episode, and
186
+ // an in-flight fan-out must not be able to earn a second one.
187
+ pending.delete(key);
188
+ void sendWaitingPush({ ...wait, kind: episode.kind ?? wait.kind }, true, now);
189
+ }
190
+ stopEscalationTimerIfIdle();
191
+ }
192
+ /**
193
+ * Subscribe to the waiting edge.
194
+ *
195
+ * Idempotent by replacement, like #1788's broadcast: calling it again drops the
196
+ * previous subscription rather than adding a second one, so a module evaluated
197
+ * twice cannot double-notify.
198
+ *
199
+ * @returns The unsubscribe function (also reachable as
200
+ * {@link stopWaitingPushNotifier}).
201
+ */
202
+ function startWaitingPushNotifier() {
203
+ stopWaitingPushNotifier();
204
+ const unsubscribe = (0, waiting_episode_state_1.onWaitingTransition)((transition) => {
205
+ handleWaitingTransition(transition);
206
+ });
207
+ globalThis.__waitingPushUnsubscribe = unsubscribe;
208
+ return unsubscribe;
209
+ }
210
+ /**
211
+ * Drop the subscription, the outstanding waits and the timer. Safe when none is
212
+ * active, and the seam a test uses to leave no interval behind (CI runs the
213
+ * whole suite in one process).
214
+ */
215
+ function stopWaitingPushNotifier() {
216
+ const existing = globalThis.__waitingPushUnsubscribe;
217
+ if (existing) {
218
+ existing();
219
+ globalThis.__waitingPushUnsubscribe = undefined;
220
+ }
221
+ pending.clear();
222
+ stopEscalationTimerIfIdle();
223
+ }
224
+ /** Whether a subscription is currently active. Test seam. */
225
+ function isWaitingPushNotifierActive() {
226
+ return globalThis.__waitingPushUnsubscribe !== undefined;
227
+ }
228
+ /** How many waits are awaiting their reminder. Test seam. */
229
+ function pendingEscalationCount() {
230
+ return pending.size;
231
+ }