commandmate 0.44.2 → 0.45.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 (621) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-build-manifest.json +289 -289
  3. package/.next/app-path-routes-manifest.json +20 -20
  4. package/.next/build-manifest.json +5 -5
  5. package/.next/next-server.js.nft.json +1 -1
  6. package/.next/prerender-manifest.json +12 -12
  7. package/.next/react-loadable-manifest.json +26 -32
  8. package/.next/required-server-files.json +1 -1
  9. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  10. package/.next/server/app/api/agents/update/route.js +1 -1
  11. package/.next/server/app/api/agents/update/route_client-reference-manifest.js +1 -1
  12. package/.next/server/app/api/agents/versions/route.js +1 -1
  13. package/.next/server/app/api/agents/versions/route_client-reference-manifest.js +1 -1
  14. package/.next/server/app/api/app/release-notes/route_client-reference-manifest.js +1 -1
  15. package/.next/server/app/api/app/update/route.js +2 -2
  16. package/.next/server/app/api/app/update/route_client-reference-manifest.js +1 -1
  17. package/.next/server/app/api/app/update-check/route_client-reference-manifest.js +1 -1
  18. package/.next/server/app/api/auth/login/route.js +1 -1
  19. package/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
  20. package/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
  21. package/.next/server/app/api/auth/status/route_client-reference-manifest.js +1 -1
  22. package/.next/server/app/api/capabilities/route.js +1 -1
  23. package/.next/server/app/api/capabilities/route_client-reference-manifest.js +1 -1
  24. package/.next/server/app/api/daily-summary/route.js +1 -1
  25. package/.next/server/app/api/daily-summary/route.js.nft.json +1 -1
  26. package/.next/server/app/api/daily-summary/route_client-reference-manifest.js +1 -1
  27. package/.next/server/app/api/daily-summary/status/route.js +1 -1
  28. package/.next/server/app/api/daily-summary/status/route.js.nft.json +1 -1
  29. package/.next/server/app/api/daily-summary/status/route_client-reference-manifest.js +1 -1
  30. package/.next/server/app/api/external-apps/[id]/health/route_client-reference-manifest.js +1 -1
  31. package/.next/server/app/api/external-apps/[id]/route.js +1 -1
  32. package/.next/server/app/api/external-apps/[id]/route_client-reference-manifest.js +1 -1
  33. package/.next/server/app/api/external-apps/route.js +1 -1
  34. package/.next/server/app/api/external-apps/route_client-reference-manifest.js +1 -1
  35. package/.next/server/app/api/fs/browse/route_client-reference-manifest.js +1 -1
  36. package/.next/server/app/api/fs/recent-paths/route_client-reference-manifest.js +1 -1
  37. package/.next/server/app/api/hooks/agent-event/route.js +2 -2
  38. package/.next/server/app/api/hooks/agent-event/route.js.nft.json +1 -1
  39. package/.next/server/app/api/hooks/agent-event/route_client-reference-manifest.js +1 -1
  40. package/.next/server/app/api/hooks/claude-done/route.js +2 -2
  41. package/.next/server/app/api/hooks/claude-done/route.js.nft.json +1 -1
  42. package/.next/server/app/api/hooks/claude-done/route_client-reference-manifest.js +1 -1
  43. package/.next/server/app/api/hooks/permission-request/route.js +1 -1
  44. package/.next/server/app/api/hooks/permission-request/route.js.nft.json +1 -1
  45. package/.next/server/app/api/hooks/permission-request/route_client-reference-manifest.js +1 -1
  46. package/.next/server/app/api/metrics/vibe/route_client-reference-manifest.js +1 -1
  47. package/.next/server/app/api/ollama/models/route_client-reference-manifest.js +1 -1
  48. package/.next/server/app/api/push/escalation/route.js +1 -1
  49. package/.next/server/app/api/push/escalation/route_client-reference-manifest.js +1 -1
  50. package/.next/server/app/api/push/subscriptions/route.js +2 -2
  51. package/.next/server/app/api/push/subscriptions/route_client-reference-manifest.js +1 -1
  52. package/.next/server/app/api/push/vapid/route.js +1 -1
  53. package/.next/server/app/api/push/vapid/route_client-reference-manifest.js +1 -1
  54. package/.next/server/app/api/relays/[relayId]/cancel/route.js +1 -1
  55. package/.next/server/app/api/relays/[relayId]/cancel/route.js.nft.json +1 -1
  56. package/.next/server/app/api/relays/[relayId]/cancel/route_client-reference-manifest.js +1 -1
  57. package/.next/server/app/api/relays/route.js +1 -1
  58. package/.next/server/app/api/relays/route.js.nft.json +1 -1
  59. package/.next/server/app/api/relays/route_client-reference-manifest.js +1 -1
  60. package/.next/server/app/api/remote/pair/route_client-reference-manifest.js +1 -1
  61. package/.next/server/app/api/repositories/[id]/route.js +1 -1
  62. package/.next/server/app/api/repositories/[id]/route_client-reference-manifest.js +1 -1
  63. package/.next/server/app/api/repositories/clone/[jobId]/route.js +1 -1
  64. package/.next/server/app/api/repositories/clone/[jobId]/route.js.nft.json +1 -1
  65. package/.next/server/app/api/repositories/clone/[jobId]/route_client-reference-manifest.js +1 -1
  66. package/.next/server/app/api/repositories/clone/route.js +1 -1
  67. package/.next/server/app/api/repositories/clone/route.js.nft.json +1 -1
  68. package/.next/server/app/api/repositories/clone/route_client-reference-manifest.js +1 -1
  69. package/.next/server/app/api/repositories/excluded/route_client-reference-manifest.js +1 -1
  70. package/.next/server/app/api/repositories/restore/route.js +1 -1
  71. package/.next/server/app/api/repositories/restore/route.js.nft.json +1 -1
  72. package/.next/server/app/api/repositories/restore/route_client-reference-manifest.js +1 -1
  73. package/.next/server/app/api/repositories/route.js +1 -1
  74. package/.next/server/app/api/repositories/route.js.nft.json +1 -1
  75. package/.next/server/app/api/repositories/route_client-reference-manifest.js +1 -1
  76. package/.next/server/app/api/repositories/scan/route.js +1 -1
  77. package/.next/server/app/api/repositories/scan/route.js.nft.json +1 -1
  78. package/.next/server/app/api/repositories/scan/route_client-reference-manifest.js +1 -1
  79. package/.next/server/app/api/repositories/sync/route.js +1 -1
  80. package/.next/server/app/api/repositories/sync/route.js.nft.json +1 -1
  81. package/.next/server/app/api/repositories/sync/route_client-reference-manifest.js +1 -1
  82. package/.next/server/app/api/repositories/validate-path/route_client-reference-manifest.js +1 -1
  83. package/.next/server/app/api/settings/default-agents/route.js +1 -1
  84. package/.next/server/app/api/settings/default-agents/route.js.nft.json +1 -1
  85. package/.next/server/app/api/settings/default-agents/route_client-reference-manifest.js +1 -1
  86. package/.next/server/app/api/settings/default-surface-mode/route_client-reference-manifest.js +1 -1
  87. package/.next/server/app/api/sidebar/group-order/route.js +1 -1
  88. package/.next/server/app/api/sidebar/group-order/route_client-reference-manifest.js +1 -1
  89. package/.next/server/app/api/skills/[id]/route.js +1 -1
  90. package/.next/server/app/api/skills/[id]/route_client-reference-manifest.js +1 -1
  91. package/.next/server/app/api/skills/installations/route_client-reference-manifest.js +1 -1
  92. package/.next/server/app/api/skills/operations/route_client-reference-manifest.js +1 -1
  93. package/.next/server/app/api/skills/reindex/route_client-reference-manifest.js +1 -1
  94. package/.next/server/app/api/skills/route.js +1 -1
  95. package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
  96. package/.next/server/app/api/slash-commands/route_client-reference-manifest.js +1 -1
  97. package/.next/server/app/api/tasks/[taskId]/cancel/route_client-reference-manifest.js +1 -1
  98. package/.next/server/app/api/tasks/[taskId]/route_client-reference-manifest.js +1 -1
  99. package/.next/server/app/api/templates/[id]/route.js +2 -2
  100. package/.next/server/app/api/templates/[id]/route_client-reference-manifest.js +1 -1
  101. package/.next/server/app/api/templates/route.js +2 -2
  102. package/.next/server/app/api/templates/route_client-reference-manifest.js +1 -1
  103. package/.next/server/app/api/verification/runs/[runId]/route_client-reference-manifest.js +1 -1
  104. package/.next/server/app/api/verification/runs/route_client-reference-manifest.js +1 -1
  105. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js +1 -1
  106. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js.nft.json +1 -1
  107. package/.next/server/app/api/worktrees/[id]/auto-yes/route_client-reference-manifest.js +1 -1
  108. package/.next/server/app/api/worktrees/[id]/capture/route.js +1 -1
  109. package/.next/server/app/api/worktrees/[id]/capture/route.js.nft.json +1 -1
  110. package/.next/server/app/api/worktrees/[id]/capture/route_client-reference-manifest.js +1 -1
  111. package/.next/server/app/api/worktrees/[id]/clear-composer/route.js +1 -1
  112. package/.next/server/app/api/worktrees/[id]/clear-composer/route.js.nft.json +1 -1
  113. package/.next/server/app/api/worktrees/[id]/clear-composer/route_client-reference-manifest.js +1 -1
  114. package/.next/server/app/api/worktrees/[id]/cli-reference/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 +3 -3
  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]/direct-input/route.js +1 -1
  124. package/.next/server/app/api/worktrees/[id]/direct-input/route.js.nft.json +1 -1
  125. package/.next/server/app/api/worktrees/[id]/direct-input/route_client-reference-manifest.js +1 -1
  126. package/.next/server/app/api/worktrees/[id]/env/route_client-reference-manifest.js +1 -1
  127. package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route_client-reference-manifest.js +1 -1
  128. package/.next/server/app/api/worktrees/[id]/execution-logs/route.js +2 -2
  129. package/.next/server/app/api/worktrees/[id]/execution-logs/route.js.nft.json +1 -1
  130. package/.next/server/app/api/worktrees/[id]/execution-logs/route_client-reference-manifest.js +1 -1
  131. package/.next/server/app/api/worktrees/[id]/files/[...path]/route.js +1 -1
  132. package/.next/server/app/api/worktrees/[id]/files/[...path]/route_client-reference-manifest.js +1 -1
  133. package/.next/server/app/api/worktrees/[id]/git/branch/create/route.js +1 -1
  134. package/.next/server/app/api/worktrees/[id]/git/branch/create/route_client-reference-manifest.js +1 -1
  135. package/.next/server/app/api/worktrees/[id]/git/branch/delete/route.js +1 -1
  136. package/.next/server/app/api/worktrees/[id]/git/branch/delete/route_client-reference-manifest.js +1 -1
  137. package/.next/server/app/api/worktrees/[id]/git/branches/route_client-reference-manifest.js +1 -1
  138. package/.next/server/app/api/worktrees/[id]/git/checkout/route.js +1 -1
  139. package/.next/server/app/api/worktrees/[id]/git/checkout/route_client-reference-manifest.js +1 -1
  140. package/.next/server/app/api/worktrees/[id]/git/commit/route.js +1 -1
  141. package/.next/server/app/api/worktrees/[id]/git/commit/route_client-reference-manifest.js +1 -1
  142. package/.next/server/app/api/worktrees/[id]/git/diff/route_client-reference-manifest.js +1 -1
  143. package/.next/server/app/api/worktrees/[id]/git/fetch/route.js +1 -1
  144. package/.next/server/app/api/worktrees/[id]/git/fetch/route_client-reference-manifest.js +1 -1
  145. package/.next/server/app/api/worktrees/[id]/git/log/route_client-reference-manifest.js +1 -1
  146. package/.next/server/app/api/worktrees/[id]/git/pull/route.js +1 -1
  147. package/.next/server/app/api/worktrees/[id]/git/pull/route_client-reference-manifest.js +1 -1
  148. package/.next/server/app/api/worktrees/[id]/git/push/route.js +1 -1
  149. package/.next/server/app/api/worktrees/[id]/git/push/route_client-reference-manifest.js +1 -1
  150. package/.next/server/app/api/worktrees/[id]/git/reset/route.js +1 -1
  151. package/.next/server/app/api/worktrees/[id]/git/reset/route_client-reference-manifest.js +1 -1
  152. package/.next/server/app/api/worktrees/[id]/git/revert/route.js +1 -1
  153. package/.next/server/app/api/worktrees/[id]/git/revert/route_client-reference-manifest.js +1 -1
  154. package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route_client-reference-manifest.js +1 -1
  155. package/.next/server/app/api/worktrees/[id]/git/stage/route.js +1 -1
  156. package/.next/server/app/api/worktrees/[id]/git/stage/route_client-reference-manifest.js +1 -1
  157. package/.next/server/app/api/worktrees/[id]/git/staged/route_client-reference-manifest.js +1 -1
  158. package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route_client-reference-manifest.js +1 -1
  159. package/.next/server/app/api/worktrees/[id]/git/stash/apply/route.js +1 -1
  160. package/.next/server/app/api/worktrees/[id]/git/stash/apply/route_client-reference-manifest.js +1 -1
  161. package/.next/server/app/api/worktrees/[id]/git/stash/pop/route.js +1 -1
  162. package/.next/server/app/api/worktrees/[id]/git/stash/pop/route_client-reference-manifest.js +1 -1
  163. package/.next/server/app/api/worktrees/[id]/git/stash/push/route.js +1 -1
  164. package/.next/server/app/api/worktrees/[id]/git/stash/push/route_client-reference-manifest.js +1 -1
  165. package/.next/server/app/api/worktrees/[id]/git/stash/route_client-reference-manifest.js +1 -1
  166. package/.next/server/app/api/worktrees/[id]/git/status/route_client-reference-manifest.js +1 -1
  167. package/.next/server/app/api/worktrees/[id]/git/unstage/route.js +1 -1
  168. package/.next/server/app/api/worktrees/[id]/git/unstage/route_client-reference-manifest.js +1 -1
  169. package/.next/server/app/api/worktrees/[id]/git/working-diff/route_client-reference-manifest.js +1 -1
  170. package/.next/server/app/api/worktrees/[id]/instances/notes/route.js +1 -1
  171. package/.next/server/app/api/worktrees/[id]/instances/notes/route_client-reference-manifest.js +1 -1
  172. package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js +1 -1
  173. package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js.nft.json +1 -1
  174. package/.next/server/app/api/worktrees/[id]/instances/opencode/route_client-reference-manifest.js +1 -1
  175. package/.next/server/app/api/worktrees/[id]/interrupt/route.js +1 -1
  176. package/.next/server/app/api/worktrees/[id]/interrupt/route.js.nft.json +1 -1
  177. package/.next/server/app/api/worktrees/[id]/interrupt/route_client-reference-manifest.js +1 -1
  178. package/.next/server/app/api/worktrees/[id]/kill-session/route.js +1 -1
  179. package/.next/server/app/api/worktrees/[id]/kill-session/route.js.nft.json +1 -1
  180. package/.next/server/app/api/worktrees/[id]/kill-session/route_client-reference-manifest.js +1 -1
  181. package/.next/server/app/api/worktrees/[id]/logs/[filename]/route_client-reference-manifest.js +1 -1
  182. package/.next/server/app/api/worktrees/[id]/logs/route_client-reference-manifest.js +1 -1
  183. package/.next/server/app/api/worktrees/[id]/marp-render/route.js +3 -3
  184. package/.next/server/app/api/worktrees/[id]/marp-render/route_client-reference-manifest.js +1 -1
  185. package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route.js +1 -1
  186. package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route_client-reference-manifest.js +1 -1
  187. package/.next/server/app/api/worktrees/[id]/memos/route.js +1 -1
  188. package/.next/server/app/api/worktrees/[id]/memos/route_client-reference-manifest.js +1 -1
  189. package/.next/server/app/api/worktrees/[id]/messages/route_client-reference-manifest.js +1 -1
  190. package/.next/server/app/api/worktrees/[id]/opencode/diff/route.js +1 -1
  191. package/.next/server/app/api/worktrees/[id]/opencode/diff/route_client-reference-manifest.js +1 -1
  192. package/.next/server/app/api/worktrees/[id]/opencode/session/route.js +1 -1
  193. package/.next/server/app/api/worktrees/[id]/opencode/session/route.js.nft.json +1 -1
  194. package/.next/server/app/api/worktrees/[id]/opencode/session/route_client-reference-manifest.js +1 -1
  195. package/.next/server/app/api/worktrees/[id]/opencode/share/route.js +1 -1
  196. package/.next/server/app/api/worktrees/[id]/opencode/share/route.js.nft.json +1 -1
  197. package/.next/server/app/api/worktrees/[id]/opencode/share/route_client-reference-manifest.js +1 -1
  198. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js +1 -1
  199. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js.nft.json +1 -1
  200. package/.next/server/app/api/worktrees/[id]/prompt-response/route_client-reference-manifest.js +1 -1
  201. package/.next/server/app/api/worktrees/[id]/resolve-target/route_client-reference-manifest.js +1 -1
  202. package/.next/server/app/api/worktrees/[id]/respond/route.js +1 -1
  203. package/.next/server/app/api/worktrees/[id]/respond/route.js.nft.json +1 -1
  204. package/.next/server/app/api/worktrees/[id]/respond/route_client-reference-manifest.js +1 -1
  205. package/.next/server/app/api/worktrees/[id]/route.js +1 -1
  206. package/.next/server/app/api/worktrees/[id]/route.js.nft.json +1 -1
  207. package/.next/server/app/api/worktrees/[id]/route_client-reference-manifest.js +1 -1
  208. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route.js +2 -2
  209. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route.js.nft.json +1 -1
  210. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route_client-reference-manifest.js +1 -1
  211. package/.next/server/app/api/worktrees/[id]/schedules/active/route.js +2 -2
  212. package/.next/server/app/api/worktrees/[id]/schedules/active/route.js.nft.json +1 -1
  213. package/.next/server/app/api/worktrees/[id]/schedules/active/route_client-reference-manifest.js +1 -1
  214. package/.next/server/app/api/worktrees/[id]/schedules/route.js +3 -3
  215. package/.next/server/app/api/worktrees/[id]/schedules/route.js.nft.json +1 -1
  216. package/.next/server/app/api/worktrees/[id]/schedules/route_client-reference-manifest.js +1 -1
  217. package/.next/server/app/api/worktrees/[id]/search/route_client-reference-manifest.js +1 -1
  218. package/.next/server/app/api/worktrees/[id]/send/route.js +1 -1
  219. package/.next/server/app/api/worktrees/[id]/send/route.js.nft.json +1 -1
  220. package/.next/server/app/api/worktrees/[id]/send/route_client-reference-manifest.js +1 -1
  221. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js +2 -2
  222. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js.nft.json +1 -1
  223. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route_client-reference-manifest.js +1 -1
  224. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route_client-reference-manifest.js +1 -1
  225. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route.js +1 -1
  226. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route_client-reference-manifest.js +1 -1
  227. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route_client-reference-manifest.js +1 -1
  228. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route_client-reference-manifest.js +1 -1
  229. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update/route_client-reference-manifest.js +1 -1
  230. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route.js +1 -1
  231. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route_client-reference-manifest.js +1 -1
  232. package/.next/server/app/api/worktrees/[id]/skills/route_client-reference-manifest.js +1 -1
  233. package/.next/server/app/api/worktrees/[id]/slash-commands/route.js +1 -1
  234. package/.next/server/app/api/worktrees/[id]/slash-commands/route_client-reference-manifest.js +1 -1
  235. package/.next/server/app/api/worktrees/[id]/special-keys/route.js +1 -1
  236. package/.next/server/app/api/worktrees/[id]/special-keys/route.js.nft.json +1 -1
  237. package/.next/server/app/api/worktrees/[id]/special-keys/route_client-reference-manifest.js +1 -1
  238. package/.next/server/app/api/worktrees/[id]/tasks/route.js +1 -1
  239. package/.next/server/app/api/worktrees/[id]/tasks/route_client-reference-manifest.js +1 -1
  240. package/.next/server/app/api/worktrees/[id]/terminal/route.js +2 -2
  241. package/.next/server/app/api/worktrees/[id]/terminal/route.js.nft.json +1 -1
  242. package/.next/server/app/api/worktrees/[id]/terminal/route_client-reference-manifest.js +1 -1
  243. package/.next/server/app/api/worktrees/[id]/timers/history/route_client-reference-manifest.js +1 -1
  244. package/.next/server/app/api/worktrees/[id]/timers/route.js +1 -1
  245. package/.next/server/app/api/worktrees/[id]/timers/route.js.nft.json +1 -1
  246. package/.next/server/app/api/worktrees/[id]/timers/route_client-reference-manifest.js +1 -1
  247. package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route.js +1 -1
  248. package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
  249. package/.next/server/app/api/worktrees/[id]/todos/route.js +1 -1
  250. package/.next/server/app/api/worktrees/[id]/todos/route_client-reference-manifest.js +1 -1
  251. package/.next/server/app/api/worktrees/[id]/tree/[...path]/route_client-reference-manifest.js +1 -1
  252. package/.next/server/app/api/worktrees/[id]/tree/route_client-reference-manifest.js +1 -1
  253. package/.next/server/app/api/worktrees/[id]/upload/[...path]/route_client-reference-manifest.js +1 -1
  254. package/.next/server/app/api/worktrees/[id]/verify/config/route.js +1 -1
  255. package/.next/server/app/api/worktrees/[id]/verify/config/route_client-reference-manifest.js +1 -1
  256. package/.next/server/app/api/worktrees/[id]/verify/route.js +1 -1
  257. package/.next/server/app/api/worktrees/[id]/verify/route_client-reference-manifest.js +1 -1
  258. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route.js +1 -1
  259. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route_client-reference-manifest.js +1 -1
  260. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route_client-reference-manifest.js +1 -1
  261. package/.next/server/app/api/worktrees/[id]/verify/runs/route_client-reference-manifest.js +1 -1
  262. package/.next/server/app/api/worktrees/[id]/viewed/route_client-reference-manifest.js +1 -1
  263. package/.next/server/app/api/worktrees/apply-default-agents/route_client-reference-manifest.js +1 -1
  264. package/.next/server/app/api/worktrees/route.js +1 -1
  265. package/.next/server/app/api/worktrees/route.js.nft.json +1 -1
  266. package/.next/server/app/api/worktrees/route_client-reference-manifest.js +1 -1
  267. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  268. package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
  269. package/.next/server/app/more/page_client-reference-manifest.js +1 -1
  270. package/.next/server/app/offline/page_client-reference-manifest.js +1 -1
  271. package/.next/server/app/page_client-reference-manifest.js +1 -1
  272. package/.next/server/app/proxy/[...path]/route_client-reference-manifest.js +1 -1
  273. package/.next/server/app/repositories/page_client-reference-manifest.js +1 -1
  274. package/.next/server/app/review/page_client-reference-manifest.js +1 -1
  275. package/.next/server/app/sessions/page.js +1 -1
  276. package/.next/server/app/sessions/page.js.nft.json +1 -1
  277. package/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  278. package/.next/server/app/skills/[skillId]/page_client-reference-manifest.js +1 -1
  279. package/.next/server/app/skills/installed/page_client-reference-manifest.js +1 -1
  280. package/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  281. package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -1
  282. package/.next/server/app/worktrees/[id]/page.js +11 -11
  283. package/.next/server/app/worktrees/[id]/page.js.nft.json +1 -1
  284. package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -1
  285. package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
  286. package/.next/server/app-paths-manifest.json +20 -20
  287. package/.next/server/chunks/1191.js +2 -2
  288. package/.next/server/chunks/1210.js +1 -1
  289. package/.next/server/chunks/1503.js +2 -2
  290. package/.next/server/chunks/1559.js +2 -0
  291. package/.next/server/chunks/1789.js +1 -0
  292. package/.next/server/chunks/1944.js +1 -1
  293. package/.next/server/chunks/2119.js +1 -1
  294. package/.next/server/chunks/22.js +1 -1
  295. package/.next/server/chunks/2404.js +1 -1
  296. package/.next/server/chunks/2445.js +1 -1
  297. package/.next/server/chunks/2460.js +1 -1
  298. package/.next/server/chunks/2710.js +2 -2
  299. package/.next/server/chunks/2908.js +1 -1
  300. package/.next/server/chunks/2980.js +1 -1
  301. package/.next/server/chunks/3241.js +1 -1
  302. package/.next/server/chunks/3480.js +1 -1
  303. package/.next/server/chunks/3718.js +1 -1
  304. package/.next/server/chunks/4207.js +2 -2
  305. package/.next/server/chunks/450.js +1 -1
  306. package/.next/server/chunks/{9353.js → 4718.js} +2 -2
  307. package/.next/server/chunks/4802.js +1 -1
  308. package/.next/server/chunks/4837.js +14 -0
  309. package/.next/server/chunks/5048.js +1 -1
  310. package/.next/server/chunks/5064.js +1 -1
  311. package/.next/server/chunks/5209.js +1 -0
  312. package/.next/server/chunks/5292.js +7 -0
  313. package/.next/server/chunks/5595.js +1 -1
  314. package/.next/server/chunks/5625.js +25 -0
  315. package/.next/server/chunks/5737.js +1 -1
  316. package/.next/server/chunks/6065.js +1 -1
  317. package/.next/server/chunks/611.js +1 -1
  318. package/.next/server/chunks/6130.js +1 -1
  319. package/.next/server/chunks/6401.js +1 -1
  320. package/.next/server/chunks/6781.js +1 -1
  321. package/.next/server/chunks/6793.js +3 -3
  322. package/.next/server/chunks/7491.js +2 -2
  323. package/.next/server/chunks/7905.js +1 -1
  324. package/.next/server/chunks/850.js +1 -1
  325. package/.next/server/chunks/8728.js +3 -3
  326. package/.next/server/chunks/8791.js +1 -1
  327. package/.next/server/chunks/8800.js +1 -1
  328. package/.next/server/chunks/8918.js +6 -8
  329. package/.next/server/chunks/9051.js +1 -1
  330. package/.next/server/chunks/9130.js +1 -1
  331. package/.next/server/chunks/9390.js +2 -2
  332. package/.next/server/chunks/9584.js +1 -1
  333. package/.next/server/chunks/9627.js +6 -6
  334. package/.next/server/chunks/9731.js +3 -3
  335. package/.next/server/middleware-build-manifest.js +1 -1
  336. package/.next/server/middleware-manifest.json +5 -5
  337. package/.next/server/middleware-react-loadable-manifest.js +1 -1
  338. package/.next/server/pages/500.html +1 -1
  339. package/.next/server/server-reference-manifest.json +1 -1
  340. package/.next/static/chunks/1464.09cd37fee202ec4b.js +1 -0
  341. package/.next/static/chunks/{1642-fb2e176aaadbd137.js → 1642-767aed8e7c61ef7f.js} +1 -1
  342. package/.next/static/chunks/2053-390e77fce43b555c.js +1 -0
  343. package/.next/static/chunks/{2407-051f6f84226a9f2c.js → 2407-dd4a0f04f1349221.js} +1 -1
  344. package/.next/static/chunks/{2619-04bc32f026a0d946.js → 2619-a305ad4810f1393a.js} +1 -1
  345. package/.next/static/chunks/{2751-9ef0f4b450bd4ef0.js → 2751-5f0b2702accd164d.js} +1 -1
  346. package/.next/static/chunks/{282.6b6f2e31a96674dd.js → 282.a1013532fd9a61b4.js} +1 -1
  347. package/.next/static/chunks/3237.94c29281d9ec122e.js +1 -0
  348. package/.next/static/chunks/3480.2e21f62e5e9d3ba5.js +1 -0
  349. package/.next/static/chunks/4290.c06dbe243819fea0.js +66 -0
  350. package/.next/static/chunks/4727-5d695d71e3fdf97b.js +1 -0
  351. package/.next/static/chunks/{5222.305dc0ebba9c0784.js → 5222.39e2034d3fce233c.js} +1 -1
  352. package/.next/static/chunks/{7095.8c869e553133a40e.js → 7095.87323a4fdf426341.js} +1 -1
  353. package/.next/static/chunks/{7485.442b21101fca7257.js → 7485.8a2a9d7c5396aa26.js} +3 -3
  354. package/.next/static/chunks/{8165-3853772f6ae1299b.js → 8165-3525fb42f1b4976e.js} +1 -1
  355. package/.next/static/chunks/app/{layout-9da1ab602bcb3051.js → layout-07d040cb3d3ea657.js} +1 -1
  356. package/.next/static/chunks/app/sessions/page-2af68c63211c751f.js +1 -0
  357. package/.next/static/chunks/app/worktrees/[id]/page-35f0e31a725d1c89.js +1 -0
  358. package/.next/static/chunks/app/worktrees/[id]/terminal/{page-373ea37b16d930c7.js → page-c601f3b3ece6557e.js} +1 -1
  359. package/.next/static/chunks/{webpack-021f0741f22dd16a.js → webpack-165d8df9acd1c5d4.js} +1 -1
  360. package/.next/static/css/057f64a65726c439.css +1 -0
  361. package/.next/trace +13 -13
  362. package/dist/cli/commands/ask.d.ts.map +1 -1
  363. package/dist/cli/commands/ask.js +120 -119
  364. package/dist/cli/commands/attach.d.ts +94 -0
  365. package/dist/cli/commands/attach.d.ts.map +1 -1
  366. package/dist/cli/commands/attach.js +145 -7
  367. package/dist/cli/commands/auto-yes.js +1 -1
  368. package/dist/cli/commands/capture.d.ts.map +1 -1
  369. package/dist/cli/commands/capture.js +3 -5
  370. package/dist/cli/commands/command-target.d.ts +23 -0
  371. package/dist/cli/commands/command-target.d.ts.map +1 -0
  372. package/dist/cli/commands/command-target.js +25 -0
  373. package/dist/cli/commands/instances.d.ts.map +1 -1
  374. package/dist/cli/commands/instances.js +41 -2
  375. package/dist/cli/commands/message-dispatch.d.ts +36 -0
  376. package/dist/cli/commands/message-dispatch.d.ts.map +1 -0
  377. package/dist/cli/commands/message-dispatch.js +63 -0
  378. package/dist/cli/commands/reply.d.ts.map +1 -1
  379. package/dist/cli/commands/reply.js +2 -5
  380. package/dist/cli/commands/respond.d.ts.map +1 -1
  381. package/dist/cli/commands/respond.js +3 -6
  382. package/dist/cli/commands/send.d.ts.map +1 -1
  383. package/dist/cli/commands/send.js +149 -146
  384. package/dist/cli/commands/skill-format.d.ts +8 -0
  385. package/dist/cli/commands/skill-format.d.ts.map +1 -1
  386. package/dist/cli/commands/skill-format.js +13 -3
  387. package/dist/cli/commands/wait.d.ts.map +1 -1
  388. package/dist/cli/commands/wait.js +657 -431
  389. package/dist/cli/types/api-responses.d.ts +156 -27
  390. package/dist/cli/types/api-responses.d.ts.map +1 -1
  391. package/dist/cli/types/api-responses.js +4 -2
  392. package/dist/cli/utils/api-client.d.ts +25 -5
  393. package/dist/cli/utils/api-client.d.ts.map +1 -1
  394. package/dist/cli/utils/api-client.js +87 -55
  395. package/dist/cli/utils/server-url.d.ts +1 -0
  396. package/dist/cli/utils/server-url.d.ts.map +1 -1
  397. package/dist/cli/utils/server-url.js +7 -0
  398. package/dist/cli/utils/verify-runner.d.ts +21 -0
  399. package/dist/cli/utils/verify-runner.d.ts.map +1 -1
  400. package/dist/cli/utils/verify-runner.js +38 -1
  401. package/dist/config/uat-isolation.d.ts +140 -0
  402. package/dist/config/uat-isolation.d.ts.map +1 -0
  403. package/dist/config/uat-isolation.js +246 -0
  404. package/dist/lib/global-state.d.ts +12 -0
  405. package/dist/lib/global-state.d.ts.map +1 -0
  406. package/dist/lib/global-state.js +16 -0
  407. package/dist/lib/polling/auto-yes-suppression-reason.d.ts +33 -0
  408. package/dist/lib/polling/auto-yes-suppression-reason.d.ts.map +1 -0
  409. package/dist/lib/polling/auto-yes-suppression-reason.js +2 -0
  410. package/dist/lib/session/prompt-view.d.ts +26 -3
  411. package/dist/lib/session/prompt-view.d.ts.map +1 -1
  412. package/dist/lib/session/prompt-view.js +26 -3
  413. package/dist/lib/session/status-evidence-type.d.ts +16 -0
  414. package/dist/lib/session/status-evidence-type.d.ts.map +1 -0
  415. package/dist/lib/session/status-evidence-type.js +2 -0
  416. package/dist/lib/tmux/legacy-session-alias.d.ts.map +1 -1
  417. package/dist/lib/tmux/legacy-session-alias.js +2 -1
  418. package/dist/server/locales/en/worktree.json +8 -2
  419. package/dist/server/locales/ja/worktree.json +8 -2
  420. package/dist/server/src/cli/types/api-responses.js +4 -2
  421. package/dist/server/src/config/cli-tool-timing-config.js +1 -6
  422. package/dist/server/src/config/uat-isolation.js +246 -0
  423. package/dist/server/src/lib/assistant-response-saver.js +62 -3
  424. package/dist/server/src/lib/auto-yes-lifecycle.js +6 -0
  425. package/dist/server/src/lib/auto-yes-poller.js +450 -160
  426. package/dist/server/src/lib/auto-yes-state.js +2 -2
  427. package/dist/server/src/lib/cli-tools/antigravity.js +38 -79
  428. package/dist/server/src/lib/cli-tools/base.js +151 -0
  429. package/dist/server/src/lib/cli-tools/codex.js +44 -80
  430. package/dist/server/src/lib/cli-tools/command-code.js +24 -56
  431. package/dist/server/src/lib/cli-tools/copilot.js +25 -67
  432. package/dist/server/src/lib/cli-tools/direct-input.js +8 -0
  433. package/dist/server/src/lib/cli-tools/gemini.js +23 -73
  434. package/dist/server/src/lib/cli-tools/opencode-pane-width.js +53 -0
  435. package/dist/server/src/lib/cli-tools/opencode-v2.js +9 -7
  436. package/dist/server/src/lib/cli-tools/opencode.js +21 -85
  437. package/dist/server/src/lib/cli-tools/submit-verified-sender.js +127 -4
  438. package/dist/server/src/lib/cli-tools/vibe-local.js +21 -66
  439. package/dist/server/src/lib/detection/cli-patterns.js +374 -3065
  440. package/dist/server/src/lib/detection/idle-evidence-observation.js +2 -2
  441. package/dist/server/src/lib/detection/model-info-extractor.js +57 -3
  442. package/dist/server/src/lib/detection/prompt-detect-multiple-choice.js +7 -32
  443. package/dist/server/src/lib/detection/prompt-detector.js +2 -35
  444. package/dist/server/src/lib/detection/selection-shape-patterns.js +69 -0
  445. package/dist/server/src/lib/detection/selection-shape.js +32 -520
  446. package/dist/server/src/lib/detection/shared/pasted-text.js +41 -0
  447. package/dist/server/src/lib/detection/shared/shell-pane-command.js +16 -0
  448. package/dist/server/src/lib/detection/shared/strip-box-drawing.js +25 -0
  449. package/dist/server/src/lib/detection/status-detector.js +1 -1
  450. package/dist/server/src/lib/detection/tools/antigravity/detect.js +5 -29
  451. package/dist/server/src/lib/detection/tools/antigravity/dialog.js +2 -15
  452. package/dist/server/src/lib/detection/tools/antigravity/patterns.js +286 -0
  453. package/dist/server/src/lib/detection/tools/claude/detect.js +3 -14
  454. package/dist/server/src/lib/detection/tools/claude/patterns.js +264 -4
  455. package/dist/server/src/lib/detection/tools/claude/prompt.js +2 -10
  456. package/dist/server/src/lib/detection/tools/codex/detect.js +46 -85
  457. package/dist/server/src/lib/detection/tools/codex/live-region.js +33 -2
  458. package/dist/server/src/lib/detection/tools/codex/patterns.js +855 -0
  459. package/dist/server/src/lib/detection/tools/codex/prompt.js +2 -10
  460. package/dist/server/src/lib/detection/tools/command-code/detect.js +8 -50
  461. package/dist/server/src/lib/detection/tools/command-code/dialog.js +2 -18
  462. package/dist/server/src/lib/detection/tools/command-code/patterns.js +234 -0
  463. package/dist/server/src/lib/detection/tools/command-code/selection-shape.js +461 -0
  464. package/dist/server/src/lib/detection/tools/context-above.js +20 -0
  465. package/dist/server/src/lib/detection/tools/copilot/detect.js +10 -35
  466. package/dist/server/src/lib/detection/tools/copilot/patterns.js +640 -0
  467. package/dist/server/src/lib/detection/tools/copilot/prompt.js +2 -10
  468. package/dist/server/src/lib/detection/tools/gemini/patterns.js +29 -0
  469. package/dist/server/src/lib/detection/tools/live-region-specs.js +1 -1
  470. package/dist/server/src/lib/detection/tools/opencode/detect.js +8 -49
  471. package/dist/server/src/lib/detection/tools/opencode/patterns.js +508 -0
  472. package/dist/server/src/lib/detection/tools/opencode-v2/detect.js +7 -42
  473. package/dist/server/src/lib/detection/tools/opencode-v2/patterns.js +63 -0
  474. package/dist/server/src/lib/detection/tools/run-detection.js +6 -47
  475. package/dist/server/src/lib/detection/tools/verdicts.js +59 -0
  476. package/dist/server/src/lib/detection/tools/vibe-local/patterns.js +20 -0
  477. package/dist/server/src/lib/detection/truncate-raw-content.js +38 -0
  478. package/dist/server/src/lib/detection/turn-abandoned.js +66 -0
  479. package/dist/server/src/lib/detection/unclassified-frame-tracker.js +2 -2
  480. package/dist/server/src/lib/git/git-exec.js +23 -5
  481. package/dist/server/src/lib/global-state.js +16 -0
  482. package/dist/server/src/lib/hooks/agent-session-telemetry.js +4 -6
  483. package/dist/server/src/lib/hooks/permission-decision-state.js +2 -2
  484. package/dist/server/src/lib/hooks/sources/antigravity/history.js +11 -76
  485. package/dist/server/src/lib/hooks/sources/antigravity/hooks-config.js +63 -1
  486. package/dist/server/src/lib/hooks/sources/antigravity/source.js +16 -0
  487. package/dist/server/src/lib/hooks/sources/antigravity/transcript.js +3 -12
  488. package/dist/server/src/lib/hooks/sources/claude/history.js +17 -156
  489. package/dist/server/src/lib/hooks/sources/claude/queued-notice.js +53 -0
  490. package/dist/server/src/lib/hooks/sources/claude/self-resume.js +213 -0
  491. package/dist/server/src/lib/hooks/sources/claude/source.js +57 -10
  492. package/dist/server/src/lib/hooks/sources/claude/transcript.js +3 -13
  493. package/dist/server/src/lib/hooks/sources/codex/history.js +11 -74
  494. package/dist/server/src/lib/hooks/sources/codex/hooks-config.js +147 -11
  495. package/dist/server/src/lib/hooks/sources/codex/relay-install.js +64 -21
  496. package/dist/server/src/lib/hooks/sources/codex/transcript.js +5 -15
  497. package/dist/server/src/lib/hooks/sources/command-code/history.js +20 -121
  498. package/dist/server/src/lib/hooks/sources/command-code/transcript.js +3 -13
  499. package/dist/server/src/lib/hooks/sources/copilot/hook-settings.js +161 -31
  500. package/dist/server/src/lib/hooks/sources/define-source.js +40 -55
  501. package/dist/server/src/lib/hooks/sources/event-mapper.js +2 -1
  502. package/dist/server/src/lib/hooks/sources/opencode/diff.js +3 -4
  503. package/dist/server/src/lib/hooks/sources/opencode/history.js +2 -1
  504. package/dist/server/src/lib/hooks/sources/opencode/launch-settings.js +2 -1
  505. package/dist/server/src/lib/hooks/sources/opencode/payloads.js +2 -1
  506. package/dist/server/src/lib/hooks/sources/opencode/ports.js +2 -1
  507. package/dist/server/src/lib/hooks/sources/opencode/subscription.js +4 -3
  508. package/dist/server/src/lib/hooks/sources/opencode/transcript.js +3 -16
  509. package/dist/server/src/lib/hooks/sources/opencode-v2/history.js +2 -1
  510. package/dist/server/src/lib/hooks/sources/opencode-v2/mappers.js +5 -4
  511. package/dist/server/src/lib/hooks/sources/opencode-v2/ports.js +2 -1
  512. package/dist/server/src/lib/hooks/sources/opencode-v2/subscription.js +3 -7
  513. package/dist/server/src/lib/hooks/sources/opencode-v2/usage.js +2 -1
  514. package/dist/server/src/lib/hooks/sources/pending-decisions.js +2 -1
  515. package/dist/server/src/lib/hooks/sources/registry.js +3 -2
  516. package/dist/server/src/lib/hooks/sources/transcript-history.js +262 -0
  517. package/dist/server/src/lib/hooks/sources/turn-body.js +31 -0
  518. package/dist/server/src/lib/hooks/tool-input-normalization-state.js +2 -2
  519. package/dist/server/src/lib/polling/antigravity-permission-receipts.js +2 -2
  520. package/dist/server/src/lib/polling/auto-yes-enter-fallback-state.js +142 -0
  521. package/dist/server/src/lib/polling/auto-yes-enter-fallback.js +187 -0
  522. package/dist/server/src/lib/polling/auto-yes-resolver.js +9 -3
  523. package/dist/server/src/lib/polling/auto-yes-suppression-reason.js +2 -0
  524. package/dist/server/src/lib/polling/auto-yes-suppression-state.js +2 -2
  525. package/dist/server/src/lib/polling/pending-scraped-response.js +190 -0
  526. package/dist/server/src/lib/polling/prompt-dedup-state.js +2 -2
  527. package/dist/server/src/lib/polling/prompt-dedup.js +2 -2
  528. package/dist/server/src/lib/polling/response-checker-dialog-gate.js +95 -0
  529. package/dist/server/src/lib/polling/response-checker-extraction-result.js +50 -0
  530. package/dist/server/src/lib/polling/response-checker-extraction-steps.js +670 -0
  531. package/dist/server/src/lib/polling/response-checker.js +641 -1142
  532. package/dist/server/src/lib/polling/response-dedup.js +3 -4
  533. package/dist/server/src/lib/polling/response-poller-constants.js +17 -0
  534. package/dist/server/src/lib/polling/response-poller-core.js +54 -20
  535. package/dist/server/src/lib/polling/startup-screen.js +142 -0
  536. package/dist/server/src/lib/polling/structured-history-gate.js +3 -2
  537. package/dist/server/src/lib/prompt-answer-semantic.js +178 -0
  538. package/dist/server/src/lib/prompt-answer-sender.js +5 -4
  539. package/dist/server/src/lib/push/failure-episode-state.js +2 -2
  540. package/dist/server/src/lib/push/notification-dedup.js +3 -4
  541. package/dist/server/src/lib/push/prompt-card-state.js +2 -2
  542. package/dist/server/src/lib/push/waiting-push-notifier.js +3 -4
  543. package/dist/server/src/lib/realtime/publisher-registry.js +3 -2
  544. package/dist/server/src/lib/realtime/terminal-broadcast.js +38 -5
  545. package/dist/server/src/lib/realtime/terminal-session-ownership.js +45 -0
  546. package/dist/server/src/lib/relay/relay-delivery.js +3 -2
  547. package/dist/server/src/lib/relay/relay-readiness.js +38 -1
  548. package/dist/server/src/lib/response-cleaner.js +24 -1
  549. package/dist/server/src/lib/response-extractor.js +16 -0
  550. package/dist/server/src/lib/schedule-manager.js +8 -10
  551. package/dist/server/src/lib/session/agent-event-ask-user-question.js +168 -0
  552. package/dist/server/src/lib/session/agent-event-awaiting-instruction.js +104 -0
  553. package/dist/server/src/lib/session/agent-event-dedup.js +539 -0
  554. package/dist/server/src/lib/session/agent-event-model.js +562 -0
  555. package/dist/server/src/lib/session/agent-event-record.js +10 -0
  556. package/dist/server/src/lib/session/agent-event-state.js +107 -1854
  557. package/dist/server/src/lib/session/agent-event-structured-state.js +109 -0
  558. package/dist/server/src/lib/session/agent-event-turn.js +862 -0
  559. package/dist/server/src/lib/session/agent-session-lifecycle.js +11 -2
  560. package/dist/server/src/lib/session/chat-turn-progress.js +322 -0
  561. package/dist/server/src/lib/session/claude-executor.js +45 -5
  562. package/dist/server/src/lib/session/claude-session.js +21 -65
  563. package/dist/server/src/lib/session/cli-session.js +17 -0
  564. package/dist/server/src/lib/session/current-output-builder.js +449 -1107
  565. package/dist/server/src/lib/session/current-output-history-writers.js +255 -0
  566. package/dist/server/src/lib/session/current-output-types.js +9 -0
  567. package/dist/server/src/lib/session/detection-divergence.js +55 -0
  568. package/dist/server/src/lib/session/global-session-constants.js +2 -13
  569. package/dist/server/src/lib/session/hook-turn-hold.js +102 -0
  570. package/dist/server/src/lib/session/layer-disagreement.js +2 -2
  571. package/dist/server/src/lib/session/opencode-session-store.js +2 -1
  572. package/dist/server/src/lib/session/prompt-view.js +26 -3
  573. package/dist/server/src/lib/session/prompt-waiting-composition.js +3 -2
  574. package/dist/server/src/lib/session/provisional-turn.js +3 -1
  575. package/dist/server/src/lib/session/send-user-message.js +1 -1
  576. package/dist/server/src/lib/session/session-starting-state.js +4 -6
  577. package/dist/server/src/lib/session/status-evidence-type.js +2 -0
  578. package/dist/server/src/lib/session/status-evidence.js +2 -2
  579. package/dist/server/src/lib/session/structured-status-merge.js +335 -0
  580. package/dist/server/src/lib/session/waiting-episode-state.js +3 -4
  581. package/dist/server/src/lib/session-cleanup.js +1 -5
  582. package/dist/server/src/lib/skills/install-plan.js +3 -1
  583. package/dist/server/src/lib/skills/preview-diff.js +24 -3
  584. package/dist/server/src/lib/skills/snapshot-store.js +2 -2
  585. package/dist/server/src/lib/skills/uninstall-plan.js +3 -2
  586. package/dist/server/src/lib/timer-manager.js +6 -8
  587. package/dist/server/src/lib/tmux/geometry-delegation.js +3 -4
  588. package/dist/server/src/lib/tmux/legacy-session-alias.js +2 -1
  589. package/dist/server/src/lib/tmux/session-hooks.js +2 -1
  590. package/dist/server/src/lib/tmux/session-status-options.js +3 -3
  591. package/dist/server/src/lib/tmux/tmux-capture-cache.js +3 -2
  592. package/dist/server/src/lib/tmux/tmux.js +33 -59
  593. package/dist/server/src/lib/tui-accumulator.js +2 -2
  594. package/dist/server/src/lib/verification/env-clean-gate.js +6 -5
  595. package/dist/server/src/lib/version-checker.js +6 -6
  596. package/dist/server/src/lib/ws-server.js +47 -11
  597. package/docs/en/user-guide/commands-guide.md +0 -1
  598. package/docs/en/user-guide/webapp-guide.md +27 -3
  599. package/package.json +3 -2
  600. package/release-notes/0.44.3.json +82 -0
  601. package/release-notes/0.45.0.json +41 -0
  602. package/scripts/hooks/cmate-agent-event.sh +38 -0
  603. package/.next/server/chunks/1068.js +0 -1
  604. package/.next/server/chunks/4372.js +0 -5
  605. package/.next/server/chunks/6474.js +0 -14
  606. package/.next/server/chunks/967.js +0 -1
  607. package/.next/server/chunks/9798.js +0 -2
  608. package/.next/server/chunks/9882.js +0 -25
  609. package/.next/static/chunks/2053-85a974ddfe7498fe.js +0 -1
  610. package/.next/static/chunks/4290.6cf86f68d73b6e77.js +0 -82
  611. package/.next/static/chunks/4459.a94b52985a76509a.js +0 -1
  612. package/.next/static/chunks/591-539fec878c9dec5e.js +0 -1
  613. package/.next/static/chunks/5951.616956b6aa5df63f.js +0 -1
  614. package/.next/static/chunks/9856.15463dd58437e2ac.js +0 -1
  615. package/.next/static/chunks/app/sessions/page-049e06335187aa91.js +0 -1
  616. package/.next/static/chunks/app/worktrees/[id]/page-2a81397e60f17e63.js +0 -1
  617. package/.next/static/css/38070d879efa1371.css +0 -1
  618. package/dist/server/src/lib/cli-tools/index.js +0 -41
  619. package/dist/server/src/lib/polling/global-session-poller.js +0 -140
  620. /package/.next/static/{QlCqLjorauDDBXPa-C7TK → TPWbZB3zBp3Zv_eFEOlmt}/_buildManifest.js +0 -0
  621. /package/.next/static/{QlCqLjorauDDBXPa-C7TK → TPWbZB3zBp3Zv_eFEOlmt}/_ssgManifest.js +0 -0
@@ -0,0 +1,862 @@
1
+ "use strict";
2
+ /**
3
+ * The turn model (Issue #1930): the generation fence, the turn record each
4
+ * instance is in, its transitions, and the decisions (dialogs) it holds.
5
+ *
6
+ * Split out of `agent-event-state` (Issue #3375), which re-exports the public
7
+ * names and drives the transitions from `recordAgentEvent`.
8
+ *
9
+ * @module lib/session/agent-event-turn
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.reopenedTurns = exports.agentTurns = exports.generationStartedAt = void 0;
13
+ exports.currentGeneration = currentGeneration;
14
+ exports.effectiveTurn = effectiveTurn;
15
+ exports.livePendingDecisions = livePendingDecisions;
16
+ exports.getPendingDecisions = getPendingDecisions;
17
+ exports.getAgentTurn = getAgentTurn;
18
+ exports.getPublishedAgentTurn = getPublishedAgentTurn;
19
+ exports.closeAgentTurn = closeAgentTurn;
20
+ exports.observeScraperCompletionEvidence = observeScraperCompletionEvidence;
21
+ exports.fenceTurnForNewGeneration = fenceTurnForNewGeneration;
22
+ exports.applyTurnTransition = applyTurnTransition;
23
+ exports.isPreToolUseOutsideTurn = isPreToolUseOutsideTurn;
24
+ exports.joinOpenTurnFromDuplicate = joinOpenTurnFromDuplicate;
25
+ exports.openDecision = openDecision;
26
+ exports.releaseAllDecisions = releaseAllDecisions;
27
+ const auto_yes_state_1 = require("../../lib/auto-yes-state");
28
+ const agent_event_types_1 = require("../../lib/hooks/agent-event-types");
29
+ // Issue #1930: the turn model. Pure, so importing it here costs nothing at
30
+ // runtime beyond the two bounds it owns.
31
+ const provisional_turn_1 = require("../../lib/session/provisional-turn");
32
+ const agent_event_dedup_1 = require("../../lib/session/agent-event-dedup");
33
+ const global_state_1 = require("../global-state");
34
+ /** compositeKey -> epoch ms the current generation began. See {@link beginAgentEventGeneration}. */
35
+ exports.generationStartedAt = (0, global_state_1.getOrInitGlobal)('__agentEventGenerationStartedAt', () => new Map());
36
+ /**
37
+ * compositeKey -> the turn this instance is in, or the last one it was in
38
+ * (Issue #1930).
39
+ *
40
+ * The map that replaced "the newest event is the verdict". `lastAgentEvent`
41
+ * above is still written on every delivery and is still what
42
+ * `structuredEvents.lastEventType` publishes — it answers "did anything reach
43
+ * this server, and for the right instance?", which is a diagnostic question.
44
+ * This map answers the state question, and the two deliberately disagree
45
+ * whenever an event carries no verdict.
46
+ *
47
+ * The open dialogs #1725 kept in a map of their own live on the turn now
48
+ * ({@link TurnRecord.pendingDecisions}), because a dialog only ever happens
49
+ * *inside* a turn and holding them apart is what let a generation bump retire
50
+ * one and not the other.
51
+ */
52
+ exports.agentTurns = (0, global_state_1.getOrInitGlobal)('__agentEventTurns', () => new Map());
53
+ /**
54
+ * compositeKey -> the open turn the newest unmarked `user_prompt_submit`
55
+ * replaced, under the id of the turn it opened in its place (Issue #3330).
56
+ *
57
+ * Kept so that a copy of that delivery which carries the queued-notice mark,
58
+ * and is dropped as a duplicate, can still undo the re-open; see
59
+ * {@link joinOpenTurnFromDuplicate}. One entry per instance, overwritten by the
60
+ * next re-open, and only ever read while the turn it names is still the
61
+ * instance's turn.
62
+ */
63
+ exports.reopenedTurns = (0, global_state_1.getOrInitGlobal)('__agentEventReopenedTurns', () => new Map());
64
+ /**
65
+ * Monotonic suffix for {@link TurnRecord.turnId}.
66
+ *
67
+ * Two turns can open in the same millisecond — a `post_tool_use` closing one
68
+ * agent's turn while another's `user_prompt_submit` lands — and an id built from
69
+ * the timestamp alone would then compare equal across instances. `wait` reads a
70
+ * change of id as "a new turn began", so the collision would be a missed turn
71
+ * boundary rather than a cosmetic clash.
72
+ */
73
+ const turnSequence = (0, global_state_1.getOrInitGlobal)('__agentEventTurnSeq', () => ({ value: 0 }));
74
+ // =============================================================================
75
+ // Turn model (Issue #1930)
76
+ // =============================================================================
77
+ /** Epoch ms the current generation began, or null when none was opened. */
78
+ function currentGeneration(key) {
79
+ return exports.generationStartedAt.get(key) ?? null;
80
+ }
81
+ /**
82
+ * The turn this instance is in, with the generation fence applied.
83
+ *
84
+ * A turn whose {@link TurnRecord.generationAt} is not the current generation was
85
+ * opened by a process that has been replaced. It is not deleted — the fence is
86
+ * cheap and deleting would lose the eviction tally — it is simply not this
87
+ * instance's turn any more.
88
+ */
89
+ function fencedTurn(key) {
90
+ const turn = exports.agentTurns.get(key);
91
+ if (!turn)
92
+ return null;
93
+ if (turn.generationAt !== currentGeneration(key))
94
+ return null;
95
+ return turn;
96
+ }
97
+ /**
98
+ * {@link fencedTurn} with the staleness bound applied.
99
+ *
100
+ * The bound is applied by *closing* the turn rather than by hiding it, so
101
+ * `capture --json` says `closedBy: 'stale'` instead of going quiet — "the agent
102
+ * never reported the end of this turn" and "nothing has been reported at all"
103
+ * are different problems and an operator has to be able to tell them apart.
104
+ *
105
+ * Writes on read, which this module already does for corroboration, and is
106
+ * idempotent: the close is stamped from the event's own clock, so it does not
107
+ * move with the reader's `now`.
108
+ */
109
+ function effectiveTurn(key, now) {
110
+ const turn = fencedTurn(key);
111
+ if (turn === null)
112
+ return null;
113
+ if (turn.closedAt === null && now - turn.displayEvent.at >= provisional_turn_1.TURN_STALE_AFTER_MS) {
114
+ turn.closedAt = turn.displayEvent.at + provisional_turn_1.TURN_STALE_AFTER_MS;
115
+ turn.closedBy = 'stale';
116
+ }
117
+ return turn;
118
+ }
119
+ /** Next {@link TurnRecord.turnId}. See {@link turnSequence}. */
120
+ function nextTurnId(at) {
121
+ turnSequence.value += 1;
122
+ return `turn-${at}-${turnSequence.value}`;
123
+ }
124
+ /**
125
+ * Drop the decisions this turn is holding, counting them.
126
+ *
127
+ * The generation path is the one §4 D3 決定 2 names: a process that has been
128
+ * replaced cannot have its approvals answered, and leaving them behind would
129
+ * publish `waiting` for a pane whose dialog went away with the process that
130
+ * drew it.
131
+ */
132
+ function evictDecisions(key, turn) {
133
+ if (turn.pendingDecisions.length === 0)
134
+ return;
135
+ (0, agent_event_dedup_1.dropsFor)(key).decisionEvicted += turn.pendingDecisions.length;
136
+ turn.pendingDecisions = [];
137
+ }
138
+ /**
139
+ * The decisions still describing something, dropping the ones that are not.
140
+ *
141
+ * The retention bound of {@link DIALOG_PENDING_MAX_MS}, applied on read and
142
+ * counted as `dialogTimedOut` so the release is visible. Kept here rather than
143
+ * in a timer for the reason the rest of this module has no timers: the state
144
+ * describes a live tmux session, and a reader is the only thing that ever needs
145
+ * the answer.
146
+ */
147
+ function livePendingDecisions(key, turn, now) {
148
+ const live = turn.pendingDecisions.filter((decision) => (0, provisional_turn_1.isDecisionLive)(decision, now));
149
+ const dropped = turn.pendingDecisions.length - live.length;
150
+ if (dropped > 0) {
151
+ (0, agent_event_dedup_1.dropsFor)(key).dialogTimedOut += dropped;
152
+ turn.pendingDecisions = live;
153
+ }
154
+ return live;
155
+ }
156
+ /**
157
+ * The approvals this instance is blocked on right now (Issue #1930).
158
+ *
159
+ * Published as `structuredEvents.pendingDecisions`; `#1932` is what teaches
160
+ * `commandmate respond` to name one of these ids.
161
+ *
162
+ * @param now - Epoch ms; defaults to now
163
+ */
164
+ function getPendingDecisions(worktreeId, cliToolId, instanceId, now = Date.now()) {
165
+ const key = (0, auto_yes_state_1.buildCompositeKey)(worktreeId, cliToolId, instanceId);
166
+ const turn = effectiveTurn(key, now);
167
+ if (turn === null)
168
+ return [];
169
+ return livePendingDecisions(key, turn, now);
170
+ }
171
+ /**
172
+ * The turn record for one instance, fenced and aged, or null.
173
+ *
174
+ * The seam `current-output-builder` publishes from and the suites drive. The
175
+ * returned object is the live record; nothing outside this module writes to it.
176
+ *
177
+ * @param now - Epoch ms; defaults to now
178
+ */
179
+ function getAgentTurn(worktreeId, cliToolId, instanceId, now = Date.now()) {
180
+ return effectiveTurn((0, auto_yes_state_1.buildCompositeKey)(worktreeId, cliToolId, instanceId), now);
181
+ }
182
+ /** {@link getAgentTurn} projected onto the four published fields. */
183
+ function getPublishedAgentTurn(worktreeId, cliToolId, instanceId, now = Date.now()) {
184
+ return (0, provisional_turn_1.derivePublishedTurn)(getAgentTurn(worktreeId, cliToolId, instanceId, now));
185
+ }
186
+ /**
187
+ * Close the open turn on evidence that did not come from the agent (Issue #1930).
188
+ *
189
+ * The one seam for the two {@link TurnCloseReason} values nothing in the event
190
+ * stream can produce:
191
+ *
192
+ * - `scraper_evidence` — see {@link observeScraperCompletionEvidence}, which is
193
+ * the caller in this tree.
194
+ * - `resync_idle` — a source whose `capabilities.resync` lets it be re-read
195
+ * answering "not busy" after a dropped transport. The reconnect loop that
196
+ * would call it lives in `sources/opencode/subscription`, which is #1931's
197
+ * file and deliberately untouched here; the value is in the vocabulary and
198
+ * the seam accepts it, so wiring it is a call site rather than a new state.
199
+ *
200
+ * A no-op when no turn is open, which is the ordinary case: neither of these is
201
+ * a statement about a session that already reported it finished.
202
+ *
203
+ * @param at - Epoch ms; defaults to now
204
+ * @returns Whether a turn was closed
205
+ */
206
+ function closeAgentTurn(worktreeId, cliToolId, instanceId, closedBy, at = Date.now()) {
207
+ const key = (0, auto_yes_state_1.buildCompositeKey)(worktreeId, cliToolId, instanceId);
208
+ const turn = fencedTurn(key);
209
+ if (turn === null || turn.closedAt !== null)
210
+ return false;
211
+ turn.closedAt = at;
212
+ turn.closedBy = closedBy;
213
+ return true;
214
+ }
215
+ /**
216
+ * Feed one poll's reading of the pane into the turn's completion counter
217
+ * (Issue #1930).
218
+ *
219
+ * `completed` is the scraper's own verdict — `ready` with positive evidence —
220
+ * NOT the merged one, which would be circular: the merge is what the structured
221
+ * layer's `running` overrides, so reading it back would only ever confirm this
222
+ * layer's own answer.
223
+ *
224
+ * See {@link SCRAPER_COMPLETION_POLLS} for why three, and for why closing here
225
+ * does not complete a `commandmate wait`.
226
+ *
227
+ * ## `mayClose` — when the screen is not allowed to close (Issue #3337)
228
+ *
229
+ * The caller passes false while the agent's own hooks are speaking for the
230
+ * pane, the tool is one whose hook turns the screen may not end (codex;
231
+ * `lib/detection/turn-abandoned`), and nothing says the `Stop` will not come. Then the counter still
232
+ * counts, but the turn stays open and the structured `running` stands.
233
+ *
234
+ * The screen's "finished composer" is a reading of one frame, and a frame of a
235
+ * live turn can be misread: codex 0.160.0's status row blinks between `•` and
236
+ * `◦`, and the `◦` half read `ready`, so three polls in a row closed a
237
+ * nine-minute codex turn and `capture --json` published `ready` in the middle
238
+ * of it (`tests/fixtures/codex-mid-turn-3337/`). An operator who sent on that
239
+ * `ready` interrupted the running turn. On a hooks source the agent itself
240
+ * reports the end, so the screen can only add a wrong answer there — except
241
+ * when the `Stop` is known not to come. Two cases say so:
242
+ *
243
+ * - the turn has been unheard from for {@link TURN_STALE_AFTER_MS}: the
244
+ * existing `stale` close, which `effectiveTurn` applies regardless of this
245
+ * function. It stays the bound on a `Stop` that was simply lost.
246
+ * - the frame shows the turn was abandoned — codex's `■ Conversation
247
+ * interrupted` — which the caller folds into `mayClose`. Measured on codex
248
+ * 0.160.0 with hooks: an Esc fires no `Stop`.
249
+ *
250
+ * A source with no hooks (`scraper`), a pull source (`sse`) and a hooks tool
251
+ * with no such policy (Claude among them) pass true and keep the #1930
252
+ * behaviour.
253
+ *
254
+ * @param at - Epoch ms; defaults to now
255
+ * @param mayClose - Whether a third positive poll may close the turn
256
+ * @returns Whether this poll closed the turn
257
+ */
258
+ function observeScraperCompletionEvidence(worktreeId, cliToolId, instanceId, completed, at = Date.now(), mayClose = true) {
259
+ const key = (0, auto_yes_state_1.buildCompositeKey)(worktreeId, cliToolId, instanceId);
260
+ const turn = fencedTurn(key);
261
+ if (turn === null || turn.closedAt !== null)
262
+ return false;
263
+ if (!completed) {
264
+ turn.scraperCompletionPolls = 0;
265
+ return false;
266
+ }
267
+ turn.scraperCompletionPolls += 1;
268
+ if (turn.scraperCompletionPolls < provisional_turn_1.SCRAPER_COMPLETION_POLLS)
269
+ return false;
270
+ if (!mayClose)
271
+ return false;
272
+ turn.closedAt = at;
273
+ turn.closedBy = 'scraper_evidence';
274
+ return true;
275
+ }
276
+ /**
277
+ * End the open turn because the process that owned it has been replaced
278
+ * (Issue #1930).
279
+ *
280
+ * The turn is closed and re-stamped into the new generation rather than
281
+ * deleted, which is the difference between `capture --json` reporting
282
+ * `closedBy: 'generation'` and reporting nothing at all. Its approvals go: they
283
+ * were raised by a process that no longer exists, and answering one would
284
+ * deliver a verdict into a slot nobody is holding.
285
+ */
286
+ function fenceTurnForNewGeneration(key, at) {
287
+ const turn = exports.agentTurns.get(key);
288
+ if (!turn)
289
+ return;
290
+ evictDecisions(key, turn);
291
+ // A turn that had ALREADY ended is left where it is, which means the fence in
292
+ // `fencedTurn` hides it from here on. That asymmetry is deliberate: the
293
+ // previous process's `Stop` is not this process's, and re-stamping it into the
294
+ // new generation would publish `ready` — "the agent finished" — for a session
295
+ // nobody has typed into yet. Before #1930 the same protection came from
296
+ // comparing the event's timestamp against the generation.
297
+ if (turn.closedAt !== null)
298
+ return;
299
+ // An OPEN turn is closed and carried across, so `capture --json` can say
300
+ // `closedBy: 'generation'` rather than going quiet. `getStructuredSessionState`
301
+ // reads that reason as "nothing is known", so it publishes no verdict either
302
+ // way; what it buys is an operator being able to tell "the session was
303
+ // restarted under this turn" from "nothing was ever reported".
304
+ turn.closedAt = at;
305
+ turn.closedBy = 'generation';
306
+ turn.generationAt = at;
307
+ }
308
+ /**
309
+ * The turn transition: what one delivery does to {@link TurnRecord}
310
+ * (Issue #1930, §4 D3 決定 2).
311
+ *
312
+ * | event | turn | dialog | display |
313
+ * |------------------------------------|-------------------------|----------|---------|
314
+ * | `user_prompt_submit` | **opens a new one** | release | yes |
315
+ * | `user_prompt_submit` (joins, #3330)| continues, else opens | release | yes |
316
+ * | `pre_tool_use` | continues, else opens | unchanged| yes |
317
+ * | `pre_tool_use` (after its stop) | unchanged (#3437) | unchanged| no |
318
+ * | `post_tool_use` | continues, else opens | release | yes |
319
+ * | `stop` (this session) | **closes** `stop` | release | yes |
320
+ * | `stop` (another session) | unchanged | unchanged| no |
321
+ * | `session_end` | **closes** `session_end`| release | no |
322
+ * | `session_start` | new generation (above) | evicted | no |
323
+ * | `notification(permission_prompt)` | unchanged | **open** | only to bootstrap |
324
+ * | `notification(permission_replied)` | unchanged | release | no |
325
+ * | `notification(idle_prompt)` | unchanged | release | yes |
326
+ * | `notification(anything else)` | unchanged | unchanged| no |
327
+ *
328
+ * Four rows are the whole point of the Issue, and each of them was a defect
329
+ * under "the newest event is the verdict":
330
+ *
331
+ * - **`user_prompt_submit` opens a new turn, the tool-call events continue the
332
+ * open one.** That is what makes {@link TurnRecord.turnId} an identity: #1926
333
+ * re-stamped it on every `pre_tool_use`, so a consumer reading a changed id
334
+ * as "a new turn began" false-positived several times inside one turn. `wait`
335
+ * reads it that way now.
336
+ * - **A `stop` naming another session changes nothing.** opencode publishes
337
+ * `session.idle` for every session its server holds, other processes'
338
+ * included (#1758 §5.6).
339
+ * - **`session_start` / `session_end` / an unknown notification /
340
+ * `permission_replied` do not become the displayed event.** An event carrying
341
+ * no verdict must not erase one. #1903 fixed the single measured instance
342
+ * (copilot's late `SessionStart`) by holding the delivery; the rule is
343
+ * general here, and the capability it reads is still the only reason a
344
+ * `session_start` is held rather than recorded.
345
+ * - **`notification(permission_prompt)` does not become the displayed event
346
+ * when a turn already exists.** The dialog is a fact about the *pane*, and
347
+ * it is published by the decision ledger below. Letting it overwrite the
348
+ * display is how the pre-#1898 `waiting` outlived the approval that caused
349
+ * it: released, the record still said `waiting`, because the only thing it
350
+ * could read was the event that opened the dialog.
351
+ *
352
+ * The `joins` row is the one exception to the first (Issue #3330). Claude Code
353
+ * fires `UserPromptSubmit` for every background-task notice it attaches to a
354
+ * turn that is already running, so a turn of an orchestrator that runs
355
+ * background work was re-opened once per notice. The source marks those
356
+ * deliveries ({@link AgentEventRecord.joinsOpenTurn}), and they continue the
357
+ * open turn of their session as a tool event does. In the server logs of
358
+ * 2026-10-02 to 2026-10-05, 188 of the 1,182 applied Claude
359
+ * `user_prompt_submit`s arrived with a turn of theirs still open, and the
360
+ * transcripts sort them as: 178 a queued notice (one `queue-operation: remove`
361
+ * of a `<task-notification>` per delivery), 0 a prompt the operator typed into
362
+ * the running turn (Claude attaches it without firing the hook), 0 a prompt
363
+ * sent after an interrupt, 6 after a turn that had ended with no `stop`
364
+ * applied, and 4 with nothing in the transcript to say. Only the first carry
365
+ * the mark; the others open a new turn, as before:
366
+ *
367
+ * - **After an interrupt** there is nothing on the hook channel to tell the
368
+ * prompt from one joining the turn — Claude Code has no interrupt hook, and
369
+ * the prompt is the operator's own text either way — so the turn the
370
+ * operator sent is a new one, which is what a resend is.
371
+ * - **After a `Stop` this server never got** the turn it opened is over, and a
372
+ * new one is right whatever the prompt was. A notice is the one case it
373
+ * cannot see: a lost `Stop` followed by a notice that opens a turn of its
374
+ * own is read as the notice joining the old turn, so the id does not change
375
+ * and the notice turn's `stop` closes it — the same `stop` a `wait` holding
376
+ * either turn was waiting for.
377
+ *
378
+ * Nothing in the row reads a clock. A burst of notices inside three seconds is
379
+ * still dropped by the window in front of it ({@link isDuplicateAgentEvent}),
380
+ * and dropped or applied, none of them moves the turn.
381
+ *
382
+ * The `after its stop` row is the other exception (Issue #3437), and it is
383
+ * narrower than it reads: it applies only to a source that reports its
384
+ * prompts ({@link AgentEventRecord.promptOpensTurns}), and only when the
385
+ * instance's last turn was closed by the agent's own `stop`. In production on
386
+ * 2026-10-07 a Claude `PreToolUse(AskUserQuestion)` landed 2.5 s after the
387
+ * `Stop`, with no `UserPromptSubmit`, no picker on the pane (the scraper read
388
+ * `ready` throughout), and nothing in the session's transcript after the
389
+ * `Stop` — something other than the conversation the `Stop` had just ended.
390
+ * It opened a turn whose `stop` never came, and a `wait` adopted that turn.
391
+ * Every turn of such a source begins with its prompt, and a tool call that
392
+ * continues past a `Stop` (a Stop hook that blocks) still reports its
393
+ * `post_tool_use`, which opens the turn as before. Sources whose turns begin
394
+ * with a tool event are untouched: Command Code's `pre_tool_use` and
395
+ * antigravity's self-resume `post_tool_use` (#2614) open turns because
396
+ * neither sends `user_prompt_submit`.
397
+ *
398
+ * `idle_prompt` is the one row that publishes `ready` **without** closing the
399
+ * turn, and that is a measurement rather than an oversight: #1839 caught Claude
400
+ * emitting it 62 s into a turn that ran nothing, so it cannot be a turn
401
+ * boundary. `wait`'s gate stays armed through it; what changes is only what the
402
+ * pane displays.
403
+ */
404
+ function applyTurnTransition(key, record) {
405
+ const generation = currentGeneration(key);
406
+ // An event stamped before the current generation was produced by a process
407
+ // that has been replaced. Refusing it here is what makes re-recording a stale
408
+ // `user_prompt_submit` at its original timestamp a no-op.
409
+ if (generation !== null && record.at < generation)
410
+ return;
411
+ switch (record.event) {
412
+ case 'user_prompt_submit':
413
+ // Issue #3330: a queued notice the agent attached to its running turn
414
+ // continues that turn; any other prompt is a new one.
415
+ openTurn(key, record, generation, { continueOpen: record.joinsOpenTurn === true });
416
+ releaseAllDecisions(key);
417
+ return;
418
+ case 'post_tool_use':
419
+ openTurn(key, record, generation, { continueOpen: true });
420
+ // The tool call the dialog was gating has finished, so somebody answered
421
+ // it (Issue #1726). This is the release #1725 could not have: it had no
422
+ // event meaning "the human answered", only `Stop` meaning "the turn
423
+ // ended", which can be minutes later.
424
+ releaseAllDecisions(key);
425
+ return;
426
+ case 'pre_tool_use':
427
+ // Deliberately leaves the dialog alone (Issue #1726). It is the
428
+ // `AskUserQuestion` invocation, and a picker being *about to be drawn* is
429
+ // not a fact this state can carry.
430
+ //
431
+ // Issue #3437: and from a source that reports its prompts, it is not the
432
+ // start of a turn when the agent's own `Stop` is the last thing that
433
+ // ended one. See the `after its stop` row above.
434
+ if (record.promptOpensTurns === true && endedByOwnStop(key))
435
+ return;
436
+ openTurn(key, record, generation, { continueOpen: true });
437
+ return;
438
+ case 'stop':
439
+ applyStopToTurn(key, record, generation);
440
+ return;
441
+ case 'session_end':
442
+ applySessionEndToTurn(key, record);
443
+ releaseAllDecisions(key);
444
+ return;
445
+ case 'session_start':
446
+ // The generation was opened by `recordAgentEvent` before this ran, and
447
+ // `fenceTurnForNewGeneration` closed the turn with it. Nothing further:
448
+ // the frame carries no verdict, so it is not the displayed event either.
449
+ return;
450
+ case 'notification':
451
+ applyNotificationToTurn(key, record, generation);
452
+ return;
453
+ default:
454
+ // exhaustive check: a new AgentEventType must decide its transition here
455
+ record.event;
456
+ return;
457
+ }
458
+ }
459
+ /**
460
+ * Whether this instance's turn was last ended by the agent's own `stop`, with
461
+ * nothing opening a turn since (Issue #3437).
462
+ *
463
+ * Only `stop`: every other close is this server's own inference (`stale`,
464
+ * `scraper_evidence`, `resync_idle`) or a session that went away
465
+ * (`session_end`, `generation`), and an agent that keeps working after one of
466
+ * those must be allowed to open the turn it is in.
467
+ */
468
+ function endedByOwnStop(key) {
469
+ const turn = fencedTurn(key);
470
+ return turn !== null && turn.closedAt !== null && turn.closedBy === 'stop';
471
+ }
472
+ /**
473
+ * Whether a `pre_tool_use` from a source that reports its prompts falls outside
474
+ * any turn: the instance's last turn was ended by the agent's own `stop` and
475
+ * nothing has opened one since (Issue #3446).
476
+ *
477
+ * The same reading {@link applyTurnTransition} uses to leave such an event's
478
+ * turn closed (#3437), exposed so the intake can decide the question that event
479
+ * carries on the same facts. Asked after the event was applied, it still holds,
480
+ * because the transition did not open a turn; for a source that does not report
481
+ * its prompts it is always false, because that event opened one.
482
+ */
483
+ function isPreToolUseOutsideTurn(worktreeId, cliToolId, instanceId, promptOpensTurns) {
484
+ return promptOpensTurns && endedByOwnStop((0, auto_yes_state_1.buildCompositeKey)(worktreeId, cliToolId, instanceId));
485
+ }
486
+ /** The three fields the turn keeps from a record. */
487
+ function displayOf(record) {
488
+ return { event: record.event, at: record.at, detail: record.detail };
489
+ }
490
+ /**
491
+ * Open a turn for this event, or move the display onto an open one.
492
+ *
493
+ * @param continueOpen - Whether an already-open turn of the same session is
494
+ * this event's turn. False for `user_prompt_submit`, which IS a new turn —
495
+ * unless the source marked it as joining the running one (Issue #3330).
496
+ */
497
+ function openTurn(key, record, generation, { continueOpen }) {
498
+ const turn = fencedTurn(key);
499
+ const openHere = turn !== null &&
500
+ turn.closedAt === null &&
501
+ turn.openedAt !== null &&
502
+ (0, provisional_turn_1.closesTurn)(turn, record.sessionId);
503
+ if (continueOpen && openHere) {
504
+ turn.displayEvent = displayOf(record);
505
+ // A hand-configured relay posts no session id, so a turn can learn one
506
+ // partway through. Learning it is what lets a later `stop` be matched.
507
+ turn.sessionId ??= record.sessionId;
508
+ turn.scraperCompletionPolls = 0;
509
+ return;
510
+ }
511
+ // A dialog-only record (openedAt null) is not a turn; its decisions belong to
512
+ // the turn that is opening now, because that is when they were raised.
513
+ const carried = turn !== null && turn.openedAt === null && turn.closedAt === null
514
+ ? turn.pendingDecisions
515
+ : [];
516
+ const opened = {
517
+ turnId: nextTurnId(record.at),
518
+ sessionId: record.sessionId,
519
+ openedAt: record.at,
520
+ closedAt: null,
521
+ closedBy: null,
522
+ generationAt: generation,
523
+ displayEvent: displayOf(record),
524
+ pendingDecisions: carried,
525
+ scraperCompletionPolls: 0,
526
+ };
527
+ exports.agentTurns.set(key, opened);
528
+ boundTurnMap();
529
+ // Issue #3330: a prompt with no mark that replaced a running turn of its
530
+ // session. A marked copy of it may still arrive and be dropped as a repeat.
531
+ if (record.event === 'user_prompt_submit' && openHere) {
532
+ exports.reopenedTurns.set(key, { turnId: opened.turnId, replaced: turn });
533
+ (0, agent_event_dedup_1.trimOldestEntries)(exports.reopenedTurns, agent_event_dedup_1.MAX_RECENT_EVENT_KEYS);
534
+ }
535
+ }
536
+ /**
537
+ * Give a dropped copy's queued-notice mark its effect (Issue #3330).
538
+ *
539
+ * The injected `type: "http"` hook posts Claude's payload, prompt included,
540
+ * and is marked {@link AgentEventRecord.joinsOpenTurn} when the prompt is a
541
+ * queued notice. A hand-configured relay beside it posts the same event a few
542
+ * milliseconds earlier or later, and the two share the de-duplication key — so
543
+ * when the relay's copy lands first and carries no mark (an older relay, or a
544
+ * hook that never forwards it), it is the one applied, it re-opens the running
545
+ * turn, and the marked copy is dropped behind it.
546
+ *
547
+ * Called for a `user_prompt_submit` the window dropped and that carries the
548
+ * mark. When the instance's turn is still exactly the one an unmarked prompt
549
+ * opened in place of a running turn of the same session, the running turn is
550
+ * put back — under its own id and `openedAt` — with what the newer record had
551
+ * learned since (display, dialogs). Anything else, and this does nothing.
552
+ *
553
+ * The other ways to keep the mark were weighed and lost:
554
+ *
555
+ * - **Put the mark in the de-duplication key.** Both copies are then applied,
556
+ * but in arrival order: the unmarked one has already re-opened the turn by
557
+ * the time the marked one joins it, so the id has moved either way.
558
+ * - **Drop the unmarked copy instead.** Which copy is the duplicate is decided
559
+ * by whichever lands first, and the first has already been applied.
560
+ *
561
+ * What it cannot tell apart: an unmarked prompt that really begins a turn (a
562
+ * resend after an interrupt) followed, inside the window, by a queued notice
563
+ * of the same session. The notice is read as a copy of the prompt and the two
564
+ * become one turn under the older id; the next `stop` closes it, which is the
565
+ * `stop` a `wait` holding either turn was waiting for.
566
+ *
567
+ * @returns Whether a turn was put back.
568
+ */
569
+ function joinOpenTurnFromDuplicate(worktreeId, cliToolId, instanceId, record) {
570
+ if (record.event !== 'user_prompt_submit' || record.joinsOpenTurn !== true)
571
+ return false;
572
+ const key = (0, auto_yes_state_1.buildCompositeKey)(worktreeId, cliToolId, instanceId);
573
+ const reopened = exports.reopenedTurns.get(key);
574
+ const current = fencedTurn(key);
575
+ if (!reopened || current === null || current.turnId !== reopened.turnId)
576
+ return false;
577
+ if (current.closedAt !== null)
578
+ return false;
579
+ if (!(0, provisional_turn_1.closesTurn)(current, record.sessionId))
580
+ return false;
581
+ const { replaced } = reopened;
582
+ if (replaced.generationAt !== current.generationAt)
583
+ return false;
584
+ exports.agentTurns.set(key, {
585
+ ...replaced,
586
+ closedAt: null,
587
+ closedBy: null,
588
+ displayEvent: current.displayEvent,
589
+ pendingDecisions: current.pendingDecisions,
590
+ scraperCompletionPolls: 0,
591
+ });
592
+ exports.reopenedTurns.delete(key);
593
+ return true;
594
+ }
595
+ /**
596
+ * Apply a `stop` — the only event that is the agent saying its turn is over.
597
+ *
598
+ * A `stop` for another session leaves everything alone; see {@link closesTurn}.
599
+ * A `stop` with no turn open still records one, because "this instance last
600
+ * reported it stopped at T" is the fact `ready` is published from, and the
601
+ * opening it never saw is published as null rather than guessed.
602
+ */
603
+ function applyStopToTurn(key, record, generation) {
604
+ const turn = fencedTurn(key);
605
+ if (turn !== null && turn.closedAt === null && turn.openedAt !== null) {
606
+ if (!(0, provisional_turn_1.closesTurn)(turn, record.sessionId))
607
+ return;
608
+ turn.closedAt = record.at;
609
+ turn.closedBy = 'stop';
610
+ turn.displayEvent = displayOf(record);
611
+ releaseAllDecisions(key);
612
+ return;
613
+ }
614
+ exports.agentTurns.set(key, {
615
+ turnId: nextTurnId(record.at),
616
+ sessionId: record.sessionId,
617
+ openedAt: null,
618
+ closedAt: record.at,
619
+ closedBy: 'stop',
620
+ generationAt: generation,
621
+ displayEvent: displayOf(record),
622
+ pendingDecisions: [],
623
+ scraperCompletionPolls: 0,
624
+ });
625
+ boundTurnMap();
626
+ }
627
+ /**
628
+ * `session_end`: the agent session this instance was talking to is gone.
629
+ *
630
+ * **Overwrites an existing close reason**, which is the one place in this
631
+ * module where a later event rewrites an earlier verdict, and #1723's contract
632
+ * is why. `/clear` emits `SessionEnd(reason=clear)` on a session that is alive
633
+ * and about to keep going, and the turn before it may perfectly well have ended
634
+ * with a `Stop`. Leaving that `Stop` standing would keep publishing "the agent
635
+ * finished" about a conversation that no longer exists — the integration pin is
636
+ * `current-output-structured-status-1723`, which asserts the session goes back
637
+ * to the scraper the moment `SessionEnd` lands.
638
+ *
639
+ * `closedBy: 'session_end'` publishes no verdict of its own (see
640
+ * {@link getStructuredSessionState}), so this is a retirement rather than a
641
+ * different answer.
642
+ */
643
+ function applySessionEndToTurn(key, record) {
644
+ const turn = fencedTurn(key);
645
+ if (turn === null)
646
+ return;
647
+ if (!(0, provisional_turn_1.closesTurn)(turn, record.sessionId))
648
+ return;
649
+ turn.closedAt = record.at;
650
+ turn.closedBy = 'session_end';
651
+ }
652
+ /**
653
+ * The notification rows of the transition table.
654
+ *
655
+ * Matched on `notification_type` ({@link AgentEventRecord.detail}), never on the
656
+ * human-facing `message` (D3): the observed messages are English prose the agent
657
+ * is free to reword.
658
+ */
659
+ function applyNotificationToTurn(key, record, generation) {
660
+ if (record.detail === 'permission_prompt') {
661
+ if (record.promptSettled === true) {
662
+ // Issue #1898: adjudicated before it was recorded, and the verdict
663
+ // reached the agent. There is no dialog and there never was one for a
664
+ // human to answer — opening a record for it published `waiting` for the
665
+ // whole of the tool call that followed (measured at eight seconds).
666
+ releaseSettledDecision(key, record);
667
+ return;
668
+ }
669
+ openDecision(key, generation, {
670
+ source: 'notification',
671
+ at: record.at,
672
+ message: record.message ?? null,
673
+ // Issue #2031. Was a hard `null`, which is what left an opencode approval
674
+ // reaching the browser with no statement of what it was for: the tool
675
+ // name is not in `permission.asked` and has to be carried on the record
676
+ // by whoever correlated it. Absent still means "this source had nothing
677
+ // to say", and `openDecision` leaves an earlier name in place for that.
678
+ toolName: record.toolName ?? null,
679
+ patterns: record.decisionPatterns ?? null,
680
+ decisionId: record.decisionId ?? null,
681
+ bootstrapDisplay: displayOf(record),
682
+ });
683
+ return;
684
+ }
685
+ if (record.detail === agent_event_types_1.PERMISSION_REPLIED_DETAIL) {
686
+ // Issue #1898. The agent's own statement that the dialog is gone — whoever
687
+ // answered it. Not a word this build reads a status from, so it decides
688
+ // nothing; all it does is retire the record.
689
+ if (record.promptSettled === true)
690
+ releaseSettledDecision(key, record);
691
+ return;
692
+ }
693
+ if (record.detail === 'idle_prompt') {
694
+ // The agent reporting it is sitting at the composer waiting for input is the
695
+ // agent saying nothing is in front of that composer.
696
+ releaseAllDecisions(key);
697
+ const turn = fencedTurn(key);
698
+ if (turn !== null && turn.closedAt === null) {
699
+ turn.displayEvent = displayOf(record);
700
+ return;
701
+ }
702
+ if (turn !== null)
703
+ return;
704
+ // Nothing to attach it to — the first thing this instance ever said, or the
705
+ // first since a generation. It still carries a verdict (`ready`), and #1723
706
+ // publishes it, so a display-only record is opened to hold it. `openedAt`
707
+ // stays null: an agent sitting at its composer is not in a turn, and a
708
+ // record that claimed otherwise would gate `wait` on a turn nobody opened.
709
+ exports.agentTurns.set(key, {
710
+ turnId: nextTurnId(record.at),
711
+ sessionId: record.sessionId,
712
+ openedAt: null,
713
+ closedAt: null,
714
+ closedBy: null,
715
+ generationAt: generation,
716
+ displayEvent: displayOf(record),
717
+ pendingDecisions: [],
718
+ scraperCompletionPolls: 0,
719
+ });
720
+ boundTurnMap();
721
+ return;
722
+ }
723
+ // An unrecognised notification type is not evidence of anything, and guessing
724
+ // would be worse than the scraper.
725
+ }
726
+ /**
727
+ * Open, or refresh, a dialog record on this instance's turn.
728
+ *
729
+ * `bootstrapDisplay` is used only when there is no record at all to hang the
730
+ * decision on. That record is deliberately **not** an open turn — its
731
+ * `openedAt` is null — so releasing the decision hands the pane back to the
732
+ * scraper rather than asserting `running` for a turn nobody ever saw open.
733
+ */
734
+ function openDecision(key, generation, input) {
735
+ let turn = fencedTurn(key);
736
+ if (turn === null) {
737
+ turn = {
738
+ turnId: nextTurnId(input.at),
739
+ sessionId: null,
740
+ openedAt: null,
741
+ closedAt: null,
742
+ closedBy: null,
743
+ generationAt: generation,
744
+ displayEvent: input.bootstrapDisplay,
745
+ pendingDecisions: [],
746
+ scraperCompletionPolls: 0,
747
+ };
748
+ exports.agentTurns.set(key, turn);
749
+ boundTurnMap();
750
+ }
751
+ else if (turn.closedAt !== null) {
752
+ // The dialog is being raised after the turn it would have belonged to
753
+ // ended — a `PermissionRequest` racing a `Stop`, or a re-check landing
754
+ // late. Re-open a dialog-only record rather than resurrecting the turn.
755
+ turn = {
756
+ turnId: nextTurnId(input.at),
757
+ sessionId: null,
758
+ openedAt: null,
759
+ closedAt: null,
760
+ closedBy: null,
761
+ generationAt: generation,
762
+ displayEvent: input.bootstrapDisplay,
763
+ pendingDecisions: [],
764
+ scraperCompletionPolls: 0,
765
+ };
766
+ exports.agentTurns.set(key, turn);
767
+ boundTurnMap();
768
+ }
769
+ // Issue #1930 / S1: an id that fails validation is DISCARDED, not truncated —
770
+ // a truncated id compares equal to a different id sharing its prefix, and the
771
+ // reply to one approval would then retire another's record.
772
+ const decisionId = input.decisionId === null ? null : (0, provisional_turn_1.acceptExternalId)(input.decisionId);
773
+ if (input.decisionId !== null && decisionId === null)
774
+ (0, agent_event_dedup_1.dropsFor)(key).idsDiscarded += 1;
775
+ const confirmed = input.source === 'notification';
776
+ // Which record, if any, this report is a second sighting of.
777
+ //
778
+ // - an id matches its own record;
779
+ // - an id with no record of its own may still be *confirming* the anonymous
780
+ // prediction that forecast it. That is the measured pair: a
781
+ // `PermissionRequest` this server declined to decide fires ~6 s before the
782
+ // `Notification(permission_prompt)` that proves the dialog, and the
783
+ // request carries no id;
784
+ // - an anonymous report merges only with another anonymous one. A source
785
+ // that publishes no ids therefore keeps exactly one dialog record per
786
+ // instance, which is what #1725 did and the honest limit for it — matching
787
+ // an anonymous report against an *identified* record would let one
788
+ // approval's forecast confirm a different approval's dialog.
789
+ const existing = decisionId !== null
790
+ ? (turn.pendingDecisions.find((decision) => decision.decisionId === decisionId) ??
791
+ turn.pendingDecisions.find((decision) => decision.decisionId === null && decision.source === 'permission-request'))
792
+ : turn.pendingDecisions.find((decision) => decision.decisionId === null);
793
+ if (existing) {
794
+ // The same dialog, reported twice: `PermissionRequest` predicted it and the
795
+ // `Notification` then proved it. Keep the earliest `at` — that is when the
796
+ // human was first blocked, and it is what the scraper-release grace and the
797
+ // age bound are measured from — and take the confirmation.
798
+ existing.message = (0, provisional_turn_1.boundDecisionMessage)(input.message) ?? existing.message;
799
+ existing.toolName = (0, provisional_turn_1.boundDecisionToolName)(input.toolName) ?? existing.toolName;
800
+ // Issue #2031, same rule as the two lines above it: a second sighting that
801
+ // knows the rules fills them in, one that does not leaves the earlier
802
+ // answer alone. The measured pair is exactly this — the `PermissionRequest`
803
+ // forecast carries no patterns, the `Notification` that confirms it does.
804
+ existing.patterns = (0, provisional_turn_1.boundDecisionPatterns)(input.patterns) ?? existing.patterns;
805
+ existing.decisionId ??= decisionId;
806
+ if (confirmed) {
807
+ existing.source = 'notification';
808
+ existing.confirmedAt ??= input.at;
809
+ }
810
+ return;
811
+ }
812
+ if (turn.pendingDecisions.length >= provisional_turn_1.MAX_PENDING_DECISIONS_PER_TURN) {
813
+ // S14(d). Counted rather than dropped in silence: an agent raising more
814
+ // approvals than this in one turn is a fact an operator has to be able to
815
+ // see, and the oldest is the one a human has been looking at.
816
+ (0, agent_event_dedup_1.dropsFor)(key).decisionOverflow += 1;
817
+ return;
818
+ }
819
+ turn.pendingDecisions.push({
820
+ decisionId,
821
+ at: input.at,
822
+ source: input.source,
823
+ message: (0, provisional_turn_1.boundDecisionMessage)(input.message),
824
+ toolName: (0, provisional_turn_1.boundDecisionToolName)(input.toolName),
825
+ patterns: (0, provisional_turn_1.boundDecisionPatterns)(input.patterns),
826
+ confirmedAt: confirmed ? input.at : null,
827
+ scraperCorroborated: false,
828
+ recorded: false,
829
+ });
830
+ }
831
+ /** Retire every dialog this instance was holding. */
832
+ function releaseAllDecisions(key) {
833
+ const turn = fencedTurn(key);
834
+ if (turn !== null)
835
+ turn.pendingDecisions = [];
836
+ }
837
+ /**
838
+ * Retire the record a verdict was delivered for (Issue #1898).
839
+ *
840
+ * Matched on {@link AgentEventRecord.decisionId} when both sides have one: an
841
+ * agent that can run two approvals at once would otherwise have the reply to
842
+ * the first retire the record for the second. When either side is anonymous the
843
+ * release is unconditional — an unmatched id is a source that publishes none,
844
+ * and refusing to act there would leave the pre-#1898 stall in place for it.
845
+ */
846
+ function releaseSettledDecision(key, record) {
847
+ const turn = fencedTurn(key);
848
+ if (turn === null || turn.pendingDecisions.length === 0)
849
+ return;
850
+ const settledId = record.decisionId === null || record.decisionId === undefined
851
+ ? null
852
+ : (0, provisional_turn_1.acceptExternalId)(record.decisionId);
853
+ if (settledId === null) {
854
+ turn.pendingDecisions = [];
855
+ return;
856
+ }
857
+ turn.pendingDecisions = turn.pendingDecisions.filter((decision) => decision.decisionId !== null && decision.decisionId !== settledId);
858
+ }
859
+ /** Keep the turn map bounded the way every other map in this module is. */
860
+ function boundTurnMap() {
861
+ (0, agent_event_dedup_1.trimOldestEntries)(exports.agentTurns, agent_event_dedup_1.MAX_RECENT_EVENT_KEYS);
862
+ }