commandmate 0.47.2 → 0.48.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 (396) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-build-manifest.json +215 -215
  3. package/.next/app-path-routes-manifest.json +41 -41
  4. package/.next/build-manifest.json +2 -2
  5. package/.next/prerender-manifest.json +9 -9
  6. package/.next/required-server-files.json +1 -1
  7. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  8. package/.next/server/app/api/agents/update/route_client-reference-manifest.js +1 -1
  9. package/.next/server/app/api/agents/versions/route_client-reference-manifest.js +1 -1
  10. package/.next/server/app/api/app/release-notes/route_client-reference-manifest.js +1 -1
  11. package/.next/server/app/api/app/update/route.js +3 -3
  12. package/.next/server/app/api/app/update/route_client-reference-manifest.js +1 -1
  13. package/.next/server/app/api/app/update-check/route_client-reference-manifest.js +1 -1
  14. package/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
  15. package/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
  16. package/.next/server/app/api/auth/status/route_client-reference-manifest.js +1 -1
  17. package/.next/server/app/api/capabilities/route.js +1 -1
  18. package/.next/server/app/api/capabilities/route_client-reference-manifest.js +1 -1
  19. package/.next/server/app/api/daily-summary/route_client-reference-manifest.js +1 -1
  20. package/.next/server/app/api/daily-summary/status/route_client-reference-manifest.js +1 -1
  21. package/.next/server/app/api/external-apps/[id]/health/route_client-reference-manifest.js +1 -1
  22. package/.next/server/app/api/external-apps/[id]/route_client-reference-manifest.js +1 -1
  23. package/.next/server/app/api/external-apps/route_client-reference-manifest.js +1 -1
  24. package/.next/server/app/api/fs/browse/route_client-reference-manifest.js +1 -1
  25. package/.next/server/app/api/fs/recent-paths/route_client-reference-manifest.js +1 -1
  26. package/.next/server/app/api/hooks/agent-event/route.js +2 -2
  27. package/.next/server/app/api/hooks/agent-event/route.js.nft.json +1 -1
  28. package/.next/server/app/api/hooks/agent-event/route_client-reference-manifest.js +1 -1
  29. package/.next/server/app/api/hooks/claude-done/route.js +2 -2
  30. package/.next/server/app/api/hooks/claude-done/route.js.nft.json +1 -1
  31. package/.next/server/app/api/hooks/claude-done/route_client-reference-manifest.js +1 -1
  32. package/.next/server/app/api/hooks/permission-request/route.js +1 -1
  33. package/.next/server/app/api/hooks/permission-request/route.js.nft.json +1 -1
  34. package/.next/server/app/api/hooks/permission-request/route_client-reference-manifest.js +1 -1
  35. package/.next/server/app/api/metrics/vibe/route_client-reference-manifest.js +1 -1
  36. package/.next/server/app/api/ollama/models/route_client-reference-manifest.js +1 -1
  37. package/.next/server/app/api/push/escalation/route.js +1 -1
  38. package/.next/server/app/api/push/escalation/route_client-reference-manifest.js +1 -1
  39. package/.next/server/app/api/push/subscriptions/route_client-reference-manifest.js +1 -1
  40. package/.next/server/app/api/push/vapid/route.js +1 -1
  41. package/.next/server/app/api/push/vapid/route_client-reference-manifest.js +1 -1
  42. package/.next/server/app/api/relays/[relayId]/cancel/route.js +1 -1
  43. package/.next/server/app/api/relays/[relayId]/cancel/route.js.nft.json +1 -1
  44. package/.next/server/app/api/relays/[relayId]/cancel/route_client-reference-manifest.js +1 -1
  45. package/.next/server/app/api/relays/route.js +1 -1
  46. package/.next/server/app/api/relays/route.js.nft.json +1 -1
  47. package/.next/server/app/api/relays/route_client-reference-manifest.js +1 -1
  48. package/.next/server/app/api/remote/pair/route_client-reference-manifest.js +1 -1
  49. package/.next/server/app/api/repositories/[id]/route_client-reference-manifest.js +1 -1
  50. package/.next/server/app/api/repositories/clone/[jobId]/route.js +1 -1
  51. package/.next/server/app/api/repositories/clone/[jobId]/route.js.nft.json +1 -1
  52. package/.next/server/app/api/repositories/clone/[jobId]/route_client-reference-manifest.js +1 -1
  53. package/.next/server/app/api/repositories/clone/route.js +1 -1
  54. package/.next/server/app/api/repositories/clone/route.js.nft.json +1 -1
  55. package/.next/server/app/api/repositories/clone/route_client-reference-manifest.js +1 -1
  56. package/.next/server/app/api/repositories/excluded/route_client-reference-manifest.js +1 -1
  57. package/.next/server/app/api/repositories/restore/route.js +1 -1
  58. package/.next/server/app/api/repositories/restore/route.js.nft.json +1 -1
  59. package/.next/server/app/api/repositories/restore/route_client-reference-manifest.js +1 -1
  60. package/.next/server/app/api/repositories/route.js +1 -1
  61. package/.next/server/app/api/repositories/route.js.nft.json +1 -1
  62. package/.next/server/app/api/repositories/route_client-reference-manifest.js +1 -1
  63. package/.next/server/app/api/repositories/scan/route.js +1 -1
  64. package/.next/server/app/api/repositories/scan/route.js.nft.json +1 -1
  65. package/.next/server/app/api/repositories/scan/route_client-reference-manifest.js +1 -1
  66. package/.next/server/app/api/repositories/sync/route.js +1 -1
  67. package/.next/server/app/api/repositories/sync/route.js.nft.json +1 -1
  68. package/.next/server/app/api/repositories/sync/route_client-reference-manifest.js +1 -1
  69. package/.next/server/app/api/repositories/validate-path/route_client-reference-manifest.js +1 -1
  70. package/.next/server/app/api/settings/default-agents/route.js +1 -1
  71. package/.next/server/app/api/settings/default-agents/route.js.nft.json +1 -1
  72. package/.next/server/app/api/settings/default-agents/route_client-reference-manifest.js +1 -1
  73. package/.next/server/app/api/settings/default-surface-mode/route_client-reference-manifest.js +1 -1
  74. package/.next/server/app/api/sidebar/group-order/route_client-reference-manifest.js +1 -1
  75. package/.next/server/app/api/skills/[id]/route_client-reference-manifest.js +1 -1
  76. package/.next/server/app/api/skills/installations/route_client-reference-manifest.js +1 -1
  77. package/.next/server/app/api/skills/operations/route_client-reference-manifest.js +1 -1
  78. package/.next/server/app/api/skills/reindex/route_client-reference-manifest.js +1 -1
  79. package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
  80. package/.next/server/app/api/slash-commands/route_client-reference-manifest.js +1 -1
  81. package/.next/server/app/api/tasks/[taskId]/cancel/route_client-reference-manifest.js +1 -1
  82. package/.next/server/app/api/tasks/[taskId]/route_client-reference-manifest.js +1 -1
  83. package/.next/server/app/api/templates/[id]/route_client-reference-manifest.js +1 -1
  84. package/.next/server/app/api/templates/route_client-reference-manifest.js +1 -1
  85. package/.next/server/app/api/verification/runs/[runId]/route_client-reference-manifest.js +1 -1
  86. package/.next/server/app/api/verification/runs/route_client-reference-manifest.js +1 -1
  87. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js +1 -1
  88. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js.nft.json +1 -1
  89. package/.next/server/app/api/worktrees/[id]/auto-yes/route_client-reference-manifest.js +1 -1
  90. package/.next/server/app/api/worktrees/[id]/capture/route.js +1 -1
  91. package/.next/server/app/api/worktrees/[id]/capture/route.js.nft.json +1 -1
  92. package/.next/server/app/api/worktrees/[id]/capture/route_client-reference-manifest.js +1 -1
  93. package/.next/server/app/api/worktrees/[id]/clear-composer/route.js +1 -1
  94. package/.next/server/app/api/worktrees/[id]/clear-composer/route.js.nft.json +1 -1
  95. package/.next/server/app/api/worktrees/[id]/clear-composer/route_client-reference-manifest.js +1 -1
  96. package/.next/server/app/api/worktrees/[id]/cli-reference/route_client-reference-manifest.js +1 -1
  97. package/.next/server/app/api/worktrees/[id]/cli-tool/route_client-reference-manifest.js +1 -1
  98. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route_client-reference-manifest.js +1 -1
  99. package/.next/server/app/api/worktrees/[id]/current-output/route.js +1 -1
  100. package/.next/server/app/api/worktrees/[id]/current-output/route.js.nft.json +1 -1
  101. package/.next/server/app/api/worktrees/[id]/current-output/route_client-reference-manifest.js +1 -1
  102. package/.next/server/app/api/worktrees/[id]/direct-input/route.js +1 -1
  103. package/.next/server/app/api/worktrees/[id]/direct-input/route.js.nft.json +1 -1
  104. package/.next/server/app/api/worktrees/[id]/direct-input/route_client-reference-manifest.js +1 -1
  105. package/.next/server/app/api/worktrees/[id]/env/route_client-reference-manifest.js +1 -1
  106. package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route_client-reference-manifest.js +1 -1
  107. package/.next/server/app/api/worktrees/[id]/execution-logs/route_client-reference-manifest.js +1 -1
  108. package/.next/server/app/api/worktrees/[id]/files/[...path]/route_client-reference-manifest.js +1 -1
  109. package/.next/server/app/api/worktrees/[id]/git/branch/create/route_client-reference-manifest.js +1 -1
  110. package/.next/server/app/api/worktrees/[id]/git/branch/delete/route_client-reference-manifest.js +1 -1
  111. package/.next/server/app/api/worktrees/[id]/git/branches/route_client-reference-manifest.js +1 -1
  112. package/.next/server/app/api/worktrees/[id]/git/checkout/route_client-reference-manifest.js +1 -1
  113. package/.next/server/app/api/worktrees/[id]/git/commit/route_client-reference-manifest.js +1 -1
  114. package/.next/server/app/api/worktrees/[id]/git/diff/route_client-reference-manifest.js +1 -1
  115. package/.next/server/app/api/worktrees/[id]/git/fetch/route_client-reference-manifest.js +1 -1
  116. package/.next/server/app/api/worktrees/[id]/git/log/route_client-reference-manifest.js +1 -1
  117. package/.next/server/app/api/worktrees/[id]/git/pull/route_client-reference-manifest.js +1 -1
  118. package/.next/server/app/api/worktrees/[id]/git/push/route_client-reference-manifest.js +1 -1
  119. package/.next/server/app/api/worktrees/[id]/git/reset/route_client-reference-manifest.js +1 -1
  120. package/.next/server/app/api/worktrees/[id]/git/revert/route_client-reference-manifest.js +1 -1
  121. package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route_client-reference-manifest.js +1 -1
  122. package/.next/server/app/api/worktrees/[id]/git/stage/route_client-reference-manifest.js +1 -1
  123. package/.next/server/app/api/worktrees/[id]/git/staged/route_client-reference-manifest.js +1 -1
  124. package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route_client-reference-manifest.js +1 -1
  125. package/.next/server/app/api/worktrees/[id]/git/stash/apply/route_client-reference-manifest.js +1 -1
  126. package/.next/server/app/api/worktrees/[id]/git/stash/pop/route_client-reference-manifest.js +1 -1
  127. package/.next/server/app/api/worktrees/[id]/git/stash/push/route_client-reference-manifest.js +1 -1
  128. package/.next/server/app/api/worktrees/[id]/git/stash/route_client-reference-manifest.js +1 -1
  129. package/.next/server/app/api/worktrees/[id]/git/status/route_client-reference-manifest.js +1 -1
  130. package/.next/server/app/api/worktrees/[id]/git/unstage/route_client-reference-manifest.js +1 -1
  131. package/.next/server/app/api/worktrees/[id]/git/working-diff/route_client-reference-manifest.js +1 -1
  132. package/.next/server/app/api/worktrees/[id]/instances/notes/route_client-reference-manifest.js +1 -1
  133. package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js +1 -1
  134. package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js.nft.json +1 -1
  135. package/.next/server/app/api/worktrees/[id]/instances/opencode/route_client-reference-manifest.js +1 -1
  136. package/.next/server/app/api/worktrees/[id]/interrupt/route.js +1 -1
  137. package/.next/server/app/api/worktrees/[id]/interrupt/route.js.nft.json +1 -1
  138. package/.next/server/app/api/worktrees/[id]/interrupt/route_client-reference-manifest.js +1 -1
  139. package/.next/server/app/api/worktrees/[id]/kill-session/route.js +1 -1
  140. package/.next/server/app/api/worktrees/[id]/kill-session/route.js.nft.json +1 -1
  141. package/.next/server/app/api/worktrees/[id]/kill-session/route_client-reference-manifest.js +1 -1
  142. package/.next/server/app/api/worktrees/[id]/logs/[filename]/route_client-reference-manifest.js +1 -1
  143. package/.next/server/app/api/worktrees/[id]/logs/route_client-reference-manifest.js +1 -1
  144. package/.next/server/app/api/worktrees/[id]/marp-render/route_client-reference-manifest.js +1 -1
  145. package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route_client-reference-manifest.js +1 -1
  146. package/.next/server/app/api/worktrees/[id]/memos/route_client-reference-manifest.js +1 -1
  147. package/.next/server/app/api/worktrees/[id]/messages/route_client-reference-manifest.js +1 -1
  148. package/.next/server/app/api/worktrees/[id]/opencode/diff/route_client-reference-manifest.js +1 -1
  149. package/.next/server/app/api/worktrees/[id]/opencode/session/route.js +1 -1
  150. package/.next/server/app/api/worktrees/[id]/opencode/session/route.js.nft.json +1 -1
  151. package/.next/server/app/api/worktrees/[id]/opencode/session/route_client-reference-manifest.js +1 -1
  152. package/.next/server/app/api/worktrees/[id]/opencode/share/route.js +1 -1
  153. package/.next/server/app/api/worktrees/[id]/opencode/share/route.js.nft.json +1 -1
  154. package/.next/server/app/api/worktrees/[id]/opencode/share/route_client-reference-manifest.js +1 -1
  155. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js +1 -1
  156. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js.nft.json +1 -1
  157. package/.next/server/app/api/worktrees/[id]/prompt-response/route_client-reference-manifest.js +1 -1
  158. package/.next/server/app/api/worktrees/[id]/prompt-response/strict/route.js +1 -1
  159. package/.next/server/app/api/worktrees/[id]/prompt-response/strict/route.js.nft.json +1 -1
  160. package/.next/server/app/api/worktrees/[id]/prompt-response/strict/route_client-reference-manifest.js +1 -1
  161. package/.next/server/app/api/worktrees/[id]/resolve-target/route_client-reference-manifest.js +1 -1
  162. package/.next/server/app/api/worktrees/[id]/respond/route.js +1 -1
  163. package/.next/server/app/api/worktrees/[id]/respond/route.js.nft.json +1 -1
  164. package/.next/server/app/api/worktrees/[id]/respond/route_client-reference-manifest.js +1 -1
  165. package/.next/server/app/api/worktrees/[id]/route.js +1 -1
  166. package/.next/server/app/api/worktrees/[id]/route.js.nft.json +1 -1
  167. package/.next/server/app/api/worktrees/[id]/route_client-reference-manifest.js +1 -1
  168. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route_client-reference-manifest.js +1 -1
  169. package/.next/server/app/api/worktrees/[id]/schedules/active/route_client-reference-manifest.js +1 -1
  170. package/.next/server/app/api/worktrees/[id]/schedules/route_client-reference-manifest.js +1 -1
  171. package/.next/server/app/api/worktrees/[id]/search/route_client-reference-manifest.js +1 -1
  172. package/.next/server/app/api/worktrees/[id]/send/route.js +1 -1
  173. package/.next/server/app/api/worktrees/[id]/send/route.js.nft.json +1 -1
  174. package/.next/server/app/api/worktrees/[id]/send/route_client-reference-manifest.js +1 -1
  175. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js +3 -3
  176. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js.nft.json +1 -1
  177. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route_client-reference-manifest.js +1 -1
  178. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route_client-reference-manifest.js +1 -1
  179. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route_client-reference-manifest.js +1 -1
  180. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route_client-reference-manifest.js +1 -1
  181. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route_client-reference-manifest.js +1 -1
  182. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update/route_client-reference-manifest.js +1 -1
  183. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route_client-reference-manifest.js +1 -1
  184. package/.next/server/app/api/worktrees/[id]/skills/route_client-reference-manifest.js +1 -1
  185. package/.next/server/app/api/worktrees/[id]/slash-commands/route_client-reference-manifest.js +1 -1
  186. package/.next/server/app/api/worktrees/[id]/special-keys/route.js +1 -1
  187. package/.next/server/app/api/worktrees/[id]/special-keys/route.js.nft.json +1 -1
  188. package/.next/server/app/api/worktrees/[id]/special-keys/route_client-reference-manifest.js +1 -1
  189. package/.next/server/app/api/worktrees/[id]/tasks/route_client-reference-manifest.js +1 -1
  190. package/.next/server/app/api/worktrees/[id]/terminal/route.js +1 -103
  191. package/.next/server/app/api/worktrees/[id]/terminal/route.js.nft.json +1 -1
  192. package/.next/server/app/api/worktrees/[id]/terminal/route_client-reference-manifest.js +1 -1
  193. package/.next/server/app/api/worktrees/[id]/timers/history/route_client-reference-manifest.js +1 -1
  194. package/.next/server/app/api/worktrees/[id]/timers/route.js +1 -1
  195. package/.next/server/app/api/worktrees/[id]/timers/route.js.nft.json +1 -1
  196. package/.next/server/app/api/worktrees/[id]/timers/route_client-reference-manifest.js +1 -1
  197. package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
  198. package/.next/server/app/api/worktrees/[id]/todos/route_client-reference-manifest.js +1 -1
  199. package/.next/server/app/api/worktrees/[id]/tree/[...path]/route_client-reference-manifest.js +1 -1
  200. package/.next/server/app/api/worktrees/[id]/tree/route_client-reference-manifest.js +1 -1
  201. package/.next/server/app/api/worktrees/[id]/upload/[...path]/route_client-reference-manifest.js +1 -1
  202. package/.next/server/app/api/worktrees/[id]/verify/config/route_client-reference-manifest.js +1 -1
  203. package/.next/server/app/api/worktrees/[id]/verify/route.js +1 -1
  204. package/.next/server/app/api/worktrees/[id]/verify/route_client-reference-manifest.js +1 -1
  205. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route.js +1 -1
  206. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route_client-reference-manifest.js +1 -1
  207. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route_client-reference-manifest.js +1 -1
  208. package/.next/server/app/api/worktrees/[id]/verify/runs/route_client-reference-manifest.js +1 -1
  209. package/.next/server/app/api/worktrees/[id]/viewed/route_client-reference-manifest.js +1 -1
  210. package/.next/server/app/api/worktrees/apply-default-agents/route_client-reference-manifest.js +1 -1
  211. package/.next/server/app/api/worktrees/route.js +1 -1
  212. package/.next/server/app/api/worktrees/route.js.nft.json +1 -1
  213. package/.next/server/app/api/worktrees/route_client-reference-manifest.js +1 -1
  214. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  215. package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
  216. package/.next/server/app/more/page_client-reference-manifest.js +1 -1
  217. package/.next/server/app/offline/page_client-reference-manifest.js +1 -1
  218. package/.next/server/app/page_client-reference-manifest.js +1 -1
  219. package/.next/server/app/proxy/[...path]/route_client-reference-manifest.js +1 -1
  220. package/.next/server/app/repositories/page_client-reference-manifest.js +1 -1
  221. package/.next/server/app/review/page_client-reference-manifest.js +1 -1
  222. package/.next/server/app/sessions/page.js +1 -1
  223. package/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  224. package/.next/server/app/skills/[skillId]/page_client-reference-manifest.js +1 -1
  225. package/.next/server/app/skills/installed/page_client-reference-manifest.js +1 -1
  226. package/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  227. package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -1
  228. package/.next/server/app/worktrees/[id]/page.js +12 -12
  229. package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -1
  230. package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
  231. package/.next/server/app-paths-manifest.json +41 -41
  232. package/.next/server/chunks/1191.js +11 -4
  233. package/.next/server/chunks/1501.js +1 -1
  234. package/.next/server/chunks/1601.js +2 -2
  235. package/.next/server/chunks/1656.js +2 -2
  236. package/.next/server/chunks/1945.js +3 -3
  237. package/.next/server/chunks/1990.js +103 -0
  238. package/.next/server/chunks/2119.js +1 -1
  239. package/.next/server/chunks/2404.js +1 -1
  240. package/.next/server/chunks/2422.js +1 -1
  241. package/.next/server/chunks/2445.js +1 -1
  242. package/.next/server/chunks/2534.js +1 -1
  243. package/.next/server/chunks/255.js +1 -1
  244. package/.next/server/chunks/3241.js +1 -1
  245. package/.next/server/chunks/3505.js +2 -2
  246. package/.next/server/chunks/4248.js +1 -1
  247. package/.next/server/chunks/4280.js +1 -0
  248. package/.next/server/chunks/5209.js +1 -1
  249. package/.next/server/chunks/6119.js +1 -1
  250. package/.next/server/chunks/6130.js +1 -1
  251. package/.next/server/chunks/6401.js +1 -1
  252. package/.next/server/chunks/6486.js +9 -8
  253. package/.next/server/chunks/6781.js +1 -1
  254. package/.next/server/chunks/720.js +103 -0
  255. package/.next/server/chunks/7604.js +2 -0
  256. package/.next/server/chunks/7905.js +1 -1
  257. package/.next/server/chunks/8581.js +7 -7
  258. package/.next/server/chunks/8728.js +3 -3
  259. package/.next/server/chunks/8791.js +1 -1
  260. package/.next/server/chunks/8807.js +19 -18
  261. package/.next/server/chunks/8918.js +2 -104
  262. package/.next/server/chunks/936.js +1 -1
  263. package/.next/server/chunks/9390.js +1 -1
  264. package/.next/server/chunks/9540.js +1 -1
  265. package/.next/server/chunks/9627.js +3 -3
  266. package/.next/server/chunks/9731.js +2 -2
  267. package/.next/server/middleware-manifest.json +5 -5
  268. package/.next/server/pages/500.html +1 -1
  269. package/.next/server/server-reference-manifest.json +1 -1
  270. package/.next/static/chunks/2099-c3e0ab70a1b95dd3.js +1 -0
  271. package/.next/static/chunks/{2407-a6533805a86d05bd.js → 2407-26139a8a2f1adbe8.js} +1 -1
  272. package/.next/static/chunks/{2619-04bc32f026a0d946.js → 2619-a305ad4810f1393a.js} +1 -1
  273. package/.next/static/chunks/{2863-6a07ec82fb52f4dd.js → 2863-f0121af1cbbedb3b.js} +1 -1
  274. package/.next/static/chunks/{8165-263172c17ae8e8c3.js → 8165-c68b3dc844210e6a.js} +1 -1
  275. package/.next/static/chunks/8407-35bbfc84793d7004.js +1 -0
  276. package/.next/static/chunks/9079-406b84d3cc891a87.js +1 -0
  277. package/.next/static/chunks/app/{layout-538d8d2746ad1588.js → layout-46b4cbf07520d9b6.js} +1 -1
  278. package/.next/static/chunks/app/sessions/page-fb241bed579c67aa.js +1 -0
  279. package/.next/static/chunks/app/worktrees/[id]/page-cbc7749a33450cc5.js +1 -0
  280. package/.next/static/chunks/app/worktrees/[id]/terminal/{page-373ea37b16d930c7.js → page-c601f3b3ece6557e.js} +1 -1
  281. package/.next/trace +13 -13
  282. package/dist/cli/commands/auto-yes.d.ts +24 -0
  283. package/dist/cli/commands/auto-yes.d.ts.map +1 -1
  284. package/dist/cli/commands/auto-yes.js +73 -3
  285. package/dist/cli/commands/instances.d.ts.map +1 -1
  286. package/dist/cli/commands/instances.js +10 -1
  287. package/dist/cli/commands/prompt.d.ts.map +1 -1
  288. package/dist/cli/commands/prompt.js +5 -3
  289. package/dist/cli/commands/send.d.ts.map +1 -1
  290. package/dist/cli/commands/send.js +15 -0
  291. package/dist/cli/commands/wait.d.ts.map +1 -1
  292. package/dist/cli/commands/wait.js +101 -13
  293. package/dist/cli/docs/agent-operations.d.ts +2 -2
  294. package/dist/cli/docs/agent-operations.d.ts.map +1 -1
  295. package/dist/cli/docs/agent-operations.js +27 -0
  296. package/dist/cli/types/api-responses.d.ts +116 -2
  297. package/dist/cli/types/api-responses.d.ts.map +1 -1
  298. package/dist/cli/types/index.d.ts +4 -0
  299. package/dist/cli/types/index.d.ts.map +1 -1
  300. package/dist/cli/utils/resource-resolvers.d.ts +0 -18
  301. package/dist/cli/utils/resource-resolvers.d.ts.map +1 -1
  302. package/dist/cli/utils/resource-resolvers.js +1 -51
  303. package/dist/lib/polling/auto-yes-suppression-reason.d.ts +54 -2
  304. package/dist/lib/polling/auto-yes-suppression-reason.d.ts.map +1 -1
  305. package/dist/lib/polling/auto-yes-suppression-reason.js +33 -2
  306. package/dist/lib/prompt-observation/types.d.ts +13 -0
  307. package/dist/lib/prompt-observation/types.d.ts.map +1 -1
  308. package/dist/server/locales/en/worktree.json +2 -1
  309. package/dist/server/locales/ja/worktree.json +2 -1
  310. package/dist/server/src/lib/auto-yes-poller-answer-target.js +38 -0
  311. package/dist/server/src/lib/auto-yes-poller-keys.js +35 -0
  312. package/dist/server/src/lib/auto-yes-poller-session-presence.js +26 -0
  313. package/dist/server/src/lib/auto-yes-poller-tick.js +233 -0
  314. package/dist/server/src/lib/auto-yes-poller.js +337 -376
  315. package/dist/server/src/lib/auto-yes-state.js +50 -2
  316. package/dist/server/src/lib/cli-tools/submit-verified-sender.js +107 -14
  317. package/dist/server/src/lib/db/chat-db.js +5 -1
  318. package/dist/server/src/lib/db/verification-db.js +23 -2
  319. package/dist/server/src/lib/detection/option-recommendation.js +120 -0
  320. package/dist/server/src/lib/detection/prompt-detect-multiple-choice-approval-context.js +290 -0
  321. package/dist/server/src/lib/detection/prompt-detect-multiple-choice.js +396 -350
  322. package/dist/server/src/lib/detection/prompt-detector.js +92 -21
  323. package/dist/server/src/lib/detection/prompt-screen-key.js +60 -0
  324. package/dist/server/src/lib/detection/tools/antigravity/dialog.js +158 -35
  325. package/dist/server/src/lib/detection/tools/claude/detect.js +111 -10
  326. package/dist/server/src/lib/detection/tools/command-code/dialog.js +67 -0
  327. package/dist/server/src/lib/detection/tools/dialog-block.js +16 -0
  328. package/dist/server/src/lib/detection/waiting-screen-reading.js +98 -0
  329. package/dist/server/src/lib/hooks/permission-decision-service.js +7 -0
  330. package/dist/server/src/lib/polling/auto-yes-confirm-page.js +2 -2
  331. package/dist/server/src/lib/polling/auto-yes-confirmation-ledger-types.js +3 -0
  332. package/dist/server/src/lib/polling/auto-yes-confirmation-ledger.js +34 -3
  333. package/dist/server/src/lib/polling/auto-yes-decision-state.js +195 -0
  334. package/dist/server/src/lib/polling/auto-yes-dialog-gate.js +139 -10
  335. package/dist/server/src/lib/polling/auto-yes-enter-fallback.js +14 -0
  336. package/dist/server/src/lib/polling/auto-yes-manual-answer.js +122 -0
  337. package/dist/server/src/lib/polling/auto-yes-option-effect.js +157 -0
  338. package/dist/server/src/lib/polling/auto-yes-policy.js +11 -5
  339. package/dist/server/src/lib/polling/auto-yes-poller-capture.js +15 -2
  340. package/dist/server/src/lib/polling/auto-yes-poller-generation.js +42 -1
  341. package/dist/server/src/lib/polling/auto-yes-poller-receipt-log.js +42 -5
  342. package/dist/server/src/lib/polling/auto-yes-poller-state.js +147 -49
  343. package/dist/server/src/lib/polling/auto-yes-poller-steps.js +172 -2
  344. package/dist/server/src/lib/polling/auto-yes-prompt-suppression.js +2 -2
  345. package/dist/server/src/lib/polling/auto-yes-question-choice.js +57 -0
  346. package/dist/server/src/lib/polling/auto-yes-resolver.js +96 -21
  347. package/dist/server/src/lib/polling/auto-yes-suppression-reason.js +33 -2
  348. package/dist/server/src/lib/polling/auto-yes-suppression-state.js +25 -1
  349. package/dist/server/src/lib/polling/prompt-screen-reading.js +232 -0
  350. package/dist/server/src/lib/polling/response-checker-dialog-gate.js +39 -0
  351. package/dist/server/src/lib/polling/response-checker.js +133 -43
  352. package/dist/server/src/lib/prompt-answer-sender.js +104 -10
  353. package/dist/server/src/lib/push/notification-dedup.js +15 -2
  354. package/dist/server/src/lib/push/prompt-card-state.js +140 -19
  355. package/dist/server/src/lib/push/prompt-push-gate.js +158 -12
  356. package/dist/server/src/lib/push/push-sender.js +23 -3
  357. package/dist/server/src/lib/push/resolution-push-notifier.js +14 -0
  358. package/dist/server/src/lib/push/waiting-push-notifier.js +139 -17
  359. package/dist/server/src/lib/realtime/terminal-broadcast.js +16 -0
  360. package/dist/server/src/lib/session/agent-event-state.js +25 -5
  361. package/dist/server/src/lib/session/agent-event-turn.js +140 -46
  362. package/dist/server/src/lib/session/cli-session.js +21 -2
  363. package/dist/server/src/lib/session/current-output-builder.js +64 -11
  364. package/dist/server/src/lib/session/send-attempt-state.js +23 -7
  365. package/dist/server/src/lib/session/waiting-episode-binding-observation.js +289 -0
  366. package/dist/server/src/lib/session/waiting-episode-binding-resolve.js +38 -0
  367. package/dist/server/src/lib/session/waiting-episode-binding.js +276 -0
  368. package/dist/server/src/lib/session/waiting-episode-state.js +307 -17
  369. package/dist/server/src/lib/session/waiting-episode-verdict.js +174 -0
  370. package/dist/server/src/lib/tmux/tmux-capture-cache.js +76 -11
  371. package/dist/server/src/lib/tmux/tmux.js +54 -9
  372. package/dist/server/src/lib/verification/gate-runner.js +162 -13
  373. package/dist/server/src/lib/verification/machine-lock.js +5 -0
  374. package/dist/server/src/lib/ws-server.js +18 -3
  375. package/dist/server/src/types/auto-yes-answer-mode.js +38 -0
  376. package/dist/server/src/types/auto-yes-decision.js +61 -0
  377. package/dist/server/src/types/auto-yes.js +6 -0
  378. package/dist/server/src/types/prompt-reading.js +32 -0
  379. package/dist/types/auto-yes-answer-mode.d.ts +35 -0
  380. package/dist/types/auto-yes-answer-mode.d.ts.map +1 -0
  381. package/dist/types/auto-yes-answer-mode.js +38 -0
  382. package/docs/en/user-guide/webapp-guide.md +33 -4
  383. package/package.json +1 -1
  384. package/public/sw.js +76 -4
  385. package/release-notes/0.48.0.json +57 -0
  386. package/.next/server/chunks/1559.js +0 -2
  387. package/.next/server/chunks/2460.js +0 -1
  388. package/.next/server/chunks/5595.js +0 -1
  389. package/.next/server/chunks/610.js +0 -1
  390. package/.next/static/chunks/602-1c1488959215e140.js +0 -1
  391. package/.next/static/chunks/8407-155f84e5ba05f1d5.js +0 -1
  392. package/.next/static/chunks/9079-24f9fa549ed298f1.js +0 -1
  393. package/.next/static/chunks/app/sessions/page-e02f1adb1d1c1ccc.js +0 -1
  394. package/.next/static/chunks/app/worktrees/[id]/page-46aced20b2b1c010.js +0 -1
  395. /package/.next/static/{etorRtpxbQqqOzdUeXdw2 → PTlAswXLq8PAe2vUJ8dVP}/_buildManifest.js +0 -0
  396. /package/.next/static/{etorRtpxbQqqOzdUeXdw2 → PTlAswXLq8PAe2vUJ8dVP}/_ssgManifest.js +0 -0
@@ -12,11 +12,23 @@
12
12
  *
13
13
  * So the edge is detected exactly once, here, by {@link observeWaitingEdge}, and
14
14
  * everything else either reads {@link getWaitingEpisode} or subscribes with
15
- * {@link onWaitingTransition}. There is one caller today —
16
- * `worktree-status-helper`, on the list API's per-instance probe — and it passes
17
- * the *composed* verdict (scraper OR structured), so a wait that only the
18
- * agent's own events can see opens an episode exactly like one the screen
19
- * scraper read.
15
+ * {@link onWaitingTransition}. The observers are `worktree-status-helper`, on
16
+ * the list API's per-instance probe — it passes the *composed* verdict (scraper
17
+ * OR structured), so a wait that only the agent's own events can see opens an
18
+ * episode exactly like one the screen scraper read — and `response-checker`
19
+ * (#1790), which opens the episode for a prompt it saved and closes it when it
20
+ * records a reply.
21
+ *
22
+ * Issue #3798 added the agent's own turn transitions as closers: a `stop` that
23
+ * ended the turn an episode belongs to closes it in the same synchronous step
24
+ * that records the stop (`waiting-episode-binding`), so a tool whose reply
25
+ * arrives on a hook closes its wait with no browser open. That needs each
26
+ * episode to carry an identity and the turn it belongs to; see "identity and
27
+ * attribution" below. The screen observers — the status probe, the response
28
+ * poller and now the Auto-Yes poller — go through the same module's
29
+ * observation tables (`observeWaiting`), which refuse a reading made against an
30
+ * episode that has moved since the observer started; {@link observeWaitingEdge}
31
+ * stays for the callers and suites written against #1786.
20
32
  *
21
33
  * ## Where #1788 / #1790 plug in
22
34
  *
@@ -40,6 +52,17 @@
40
52
  */
41
53
  Object.defineProperty(exports, "__esModule", { value: true });
42
54
  exports.onWaitingTransition = onWaitingTransition;
55
+ exports.onWaitingEpisodeTransition = onWaitingEpisodeTransition;
56
+ exports.openEpisode = openEpisode;
57
+ exports.closeEpisode = closeEpisode;
58
+ exports.replaceEpisode = replaceEpisode;
59
+ exports.rebindEpisode = rebindEpisode;
60
+ exports.updateEpisodeKind = updateEpisodeKind;
61
+ exports.getWaitingEpisodeRecord = getWaitingEpisodeRecord;
62
+ exports.getEpisodeVersion = getEpisodeVersion;
63
+ exports.snapshotEpisodeVersions = snapshotEpisodeVersions;
64
+ exports.getLastClosedEpisode = getLastClosedEpisode;
65
+ exports.registerEpisodeBindingResolver = registerEpisodeBindingResolver;
43
66
  exports.observeWaitingEdge = observeWaitingEdge;
44
67
  exports.getWaitingEpisode = getWaitingEpisode;
45
68
  exports.hasOpenWaitingEpisode = hasOpenWaitingEpisode;
@@ -53,6 +76,30 @@ const logger = (0, logger_1.createLogger)('waiting-episode-state');
53
76
  const episodes = (0, global_state_1.getOrInitGlobal)('__sessionWaitingEpisodes', () => new Map());
54
77
  /** Subscribers to the edge. See the module docblock. */
55
78
  const listeners = (0, global_state_1.getOrInitGlobal)('__sessionWaitingTransitionListeners', () => new Set());
79
+ const metas = (0, global_state_1.getOrInitGlobal)('__sessionWaitingEpisodeMeta', () => new WeakMap());
80
+ const versions = (0, global_state_1.getOrInitGlobal)('__sessionWaitingEpisodeVersions', () => new Map());
81
+ const lastClosed = (0, global_state_1.getOrInitGlobal)('__sessionWaitingEpisodeLastClosed', () => new Map());
82
+ const episodeSeq = (0, global_state_1.getOrInitGlobal)('__sessionWaitingEpisodeSeq', () => ({
83
+ value: 0,
84
+ nonce: Math.random().toString(36).slice(2, 10),
85
+ }));
86
+ const episodeListeners = (0, global_state_1.getOrInitGlobal)('__sessionWaitingEpisodeListeners', () => new Set());
87
+ /** The binding used when no resolver is registered: nothing is known. */
88
+ const UNKNOWN_BINDING = {
89
+ kind: 'unattributed',
90
+ generation: { kind: 'none' },
91
+ lastClosedTurnId: null,
92
+ };
93
+ function nextEpisodeId() {
94
+ episodeSeq.value += 1;
95
+ return `wep-${episodeSeq.nonce}-${episodeSeq.value}`;
96
+ }
97
+ function keyOf(parts) {
98
+ return (0, auto_yes_state_1.buildCompositeKey)(parts.worktreeId, parts.cliToolId, parts.instanceId);
99
+ }
100
+ function bumpVersion(key) {
101
+ versions.set(key, (versions.get(key) ?? 0) + 1);
102
+ }
56
103
  /**
57
104
  * Subscribe to waiting edges.
58
105
  *
@@ -64,23 +111,257 @@ function onWaitingTransition(listener) {
64
111
  listeners.delete(listener);
65
112
  };
66
113
  }
114
+ /**
115
+ * Subscribe to waiting edges with the episode's identity (Issue #3798).
116
+ *
117
+ * The same crossings `onWaitingTransition` delivers, in the same order, with
118
+ * the cause, the episode ids and the close reason added.
119
+ */
120
+ function onWaitingEpisodeTransition(listener) {
121
+ episodeListeners.add(listener);
122
+ return () => {
123
+ episodeListeners.delete(listener);
124
+ };
125
+ }
67
126
  /** Notify subscribers, containing anything they throw. */
68
127
  function emit(transition) {
128
+ const { cause: _cause, episodeId: _id, previousEpisodeId: _prev, closeReason: _reason, ...plain } = transition;
69
129
  for (const listener of listeners) {
130
+ try {
131
+ listener(plain);
132
+ }
133
+ catch (error) {
134
+ logListenerFailure(transition, error);
135
+ }
136
+ }
137
+ for (const listener of episodeListeners) {
70
138
  try {
71
139
  listener(transition);
72
140
  }
73
141
  catch (error) {
74
- logger.error('waiting-transition-listener-failed', {
75
- worktreeId: transition.worktreeId,
76
- cliToolId: transition.cliToolId,
77
- instanceId: transition.instanceId ?? transition.cliToolId,
78
- waiting: transition.waiting,
79
- error: error instanceof Error ? error.message : String(error),
80
- });
142
+ logListenerFailure(transition, error);
81
143
  }
82
144
  }
83
145
  }
146
+ function logListenerFailure(transition, error) {
147
+ logger.error('waiting-transition-listener-failed', {
148
+ worktreeId: transition.worktreeId,
149
+ cliToolId: transition.cliToolId,
150
+ instanceId: transition.instanceId ?? transition.cliToolId,
151
+ waiting: transition.waiting,
152
+ error: error instanceof Error ? error.message : String(error),
153
+ });
154
+ }
155
+ /**
156
+ * Open an episode (Issue #3798). Low-level: the caller has decided there is
157
+ * none open and what it is bound to. Emits the opening edge.
158
+ */
159
+ function openEpisode(parts, next, at) {
160
+ const key = keyOf(parts);
161
+ const view = { since: next.since, kind: next.kind };
162
+ const meta = {
163
+ episodeId: nextEpisodeId(),
164
+ openedAt: at,
165
+ boundAt: at,
166
+ binding: next.binding,
167
+ openedBy: next.openedBy,
168
+ promptScreenKey: next.promptScreenKey ?? null,
169
+ };
170
+ episodes.set(key, view);
171
+ metas.set(view, meta);
172
+ bumpVersion(key);
173
+ emit({
174
+ worktreeId: parts.worktreeId,
175
+ cliToolId: parts.cliToolId,
176
+ instanceId: parts.instanceId,
177
+ waiting: true,
178
+ since: view.since,
179
+ kind: view.kind,
180
+ at,
181
+ cause: 'opened',
182
+ episodeId: meta.episodeId,
183
+ previousEpisodeId: null,
184
+ closeReason: null,
185
+ });
186
+ return { ...view, ...meta };
187
+ }
188
+ /**
189
+ * Close the open episode when it is still `expectedId` (Issue #3798). A closer
190
+ * that names the episode it decided about cannot close a later one.
191
+ *
192
+ * @returns Whether an episode was closed
193
+ */
194
+ function closeEpisode(parts, expectedId, reason, at) {
195
+ const key = keyOf(parts);
196
+ const view = episodes.get(key);
197
+ if (view === undefined)
198
+ return false;
199
+ const meta = metaOf(view);
200
+ if (meta.episodeId !== expectedId)
201
+ return false;
202
+ episodes.delete(key);
203
+ lastClosed.set(key, { at, promptScreenKey: meta.promptScreenKey });
204
+ bumpVersion(key);
205
+ emit({
206
+ worktreeId: parts.worktreeId,
207
+ cliToolId: parts.cliToolId,
208
+ instanceId: parts.instanceId,
209
+ waiting: false,
210
+ since: null,
211
+ kind: null,
212
+ at,
213
+ cause: 'closed',
214
+ episodeId: null,
215
+ previousEpisodeId: meta.episodeId,
216
+ closeReason: reason,
217
+ });
218
+ return true;
219
+ }
220
+ /**
221
+ * Put a new episode in place of `expectedId` as one operation (Issue #3798):
222
+ * listeners hear a single opening edge for the new wait and no closing one
223
+ * in between, so nothing reports "nobody is waiting" mid-swap.
224
+ *
225
+ * @returns The new episode, or null when `expectedId` is no longer open
226
+ */
227
+ function replaceEpisode(parts, expectedId, next, reason, at) {
228
+ const key = keyOf(parts);
229
+ const old = episodes.get(key);
230
+ if (old === undefined)
231
+ return null;
232
+ const oldMeta = metaOf(old);
233
+ if (oldMeta.episodeId !== expectedId)
234
+ return null;
235
+ lastClosed.set(key, { at, promptScreenKey: oldMeta.promptScreenKey });
236
+ const view = { since: next.since, kind: next.kind };
237
+ const meta = {
238
+ episodeId: nextEpisodeId(),
239
+ openedAt: at,
240
+ boundAt: at,
241
+ binding: next.binding,
242
+ openedBy: next.openedBy,
243
+ promptScreenKey: next.promptScreenKey ?? null,
244
+ };
245
+ episodes.set(key, view);
246
+ metas.set(view, meta);
247
+ bumpVersion(key);
248
+ emit({
249
+ worktreeId: parts.worktreeId,
250
+ cliToolId: parts.cliToolId,
251
+ instanceId: parts.instanceId,
252
+ waiting: true,
253
+ since: view.since,
254
+ kind: view.kind,
255
+ at,
256
+ cause: 'replaced',
257
+ episodeId: meta.episodeId,
258
+ previousEpisodeId: oldMeta.episodeId,
259
+ closeReason: reason,
260
+ });
261
+ return { ...view, ...meta };
262
+ }
263
+ /**
264
+ * Change what the open episode `expectedId` is bound to (Issue #3798). Not an
265
+ * edge: the wait goes on, so nothing is emitted and `since` stays.
266
+ *
267
+ * @returns Whether the episode was rebound
268
+ */
269
+ function rebindEpisode(parts, expectedId, binding, at) {
270
+ const key = keyOf(parts);
271
+ const view = episodes.get(key);
272
+ if (view === undefined)
273
+ return false;
274
+ const meta = metaOf(view);
275
+ if (meta.episodeId !== expectedId)
276
+ return false;
277
+ meta.binding = binding;
278
+ meta.boundAt = at;
279
+ bumpVersion(key);
280
+ return true;
281
+ }
282
+ /**
283
+ * Refresh the kind of the open episode `expectedId` (Issue #3798, I10). The
284
+ * wait goes on: no edge, and the version does not move.
285
+ *
286
+ * @returns Whether the episode was still open
287
+ */
288
+ function updateEpisodeKind(parts, expectedId, kind) {
289
+ const view = episodes.get(keyOf(parts));
290
+ if (view === undefined || metaOf(view).episodeId !== expectedId)
291
+ return false;
292
+ view.kind = kind;
293
+ return true;
294
+ }
295
+ /**
296
+ * The meta of an episode in the map. An episode put there without one (a test
297
+ * that wrote the map directly) is given an unattributed identity on first read.
298
+ */
299
+ function metaOf(view) {
300
+ let meta = metas.get(view);
301
+ if (meta === undefined) {
302
+ meta = {
303
+ episodeId: nextEpisodeId(),
304
+ openedAt: view.since,
305
+ boundAt: view.since,
306
+ binding: UNKNOWN_BINDING,
307
+ openedBy: 'legacy-edge',
308
+ promptScreenKey: null,
309
+ };
310
+ metas.set(view, meta);
311
+ }
312
+ return meta;
313
+ }
314
+ /** The open episode with its identity and binding, or null (Issue #3798). */
315
+ function getWaitingEpisodeRecord(worktreeId, cliToolId, instanceId) {
316
+ const view = episodes.get((0, auto_yes_state_1.buildCompositeKey)(worktreeId, cliToolId, instanceId));
317
+ if (view === undefined)
318
+ return null;
319
+ const meta = metaOf(view);
320
+ return { since: view.since, kind: view.kind, ...meta, binding: meta.binding };
321
+ }
322
+ /** The instance's episode version: it moves on every open, close, replacement and rebind. */
323
+ function getEpisodeVersion(worktreeId, cliToolId, instanceId) {
324
+ return versions.get((0, auto_yes_state_1.buildCompositeKey)(worktreeId, cliToolId, instanceId)) ?? 0;
325
+ }
326
+ /**
327
+ * Every instance version of one worktree, as of now (Issue #3798): the status
328
+ * probe fixes them before it lists the tmux sessions. An instance missing from
329
+ * the map is at version 0.
330
+ */
331
+ function snapshotEpisodeVersions(worktreeId) {
332
+ const prefix = `${worktreeId}${auto_yes_state_1.COMPOSITE_KEY_SEPARATOR}`;
333
+ const snapshot = new Map();
334
+ for (const [key, version] of versions) {
335
+ if (key.startsWith(prefix))
336
+ snapshot.set(key, version);
337
+ }
338
+ return snapshot;
339
+ }
340
+ /** The last episode that ended for this instance, or null. */
341
+ function getLastClosedEpisode(worktreeId, cliToolId, instanceId) {
342
+ return lastClosed.get((0, auto_yes_state_1.buildCompositeKey)(worktreeId, cliToolId, instanceId)) ?? null;
343
+ }
344
+ /** Install the binding resolver `observeWaitingEdge` uses. The last one wins. */
345
+ function registerEpisodeBindingResolver(resolver) {
346
+ globalThis.__sessionWaitingEpisodeBindingResolver = resolver;
347
+ }
348
+ function resolveBinding(parts, at) {
349
+ const resolver = globalThis.__sessionWaitingEpisodeBindingResolver;
350
+ if (resolver === undefined)
351
+ return UNKNOWN_BINDING;
352
+ try {
353
+ return resolver(parts, at);
354
+ }
355
+ catch (error) {
356
+ logger.warn('waiting-episode-binding-resolve-failed', {
357
+ worktreeId: parts.worktreeId,
358
+ cliToolId: parts.cliToolId,
359
+ instanceId: parts.instanceId ?? parts.cliToolId,
360
+ error: error instanceof Error ? error.message : String(error),
361
+ });
362
+ return UNKNOWN_BINDING;
363
+ }
364
+ }
84
365
  /**
85
366
  * Record this poll's waiting verdict and answer when the current wait began.
86
367
  *
@@ -89,16 +370,23 @@ function emit(transition) {
89
370
  * `since` and emit nothing, so a listener hears one event per wait rather than
90
371
  * one per poll.
91
372
  *
373
+ * Issue #3798: an episode opened here is bound by the registered resolver
374
+ * (`waiting-episode-binding`), so the turn transitions can end it. The
375
+ * production observers no longer call it: they go through
376
+ * `waiting-episode-binding`'s `observeWaiting`, which also checks that the
377
+ * episode has not moved since they started and that the frame does not
378
+ * predate the close of what it shows.
379
+ *
92
380
  * @returns The episode's `since` while waiting, or null when it is not.
93
381
  */
94
382
  function observeWaitingEdge({ worktreeId, cliToolId, instanceId, waiting, kind = null, structuredSince = null, now = Date.now(), }) {
95
- const key = (0, auto_yes_state_1.buildCompositeKey)(worktreeId, cliToolId, instanceId);
383
+ const parts = { worktreeId, cliToolId, instanceId };
384
+ const key = keyOf(parts);
96
385
  const existing = episodes.get(key);
97
386
  if (!waiting) {
98
387
  if (existing === undefined)
99
388
  return null;
100
- episodes.delete(key);
101
- emit({ worktreeId, cliToolId, instanceId, waiting: false, since: null, kind: null, at: now });
389
+ closeEpisode(parts, metaOf(existing).episodeId, 'screen-cleared', now);
102
390
  return null;
103
391
  }
104
392
  if (existing !== undefined) {
@@ -109,8 +397,7 @@ function observeWaitingEdge({ worktreeId, cliToolId, instanceId, waiting, kind =
109
397
  return existing.since;
110
398
  }
111
399
  const since = structuredSince ?? now;
112
- episodes.set(key, { since, kind });
113
- emit({ worktreeId, cliToolId, instanceId, waiting: true, since, kind, at: now });
400
+ openEpisode(parts, { since, kind, binding: resolveBinding(parts, now), openedBy: 'legacy-edge' }, now);
114
401
  return since;
115
402
  }
116
403
  /**
@@ -152,8 +439,11 @@ function hasOpenWaitingEpisode(worktreeId) {
152
439
  */
153
440
  function clearWaitingEpisodes() {
154
441
  episodes.clear();
442
+ versions.clear();
443
+ lastClosed.clear();
155
444
  }
156
445
  /** Drop every subscriber. Test seam, paired with {@link clearWaitingEpisodes}. */
157
446
  function clearWaitingTransitionListeners() {
158
447
  listeners.clear();
448
+ episodeListeners.clear();
159
449
  }
@@ -0,0 +1,174 @@
1
+ "use strict";
2
+ /**
3
+ * The T table (Issue #3798, design §2.4): what one turn transition's outcome
4
+ * does to the open waiting episode. Pure — it reads the outcome, the episode's
5
+ * binding and the current generation, and writes nothing. Applying the verdict
6
+ * is `waiting-episode-binding`'s job (Issue #3864 split it out of there).
7
+ *
8
+ * Design: `docs/design/issue-3798-waiting-episode.md`.
9
+ *
10
+ * @module lib/session/waiting-episode-verdict
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.sameGeneration = sameGeneration;
14
+ exports.verdictForOutcome = verdictForOutcome;
15
+ function sameGeneration(a, b) {
16
+ if (a.kind === 'none' || b.kind === 'none')
17
+ return a.kind === b.kind;
18
+ return a.at === b.at;
19
+ }
20
+ const NONE = { action: 'none' };
21
+ const close = (reason) => ({ action: 'close', reason });
22
+ /** The previous record's turn id, for the D and F columns. Null for `none`. */
23
+ function previousTurnId(previous) {
24
+ return previous.kind === 'none' ? null : previous.turnId;
25
+ }
26
+ /** T1–T5: a turn opened. */
27
+ function verdictForOpened(outcome, binding) {
28
+ const { previous, turnId: n, event } = outcome;
29
+ const asTurnN = { kind: 'turn', generation: outcome.generation, turnId: n };
30
+ if (binding.kind === 'screen')
31
+ return NONE;
32
+ if (binding.kind === 'turn' && binding.turnId === n)
33
+ return { action: 'unmatched' }; // ※1
34
+ const p = previousTurnId(previous);
35
+ const tookOverRecord = previous.kind === 'dialog-only' || previous.kind === 'display-only';
36
+ // D: the record this turn took over (R3-4). Only T2 / T3 / T4 have one (※5).
37
+ const isD = binding.kind === 'dialog-only' && binding.recordTurnId === p;
38
+ // T5 (R1-9): a turn replaced while it was open ends every wait but a screen's.
39
+ if (previous.kind === 'open-same-session' || previous.kind === 'open-other-session') {
40
+ return isD ? { action: 'unmatched' } : close('turn-superseded');
41
+ }
42
+ // T4 (R2-4): a prompt ends them too; the turn model drops every decision here.
43
+ if (event === 'user_prompt_submit')
44
+ return close('turn-superseded');
45
+ if (binding.kind === 'turn')
46
+ return close('turn-superseded');
47
+ if (binding.kind === 'dialog-only') {
48
+ if (!isD)
49
+ return close('turn-superseded');
50
+ return tookOverRecord ? { action: 'rebind', binding: asTurnN } : { action: 'unmatched' }; // T1: ※5
51
+ }
52
+ // unattributed — F: nothing opened between the wait and this turn (R2-4).
53
+ return binding.lastClosedTurnId === p ? { action: 'rebind', binding: asTurnN } : close('turn-superseded');
54
+ }
55
+ /** T9–T11: a stop with no turn open. */
56
+ function verdictForStopWithoutTurn(outcome, binding) {
57
+ const { previous } = outcome;
58
+ const p = previousTurnId(previous);
59
+ switch (previous.kind) {
60
+ case 'closed':
61
+ // T9: B (R1-2) and F (R2-1).
62
+ if (binding.kind === 'turn' && binding.turnId === p)
63
+ return close('turn-stop');
64
+ if (binding.kind === 'unattributed' && binding.lastClosedTurnId === p)
65
+ return close('turn-stop');
66
+ if (binding.kind === 'dialog-only' && binding.recordTurnId === p)
67
+ return { action: 'unmatched' }; // ※5
68
+ return NONE;
69
+ case 'dialog-only':
70
+ // T10: D, F and G.
71
+ if (binding.kind === 'dialog-only' && binding.recordTurnId === p)
72
+ return close('turn-stop');
73
+ if (binding.kind === 'unattributed')
74
+ return close('turn-stop');
75
+ return NONE;
76
+ case 'display-only':
77
+ case 'none':
78
+ // T11: D (R3-4) and F.
79
+ if (binding.kind === 'dialog-only' && binding.recordTurnId === p)
80
+ return close('turn-stop');
81
+ if (binding.kind === 'unattributed' && binding.lastClosedTurnId === p)
82
+ return close('turn-stop');
83
+ return NONE;
84
+ default:
85
+ // An open turn is `stopped` / `stop-rejected`, never this outcome.
86
+ return { action: 'unmatched' };
87
+ }
88
+ }
89
+ /** T19 / T20 and the rest of the generation fence. */
90
+ function verdictForGenerationFenced(outcome, binding) {
91
+ // T19 / T20 (R2-8): a session start in the same process keeps a screen.
92
+ if (outcome.source === 'session-start' && binding.kind === 'screen') {
93
+ return sameGeneration(binding.generation, outcome.generation)
94
+ ? NONE
95
+ : { action: 'rebind', binding: { ...binding, generation: outcome.generation } };
96
+ }
97
+ return sameGeneration(binding.generation, outcome.generation) ? NONE : close('generation');
98
+ }
99
+ /** T7. */
100
+ function verdictForRestored(outcome, binding) {
101
+ // T7: a wait opened under the discarded turn belongs to the one put back.
102
+ return binding.kind === 'turn' && binding.turnId === outcome.discardedTurnId
103
+ ? { action: 'rebind', binding: { ...binding, turnId: outcome.restoredTurnId } }
104
+ : NONE;
105
+ }
106
+ /** T8. */
107
+ function verdictForStopped(outcome, binding) {
108
+ // T8.
109
+ return binding.kind === 'turn' && binding.turnId === outcome.turnId ? close('turn-stop') : NONE;
110
+ }
111
+ /** T13. */
112
+ function verdictForSessionEnded(outcome, binding) {
113
+ // T13.
114
+ return binding.kind === 'turn' && binding.turnId === outcome.turnId ? close('turn-session-end') : NONE;
115
+ }
116
+ /** T15 / T16. */
117
+ function verdictForDecisionOpened(outcome, binding, current) {
118
+ // T15 / T16 (R3-6): a dialog the hook reported for a wait the screen showed first.
119
+ return outcome.recordKind === 'dialog-only' && binding.kind === 'unattributed'
120
+ ? {
121
+ action: 'rebind',
122
+ binding: { kind: 'dialog-only', generation: current, recordTurnId: outcome.recordTurnId, sessionId: null },
123
+ }
124
+ : NONE;
125
+ }
126
+ /** T17 / T18. */
127
+ function verdictForDecisionAnswered(outcome, binding) {
128
+ // T17 / T18 (R3-3): an explicit answer that left nothing pending.
129
+ if (outcome.before === 0 || outcome.remaining > 0)
130
+ return NONE;
131
+ const bound = (binding.kind === 'turn' && binding.turnId === outcome.recordTurnId) ||
132
+ (binding.kind === 'dialog-only' && binding.recordTurnId === outcome.recordTurnId);
133
+ return bound ? close('decision-settled') : NONE;
134
+ }
135
+ /** Rows that close a binding of another generation (the I column). */
136
+ const CLOSES_OTHER_GENERATION = new Set([
137
+ 'opened',
138
+ 'stopped',
139
+ 'stop-without-turn',
140
+ 'session-ended',
141
+ ]);
142
+ /** The T table (design §2.4): one outcome on the open episode. */
143
+ function verdictForOutcome(outcome, binding, current) {
144
+ if (outcome.kind === 'generation-fenced')
145
+ return verdictForGenerationFenced(outcome, binding);
146
+ if (!sameGeneration(binding.generation, current)) {
147
+ return CLOSES_OTHER_GENERATION.has(outcome.kind) ? close('generation') : NONE;
148
+ }
149
+ switch (outcome.kind) {
150
+ case 'opened':
151
+ return verdictForOpened(outcome, binding);
152
+ case 'restored':
153
+ return verdictForRestored(outcome, binding);
154
+ case 'stopped':
155
+ return verdictForStopped(outcome, binding);
156
+ case 'stop-without-turn':
157
+ return verdictForStopWithoutTurn(outcome, binding);
158
+ case 'session-ended':
159
+ return verdictForSessionEnded(outcome, binding);
160
+ case 'decision-opened':
161
+ return verdictForDecisionOpened(outcome, binding, current);
162
+ case 'decision-answered':
163
+ return verdictForDecisionAnswered(outcome, binding);
164
+ case 'continued':
165
+ case 'stop-rejected':
166
+ case 'session-end-rejected':
167
+ case 'none':
168
+ // T6, T12, T14, T21.
169
+ return NONE;
170
+ default:
171
+ outcome;
172
+ return NONE;
173
+ }
174
+ }