commandmate 0.49.0 → 0.49.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (721) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-build-manifest.json +238 -231
  3. package/.next/app-path-routes-manifest.json +19 -18
  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/routes-manifest.json +8 -0
  8. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  9. package/.next/server/app/api/agents/update/route_client-reference-manifest.js +1 -1
  10. package/.next/server/app/api/agents/versions/route_client-reference-manifest.js +1 -1
  11. package/.next/server/app/api/app/release-notes/route_client-reference-manifest.js +1 -1
  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_client-reference-manifest.js +1 -1
  38. package/.next/server/app/api/push/subscriptions/route.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_client-reference-manifest.js +1 -1
  41. package/.next/server/app/api/relays/[relayId]/cancel/route.js +1 -1
  42. package/.next/server/app/api/relays/[relayId]/cancel/route.js.nft.json +1 -1
  43. package/.next/server/app/api/relays/[relayId]/cancel/route_client-reference-manifest.js +1 -1
  44. package/.next/server/app/api/relays/[relayId]/route.js +1 -0
  45. package/.next/server/app/api/relays/[relayId]/route.js.nft.json +1 -0
  46. package/.next/server/app/api/relays/[relayId]/route_client-reference-manifest.js +1 -0
  47. package/.next/server/app/api/relays/route.js +1 -1
  48. package/.next/server/app/api/relays/route.js.nft.json +1 -1
  49. package/.next/server/app/api/relays/route_client-reference-manifest.js +1 -1
  50. package/.next/server/app/api/remote/pair/route_client-reference-manifest.js +1 -1
  51. package/.next/server/app/api/repositories/[id]/route_client-reference-manifest.js +1 -1
  52. package/.next/server/app/api/repositories/clone/[jobId]/route.js +1 -1
  53. package/.next/server/app/api/repositories/clone/[jobId]/route.js.nft.json +1 -1
  54. package/.next/server/app/api/repositories/clone/[jobId]/route_client-reference-manifest.js +1 -1
  55. package/.next/server/app/api/repositories/clone/route.js +1 -1
  56. package/.next/server/app/api/repositories/clone/route.js.nft.json +1 -1
  57. package/.next/server/app/api/repositories/clone/route_client-reference-manifest.js +1 -1
  58. package/.next/server/app/api/repositories/excluded/route_client-reference-manifest.js +1 -1
  59. package/.next/server/app/api/repositories/restore/route.js +1 -1
  60. package/.next/server/app/api/repositories/restore/route.js.nft.json +1 -1
  61. package/.next/server/app/api/repositories/restore/route_client-reference-manifest.js +1 -1
  62. package/.next/server/app/api/repositories/route.js +1 -1
  63. package/.next/server/app/api/repositories/route.js.nft.json +1 -1
  64. package/.next/server/app/api/repositories/route_client-reference-manifest.js +1 -1
  65. package/.next/server/app/api/repositories/scan/route.js +1 -1
  66. package/.next/server/app/api/repositories/scan/route.js.nft.json +1 -1
  67. package/.next/server/app/api/repositories/scan/route_client-reference-manifest.js +1 -1
  68. package/.next/server/app/api/repositories/sync/route.js +1 -1
  69. package/.next/server/app/api/repositories/sync/route.js.nft.json +1 -1
  70. package/.next/server/app/api/repositories/sync/route_client-reference-manifest.js +1 -1
  71. package/.next/server/app/api/repositories/validate-path/route_client-reference-manifest.js +1 -1
  72. package/.next/server/app/api/settings/default-agents/route.js +1 -1
  73. package/.next/server/app/api/settings/default-agents/route.js.nft.json +1 -1
  74. package/.next/server/app/api/settings/default-agents/route_client-reference-manifest.js +1 -1
  75. package/.next/server/app/api/settings/default-surface-mode/route_client-reference-manifest.js +1 -1
  76. package/.next/server/app/api/sidebar/group-order/route_client-reference-manifest.js +1 -1
  77. package/.next/server/app/api/skills/[id]/route_client-reference-manifest.js +1 -1
  78. package/.next/server/app/api/skills/installations/route_client-reference-manifest.js +1 -1
  79. package/.next/server/app/api/skills/operations/route_client-reference-manifest.js +1 -1
  80. package/.next/server/app/api/skills/reindex/route_client-reference-manifest.js +1 -1
  81. package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
  82. package/.next/server/app/api/slash-commands/route_client-reference-manifest.js +1 -1
  83. package/.next/server/app/api/tasks/[taskId]/cancel/route_client-reference-manifest.js +1 -1
  84. package/.next/server/app/api/tasks/[taskId]/route.js +1 -1
  85. package/.next/server/app/api/tasks/[taskId]/route_client-reference-manifest.js +1 -1
  86. package/.next/server/app/api/templates/[id]/route_client-reference-manifest.js +1 -1
  87. package/.next/server/app/api/templates/route_client-reference-manifest.js +1 -1
  88. package/.next/server/app/api/verification/runs/[runId]/route.js +1 -1
  89. package/.next/server/app/api/verification/runs/[runId]/route_client-reference-manifest.js +1 -1
  90. package/.next/server/app/api/verification/runs/route.js +1 -1
  91. package/.next/server/app/api/verification/runs/route_client-reference-manifest.js +1 -1
  92. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js +1 -1
  93. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js.nft.json +1 -1
  94. package/.next/server/app/api/worktrees/[id]/auto-yes/route_client-reference-manifest.js +1 -1
  95. package/.next/server/app/api/worktrees/[id]/capture/route.js +1 -1
  96. package/.next/server/app/api/worktrees/[id]/capture/route.js.nft.json +1 -1
  97. package/.next/server/app/api/worktrees/[id]/capture/route_client-reference-manifest.js +1 -1
  98. package/.next/server/app/api/worktrees/[id]/clear-composer/route.js +1 -1
  99. package/.next/server/app/api/worktrees/[id]/clear-composer/route.js.nft.json +1 -1
  100. package/.next/server/app/api/worktrees/[id]/clear-composer/route_client-reference-manifest.js +1 -1
  101. package/.next/server/app/api/worktrees/[id]/cli-reference/route.js +1 -1
  102. package/.next/server/app/api/worktrees/[id]/cli-reference/route_client-reference-manifest.js +1 -1
  103. package/.next/server/app/api/worktrees/[id]/cli-tool/route.js +1 -1
  104. package/.next/server/app/api/worktrees/[id]/cli-tool/route_client-reference-manifest.js +1 -1
  105. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route.js +1 -1
  106. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route_client-reference-manifest.js +1 -1
  107. package/.next/server/app/api/worktrees/[id]/current-output/route.js +1 -1
  108. package/.next/server/app/api/worktrees/[id]/current-output/route.js.nft.json +1 -1
  109. package/.next/server/app/api/worktrees/[id]/current-output/route_client-reference-manifest.js +1 -1
  110. package/.next/server/app/api/worktrees/[id]/direct-input/route.js +1 -1
  111. package/.next/server/app/api/worktrees/[id]/direct-input/route.js.nft.json +1 -1
  112. package/.next/server/app/api/worktrees/[id]/direct-input/route_client-reference-manifest.js +1 -1
  113. package/.next/server/app/api/worktrees/[id]/env/route.js +1 -1
  114. package/.next/server/app/api/worktrees/[id]/env/route_client-reference-manifest.js +1 -1
  115. package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route.js +1 -1
  116. package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route_client-reference-manifest.js +1 -1
  117. package/.next/server/app/api/worktrees/[id]/execution-logs/route.js +1 -1
  118. package/.next/server/app/api/worktrees/[id]/execution-logs/route_client-reference-manifest.js +1 -1
  119. package/.next/server/app/api/worktrees/[id]/files/[...path]/route_client-reference-manifest.js +1 -1
  120. package/.next/server/app/api/worktrees/[id]/git/branch/create/route.js +1 -1
  121. package/.next/server/app/api/worktrees/[id]/git/branch/create/route_client-reference-manifest.js +1 -1
  122. package/.next/server/app/api/worktrees/[id]/git/branch/delete/route.js +1 -1
  123. package/.next/server/app/api/worktrees/[id]/git/branch/delete/route_client-reference-manifest.js +1 -1
  124. package/.next/server/app/api/worktrees/[id]/git/branches/route.js +1 -1
  125. package/.next/server/app/api/worktrees/[id]/git/branches/route_client-reference-manifest.js +1 -1
  126. package/.next/server/app/api/worktrees/[id]/git/checkout/route.js +1 -1
  127. package/.next/server/app/api/worktrees/[id]/git/checkout/route_client-reference-manifest.js +1 -1
  128. package/.next/server/app/api/worktrees/[id]/git/commit/route.js +1 -1
  129. package/.next/server/app/api/worktrees/[id]/git/commit/route_client-reference-manifest.js +1 -1
  130. package/.next/server/app/api/worktrees/[id]/git/diff/route.js +1 -1
  131. package/.next/server/app/api/worktrees/[id]/git/diff/route_client-reference-manifest.js +1 -1
  132. package/.next/server/app/api/worktrees/[id]/git/fetch/route.js +1 -1
  133. package/.next/server/app/api/worktrees/[id]/git/fetch/route_client-reference-manifest.js +1 -1
  134. package/.next/server/app/api/worktrees/[id]/git/log/route.js +1 -1
  135. package/.next/server/app/api/worktrees/[id]/git/log/route_client-reference-manifest.js +1 -1
  136. package/.next/server/app/api/worktrees/[id]/git/pull/route.js +1 -1
  137. package/.next/server/app/api/worktrees/[id]/git/pull/route_client-reference-manifest.js +1 -1
  138. package/.next/server/app/api/worktrees/[id]/git/push/route.js +1 -1
  139. package/.next/server/app/api/worktrees/[id]/git/push/route_client-reference-manifest.js +1 -1
  140. package/.next/server/app/api/worktrees/[id]/git/reset/route.js +1 -1
  141. package/.next/server/app/api/worktrees/[id]/git/reset/route_client-reference-manifest.js +1 -1
  142. package/.next/server/app/api/worktrees/[id]/git/revert/route.js +1 -1
  143. package/.next/server/app/api/worktrees/[id]/git/revert/route_client-reference-manifest.js +1 -1
  144. package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route.js +1 -1
  145. package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route_client-reference-manifest.js +1 -1
  146. package/.next/server/app/api/worktrees/[id]/git/stage/route.js +1 -1
  147. package/.next/server/app/api/worktrees/[id]/git/stage/route_client-reference-manifest.js +1 -1
  148. package/.next/server/app/api/worktrees/[id]/git/staged/route.js +1 -1
  149. package/.next/server/app/api/worktrees/[id]/git/staged/route_client-reference-manifest.js +1 -1
  150. package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route.js +1 -1
  151. package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route_client-reference-manifest.js +1 -1
  152. package/.next/server/app/api/worktrees/[id]/git/stash/apply/route.js +1 -1
  153. package/.next/server/app/api/worktrees/[id]/git/stash/apply/route_client-reference-manifest.js +1 -1
  154. package/.next/server/app/api/worktrees/[id]/git/stash/pop/route.js +1 -1
  155. package/.next/server/app/api/worktrees/[id]/git/stash/pop/route_client-reference-manifest.js +1 -1
  156. package/.next/server/app/api/worktrees/[id]/git/stash/push/route.js +1 -1
  157. package/.next/server/app/api/worktrees/[id]/git/stash/push/route_client-reference-manifest.js +1 -1
  158. package/.next/server/app/api/worktrees/[id]/git/stash/route.js +1 -1
  159. package/.next/server/app/api/worktrees/[id]/git/stash/route_client-reference-manifest.js +1 -1
  160. package/.next/server/app/api/worktrees/[id]/git/status/route.js +1 -1
  161. package/.next/server/app/api/worktrees/[id]/git/status/route_client-reference-manifest.js +1 -1
  162. package/.next/server/app/api/worktrees/[id]/git/unstage/route.js +1 -1
  163. package/.next/server/app/api/worktrees/[id]/git/unstage/route_client-reference-manifest.js +1 -1
  164. package/.next/server/app/api/worktrees/[id]/git/working-diff/route.js +1 -1
  165. package/.next/server/app/api/worktrees/[id]/git/working-diff/route_client-reference-manifest.js +1 -1
  166. package/.next/server/app/api/worktrees/[id]/instances/notes/route.js +1 -1
  167. package/.next/server/app/api/worktrees/[id]/instances/notes/route_client-reference-manifest.js +1 -1
  168. package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js.nft.json +1 -1
  169. package/.next/server/app/api/worktrees/[id]/instances/opencode/route_client-reference-manifest.js +1 -1
  170. package/.next/server/app/api/worktrees/[id]/interrupt/route.js +1 -1
  171. package/.next/server/app/api/worktrees/[id]/interrupt/route.js.nft.json +1 -1
  172. package/.next/server/app/api/worktrees/[id]/interrupt/route_client-reference-manifest.js +1 -1
  173. package/.next/server/app/api/worktrees/[id]/kill-session/route.js +1 -1
  174. package/.next/server/app/api/worktrees/[id]/kill-session/route.js.nft.json +1 -1
  175. package/.next/server/app/api/worktrees/[id]/kill-session/route_client-reference-manifest.js +1 -1
  176. package/.next/server/app/api/worktrees/[id]/logs/[filename]/route.js +1 -1
  177. package/.next/server/app/api/worktrees/[id]/logs/[filename]/route_client-reference-manifest.js +1 -1
  178. package/.next/server/app/api/worktrees/[id]/logs/route.js +1 -1
  179. package/.next/server/app/api/worktrees/[id]/logs/route_client-reference-manifest.js +1 -1
  180. package/.next/server/app/api/worktrees/[id]/marp-render/route.js +1 -1
  181. package/.next/server/app/api/worktrees/[id]/marp-render/route_client-reference-manifest.js +1 -1
  182. package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route.js +1 -1
  183. package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route_client-reference-manifest.js +1 -1
  184. package/.next/server/app/api/worktrees/[id]/memos/route.js +1 -1
  185. package/.next/server/app/api/worktrees/[id]/memos/route_client-reference-manifest.js +1 -1
  186. package/.next/server/app/api/worktrees/[id]/messages/route.js +1 -1
  187. package/.next/server/app/api/worktrees/[id]/messages/route_client-reference-manifest.js +1 -1
  188. package/.next/server/app/api/worktrees/[id]/opencode/diff/route.js +1 -1
  189. package/.next/server/app/api/worktrees/[id]/opencode/diff/route_client-reference-manifest.js +1 -1
  190. package/.next/server/app/api/worktrees/[id]/opencode/session/route_client-reference-manifest.js +1 -1
  191. package/.next/server/app/api/worktrees/[id]/opencode/share/route_client-reference-manifest.js +1 -1
  192. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js +1 -1
  193. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js.nft.json +1 -1
  194. package/.next/server/app/api/worktrees/[id]/prompt-response/route_client-reference-manifest.js +1 -1
  195. package/.next/server/app/api/worktrees/[id]/prompt-response/strict/route.js +1 -1
  196. package/.next/server/app/api/worktrees/[id]/prompt-response/strict/route.js.nft.json +1 -1
  197. package/.next/server/app/api/worktrees/[id]/prompt-response/strict/route_client-reference-manifest.js +1 -1
  198. package/.next/server/app/api/worktrees/[id]/resolve-target/route.js +1 -1
  199. package/.next/server/app/api/worktrees/[id]/resolve-target/route_client-reference-manifest.js +1 -1
  200. package/.next/server/app/api/worktrees/[id]/respond/route.js +1 -1
  201. package/.next/server/app/api/worktrees/[id]/respond/route.js.nft.json +1 -1
  202. package/.next/server/app/api/worktrees/[id]/respond/route_client-reference-manifest.js +1 -1
  203. package/.next/server/app/api/worktrees/[id]/route.js +1 -1
  204. package/.next/server/app/api/worktrees/[id]/route.js.nft.json +1 -1
  205. package/.next/server/app/api/worktrees/[id]/route_client-reference-manifest.js +1 -1
  206. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route.js +1 -1
  207. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route_client-reference-manifest.js +1 -1
  208. package/.next/server/app/api/worktrees/[id]/schedules/active/route.js +1 -1
  209. package/.next/server/app/api/worktrees/[id]/schedules/active/route_client-reference-manifest.js +1 -1
  210. package/.next/server/app/api/worktrees/[id]/schedules/route.js +1 -1
  211. package/.next/server/app/api/worktrees/[id]/schedules/route_client-reference-manifest.js +1 -1
  212. package/.next/server/app/api/worktrees/[id]/search/route_client-reference-manifest.js +1 -1
  213. package/.next/server/app/api/worktrees/[id]/send/route.js +144 -1
  214. package/.next/server/app/api/worktrees/[id]/send/route.js.nft.json +1 -1
  215. package/.next/server/app/api/worktrees/[id]/send/route_client-reference-manifest.js +1 -1
  216. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js +3 -3
  217. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js.nft.json +1 -1
  218. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route_client-reference-manifest.js +1 -1
  219. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route_client-reference-manifest.js +1 -1
  220. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route_client-reference-manifest.js +1 -1
  221. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route_client-reference-manifest.js +1 -1
  222. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route_client-reference-manifest.js +1 -1
  223. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update/route_client-reference-manifest.js +1 -1
  224. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route_client-reference-manifest.js +1 -1
  225. package/.next/server/app/api/worktrees/[id]/skills/route.js +1 -1
  226. package/.next/server/app/api/worktrees/[id]/skills/route_client-reference-manifest.js +1 -1
  227. package/.next/server/app/api/worktrees/[id]/slash-commands/route.js +1 -1
  228. package/.next/server/app/api/worktrees/[id]/slash-commands/route_client-reference-manifest.js +1 -1
  229. package/.next/server/app/api/worktrees/[id]/special-keys/route.js +1 -1
  230. package/.next/server/app/api/worktrees/[id]/special-keys/route.js.nft.json +1 -1
  231. package/.next/server/app/api/worktrees/[id]/special-keys/route_client-reference-manifest.js +1 -1
  232. package/.next/server/app/api/worktrees/[id]/tasks/route.js +1 -1
  233. package/.next/server/app/api/worktrees/[id]/tasks/route_client-reference-manifest.js +1 -1
  234. package/.next/server/app/api/worktrees/[id]/terminal/route.js +103 -1
  235. package/.next/server/app/api/worktrees/[id]/terminal/route.js.nft.json +1 -1
  236. package/.next/server/app/api/worktrees/[id]/terminal/route_client-reference-manifest.js +1 -1
  237. package/.next/server/app/api/worktrees/[id]/timers/history/route.js +1 -1
  238. package/.next/server/app/api/worktrees/[id]/timers/history/route_client-reference-manifest.js +1 -1
  239. package/.next/server/app/api/worktrees/[id]/timers/route.js +1 -1
  240. package/.next/server/app/api/worktrees/[id]/timers/route.js.nft.json +1 -1
  241. package/.next/server/app/api/worktrees/[id]/timers/route_client-reference-manifest.js +1 -1
  242. package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route.js +1 -1
  243. package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
  244. package/.next/server/app/api/worktrees/[id]/todos/route.js +1 -1
  245. package/.next/server/app/api/worktrees/[id]/todos/route_client-reference-manifest.js +1 -1
  246. package/.next/server/app/api/worktrees/[id]/tree/[...path]/route_client-reference-manifest.js +1 -1
  247. package/.next/server/app/api/worktrees/[id]/tree/route_client-reference-manifest.js +1 -1
  248. package/.next/server/app/api/worktrees/[id]/upload/[...path]/route_client-reference-manifest.js +1 -1
  249. package/.next/server/app/api/worktrees/[id]/verify/config/route.js +1 -1
  250. package/.next/server/app/api/worktrees/[id]/verify/config/route_client-reference-manifest.js +1 -1
  251. package/.next/server/app/api/worktrees/[id]/verify/route.js +1 -1
  252. package/.next/server/app/api/worktrees/[id]/verify/route_client-reference-manifest.js +1 -1
  253. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route.js +1 -1
  254. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route_client-reference-manifest.js +1 -1
  255. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route.js +1 -1
  256. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route_client-reference-manifest.js +1 -1
  257. package/.next/server/app/api/worktrees/[id]/verify/runs/route.js +1 -1
  258. package/.next/server/app/api/worktrees/[id]/verify/runs/route_client-reference-manifest.js +1 -1
  259. package/.next/server/app/api/worktrees/[id]/viewed/route.js +1 -1
  260. package/.next/server/app/api/worktrees/[id]/viewed/route_client-reference-manifest.js +1 -1
  261. package/.next/server/app/api/worktrees/apply-default-agents/route_client-reference-manifest.js +1 -1
  262. package/.next/server/app/api/worktrees/route.js +1 -1
  263. package/.next/server/app/api/worktrees/route.js.nft.json +1 -1
  264. package/.next/server/app/api/worktrees/route_client-reference-manifest.js +1 -1
  265. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  266. package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
  267. package/.next/server/app/more/page_client-reference-manifest.js +1 -1
  268. package/.next/server/app/offline/page_client-reference-manifest.js +1 -1
  269. package/.next/server/app/page_client-reference-manifest.js +1 -1
  270. package/.next/server/app/proxy/[...path]/route_client-reference-manifest.js +1 -1
  271. package/.next/server/app/repositories/page_client-reference-manifest.js +1 -1
  272. package/.next/server/app/review/page_client-reference-manifest.js +1 -1
  273. package/.next/server/app/sessions/page.js +1 -1
  274. package/.next/server/app/sessions/page.js.nft.json +1 -1
  275. package/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  276. package/.next/server/app/skills/[skillId]/page_client-reference-manifest.js +1 -1
  277. package/.next/server/app/skills/installed/page_client-reference-manifest.js +1 -1
  278. package/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  279. package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -1
  280. package/.next/server/app/worktrees/[id]/page.js +11 -11
  281. package/.next/server/app/worktrees/[id]/page.js.nft.json +1 -1
  282. package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -1
  283. package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
  284. package/.next/server/app-paths-manifest.json +19 -18
  285. package/.next/server/chunks/1656.js +2 -2
  286. package/.next/server/chunks/2119.js +1 -1
  287. package/.next/server/chunks/2404.js +1 -1
  288. package/.next/server/chunks/2445.js +1 -1
  289. package/.next/server/chunks/3773.js +1 -0
  290. package/.next/server/chunks/3801.js +31 -0
  291. package/.next/server/chunks/5209.js +1 -1
  292. package/.next/server/chunks/5354.js +1 -1
  293. package/.next/server/chunks/{9130.js → 5630.js} +1 -1
  294. package/.next/server/chunks/5775.js +1 -0
  295. package/.next/server/chunks/610.js +1 -0
  296. package/.next/server/chunks/6119.js +1 -1
  297. package/.next/server/chunks/6130.js +1 -1
  298. package/.next/server/chunks/6401.js +1 -1
  299. package/.next/server/chunks/6486.js +1 -1
  300. package/.next/server/chunks/6781.js +1 -1
  301. package/.next/server/chunks/6808.js +4 -0
  302. package/.next/server/chunks/7023.js +14 -0
  303. package/.next/server/chunks/7604.js +1 -1
  304. package/.next/server/chunks/7905.js +1 -1
  305. package/.next/server/chunks/8581.js +15 -15
  306. package/.next/server/chunks/8728.js +2 -2
  307. package/.next/server/chunks/8782.js +1 -1
  308. package/.next/server/chunks/8807.js +63 -53
  309. package/.next/server/chunks/8918.js +103 -1
  310. package/.next/server/chunks/9198.js +144 -0
  311. package/.next/server/chunks/9390.js +1 -1
  312. package/.next/server/chunks/9584.js +1 -1
  313. package/.next/server/chunks/9627.js +1 -1
  314. package/.next/server/chunks/9731.js +3 -3
  315. package/.next/server/middleware-manifest.json +5 -5
  316. package/.next/server/pages/500.html +1 -1
  317. package/.next/server/server-reference-manifest.json +1 -1
  318. package/.next/static/chunks/{2407-ab92ae9837c39dce.js → 2407-675ba6b21844dc3b.js} +1 -1
  319. package/.next/static/chunks/3931-1a1abab16248f14d.js +1 -0
  320. package/.next/static/chunks/8606-ce17ffa77f39608e.js +1 -0
  321. package/.next/static/chunks/app/api/agents/update/route-a4f129c451de7859.js +1 -0
  322. package/.next/static/chunks/app/api/agents/versions/route-a4f129c451de7859.js +1 -0
  323. package/.next/static/chunks/app/api/app/release-notes/route-a4f129c451de7859.js +1 -0
  324. package/.next/static/chunks/app/api/app/update/route-a4f129c451de7859.js +1 -0
  325. package/.next/static/chunks/app/api/app/update-check/route-a4f129c451de7859.js +1 -0
  326. package/.next/static/chunks/app/api/auth/login/route-a4f129c451de7859.js +1 -0
  327. package/.next/static/chunks/app/api/auth/logout/route-a4f129c451de7859.js +1 -0
  328. package/.next/static/chunks/app/api/auth/status/route-a4f129c451de7859.js +1 -0
  329. package/.next/static/chunks/app/api/capabilities/route-a4f129c451de7859.js +1 -0
  330. package/.next/static/chunks/app/api/daily-summary/route-a4f129c451de7859.js +1 -0
  331. package/.next/static/chunks/app/api/daily-summary/status/route-a4f129c451de7859.js +1 -0
  332. package/.next/static/chunks/app/api/external-apps/[id]/health/route-a4f129c451de7859.js +1 -0
  333. package/.next/static/chunks/app/api/external-apps/[id]/route-a4f129c451de7859.js +1 -0
  334. package/.next/static/chunks/app/api/external-apps/route-a4f129c451de7859.js +1 -0
  335. package/.next/static/chunks/app/api/fs/browse/route-a4f129c451de7859.js +1 -0
  336. package/.next/static/chunks/app/api/fs/recent-paths/route-a4f129c451de7859.js +1 -0
  337. package/.next/static/chunks/app/api/hooks/agent-event/route-a4f129c451de7859.js +1 -0
  338. package/.next/static/chunks/app/api/hooks/claude-done/route-a4f129c451de7859.js +1 -0
  339. package/.next/static/chunks/app/api/hooks/permission-request/route-a4f129c451de7859.js +1 -0
  340. package/.next/static/chunks/app/api/metrics/vibe/route-a4f129c451de7859.js +1 -0
  341. package/.next/static/chunks/app/api/ollama/models/route-a4f129c451de7859.js +1 -0
  342. package/.next/static/chunks/app/api/push/escalation/route-a4f129c451de7859.js +1 -0
  343. package/.next/static/chunks/app/api/push/subscriptions/route-a4f129c451de7859.js +1 -0
  344. package/.next/static/chunks/app/api/push/vapid/route-a4f129c451de7859.js +1 -0
  345. package/.next/static/chunks/app/api/relays/[relayId]/cancel/route-a4f129c451de7859.js +1 -0
  346. package/.next/static/chunks/app/api/relays/[relayId]/route-a4f129c451de7859.js +1 -0
  347. package/.next/static/chunks/app/api/relays/route-a4f129c451de7859.js +1 -0
  348. package/.next/static/chunks/app/api/remote/pair/route-a4f129c451de7859.js +1 -0
  349. package/.next/static/chunks/app/api/repositories/[id]/route-a4f129c451de7859.js +1 -0
  350. package/.next/static/chunks/app/api/repositories/clone/[jobId]/route-a4f129c451de7859.js +1 -0
  351. package/.next/static/chunks/app/api/repositories/clone/route-a4f129c451de7859.js +1 -0
  352. package/.next/static/chunks/app/api/repositories/excluded/route-a4f129c451de7859.js +1 -0
  353. package/.next/static/chunks/app/api/repositories/restore/route-a4f129c451de7859.js +1 -0
  354. package/.next/static/chunks/app/api/repositories/route-a4f129c451de7859.js +1 -0
  355. package/.next/static/chunks/app/api/repositories/scan/route-a4f129c451de7859.js +1 -0
  356. package/.next/static/chunks/app/api/repositories/sync/route-a4f129c451de7859.js +1 -0
  357. package/.next/static/chunks/app/api/repositories/validate-path/route-a4f129c451de7859.js +1 -0
  358. package/.next/static/chunks/app/api/settings/default-agents/route-a4f129c451de7859.js +1 -0
  359. package/.next/static/chunks/app/api/settings/default-surface-mode/route-a4f129c451de7859.js +1 -0
  360. package/.next/static/chunks/app/api/sidebar/group-order/route-a4f129c451de7859.js +1 -0
  361. package/.next/static/chunks/app/api/skills/[id]/route-a4f129c451de7859.js +1 -0
  362. package/.next/static/chunks/app/api/skills/installations/route-a4f129c451de7859.js +1 -0
  363. package/.next/static/chunks/app/api/skills/operations/route-a4f129c451de7859.js +1 -0
  364. package/.next/static/chunks/app/api/skills/reindex/route-a4f129c451de7859.js +1 -0
  365. package/.next/static/chunks/app/api/skills/route-a4f129c451de7859.js +1 -0
  366. package/.next/static/chunks/app/api/slash-commands/route-a4f129c451de7859.js +1 -0
  367. package/.next/static/chunks/app/api/tasks/[taskId]/cancel/route-a4f129c451de7859.js +1 -0
  368. package/.next/static/chunks/app/api/tasks/[taskId]/route-a4f129c451de7859.js +1 -0
  369. package/.next/static/chunks/app/api/templates/[id]/route-a4f129c451de7859.js +1 -0
  370. package/.next/static/chunks/app/api/templates/route-a4f129c451de7859.js +1 -0
  371. package/.next/static/chunks/app/api/verification/runs/[runId]/route-a4f129c451de7859.js +1 -0
  372. package/.next/static/chunks/app/api/verification/runs/route-a4f129c451de7859.js +1 -0
  373. package/.next/static/chunks/app/api/worktrees/[id]/auto-yes/route-a4f129c451de7859.js +1 -0
  374. package/.next/static/chunks/app/api/worktrees/[id]/capture/route-a4f129c451de7859.js +1 -0
  375. package/.next/static/chunks/app/api/worktrees/[id]/clear-composer/route-a4f129c451de7859.js +1 -0
  376. package/.next/static/chunks/app/api/worktrees/[id]/cli-reference/route-a4f129c451de7859.js +1 -0
  377. package/.next/static/chunks/app/api/worktrees/[id]/cli-tool/route-a4f129c451de7859.js +1 -0
  378. package/.next/static/chunks/app/api/worktrees/[id]/cmate/schedules/route-a4f129c451de7859.js +1 -0
  379. package/.next/static/chunks/app/api/worktrees/[id]/current-output/route-a4f129c451de7859.js +1 -0
  380. package/.next/static/chunks/app/api/worktrees/[id]/direct-input/route-a4f129c451de7859.js +1 -0
  381. package/.next/static/chunks/app/api/worktrees/[id]/env/route-a4f129c451de7859.js +1 -0
  382. package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/[logId]/route-a4f129c451de7859.js +1 -0
  383. package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/route-a4f129c451de7859.js +1 -0
  384. package/.next/static/chunks/app/api/worktrees/[id]/files/[...path]/route-a4f129c451de7859.js +1 -0
  385. package/.next/static/chunks/app/api/worktrees/[id]/git/branch/create/route-a4f129c451de7859.js +1 -0
  386. package/.next/static/chunks/app/api/worktrees/[id]/git/branch/delete/route-a4f129c451de7859.js +1 -0
  387. package/.next/static/chunks/app/api/worktrees/[id]/git/branches/route-a4f129c451de7859.js +1 -0
  388. package/.next/static/chunks/app/api/worktrees/[id]/git/checkout/route-a4f129c451de7859.js +1 -0
  389. package/.next/static/chunks/app/api/worktrees/[id]/git/commit/route-a4f129c451de7859.js +1 -0
  390. package/.next/static/chunks/app/api/worktrees/[id]/git/diff/route-a4f129c451de7859.js +1 -0
  391. package/.next/static/chunks/app/api/worktrees/[id]/git/fetch/route-a4f129c451de7859.js +1 -0
  392. package/.next/static/chunks/app/api/worktrees/[id]/git/log/route-a4f129c451de7859.js +1 -0
  393. package/.next/static/chunks/app/api/worktrees/[id]/git/pull/route-a4f129c451de7859.js +1 -0
  394. package/.next/static/chunks/app/api/worktrees/[id]/git/push/route-a4f129c451de7859.js +1 -0
  395. package/.next/static/chunks/app/api/worktrees/[id]/git/reset/route-a4f129c451de7859.js +1 -0
  396. package/.next/static/chunks/app/api/worktrees/[id]/git/revert/route-a4f129c451de7859.js +1 -0
  397. package/.next/static/chunks/app/api/worktrees/[id]/git/show/[commitHash]/route-a4f129c451de7859.js +1 -0
  398. package/.next/static/chunks/app/api/worktrees/[id]/git/stage/route-a4f129c451de7859.js +1 -0
  399. package/.next/static/chunks/app/api/worktrees/[id]/git/staged/route-a4f129c451de7859.js +1 -0
  400. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/[index]/route-a4f129c451de7859.js +1 -0
  401. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/apply/route-a4f129c451de7859.js +1 -0
  402. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/pop/route-a4f129c451de7859.js +1 -0
  403. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/push/route-a4f129c451de7859.js +1 -0
  404. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/route-a4f129c451de7859.js +1 -0
  405. package/.next/static/chunks/app/api/worktrees/[id]/git/status/route-a4f129c451de7859.js +1 -0
  406. package/.next/static/chunks/app/api/worktrees/[id]/git/unstage/route-a4f129c451de7859.js +1 -0
  407. package/.next/static/chunks/app/api/worktrees/[id]/git/working-diff/route-a4f129c451de7859.js +1 -0
  408. package/.next/static/chunks/app/api/worktrees/[id]/instances/notes/route-a4f129c451de7859.js +1 -0
  409. package/.next/static/chunks/app/api/worktrees/[id]/instances/opencode/route-a4f129c451de7859.js +1 -0
  410. package/.next/static/chunks/app/api/worktrees/[id]/interrupt/route-a4f129c451de7859.js +1 -0
  411. package/.next/static/chunks/app/api/worktrees/[id]/kill-session/route-a4f129c451de7859.js +1 -0
  412. package/.next/static/chunks/app/api/worktrees/[id]/logs/[filename]/route-a4f129c451de7859.js +1 -0
  413. package/.next/static/chunks/app/api/worktrees/[id]/logs/route-a4f129c451de7859.js +1 -0
  414. package/.next/static/chunks/app/api/worktrees/[id]/marp-render/route-a4f129c451de7859.js +1 -0
  415. package/.next/static/chunks/app/api/worktrees/[id]/memos/[memoId]/route-a4f129c451de7859.js +1 -0
  416. package/.next/static/chunks/app/api/worktrees/[id]/memos/route-a4f129c451de7859.js +1 -0
  417. package/.next/static/chunks/app/api/worktrees/[id]/messages/route-a4f129c451de7859.js +1 -0
  418. package/.next/static/chunks/app/api/worktrees/[id]/opencode/diff/route-a4f129c451de7859.js +1 -0
  419. package/.next/static/chunks/app/api/worktrees/[id]/opencode/session/route-a4f129c451de7859.js +1 -0
  420. package/.next/static/chunks/app/api/worktrees/[id]/opencode/share/route-a4f129c451de7859.js +1 -0
  421. package/.next/static/chunks/app/api/worktrees/[id]/prompt-response/route-a4f129c451de7859.js +1 -0
  422. package/.next/static/chunks/app/api/worktrees/[id]/prompt-response/strict/route-a4f129c451de7859.js +1 -0
  423. package/.next/static/chunks/app/api/worktrees/[id]/resolve-target/route-a4f129c451de7859.js +1 -0
  424. package/.next/static/chunks/app/api/worktrees/[id]/respond/route-a4f129c451de7859.js +1 -0
  425. package/.next/static/chunks/app/api/worktrees/[id]/route-a4f129c451de7859.js +1 -0
  426. package/.next/static/chunks/app/api/worktrees/[id]/schedules/[scheduleId]/route-a4f129c451de7859.js +1 -0
  427. package/.next/static/chunks/app/api/worktrees/[id]/schedules/active/route-a4f129c451de7859.js +1 -0
  428. package/.next/static/chunks/app/api/worktrees/[id]/schedules/route-a4f129c451de7859.js +1 -0
  429. package/.next/static/chunks/app/api/worktrees/[id]/search/route-a4f129c451de7859.js +1 -0
  430. package/.next/static/chunks/app/api/worktrees/[id]/send/route-a4f129c451de7859.js +1 -0
  431. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route-a4f129c451de7859.js +1 -0
  432. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/install/route-a4f129c451de7859.js +1 -0
  433. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/plan/route-a4f129c451de7859.js +1 -0
  434. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall/route-a4f129c451de7859.js +1 -0
  435. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route-a4f129c451de7859.js +1 -0
  436. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update/route-a4f129c451de7859.js +1 -0
  437. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update-plan/route-a4f129c451de7859.js +1 -0
  438. package/.next/static/chunks/app/api/worktrees/[id]/skills/route-a4f129c451de7859.js +1 -0
  439. package/.next/static/chunks/app/api/worktrees/[id]/slash-commands/route-a4f129c451de7859.js +1 -0
  440. package/.next/static/chunks/app/api/worktrees/[id]/special-keys/route-a4f129c451de7859.js +1 -0
  441. package/.next/static/chunks/app/api/worktrees/[id]/tasks/route-a4f129c451de7859.js +1 -0
  442. package/.next/static/chunks/app/api/worktrees/[id]/terminal/route-a4f129c451de7859.js +1 -0
  443. package/.next/static/chunks/app/api/worktrees/[id]/timers/history/route-a4f129c451de7859.js +1 -0
  444. package/.next/static/chunks/app/api/worktrees/[id]/timers/route-a4f129c451de7859.js +1 -0
  445. package/.next/static/chunks/app/api/worktrees/[id]/todos/[todoId]/route-a4f129c451de7859.js +1 -0
  446. package/.next/static/chunks/app/api/worktrees/[id]/todos/route-a4f129c451de7859.js +1 -0
  447. package/.next/static/chunks/app/api/worktrees/[id]/tree/[...path]/route-a4f129c451de7859.js +1 -0
  448. package/.next/static/chunks/app/api/worktrees/[id]/tree/route-a4f129c451de7859.js +1 -0
  449. package/.next/static/chunks/app/api/worktrees/[id]/upload/[...path]/route-a4f129c451de7859.js +1 -0
  450. package/.next/static/chunks/app/api/worktrees/[id]/verify/config/route-a4f129c451de7859.js +1 -0
  451. package/.next/static/chunks/app/api/worktrees/[id]/verify/route-a4f129c451de7859.js +1 -0
  452. package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route-a4f129c451de7859.js +1 -0
  453. package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/[runId]/route-a4f129c451de7859.js +1 -0
  454. package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/route-a4f129c451de7859.js +1 -0
  455. package/.next/static/chunks/app/api/worktrees/[id]/viewed/route-a4f129c451de7859.js +1 -0
  456. package/.next/static/chunks/app/api/worktrees/apply-default-agents/route-a4f129c451de7859.js +1 -0
  457. package/.next/static/chunks/app/api/worktrees/route-a4f129c451de7859.js +1 -0
  458. package/.next/static/chunks/app/layout-8bfac4724277b47f.js +1 -0
  459. package/.next/static/chunks/app/manifest.webmanifest/route-a4f129c451de7859.js +1 -0
  460. package/.next/static/chunks/app/proxy/[...path]/route-a4f129c451de7859.js +1 -0
  461. package/.next/static/chunks/app/sessions/page-890fd50ec9739973.js +1 -0
  462. package/.next/static/chunks/app/worktrees/[id]/layout-a4f129c451de7859.js +1 -0
  463. package/.next/static/chunks/app/worktrees/[id]/page-f6d3ab8185d93aae.js +1 -0
  464. package/.next/static/css/c1e307d05daf93b6.css +1 -0
  465. package/.next/trace +13 -13
  466. package/.next/types/app/api/relays/[relayId]/route.ts +347 -0
  467. package/.next/types/routes.d.ts +2 -1
  468. package/.next/types/validator.ts +9 -0
  469. package/dist/cli/commands/ask.d.ts.map +1 -1
  470. package/dist/cli/commands/ask.js +178 -13
  471. package/dist/cli/commands/message-dispatch.d.ts +25 -5
  472. package/dist/cli/commands/message-dispatch.d.ts.map +1 -1
  473. package/dist/cli/commands/message-dispatch.js +92 -6
  474. package/dist/cli/commands/relays.d.ts +25 -2
  475. package/dist/cli/commands/relays.d.ts.map +1 -1
  476. package/dist/cli/commands/relays.js +69 -5
  477. package/dist/cli/commands/respond.d.ts +12 -0
  478. package/dist/cli/commands/respond.d.ts.map +1 -1
  479. package/dist/cli/commands/respond.js +63 -1
  480. package/dist/cli/commands/send.d.ts.map +1 -1
  481. package/dist/cli/commands/send.js +6 -4
  482. package/dist/cli/commands/wait-hook-stop-settle.d.ts +66 -0
  483. package/dist/cli/commands/wait-hook-stop-settle.d.ts.map +1 -0
  484. package/dist/cli/commands/wait-hook-stop-settle.js +150 -0
  485. package/dist/cli/commands/wait-instance.d.ts +21 -0
  486. package/dist/cli/commands/wait-instance.d.ts.map +1 -0
  487. package/dist/cli/commands/wait-instance.js +41 -0
  488. package/dist/cli/commands/wait-notices.d.ts +87 -0
  489. package/dist/cli/commands/wait-notices.d.ts.map +1 -0
  490. package/dist/cli/commands/wait-notices.js +301 -0
  491. package/dist/cli/commands/wait-poll-bookkeeping.d.ts +15 -0
  492. package/dist/cli/commands/wait-poll-bookkeeping.d.ts.map +1 -0
  493. package/dist/cli/commands/wait-poll-bookkeeping.js +57 -0
  494. package/dist/cli/commands/wait-poll-state.d.ts +118 -0
  495. package/dist/cli/commands/wait-poll-state.d.ts.map +1 -0
  496. package/dist/cli/commands/wait-poll-state.js +6 -0
  497. package/dist/cli/commands/wait-timing.d.ts +46 -0
  498. package/dist/cli/commands/wait-timing.d.ts.map +1 -0
  499. package/dist/cli/commands/wait-timing.js +99 -0
  500. package/dist/cli/commands/wait-turn-boundary.d.ts +284 -0
  501. package/dist/cli/commands/wait-turn-boundary.d.ts.map +1 -0
  502. package/dist/cli/commands/wait-turn-boundary.js +427 -0
  503. package/dist/cli/commands/wait-verify.d.ts +50 -0
  504. package/dist/cli/commands/wait-verify.d.ts.map +1 -0
  505. package/dist/cli/commands/wait-verify.js +124 -0
  506. package/dist/cli/commands/wait.d.ts +6 -105
  507. package/dist/cli/commands/wait.d.ts.map +1 -1
  508. package/dist/cli/commands/wait.js +207 -959
  509. package/dist/cli/docs/agent-operations.d.ts +2 -2
  510. package/dist/cli/docs/agent-operations.d.ts.map +1 -1
  511. package/dist/cli/docs/agent-operations.js +23 -1
  512. package/dist/cli/types/api-responses.d.ts +47 -3
  513. package/dist/cli/types/api-responses.d.ts.map +1 -1
  514. package/dist/cli/utils/api-client.d.ts +15 -1
  515. package/dist/cli/utils/api-client.d.ts.map +1 -1
  516. package/dist/cli/utils/api-client.js +7 -1
  517. package/dist/cli/utils/reply-ledger.d.ts +79 -0
  518. package/dist/cli/utils/reply-ledger.d.ts.map +1 -1
  519. package/dist/cli/utils/reply-ledger.js +141 -1
  520. package/dist/lib/session/send-attempt-types.d.ts +23 -1
  521. package/dist/lib/session/send-attempt-types.d.ts.map +1 -1
  522. package/dist/lib/session/send-attempt-types.js +9 -1
  523. package/dist/server/locales/en/worktree.json +18 -3
  524. package/dist/server/locales/ja/worktree.json +18 -3
  525. package/dist/server/src/lib/auto-yes-poller.js +49 -10
  526. package/dist/server/src/lib/cli-tools/antigravity.js +40 -7
  527. package/dist/server/src/lib/cli-tools/codex.js +60 -11
  528. package/dist/server/src/lib/cli-tools/command-code-plan-review.js +24 -2
  529. package/dist/server/src/lib/cli-tools/copilot.js +120 -30
  530. package/dist/server/src/lib/cli-tools/gemini.js +28 -9
  531. package/dist/server/src/lib/cli-tools/opencode.js +55 -13
  532. package/dist/server/src/lib/cli-tools/submit-composer-read.js +580 -0
  533. package/dist/server/src/lib/cli-tools/submit-verified-sender.js +356 -621
  534. package/dist/server/src/lib/db/migrations/index.js +2 -0
  535. package/dist/server/src/lib/db/migrations/pre-migration-backup.js +266 -0
  536. package/dist/server/src/lib/db/migrations/runner.js +37 -4
  537. package/dist/server/src/lib/db/migrations/v62-session-relays-bind.js +102 -0
  538. package/dist/server/src/lib/db/relay-bind-db.js +437 -0
  539. package/dist/server/src/lib/db/relay-db.js +59 -96
  540. package/dist/server/src/lib/detection/upstream-faults.js +40 -6
  541. package/dist/server/src/lib/hooks/sources/opencode/client.js +12 -6
  542. package/dist/server/src/lib/polling/response-checker.js +7 -5
  543. package/dist/server/src/lib/prompt-answer-errors.js +288 -0
  544. package/dist/server/src/lib/prompt-answer-sender.js +264 -288
  545. package/dist/server/src/lib/push/failure-episode-state.js +4 -1
  546. package/dist/server/src/lib/realtime/terminal-broadcast.js +1 -4
  547. package/dist/server/src/lib/realtime-snippet.js +54 -0
  548. package/dist/server/src/lib/relay/relay-bind.js +294 -0
  549. package/dist/server/src/lib/relay/relay-boot.js +51 -0
  550. package/dist/server/src/lib/relay/relay-bound-reply.js +519 -0
  551. package/dist/server/src/lib/relay/relay-delivery.js +134 -220
  552. package/dist/server/src/lib/relay/relay-messages.js +39 -4
  553. package/dist/server/src/lib/relay/relay-overlap.js +92 -0
  554. package/dist/server/src/lib/relay/relay-system-line.js +3 -2
  555. package/dist/server/src/lib/relay/types.js +12 -1
  556. package/dist/server/src/lib/session/agent-session-lifecycle.js +18 -0
  557. package/dist/server/src/lib/session/claude-session.js +41 -6
  558. package/dist/server/src/lib/session/composer-clear.js +54 -1
  559. package/dist/server/src/lib/session/current-output-builder.js +21 -5
  560. package/dist/server/src/lib/session/instance-input-lock.js +664 -0
  561. package/dist/server/src/lib/session/send-attempt-state.js +17 -0
  562. package/dist/server/src/lib/session/send-attempt-types.js +9 -1
  563. package/dist/server/src/lib/session/send-user-message.js +82 -13
  564. package/package.json +1 -1
  565. package/release-notes/0.49.1.json +66 -0
  566. package/.next/server/chunks/1210.js +0 -1
  567. package/.next/server/chunks/1945.js +0 -14
  568. package/.next/server/chunks/1990.js +0 -103
  569. package/.next/server/chunks/4194.js +0 -67
  570. package/.next/server/chunks/4280.js +0 -1
  571. package/.next/server/chunks/5845.js +0 -1
  572. package/.next/server/chunks/720.js +0 -103
  573. package/.next/server/chunks/936.js +0 -1
  574. package/.next/server/chunks/9540.js +0 -1
  575. package/.next/static/chunks/8606-cf6bdbff44a764cf.js +0 -1
  576. package/.next/static/chunks/9079-987939d231704218.js +0 -1
  577. package/.next/static/chunks/app/api/agents/update/route-c81284a9d8b35304.js +0 -1
  578. package/.next/static/chunks/app/api/agents/versions/route-c81284a9d8b35304.js +0 -1
  579. package/.next/static/chunks/app/api/app/release-notes/route-c81284a9d8b35304.js +0 -1
  580. package/.next/static/chunks/app/api/app/update/route-c81284a9d8b35304.js +0 -1
  581. package/.next/static/chunks/app/api/app/update-check/route-c81284a9d8b35304.js +0 -1
  582. package/.next/static/chunks/app/api/auth/login/route-c81284a9d8b35304.js +0 -1
  583. package/.next/static/chunks/app/api/auth/logout/route-c81284a9d8b35304.js +0 -1
  584. package/.next/static/chunks/app/api/auth/status/route-c81284a9d8b35304.js +0 -1
  585. package/.next/static/chunks/app/api/capabilities/route-c81284a9d8b35304.js +0 -1
  586. package/.next/static/chunks/app/api/daily-summary/route-c81284a9d8b35304.js +0 -1
  587. package/.next/static/chunks/app/api/daily-summary/status/route-c81284a9d8b35304.js +0 -1
  588. package/.next/static/chunks/app/api/external-apps/[id]/health/route-c81284a9d8b35304.js +0 -1
  589. package/.next/static/chunks/app/api/external-apps/[id]/route-c81284a9d8b35304.js +0 -1
  590. package/.next/static/chunks/app/api/external-apps/route-c81284a9d8b35304.js +0 -1
  591. package/.next/static/chunks/app/api/fs/browse/route-c81284a9d8b35304.js +0 -1
  592. package/.next/static/chunks/app/api/fs/recent-paths/route-c81284a9d8b35304.js +0 -1
  593. package/.next/static/chunks/app/api/hooks/agent-event/route-c81284a9d8b35304.js +0 -1
  594. package/.next/static/chunks/app/api/hooks/claude-done/route-c81284a9d8b35304.js +0 -1
  595. package/.next/static/chunks/app/api/hooks/permission-request/route-c81284a9d8b35304.js +0 -1
  596. package/.next/static/chunks/app/api/metrics/vibe/route-c81284a9d8b35304.js +0 -1
  597. package/.next/static/chunks/app/api/ollama/models/route-c81284a9d8b35304.js +0 -1
  598. package/.next/static/chunks/app/api/push/escalation/route-c81284a9d8b35304.js +0 -1
  599. package/.next/static/chunks/app/api/push/subscriptions/route-c81284a9d8b35304.js +0 -1
  600. package/.next/static/chunks/app/api/push/vapid/route-c81284a9d8b35304.js +0 -1
  601. package/.next/static/chunks/app/api/relays/[relayId]/cancel/route-c81284a9d8b35304.js +0 -1
  602. package/.next/static/chunks/app/api/relays/route-c81284a9d8b35304.js +0 -1
  603. package/.next/static/chunks/app/api/remote/pair/route-c81284a9d8b35304.js +0 -1
  604. package/.next/static/chunks/app/api/repositories/[id]/route-c81284a9d8b35304.js +0 -1
  605. package/.next/static/chunks/app/api/repositories/clone/[jobId]/route-c81284a9d8b35304.js +0 -1
  606. package/.next/static/chunks/app/api/repositories/clone/route-c81284a9d8b35304.js +0 -1
  607. package/.next/static/chunks/app/api/repositories/excluded/route-c81284a9d8b35304.js +0 -1
  608. package/.next/static/chunks/app/api/repositories/restore/route-c81284a9d8b35304.js +0 -1
  609. package/.next/static/chunks/app/api/repositories/route-c81284a9d8b35304.js +0 -1
  610. package/.next/static/chunks/app/api/repositories/scan/route-c81284a9d8b35304.js +0 -1
  611. package/.next/static/chunks/app/api/repositories/sync/route-c81284a9d8b35304.js +0 -1
  612. package/.next/static/chunks/app/api/repositories/validate-path/route-c81284a9d8b35304.js +0 -1
  613. package/.next/static/chunks/app/api/settings/default-agents/route-c81284a9d8b35304.js +0 -1
  614. package/.next/static/chunks/app/api/settings/default-surface-mode/route-c81284a9d8b35304.js +0 -1
  615. package/.next/static/chunks/app/api/sidebar/group-order/route-c81284a9d8b35304.js +0 -1
  616. package/.next/static/chunks/app/api/skills/[id]/route-c81284a9d8b35304.js +0 -1
  617. package/.next/static/chunks/app/api/skills/installations/route-c81284a9d8b35304.js +0 -1
  618. package/.next/static/chunks/app/api/skills/operations/route-c81284a9d8b35304.js +0 -1
  619. package/.next/static/chunks/app/api/skills/reindex/route-c81284a9d8b35304.js +0 -1
  620. package/.next/static/chunks/app/api/skills/route-c81284a9d8b35304.js +0 -1
  621. package/.next/static/chunks/app/api/slash-commands/route-c81284a9d8b35304.js +0 -1
  622. package/.next/static/chunks/app/api/tasks/[taskId]/cancel/route-c81284a9d8b35304.js +0 -1
  623. package/.next/static/chunks/app/api/tasks/[taskId]/route-c81284a9d8b35304.js +0 -1
  624. package/.next/static/chunks/app/api/templates/[id]/route-c81284a9d8b35304.js +0 -1
  625. package/.next/static/chunks/app/api/templates/route-c81284a9d8b35304.js +0 -1
  626. package/.next/static/chunks/app/api/verification/runs/[runId]/route-c81284a9d8b35304.js +0 -1
  627. package/.next/static/chunks/app/api/verification/runs/route-c81284a9d8b35304.js +0 -1
  628. package/.next/static/chunks/app/api/worktrees/[id]/auto-yes/route-c81284a9d8b35304.js +0 -1
  629. package/.next/static/chunks/app/api/worktrees/[id]/capture/route-c81284a9d8b35304.js +0 -1
  630. package/.next/static/chunks/app/api/worktrees/[id]/clear-composer/route-c81284a9d8b35304.js +0 -1
  631. package/.next/static/chunks/app/api/worktrees/[id]/cli-reference/route-c81284a9d8b35304.js +0 -1
  632. package/.next/static/chunks/app/api/worktrees/[id]/cli-tool/route-c81284a9d8b35304.js +0 -1
  633. package/.next/static/chunks/app/api/worktrees/[id]/cmate/schedules/route-c81284a9d8b35304.js +0 -1
  634. package/.next/static/chunks/app/api/worktrees/[id]/current-output/route-c81284a9d8b35304.js +0 -1
  635. package/.next/static/chunks/app/api/worktrees/[id]/direct-input/route-c81284a9d8b35304.js +0 -1
  636. package/.next/static/chunks/app/api/worktrees/[id]/env/route-c81284a9d8b35304.js +0 -1
  637. package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/[logId]/route-c81284a9d8b35304.js +0 -1
  638. package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/route-c81284a9d8b35304.js +0 -1
  639. package/.next/static/chunks/app/api/worktrees/[id]/files/[...path]/route-c81284a9d8b35304.js +0 -1
  640. package/.next/static/chunks/app/api/worktrees/[id]/git/branch/create/route-c81284a9d8b35304.js +0 -1
  641. package/.next/static/chunks/app/api/worktrees/[id]/git/branch/delete/route-c81284a9d8b35304.js +0 -1
  642. package/.next/static/chunks/app/api/worktrees/[id]/git/branches/route-c81284a9d8b35304.js +0 -1
  643. package/.next/static/chunks/app/api/worktrees/[id]/git/checkout/route-c81284a9d8b35304.js +0 -1
  644. package/.next/static/chunks/app/api/worktrees/[id]/git/commit/route-c81284a9d8b35304.js +0 -1
  645. package/.next/static/chunks/app/api/worktrees/[id]/git/diff/route-c81284a9d8b35304.js +0 -1
  646. package/.next/static/chunks/app/api/worktrees/[id]/git/fetch/route-c81284a9d8b35304.js +0 -1
  647. package/.next/static/chunks/app/api/worktrees/[id]/git/log/route-c81284a9d8b35304.js +0 -1
  648. package/.next/static/chunks/app/api/worktrees/[id]/git/pull/route-c81284a9d8b35304.js +0 -1
  649. package/.next/static/chunks/app/api/worktrees/[id]/git/push/route-c81284a9d8b35304.js +0 -1
  650. package/.next/static/chunks/app/api/worktrees/[id]/git/reset/route-c81284a9d8b35304.js +0 -1
  651. package/.next/static/chunks/app/api/worktrees/[id]/git/revert/route-c81284a9d8b35304.js +0 -1
  652. package/.next/static/chunks/app/api/worktrees/[id]/git/show/[commitHash]/route-c81284a9d8b35304.js +0 -1
  653. package/.next/static/chunks/app/api/worktrees/[id]/git/stage/route-c81284a9d8b35304.js +0 -1
  654. package/.next/static/chunks/app/api/worktrees/[id]/git/staged/route-c81284a9d8b35304.js +0 -1
  655. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/[index]/route-c81284a9d8b35304.js +0 -1
  656. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/apply/route-c81284a9d8b35304.js +0 -1
  657. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/pop/route-c81284a9d8b35304.js +0 -1
  658. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/push/route-c81284a9d8b35304.js +0 -1
  659. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/route-c81284a9d8b35304.js +0 -1
  660. package/.next/static/chunks/app/api/worktrees/[id]/git/status/route-c81284a9d8b35304.js +0 -1
  661. package/.next/static/chunks/app/api/worktrees/[id]/git/unstage/route-c81284a9d8b35304.js +0 -1
  662. package/.next/static/chunks/app/api/worktrees/[id]/git/working-diff/route-c81284a9d8b35304.js +0 -1
  663. package/.next/static/chunks/app/api/worktrees/[id]/instances/notes/route-c81284a9d8b35304.js +0 -1
  664. package/.next/static/chunks/app/api/worktrees/[id]/instances/opencode/route-c81284a9d8b35304.js +0 -1
  665. package/.next/static/chunks/app/api/worktrees/[id]/interrupt/route-c81284a9d8b35304.js +0 -1
  666. package/.next/static/chunks/app/api/worktrees/[id]/kill-session/route-c81284a9d8b35304.js +0 -1
  667. package/.next/static/chunks/app/api/worktrees/[id]/logs/[filename]/route-c81284a9d8b35304.js +0 -1
  668. package/.next/static/chunks/app/api/worktrees/[id]/logs/route-c81284a9d8b35304.js +0 -1
  669. package/.next/static/chunks/app/api/worktrees/[id]/marp-render/route-c81284a9d8b35304.js +0 -1
  670. package/.next/static/chunks/app/api/worktrees/[id]/memos/[memoId]/route-c81284a9d8b35304.js +0 -1
  671. package/.next/static/chunks/app/api/worktrees/[id]/memos/route-c81284a9d8b35304.js +0 -1
  672. package/.next/static/chunks/app/api/worktrees/[id]/messages/route-c81284a9d8b35304.js +0 -1
  673. package/.next/static/chunks/app/api/worktrees/[id]/opencode/diff/route-c81284a9d8b35304.js +0 -1
  674. package/.next/static/chunks/app/api/worktrees/[id]/opencode/session/route-c81284a9d8b35304.js +0 -1
  675. package/.next/static/chunks/app/api/worktrees/[id]/opencode/share/route-c81284a9d8b35304.js +0 -1
  676. package/.next/static/chunks/app/api/worktrees/[id]/prompt-response/route-c81284a9d8b35304.js +0 -1
  677. package/.next/static/chunks/app/api/worktrees/[id]/prompt-response/strict/route-c81284a9d8b35304.js +0 -1
  678. package/.next/static/chunks/app/api/worktrees/[id]/resolve-target/route-c81284a9d8b35304.js +0 -1
  679. package/.next/static/chunks/app/api/worktrees/[id]/respond/route-c81284a9d8b35304.js +0 -1
  680. package/.next/static/chunks/app/api/worktrees/[id]/route-c81284a9d8b35304.js +0 -1
  681. package/.next/static/chunks/app/api/worktrees/[id]/schedules/[scheduleId]/route-c81284a9d8b35304.js +0 -1
  682. package/.next/static/chunks/app/api/worktrees/[id]/schedules/active/route-c81284a9d8b35304.js +0 -1
  683. package/.next/static/chunks/app/api/worktrees/[id]/schedules/route-c81284a9d8b35304.js +0 -1
  684. package/.next/static/chunks/app/api/worktrees/[id]/search/route-c81284a9d8b35304.js +0 -1
  685. package/.next/static/chunks/app/api/worktrees/[id]/send/route-c81284a9d8b35304.js +0 -1
  686. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route-c81284a9d8b35304.js +0 -1
  687. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/install/route-c81284a9d8b35304.js +0 -1
  688. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/plan/route-c81284a9d8b35304.js +0 -1
  689. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall/route-c81284a9d8b35304.js +0 -1
  690. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route-c81284a9d8b35304.js +0 -1
  691. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update/route-c81284a9d8b35304.js +0 -1
  692. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update-plan/route-c81284a9d8b35304.js +0 -1
  693. package/.next/static/chunks/app/api/worktrees/[id]/skills/route-c81284a9d8b35304.js +0 -1
  694. package/.next/static/chunks/app/api/worktrees/[id]/slash-commands/route-c81284a9d8b35304.js +0 -1
  695. package/.next/static/chunks/app/api/worktrees/[id]/special-keys/route-c81284a9d8b35304.js +0 -1
  696. package/.next/static/chunks/app/api/worktrees/[id]/tasks/route-c81284a9d8b35304.js +0 -1
  697. package/.next/static/chunks/app/api/worktrees/[id]/terminal/route-c81284a9d8b35304.js +0 -1
  698. package/.next/static/chunks/app/api/worktrees/[id]/timers/history/route-c81284a9d8b35304.js +0 -1
  699. package/.next/static/chunks/app/api/worktrees/[id]/timers/route-c81284a9d8b35304.js +0 -1
  700. package/.next/static/chunks/app/api/worktrees/[id]/todos/[todoId]/route-c81284a9d8b35304.js +0 -1
  701. package/.next/static/chunks/app/api/worktrees/[id]/todos/route-c81284a9d8b35304.js +0 -1
  702. package/.next/static/chunks/app/api/worktrees/[id]/tree/[...path]/route-c81284a9d8b35304.js +0 -1
  703. package/.next/static/chunks/app/api/worktrees/[id]/tree/route-c81284a9d8b35304.js +0 -1
  704. package/.next/static/chunks/app/api/worktrees/[id]/upload/[...path]/route-c81284a9d8b35304.js +0 -1
  705. package/.next/static/chunks/app/api/worktrees/[id]/verify/config/route-c81284a9d8b35304.js +0 -1
  706. package/.next/static/chunks/app/api/worktrees/[id]/verify/route-c81284a9d8b35304.js +0 -1
  707. package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route-c81284a9d8b35304.js +0 -1
  708. package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/[runId]/route-c81284a9d8b35304.js +0 -1
  709. package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/route-c81284a9d8b35304.js +0 -1
  710. package/.next/static/chunks/app/api/worktrees/[id]/viewed/route-c81284a9d8b35304.js +0 -1
  711. package/.next/static/chunks/app/api/worktrees/apply-default-agents/route-c81284a9d8b35304.js +0 -1
  712. package/.next/static/chunks/app/api/worktrees/route-c81284a9d8b35304.js +0 -1
  713. package/.next/static/chunks/app/layout-aa8e66164a4367af.js +0 -1
  714. package/.next/static/chunks/app/manifest.webmanifest/route-c81284a9d8b35304.js +0 -1
  715. package/.next/static/chunks/app/proxy/[...path]/route-c81284a9d8b35304.js +0 -1
  716. package/.next/static/chunks/app/sessions/page-cfd645305e25fd33.js +0 -1
  717. package/.next/static/chunks/app/worktrees/[id]/layout-c81284a9d8b35304.js +0 -1
  718. package/.next/static/chunks/app/worktrees/[id]/page-a8d7886703ffc7b4.js +0 -1
  719. package/.next/static/css/db8959555c3d9c96.css +0 -1
  720. /package/.next/static/{3_JtAZaKMJEDFIIfkHv4n → fqfSDqQMweROeHUzOt_m1}/_buildManifest.js +0 -0
  721. /package/.next/static/{3_JtAZaKMJEDFIIfkHv4n → fqfSDqQMweROeHUzOt_m1}/_ssgManifest.js +0 -0
@@ -22,21 +22,37 @@
22
22
  * Infrastructure errors use ExitCode (1, 2, 99)
23
23
  */
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
- exports.SELF_RESUME_HOLD_MS = exports.SELF_RESUME_CAPABILITY = exports.SELF_RESUME_PENDING_DETAIL = exports.TURN_OPENING_EVENT_TYPES = void 0;
26
- exports.formatRestartReleaseNotice = formatRestartReleaseNotice;
25
+ exports.settleCurrentOutputPath = exports.HOOK_STOP_SETTLE_MAX_MS = exports.HOOK_STOP_SETTLE_INTERVAL_MS = exports.TURN_OPENING_EVENT_TYPES = exports.SELF_RESUME_PENDING_DETAIL = exports.SELF_RESUME_HOLD_MS = exports.SELF_RESUME_CAPABILITY = exports.formatRestartReleaseNotice = void 0;
27
26
  exports.pollWorktree = pollWorktree;
28
27
  exports.createWaitCommand = createWaitCommand;
29
28
  const commander_1 = require("commander");
30
29
  const types_1 = require("../types");
31
30
  const api_client_1 = require("../utils/api-client");
32
31
  const command_helpers_1 = require("../utils/command-helpers");
33
- const verify_runner_1 = require("../utils/verify-runner");
34
32
  const agent_target_options_1 = require("../config/agent-target-options");
35
33
  const prompt_1 = require("./prompt");
36
34
  const prompt_view_1 = require("../../lib/session/prompt-view");
37
35
  const instances_1 = require("./instances");
38
- /** [IA3-02] Polling interval 5 seconds (matches tmux-capture-cache TTL=2s) */
39
- const POLL_INTERVAL_MS = 5000;
36
+ const wait_timing_1 = require("./wait-timing");
37
+ const wait_notices_1 = require("./wait-notices");
38
+ const wait_turn_boundary_1 = require("./wait-turn-boundary");
39
+ const wait_hook_stop_settle_1 = require("./wait-hook-stop-settle");
40
+ const wait_verify_1 = require("./wait-verify");
41
+ const wait_instance_1 = require("./wait-instance");
42
+ const wait_poll_bookkeeping_1 = require("./wait-poll-bookkeeping");
43
+ // Issue #3964: the split-out modules' exports, re-exported so every import of
44
+ // `./wait` keeps working.
45
+ var wait_notices_2 = require("./wait-notices");
46
+ Object.defineProperty(exports, "formatRestartReleaseNotice", { enumerable: true, get: function () { return wait_notices_2.formatRestartReleaseNotice; } });
47
+ var wait_turn_boundary_2 = require("./wait-turn-boundary");
48
+ Object.defineProperty(exports, "SELF_RESUME_CAPABILITY", { enumerable: true, get: function () { return wait_turn_boundary_2.SELF_RESUME_CAPABILITY; } });
49
+ Object.defineProperty(exports, "SELF_RESUME_HOLD_MS", { enumerable: true, get: function () { return wait_turn_boundary_2.SELF_RESUME_HOLD_MS; } });
50
+ Object.defineProperty(exports, "SELF_RESUME_PENDING_DETAIL", { enumerable: true, get: function () { return wait_turn_boundary_2.SELF_RESUME_PENDING_DETAIL; } });
51
+ Object.defineProperty(exports, "TURN_OPENING_EVENT_TYPES", { enumerable: true, get: function () { return wait_turn_boundary_2.TURN_OPENING_EVENT_TYPES; } });
52
+ var wait_hook_stop_settle_2 = require("./wait-hook-stop-settle");
53
+ Object.defineProperty(exports, "HOOK_STOP_SETTLE_INTERVAL_MS", { enumerable: true, get: function () { return wait_hook_stop_settle_2.HOOK_STOP_SETTLE_INTERVAL_MS; } });
54
+ Object.defineProperty(exports, "HOOK_STOP_SETTLE_MAX_MS", { enumerable: true, get: function () { return wait_hook_stop_settle_2.HOOK_STOP_SETTLE_MAX_MS; } });
55
+ Object.defineProperty(exports, "settleCurrentOutputPath", { enumerable: true, get: function () { return wait_hook_stop_settle_2.settleCurrentOutputPath; } });
40
56
  /**
41
57
  * `type` reported for a blocked-on-a-human frame that carries no parsable prompt
42
58
  * (Issue #1628). Arrow-key menus — Codex's pager and `/model`, antigravity's
@@ -74,76 +90,6 @@ function waitAnswerVia(view) {
74
90
  return 'api';
75
91
  return 'terminal';
76
92
  }
77
- /**
78
- * Why `wait` decided the agent was done, printed on the completion line
79
- * (Issue #1839).
80
- *
81
- * `Completed: <id>` used to be the whole story, which made two very different
82
- * situations indistinguishable in a log: the agent's own `Stop` hook arrived, or
83
- * nothing but the screen said so. The measurement behind this Issue is exactly
84
- * that difference — a 529 storm returns Claude to its composer in ~3 s with the
85
- * scraper reporting `ready`/`input_prompt` and no `Stop` ever sent — so the
86
- * basis belongs next to the verdict rather than in a triage session afterwards.
87
- */
88
- const COMPLETION_BASIS = {
89
- /** The agent reported the turn ended, and the report postdates this wait's turn. */
90
- HOOK_STOP: 'hook_stop',
91
- /** The tmux session went away after we had seen it alive. */
92
- SESSION_GONE: 'session_gone',
93
- /** The terminal frame says the agent is back at its composer. Nothing corroborated it. */
94
- SCRAPER_READY: 'scraper_ready',
95
- };
96
- /**
97
- * Structured event types that mean "a turn is under way" (Issue #1839).
98
- *
99
- * Mirrors AGENT_EVENT_TYPES in src/lib/hooks/agent-event-types.ts; duplicated
100
- * rather than imported because the CLI bundle keeps its own copy of the API
101
- * shapes (see api-responses.ts).
102
- *
103
- * `notification` is deliberately absent, and that is the one measured deviation
104
- * from the design sketched in Issue #1839. The Issue proposed accepting
105
- * `stop` **or** `idle_prompt` as the end of a turn; the live capture of
106
- * 2026-08-20 (see docs/design/upstream-fault-turn-boundary-1839.md) shows
107
- * Claude 2.1.236 emitting `Notification(idle_prompt)` 62 s into a turn that
108
- * ran nothing at all, because the composer had been idle for a minute. Reading
109
- * it as a turn boundary would have re-created the false completion this gate
110
- * exists to stop, one minute later. Only `Stop` ends a turn.
111
- *
112
- * Exported for the cross-layer pin in
113
- * `tests/unit/session/status-contract-1926.test.ts`. The server opens a turn on
114
- * the same three events (`src/lib/session/provisional-turn.ts`
115
- * TURN_ACTIVITY_EVENTS), and since Issue #1930 `adoptTurnStart` reads that
116
- * turn's `openedAt` rather than this set — so a set that drifted would change
117
- * this gate silently. The set is still read here for the pre-#1930 fallback
118
- * path, and the CLI cannot import the server module (`tsconfig.cli.json` sets
119
- * `"paths": {}`), so the test is the only thing holding the two together.
120
- */
121
- exports.TURN_OPENING_EVENT_TYPES = new Set([
122
- 'user_prompt_submit',
123
- 'pre_tool_use',
124
- 'post_tool_use',
125
- ]);
126
- /**
127
- * How far *before* this wait started a turn-opening event may sit and still be
128
- * read as the turn this wait is about (Issue #1839).
129
- *
130
- * `wait` does not know when `send` ran, and the honest proxy is its own start:
131
- * an orchestrator sends and then waits, so the turn's `UserPromptSubmit` lands
132
- * after `wait` is already polling (measured at +0.6 s from the send). One poll
133
- * interval of slack covers a `wait` that starts a moment late.
134
- *
135
- * The bound is what keeps this from being a new way to hang, and Issue #1930
136
- * narrowed what it has to defend against. It was written when structured events
137
- * were NOT fenced by generation on the way into `structuredEvents`, so a stale
138
- * `user_prompt_submit` from a previous agent process could still be the last
139
- * event on the wire and this window was the only thing stopping it from gating
140
- * a wait for ever. The server fences the turn now and publishes null when it
141
- * does, so the window's remaining job is narrower and sharper: a turn that has
142
- * already CLOSED must have closed inside this wait to count, or `wait` on a
143
- * session that finished an hour ago would inherit that turn's gate. An open
144
- * turn is adopted whatever its age — see {@link adoptTurnStart}.
145
- */
146
- const TURN_ADOPTION_GRACE_MS = POLL_INTERVAL_MS;
147
93
  /**
148
94
  * How long `isUnclassifiedActive` must hold before `wait` treats it as a stop
149
95
  * reason (Issue #1708).
@@ -163,625 +109,6 @@ const TURN_ADOPTION_GRACE_MS = POLL_INTERVAL_MS;
163
109
  * for working around a detector bug, and the bug is the thing to fix.
164
110
  */
165
111
  const UNCLASSIFIED_DWELL_MS = 60_000;
166
- /**
167
- * The keystroke that closes opencode's sidebar, in opencode's own notation
168
- * (Issue #2095).
169
- *
170
- * A local copy of `OPENCODE_SIDEBAR_RECOVERY_CHORD` from
171
- * `src/lib/detection/opencode-pane-obstruction.ts` and not an import: the CLI
172
- * builds with `"paths": {}` (tsconfig.cli.json) and cannot reach `@/lib` at all,
173
- * which is why `api-responses.ts` mirrors payload shapes rather than importing
174
- * them. Taken from opencode's own keybind table, which its `ctrl+p` palette
175
- * prints as `Show sidebar ctrl+x b`.
176
- */
177
- const OPENCODE_SIDEBAR_RECOVERY_CHORD = 'ctrl+x b';
178
- /**
179
- * The cause sentence to append when the frame carries a pane obstruction, or ''
180
- * (Issue #2095).
181
- *
182
- * Appended rather than substituted, and no exit code moves: the frame is
183
- * genuinely unclassified and `wait` was already right to stop on it. What it
184
- * could not say before is WHY, which left an operator with `capture --pane` and
185
- * a screenful of box drawing to work it out from.
186
- *
187
- * Empty for a server too old to publish the field, which is the same output
188
- * `wait` produced before this Issue.
189
- */
190
- function describePaneObstruction(data) {
191
- const obstruction = data.paneObstruction;
192
- if (!obstruction)
193
- return '';
194
- return (` Cause: paneObstruction=${obstruction.id} — a second column is sharing rows with the ` +
195
- `transcript (it reads ${JSON.stringify(obstruction.matchedText)}), which covers the marker ` +
196
- `that ends a turn. Press \`${OPENCODE_SIDEBAR_RECOVERY_CHORD}\` in the pane to close ` +
197
- `opencode's sidebar.`);
198
- }
199
- /**
200
- * How recent `autoYes.lastSuppression` must be to be reported as the reason this
201
- * wait is blocked (Issue #1699).
202
- *
203
- * The record is refreshed on every poll for as long as the suppressed prompt is
204
- * on screen, so a fresh timestamp means "this is happening now" while an old one
205
- * is a historical suppression of some earlier prompt. The window is generous
206
- * against the server's own poll interval — being a few seconds late with a true
207
- * report beats staying silent, which is the failure this exists to fix.
208
- *
209
- * Issue #2463 reads the same window as "the policy withheld THIS prompt", which
210
- * is what ends the Auto-Yes hold at once. `current-output` publishes no start
211
- * time for a scraped prompt, so the push gate's `suppression.at >= waitingSince`
212
- * (`src/lib/push/prompt-push-gate.ts`) cannot be computed here; a record that is
213
- * still being re-stamped is the CLI's reading of it. Using one window for both
214
- * keeps the hold and the payload in agreement: an exit 10 carries
215
- * `autoYesSuppression` exactly when the hold judged the answer withheld. The
216
- * error runs towards reporting — a withheld answer to an earlier prompt, under a
217
- * minute old, still ends the hold, which is the pre-#2463 exit rather than a
218
- * new failure.
219
- *
220
- * Issue #3798: a server that names the waiting episodes does what the push gate
221
- * does — the record's `episodeId` against the payload's
222
- * `autoYes.waitingEpisodeId`, which decide when both are present: another id
223
- * (or no wait open) is a record of an earlier wait, however recent; the same
224
- * id is this wait's. Either one missing (an older server, a record written
225
- * before any wait was open), this window decides as before. Whichever
226
- * decides, a record the server marks `lastSuppressionAnswered` — Auto-Yes
227
- * answered the open wait after it was written — is history, not this wait's
228
- * reason, as the push gate reads it: the hold goes on.
229
- */
230
- const SUPPRESSION_FRESH_MS = 60_000;
231
- /**
232
- * The suppression currently blocking this session, or null.
233
- *
234
- * Issue #3863: with the Auto-Yes answer mode in effect (`autoYesAnswerMode`)
235
- * when the server publishes one — what `question-left-to-human` and
236
- * `recommended-option-unidentified` depend on.
237
- */
238
- function activeSuppression(data, now) {
239
- // No `autoYes` at all (a session that is not running, Issue #3300) reads as
240
- // "nothing was withheld", the same as a null record.
241
- const suppression = data.autoYes?.lastSuppression;
242
- if (!suppression)
243
- return null;
244
- const ageMs = now - suppression.at;
245
- const waitId = data.autoYes?.waitingEpisodeId;
246
- if (suppression.episodeId !== undefined && waitId !== undefined) {
247
- if (suppression.episodeId !== waitId)
248
- return null;
249
- }
250
- else if (ageMs > SUPPRESSION_FRESH_MS) {
251
- // A negative age is clock skew between the CLI and the server, not staleness.
252
- return null;
253
- }
254
- if (data.autoYes?.lastSuppressionAnswered === true)
255
- return null;
256
- const answerMode = data.autoYesAnswerMode;
257
- return {
258
- suppression,
259
- ageSeconds: Math.max(0, Math.round(ageMs / 1000)),
260
- ...(answerMode !== undefined ? { answerMode } : {}),
261
- };
262
- }
263
- /** The wording for the four reasons a contract's `autoYes` block really authors. */
264
- const CONTRACT_POLICY_CAUSE = 'by contract policy';
265
- /**
266
- * What withheld the answer, in the words `wait` puts on stderr (Issue #1843).
267
- *
268
- * A Record over the whole reason union rather than one fixed phrase: adding a
269
- * reason to {@link AutoYesSuppressionReason} without deciding what `wait` should
270
- * say about it is a compile error here, which is the point. Until #1843 the
271
- * notice hard-coded "by contract policy" for every reason, so #1829's
272
- * `agent-launch-dialog` — a product-side decision the poller makes with no
273
- * contract in sight (`suppressIfNotOursToAnswer` in
274
- * `src/lib/polling/auto-yes-prompt-suppression.ts`: codex's lifecycle dialogs,
275
- * gemini's folder trust since #3776 and copilot's since #3790) — sent operators
276
- * of contract-less worktrees hunting for a `denyPatterns` entry that did not
277
- * exist.
278
- *
279
- * The three sites that record a suppression are covered: the poller's launch-dialog
280
- * branch (`agent-launch-dialog`), the poller's policy branch and
281
- * `lib/hooks/permission-decision-service.ts` (both the four `evaluatePolicyAgainstTexts`
282
- * verdicts, which is why those four keep the pre-#1843 wording exactly), and
283
- * the poller's stopped-answer branch (`partial-answer`, Issue #3706 / #3713),
284
- * and the poller's agy trust-screen branch (`startup-trust-unhandled`, Issue #3757),
285
- * and the poller's question confirm-page branch (`question-confirm-page`, Issue #3748),
286
- * and the poller's question branch (`question-left-to-human`, Issue #3822),
287
- * and the resolver's permission-row reading (`allow-once-unidentified`, Issue #3822),
288
- * and the resolver's choice of a question's recommended option
289
- * (`recommended-option-unidentified`, Issue #3863),
290
- * and the poller's agy receipt-gate branch (`no-hook-receipt`, Issue #3767),
291
- * and a contract lookup that failed on either of the policy paths
292
- * (`policy-lookup-failed`, Issue #3822).
293
- */
294
- const SUPPRESSION_CAUSE = {
295
- 'mode-off': CONTRACT_POLICY_CAUSE,
296
- 'deny-pattern': CONTRACT_POLICY_CAUSE,
297
- 'deny-pattern-unusable': CONTRACT_POLICY_CAUSE,
298
- 'type-not-allowed': CONTRACT_POLICY_CAUSE,
299
- // Issue #3822. Not "by contract policy": the contract could not be read at
300
- // all, so nothing it says was applied. Withheld rather than answered, since
301
- // the contract may state `off`; it clears once the server reads it again.
302
- 'policy-lookup-failed': 'because the server could not read the execution contract (the database lookup failed), so Auto-Yes does not answer until it can; check the server log for policy-lookup-failed',
303
- // Issue #3790: after the launch window the poller still leaves copilot's and
304
- // gemini's trust dialogs alone when the cursor is not on the safe row, and
305
- // nobody else answers them then.
306
- 'agent-launch-dialog': "while the agent's launch dialog was on screen; if it stays after the launch (copilot's cursor on 2. or 3., gemini's not on 1. Trust folder), answer it at the pane",
307
- // Issue #1924. Deliberately not "by contract policy": no contract was
308
- // consulted. The frame looked like a numbered list to the generic estimator
309
- // and like prose to the tool's own detector, and an operator who reads this
310
- // should go and look at the pane rather than at `denyPatterns`.
311
- 'unclassified-frame': 'because no tool-specific dialog detector recognised the frame',
312
- // Issue #3713 (#3706's reason). Not "by contract policy" either: an earlier
313
- // Auto-Yes answer was stopped with some of its keys already in the input, and
314
- // typing it again would append to them, so the prompt waits for a human.
315
- // Issue #3880: or a send of it (Auto-Yes's, or a person's that failed) ended
316
- // without tmux confirming it, and no key may be known to be there. The #3713
317
- // sentence is kept as it was and the other case follows it.
318
- 'partial-answer': "because an earlier answer left partial input; Auto-Yes is waiting for a human (or that answer's send could not be confirmed, so the input may hold it: check the pane, then answer; an answer that goes through releases the hold)",
319
- // Issue #3757. agy's startup folder-trust screen: the launch's to confirm, not
320
- // Auto-Yes's, and agy drew it after the launch window had ended.
321
- 'startup-trust-unhandled': "because agy's startup folder-trust confirmation is the launch's to answer, not Auto-Yes's; the next send confirms it once, or answer it at the pane",
322
- // Issue #3748. The AskUserQuestion confirm page (`Submit` / `Cancel`): the
323
- // tool's own reader recognised it, and `Submit` commits whatever stands as the
324
- // answers, so it waits for a human. Was recorded as `unclassified-frame`,
325
- // whose wording above says the opposite (nothing recognised the frame).
326
- 'question-confirm-page': "because the question's Submit/Cancel confirmation commits the answers as they stand, so Auto-Yes leaves it to a human",
327
- // Issue #3822. A question the agent asks the operator (an AskUserQuestion
328
- // picker, OpenCode V2's question form): Auto-Yes answers permissions only,
329
- // and no contract setting delegates the question. Issue #3863: since the
330
- // answer modes, that is the `careful` mode's rule (and OpenCode V2's form
331
- // under either mode); `answerMode=` on the line says which mode was on.
332
- 'question-left-to-human': 'because the agent is asking a question, and Auto-Yes answers permissions only (the careful answer mode, or a question form no mode answers); answer it at the pane (prompt --json, respond), or turn Auto-Yes on with --answer-mode recommended to have it pick the recommended option',
333
- // Issue #3822. A permission dialog none of whose rows allows this call only
334
- // (each saves a rule, changes the mode or denies), or two of which read so.
335
- // Auto-Yes never picks a row that outlives this call, so it waits for a human.
336
- 'allow-once-unidentified': 'because no single option of the permission dialog allows this call only (the others save a rule, change the permission mode, or deny); Auto-Yes does not pick those, so answer it at the pane (prompt --json, respond)',
337
- // Issue #3863. The recommended answer mode answers a question with its one
338
- // recommended option (else its default), and could not tell which that is.
339
- 'recommended-option-unidentified': "because the question's recommended option could not be told (two or more marked recommended, a title it could not tell from its description, a typed-text or multi-select answer); answer it at the pane (prompt --json, respond)",
340
- // Issue #3767. agy's approval dialog has no matching hook question (none, too
341
- // late, already on screen, or the hook stopped arriving). Not a contract verdict.
342
- // Issue #3789: nor one left unused — the last was spent on keys Auto-Yes sent,
343
- // and a dialog is still up past the grace — so "no unused question" covers both.
344
- 'no-hook-receipt': "because there is no unused agy hook permission question for this dialog (none arrived in time, or the last one was spent on keys that did not clear it); answer it yourself (auto-yes --disable, prompt --json, respond --expect-screen) or check hooks.json",
345
- };
346
- /**
347
- * {@link SUPPRESSION_CAUSE} for a reason that arrived over the wire.
348
- *
349
- * `reason` is a server-supplied string, so a server newer than this CLI can name
350
- * a reason the union does not have. Naming it verbatim is the only honest answer:
351
- * quietly folding an unknown reason into "by contract policy" is the same
352
- * misattribution #1843 exists to remove, just for a future reason instead of
353
- * `agent-launch-dialog`.
354
- */
355
- function suppressionCause(reason) {
356
- return Object.prototype.hasOwnProperty.call(SUPPRESSION_CAUSE, reason)
357
- ? SUPPRESSION_CAUSE[reason]
358
- : `for a reason this CLI does not recognise (${reason})`;
359
- }
360
- /**
361
- * One stderr line naming what is holding this prompt (Issue #1699).
362
- *
363
- * `wait` used to print only "Waiting for human response...", which reads the
364
- * same whether a human was always going to answer or whether Auto-Yes silently
365
- * refused to. That ambiguity is what let a deny pattern matching a finished turn
366
- * stall two workers unnoticed; the pattern and the reason code belong on screen.
367
- *
368
- * Issue #1843: the cause is chosen per reason rather than asserted. `reason=` is
369
- * in the payload either way, so the prefix is the only part that can lie — and it
370
- * did, for every non-contract suppression.
371
- */
372
- function formatSuppressionNotice(suppression, ageSeconds, answerMode) {
373
- const parts = [
374
- `reason=${suppression.reason}`,
375
- `mode=${suppression.mode ?? 'none'}`,
376
- `promptType=${suppression.promptType}`,
377
- ];
378
- if (suppression.pattern !== undefined) {
379
- parts.push(`pattern=${JSON.stringify(suppression.pattern)}`);
380
- }
381
- // Issue #3863: the Auto-Yes answer mode in effect, when the server says.
382
- if (answerMode !== undefined) {
383
- parts.push(`answerMode=${answerMode}`);
384
- }
385
- const cause = suppressionCause(suppression.reason);
386
- return ` auto-yes suppressed this prompt ${cause}: ${parts.join(' ')} (${ageSeconds}s ago)`;
387
- }
388
- /**
389
- * One stderr line saying Auto-Yes is off on this instance because the server
390
- * restarted (Issue #3730), or null.
391
- *
392
- * Only words: the prompt was going to be reported either way — an instance
393
- * whose grant the restart released is an instance with Auto-Yes off, and exit
394
- * 10 for it is exactly the hand-back it always was. What this adds is the WHY,
395
- * so a delegating agent re-enables Auto-Yes instead of guessing. A server
396
- * older than the reason sends none, and nothing is printed.
397
- *
398
- * The command it suggests names the instance this wait is about: without
399
- * `--instance`, `auto-yes --enable` arms the worktree's default primary, which
400
- * for an alias (or a non-default tool) is another instance — the waited-on one
401
- * would stay off while a grant went somewhere nobody asked for. The instance is
402
- * the resolved `--instance` when one was given, else the CLI tool the server
403
- * answered for (a primary's instance ID is its tool ID).
404
- *
405
- * @param instanceId - The resolved `--instance` of this wait, if any
406
- */
407
- function formatRestartReleaseNotice(worktreeId, data, instanceId) {
408
- if (data.autoYes?.enabled !== false || data.autoYes.stopReason !== 'server-restart')
409
- return null;
410
- const target = instanceId ?? data.cliToolId;
411
- const command = `commandmate auto-yes ${worktreeId} --enable${target ? ` --instance ${target}` : ''}`;
412
- return ` auto-yes was released by a server restart on ${worktreeId} (it is not turned back on ` +
413
- `automatically); re-enable it with \`${command}\` if this session should keep answering.`;
414
- }
415
- /**
416
- * One stderr line saying Auto-Yes pressed Enter on THIS prompt (Issue #3397), or
417
- * null when the record is absent or about another screen.
418
- *
419
- * The prompt is one CommandMate could not read (the window offers direct input
420
- * for it). `sent` — Auto-Yes confirmed whatever was selected; `no-effect` — the
421
- * same screen outlived the Enter, no second one was sent, and it is a human's
422
- * again. An outcome this CLI does not know is named verbatim (#1843's rule).
423
- * `currentPrompt` is the server's judgement that the record is about the
424
- * `promptData` of the same response, so an Enter sent to an earlier screen is
425
- * never reported against this one.
426
- */
427
- function formatEnterFallbackNotice(data, now) {
428
- const record = data.autoYes?.lastEnterFallback;
429
- if (!record || record.currentPrompt !== true)
430
- return null;
431
- const detail = `refusal=${record.refusalReason} promptType=${record.promptType}`;
432
- const ago = `(${Math.max(0, Math.round((now - record.at) / 1000))}s ago)`;
433
- if (record.outcome === 'sent') {
434
- return ` auto-yes sent Enter to this prompt (CommandMate could not read it): ${detail} ${ago}`;
435
- }
436
- if (record.outcome === 'no-effect') {
437
- return ` auto-yes sent Enter to this prompt, but the same screen is still up (no-effect); ` +
438
- `answer it in the terminal: ${detail} ${ago}`;
439
- }
440
- return ` auto-yes Enter record for this prompt: outcome=${record.outcome} ${detail} ${ago}`;
441
- }
442
- /**
443
- * Issue #3821: the server's own word that Auto-Yes left this prompt to a human
444
- * (`autoYesDecision.state === 'withheld'`) — `server-poller-inactive` when no
445
- * poller runs for the instance, or a stop the suppression record does not
446
- * carry. Read only when the server publishes the field; an older one leaves
447
- * `wait` holding as before.
448
- */
449
- function decisionWithheldReason(data) {
450
- const decision = data.autoYesDecision;
451
- if (decision?.state !== 'withheld')
452
- return null;
453
- return decision.reason ?? 'unknown';
454
- }
455
- /**
456
- * Whether this server publishes a real turn record (Issue #1930).
457
- *
458
- * `dialogPendingMaxMs` landed with the turn model and is set on every payload a
459
- * server of that vintage produces, so its presence is the version probe. A
460
- * *value* rather than a version string, for the reason #1924 gives for the
461
- * capability block: a payload that has to be interpreted by its sender's
462
- * version number is a payload nobody can read forward.
463
- *
464
- * The probe is needed because the two readings below disagree in exactly the
465
- * case that matters. On a #1930 server, `openedAt` being null while
466
- * `lastEventType` is `user_prompt_submit` means the turn was fenced off by a
467
- * generation or aged out — the server has *decided* it is not this instance's
468
- * turn. Falling back to the event on such a payload would put back the stale
469
- * adoption the turn record exists to remove.
470
- */
471
- function publishesTurnRecord(data) {
472
- return data.structuredEvents?.dialogPendingMaxMs != null;
473
- }
474
- /**
475
- * Adopt the turn this wait is about, if this poll shows one (Issue #1839,
476
- * moved onto the turn record in #1930).
477
- *
478
- * ## What changed, and why the grace window is no longer the whole guard
479
- *
480
- * Before #1930 this read `lastEventType` / `lastEventAt` — the newest event of
481
- * any kind — and refused anything older than {@link TURN_ADOPTION_GRACE_MS},
482
- * because (in the words of that constant) structured events "are NOT fenced by
483
- * generation on the way into `structuredEvents`", so a stale
484
- * `user_prompt_submit` from a previous agent process could still be the last
485
- * event on the wire. The bound was the only thing keeping such a record from
486
- * gating a wait for ever.
487
- *
488
- * The server fences the turn now, and publishes null when it does. So an **open**
489
- * turn is adopted whatever its age — which closes a hole the old reading had:
490
- * a turn that opened ten minutes before this `wait` started, and is still
491
- * running, used to be adopted only because its *newest* event was fresh. An
492
- * agent that goes quiet mid-turn (thinking, a long tool call) has no fresh
493
- * event, so the #1839 gate came down at exactly the moment a 529 storm would
494
- * exploit it.
495
- *
496
- * A **closed** turn still has to have opened inside this wait's window, and the
497
- * reason is the one the grace constant gives: `wait` does not know when `send`
498
- * ran, so the last turn of a session that finished an hour ago must not gate a
499
- * wait that has only just started. `commandmate wait` on an already-idle
500
- * session therefore adopts nothing and completes on its first poll, exactly as
501
- * it did before — #1975 measured that at 234/242/259 ms and it is the
502
- * orchestrator's normal path.
503
- *
504
- * @param previous - the turn start adopted so far, or null
505
- * @returns the newest adopted turn start, or `previous` when nothing qualified
506
- */
507
- function adoptTurnStart(data, waitStartedAt, previous) {
508
- const events = data.structuredEvents;
509
- if (!events)
510
- return previous;
511
- if (!publishesTurnRecord(data)) {
512
- // A server older than #1930. Same reading this function has had since
513
- // #1839, kept so a newer CLI pointed at an older server does not silently
514
- // lose the gate.
515
- if (events.lastEventAt == null || events.lastEventType == null)
516
- return previous;
517
- if (!exports.TURN_OPENING_EVENT_TYPES.has(events.lastEventType))
518
- return previous;
519
- if (events.lastEventAt < waitStartedAt - TURN_ADOPTION_GRACE_MS)
520
- return previous;
521
- return previous === null || events.lastEventAt > previous ? events.lastEventAt : previous;
522
- }
523
- const openedAt = events.openedAt;
524
- // Null covers every "there is no turn to adopt" case the server knows about:
525
- // nothing reported, a previous generation, aged out, or a `stop` whose
526
- // opening was never observed.
527
- if (openedAt == null)
528
- return previous;
529
- if (events.closedAt != null && openedAt < waitStartedAt - TURN_ADOPTION_GRACE_MS) {
530
- return previous;
531
- }
532
- return previous === null || openedAt > previous ? openedAt : previous;
533
- }
534
- /**
535
- * `structuredEvents.closedBy`, phrased for a diagnostic line (Issue #1930).
536
- *
537
- * The server's close-reason vocabulary and {@link COMPLETION_BASIS} answer two
538
- * different questions — "why did the turn end" and "what did `wait` decide on"
539
- * — and are deliberately printed side by side rather than folded together.
540
- * `hook_stop` is the only place they meet: it is `closedBy: 'stop'` seen from
541
- * the CLI's end. Everything else (`stale`, `scraper_evidence`, `session_end`,
542
- * `generation`, `resync_idle`) is a reason the turn stopped being trusted, which
543
- * is precisely what `wait` must NOT read as completion.
544
- */
545
- function describeTurnClose(data) {
546
- const events = data.structuredEvents;
547
- if (!events)
548
- return 'turn=unknown';
549
- const id = events.turnId ?? 'none';
550
- const closedBy = events.closedBy ?? (events.openedAt != null ? 'open' : 'none');
551
- return `turn=${id} closedBy=${closedBy}`;
552
- }
553
- /**
554
- * Whether the agent has reported the end of the turn this wait adopted
555
- * (Issue #1839).
556
- *
557
- * True when no turn was adopted at all, which is the whole of the unchanged
558
- * path: a session whose agent posts no hooks never adopts one, so every caller
559
- * on a machine without hook injection sees precisely the pre-#1839 behaviour.
560
- */
561
- function turnSettled(data, turnStartedAt) {
562
- if (turnStartedAt === null)
563
- return true;
564
- const stoppedAt = data.lastStopEventAt;
565
- return stoppedAt != null && stoppedAt >= turnStartedAt;
566
- }
567
- /**
568
- * The structured event that ends a turn (Issue #1975).
569
- *
570
- * The counterpart of {@link TURN_OPENING_EVENT_TYPES}, kept as a bare constant
571
- * because the vocabulary a source declares in `capabilities.supportedEvents` is
572
- * the wire's, not this build's: a tool that cannot say `stop` cannot release the
573
- * hold below, so asking for the word by name is the whole of the check.
574
- */
575
- const TURN_CLOSING_EVENT_TYPE = 'stop';
576
- /**
577
- * How long `wait` will hold a composer frame open for an agent that has been
578
- * handed a prompt it has not reported the end of (Issue #1975).
579
- *
580
- * The hold's *reason* is exact — see {@link outstandingPrompt} — so this is not
581
- * a settling window standing in for evidence. It is the bound the contract of
582
- * this Issue asks for: hooks are fail-open on every path, so a `Stop` that is
583
- * simply lost (the receiver was restarted, the machine-wide
584
- * `~/.copilot/settings.json` was rewritten by another server mid-session, the
585
- * 4-second curl in the hook timed out) must not turn `wait` into a command that
586
- * never returns. After this it completes on the frame alone, exactly as it did
587
- * before this Issue, and says so.
588
- *
589
- * 60s is the same dwell {@link UNCLASSIFIED_DWELL_MS} uses for the same job, and
590
- * it is ~55x the widest send-to-turn-open window measured for this Issue
591
- * (2026-08-22, copilot 1.0.80 against an isolated server: 0.04s / 0.75s / 0.88s
592
- * / 1.10s over four sends, the last of them a cold session start). `--timeout`
593
- * and `--stall-timeout` below 60s still win, as they do for the unclassified
594
- * dwell: this pre-empts long waits, it does not extend short ones.
595
- */
596
- const PENDING_PROMPT_HOLD_MS = 60_000;
597
- /**
598
- * Whether this tool's event source claims it can report both ends of a turn
599
- * (Issue #1975).
600
- *
601
- * The gate that keeps the hold below off every path it has no evidence for.
602
- * `structuredEvents.source.capabilities` is #1924's declaration, published to
603
- * the CLI already, and the compatibility source a tool with no implementation
604
- * gets (`src/lib/hooks/sources/legacy-relay.ts`) declares `supportedEvents: []`
605
- * — so a tool that posts no hooks answers `false` here and takes precisely the
606
- * pre-#1975 path. So does a server older than #1924, which sends no `source` at
607
- * all.
608
- *
609
- * Both words are required. Without a turn-opening word nothing would ever open
610
- * the turn this waits for; without `stop` nothing could ever close it, and the
611
- * hold would only ever end at its own bound.
612
- */
613
- function reportsTurnBoundaries(data) {
614
- const declared = data.structuredEvents?.source?.capabilities?.supportedEvents;
615
- if (!Array.isArray(declared))
616
- return false;
617
- return (declared.includes(TURN_CLOSING_EVENT_TYPE) &&
618
- declared.some(event => exports.TURN_OPENING_EVENT_TYPES.has(event)));
619
- }
620
- /**
621
- * The `stop` detail meaning "the agent ended its turn with its own background
622
- * work still running, and resumes by itself when that work finishes"
623
- * (Issue #2614).
624
- *
625
- * A copy of `SELF_RESUME_PENDING_DETAIL` in `src/lib/hooks/agent-event-types.ts`
626
- * for the reason {@link TURN_OPENING_EVENT_TYPES} is a copy: the CLI builds with
627
- * `"paths": {}`. `tests/unit/cli/commands/wait-self-resume-2614.test.ts` pins the
628
- * two together.
629
- */
630
- exports.SELF_RESUME_PENDING_DETAIL = 'self_resume_pending';
631
- /**
632
- * The capability a source declares when its `stop` can carry
633
- * {@link SELF_RESUME_PENDING_DETAIL} (Issue #2614).
634
- *
635
- * Read by name rather than through the mirrored type in `api-responses.ts`,
636
- * which predates it: `structuredEvents.source.capabilities` is published as the
637
- * source's whole declaration, so a newer server sends the key and an older one
638
- * simply does not.
639
- */
640
- exports.SELF_RESUME_CAPABILITY = 'stopReportsSelfResume';
641
- /**
642
- * How long `wait` holds a `stop` whose agent said it would resume by itself
643
- * (Issue #2614).
644
- *
645
- * Measured 2026-09-17 against antigravity 1.2.4: a `schedule` of 60 s closed the
646
- * turn, the agent woke 58 s after its `Stop` and did it again three more times,
647
- * and the real end came five minutes after the first `Stop` — which is where
648
- * `wait` had already reported `Completed (basis=hook_stop)` and started a
649
- * verification against a half-finished worktree. The wake is not something to
650
- * time: it is a `post_tool_use` that opens a new turn, and #1839's gate takes
651
- * over from there. What needs a bound is only the case where it never comes.
652
- *
653
- * A timer's own length is not on the wire (the `schedule` arguments reach the
654
- * permission receiver and stop there), and a command sent to the background has
655
- * no length at all, so the bound is the one the server already uses for the
656
- * same question the other way round: how long an open turn is trusted with
657
- * nothing heard (`TURN_STALE_AFTER_MS` in `src/lib/session/provisional-turn.ts`,
658
- * pinned equal by `wait-self-resume-2614.test.ts`). Every wake starts a new
659
- * `stop` and a new hold, so an agent that keeps rescheduling never reaches it.
660
- *
661
- * A constant, like {@link PENDING_PROMPT_HOLD_MS}: `--timeout` and
662
- * `--stall-timeout` below it still win.
663
- */
664
- exports.SELF_RESUME_HOLD_MS = 30 * 60 * 1000;
665
- /**
666
- * Whether this tool's event source can say, on its `stop`, that the agent will
667
- * resume by itself (Issue #2614).
668
- *
669
- * The same kind of gate as {@link reportsTurnBoundaries}, and it requires that
670
- * one too: the hold below is released by a turn-opening event, and a source
671
- * that cannot send one could only ever end the hold at its bound. A server that
672
- * predates the declaration answers `false`, and so does every source but the one
673
- * that writes the detail.
674
- */
675
- function reportsSelfResume(data) {
676
- const declared = data.structuredEvents?.source?.capabilities;
677
- return declared?.[exports.SELF_RESUME_CAPABILITY] === true && reportsTurnBoundaries(data);
678
- }
679
- /**
680
- * The instant of the `stop` this agent said it would resume from, or null
681
- * (Issue #2614).
682
- *
683
- * Non-null only while that `stop` is still the newest thing the agent has said.
684
- * The wake is a `post_tool_use` (antigravity reports the timer's own tool call
685
- * finishing when it fires), which replaces the displayed event and opens a new
686
- * turn, so this answers null from the first poll after it — and a later `stop`
687
- * is a different instant, which is how a hold knows it is about a new one.
688
- *
689
- * On a server that publishes a turn record the `stop` must also be what closed
690
- * that turn: a turn ended by `generation` or `session_end` belongs to a process
691
- * that is gone, and nothing it scheduled is going to wake anything.
692
- */
693
- function pendingSelfResumeStop(data) {
694
- if (!reportsSelfResume(data))
695
- return null;
696
- const events = data.structuredEvents;
697
- if (!events || events.lastEventType !== TURN_CLOSING_EVENT_TYPE)
698
- return null;
699
- if (events.lastEventDetail !== exports.SELF_RESUME_PENDING_DETAIL)
700
- return null;
701
- // `closedBy` is the server's close-reason vocabulary; `'stop'` there is the
702
- // agent's own `Stop`, the only close this hold is about.
703
- if (publishesTurnRecord(data) && events.closedBy !== 'stop')
704
- return null;
705
- return events.lastEventAt ?? null;
706
- }
707
- /**
708
- * When this (worktree, instance) was last handed a prompt (Issue #1975).
709
- *
710
- * `limit=1&unit=pairs` is "every row at or after the newest user message"
711
- * (src/lib/db/chat-db.ts), which is the smallest query that is *guaranteed* to
712
- * contain that message: plain `limit=1` returns the newest row of either role,
713
- * and for a turn the agent has already answered that row is the assistant's.
714
- *
715
- * Scoped the same way the poll above is: `--instance` when the caller named one,
716
- * otherwise the `cliToolId` the server resolved for that same poll. Asking
717
- * unscoped would let a message sent to claude decide a wait on codex.
718
- *
719
- * Never throws. An unreadable ledger is not evidence that nothing was sent, so
720
- * it is reported as such rather than as "nothing was sent" — the call site
721
- * degrades to the pre-#1975 behaviour instead of holding on a guess.
722
- */
723
- async function readNewestPromptAt(client, worktreeId, options, data) {
724
- const query = new URLSearchParams({ limit: '1', unit: 'pairs' });
725
- if (options.instance)
726
- query.set('instance', options.instance);
727
- else if (data.cliToolId)
728
- query.set('cliTool', data.cliToolId);
729
- try {
730
- const rows = await client.get(`/api/worktrees/${worktreeId}/messages?${query.toString()}`);
731
- let newest = null;
732
- for (const row of rows ?? []) {
733
- if (row.role !== 'user')
734
- continue;
735
- // ISO string on the wire (a JSON-serialized Date), so this is the only
736
- // place the two clocks meet — and both sides of the comparison below are
737
- // stamped by the server, so no CLI/server skew enters the verdict.
738
- const at = Date.parse(row.timestamp);
739
- if (Number.isNaN(at))
740
- continue;
741
- if (newest === null || at > newest)
742
- newest = at;
743
- }
744
- return { readable: true, submittedAt: newest };
745
- }
746
- catch (error) {
747
- console.error(`Note: could not read the message ledger for ${worktreeId} ` +
748
- `(${error instanceof Error ? error.message : String(error)}); ` +
749
- 'completion will be judged from the frame alone.');
750
- return { readable: false };
751
- }
752
- }
753
- /**
754
- * Whether the newest prompt this instance was handed is still unanswered
755
- * (Issue #1975).
756
- *
757
- * This is the distinction the whole Issue turns on, and it is a comparison of
758
- * two server-stamped facts rather than a timer:
759
- *
760
- * - **idle before this wait began** — the agent's `Stop` postdates the newest
761
- * prompt. Nothing is outstanding; `wait` completes on the first poll exactly
762
- * as it always has. An orchestrator waiting on a session that finished long
763
- * ago pays nothing.
764
- * - **`send` a moment ago** — the newest prompt postdates the last `Stop`
765
- * (or there has never been one). The agent has been given work and has not
766
- * reported finishing it, so a composer frame is "it has not started yet",
767
- * not "it is done".
768
- *
769
- * `wait` could not tell these apart before, because from `current-output` alone
770
- * they are the same payload: in both, the last thing the agent said was the
771
- * previous turn's `stop`, and `adoptTurnStart` adopts nothing. Measured against
772
- * copilot 1.0.80 on 2026-08-22, the window in which that is true after a send is
773
- * ~1s wide, and `wait`'s first poll is immediate — which is why the false
774
- * completions came back in 0.3s with `basis=scraper_ready`, 3 times in 5.
775
- *
776
- * The fast-turn case falls out of the same comparison rather than needing a rule
777
- * of its own: a turn that opens and closes between two polls leaves
778
- * `lastEventType: 'stop'` (so no turn is adopted) but a `stop` that postdates
779
- * the prompt — answered, and completed on the spot.
780
- */
781
- function outstandingPrompt(data, submittedAt) {
782
- const stoppedAt = data.lastStopEventAt;
783
- return stoppedAt == null || stoppedAt < submittedAt;
784
- }
785
112
  /**
786
113
  * How long `--on-prompt agent` holds a prompt the target's own Auto-Yes is
787
114
  * answering before reporting it anyway, in seconds (Issue #2463).
@@ -815,25 +142,6 @@ function parseGraceSeconds(raw) {
815
142
  const trimmed = raw.trim();
816
143
  return /^\d+$/.test(trimmed) ? Number(trimmed) : Number.NaN;
817
144
  }
818
- /**
819
- * Whether one more poll interval still lands inside `--timeout` and
820
- * `--stall-timeout` (Issue #2463).
821
- *
822
- * The Auto-Yes hold asks before it sleeps. Otherwise a caller whose deadline
823
- * lapses during the hold would hear 124 about a prompt it used to hear 10 about:
824
- * the hold is there to give Auto-Yes a chance to answer, not to turn an open
825
- * prompt into a timeout. The same two checks the top of {@link pollWorktree}'s
826
- * loop makes, one interval ahead.
827
- */
828
- function nextPollWithinDeadlines(options, startTime, lastActivityTime, now) {
829
- const nextPollAt = now + POLL_INTERVAL_MS;
830
- if (options.timeout && nextPollAt - startTime >= options.timeout * 1000)
831
- return false;
832
- if (options.stallTimeout && nextPollAt - lastActivityTime >= options.stallTimeout * 1000) {
833
- return false;
834
- }
835
- return true;
836
- }
837
145
  /**
838
146
  * The exit-10 payload for a prompt the detection layer parsed. `suppressed` is
839
147
  * {@link activeSuppression}'s reading of the same poll.
@@ -922,7 +230,7 @@ function describeUnclassifiedFrame(worktreeId, data, dwellMs) {
922
230
  // one recovery is a keystroke in the pane. Riding the message keeps
923
231
  // the exit-code table (10, `type: unclassified`) unchanged for every
924
232
  // caller that already branches on it.
925
- describePaneObstruction(data));
233
+ (0, wait_notices_1.describePaneObstruction)(data));
926
234
  }
927
235
  /** The exit-10 payload for a persistently unclassified frame (Issue #1708). */
928
236
  function buildUnclassifiedOutput(worktreeId, data, question) {
@@ -1004,9 +312,9 @@ function promptStage(poll, state, data) {
1004
312
  // Issue #1699: report a policy suppression on both exits — the human one
1005
313
  // keeps polling and would otherwise say nothing about why nobody
1006
314
  // answered, and the agent one is read by pipelines that never see stderr.
1007
- const suppressed = activeSuppression(data, Date.now());
315
+ const suppressed = (0, wait_notices_1.activeSuppression)(data, Date.now());
1008
316
  // Issue #3821: withheld by the server's decision, with no suppression to say so.
1009
- const decisionWithheld = suppressed ? null : decisionWithheldReason(data);
317
+ const decisionWithheld = suppressed ? null : (0, wait_notices_1.decisionWithheldReason)(data);
1010
318
  const decisionNotice = decisionWithheld === null
1011
319
  ? null
1012
320
  : ` auto-yes is not answering this prompt (reason=${decisionWithheld}); it is a human's to answer.`;
@@ -1015,16 +323,16 @@ function promptStage(poll, state, data) {
1015
323
  // Block and continue polling - user handles prompt manually
1016
324
  console.error(`Prompt detected on ${worktreeId}. Waiting for human response...`);
1017
325
  if (suppressed) {
1018
- console.error(formatSuppressionNotice(suppressed.suppression, suppressed.ageSeconds, suppressed.answerMode));
326
+ console.error((0, wait_notices_1.formatSuppressionNotice)(suppressed.suppression, suppressed.ageSeconds, suppressed.answerMode));
1019
327
  }
1020
328
  if (decisionNotice)
1021
329
  console.error(decisionNotice);
1022
330
  // Issue #3397: and whether Auto-Yes already pressed Enter on it.
1023
- const enterNotice = formatEnterFallbackNotice(data, Date.now());
331
+ const enterNotice = (0, wait_notices_1.formatEnterFallbackNotice)(data, Date.now());
1024
332
  if (enterNotice)
1025
333
  console.error(enterNotice);
1026
334
  // Issue #3730: and whether a restart is why nothing is answering it.
1027
- const restartNotice = formatRestartReleaseNotice(worktreeId, data, poll.options.instance);
335
+ const restartNotice = (0, wait_notices_1.formatRestartReleaseNotice)(worktreeId, data, poll.options.instance);
1028
336
  if (restartNotice)
1029
337
  console.error(restartNotice);
1030
338
  return { kind: 'wait' };
@@ -1047,7 +355,7 @@ function promptStage(poll, state, data) {
1047
355
  }
1048
356
  const heldMs = now - state.autoYesAnsweringSince;
1049
357
  if (heldMs < autoYesGraceMs &&
1050
- nextPollWithinDeadlines(options, startTime, state.lastActivityTime, now)) {
358
+ (0, wait_timing_1.nextPollWithinDeadlines)(options, startTime, state.lastActivityTime, now)) {
1051
359
  return { kind: 'wait' };
1052
360
  }
1053
361
  console.error(heldMs < autoYesGraceMs
@@ -1062,16 +370,16 @@ function promptStage(poll, state, data) {
1062
370
  // Default (agent mode): output prompt info and exit 10
1063
371
  const promptOutput = buildPromptOutput(worktreeId, data, data.promptData, suppressed);
1064
372
  if (suppressed) {
1065
- console.error(formatSuppressionNotice(suppressed.suppression, suppressed.ageSeconds, suppressed.answerMode));
373
+ console.error((0, wait_notices_1.formatSuppressionNotice)(suppressed.suppression, suppressed.ageSeconds, suppressed.answerMode));
1066
374
  }
1067
375
  if (decisionNotice)
1068
376
  console.error(decisionNotice);
1069
377
  // Issue #3397: stderr only, like the notice above; the exit-10 payload is unchanged.
1070
- const enterNotice = formatEnterFallbackNotice(data, Date.now());
378
+ const enterNotice = (0, wait_notices_1.formatEnterFallbackNotice)(data, Date.now());
1071
379
  if (enterNotice)
1072
380
  console.error(enterNotice);
1073
381
  // Issue #3730: stderr only as well.
1074
- const restartNotice = formatRestartReleaseNotice(worktreeId, data, poll.options.instance);
382
+ const restartNotice = (0, wait_notices_1.formatRestartReleaseNotice)(worktreeId, data, poll.options.instance);
1075
383
  if (restartNotice)
1076
384
  console.error(restartNotice);
1077
385
  return exitWith({ exitCode: types_1.WaitExitCode.PROMPT_DETECTED, output: promptOutput });
@@ -1091,18 +399,18 @@ function selectionListStage(poll, data) {
1091
399
  'Waiting for human response...');
1092
400
  // Issue #1699: the poller parses frames status-detector publishes as
1093
401
  // selection lists, so a policy can be the reason this one is stuck too.
1094
- const suppressed = activeSuppression(data, Date.now());
402
+ const suppressed = (0, wait_notices_1.activeSuppression)(data, Date.now());
1095
403
  if (suppressed) {
1096
- console.error(formatSuppressionNotice(suppressed.suppression, suppressed.ageSeconds, suppressed.answerMode));
404
+ console.error((0, wait_notices_1.formatSuppressionNotice)(suppressed.suppression, suppressed.ageSeconds, suppressed.answerMode));
1097
405
  }
1098
406
  // Issue #3730
1099
- const restartNotice = formatRestartReleaseNotice(worktreeId, data, poll.options.instance);
407
+ const restartNotice = (0, wait_notices_1.formatRestartReleaseNotice)(worktreeId, data, poll.options.instance);
1100
408
  if (restartNotice)
1101
409
  console.error(restartNotice);
1102
410
  return { kind: 'wait' };
1103
411
  }
1104
412
  // Issue #3730: stderr only; the exit-10 payload is unchanged.
1105
- const restartNotice = formatRestartReleaseNotice(worktreeId, data, poll.options.instance);
413
+ const restartNotice = (0, wait_notices_1.formatRestartReleaseNotice)(worktreeId, data, poll.options.instance);
1106
414
  if (restartNotice)
1107
415
  console.error(restartNotice);
1108
416
  return exitWith({
@@ -1161,7 +469,7 @@ function unclassifiedStage(poll, state, data) {
1161
469
  if (dwellMs >= UNCLASSIFIED_DWELL_MS) {
1162
470
  const question = describeUnclassifiedFrame(worktreeId, data, dwellMs);
1163
471
  // Issue #3730: why Auto-Yes is not there to answer it, if a restart is why.
1164
- const restartNotice = formatRestartReleaseNotice(worktreeId, data, poll.options.instance);
472
+ const restartNotice = (0, wait_notices_1.formatRestartReleaseNotice)(worktreeId, data, poll.options.instance);
1165
473
  if (options.onPrompt === 'human') {
1166
474
  console.error(question);
1167
475
  if (restartNotice)
@@ -1203,14 +511,25 @@ function notRunningStage(poll, state, data, selfResumeSuffix) {
1203
511
  return exitWith({ exitCode: types_1.VerifyExitCode.NOT_STARTED });
1204
512
  }
1205
513
  if (!data.isRunning) {
1206
- console.error(`Completed: ${worktreeId} (basis=${COMPLETION_BASIS.SESSION_GONE}${selfResumeSuffix()})`);
514
+ console.error(`Completed: ${worktreeId} (basis=${wait_turn_boundary_1.COMPLETION_BASIS.SESSION_GONE}${selfResumeSuffix()})`);
1207
515
  return exitWith({ exitCode: types_1.WaitExitCode.SUCCESS });
1208
516
  }
1209
517
  return { kind: 'next' };
1210
518
  }
519
+ /**
520
+ * The upstream fault on the frame that `--fail-on-upstream-fault` reports, or
521
+ * null (Issue #1839). Prints nothing, so a caller can decide which frame the
522
+ * verdict is on before {@link upstreamFaultStage} reports it (Issue #3956).
523
+ */
524
+ function reportableUpstreamFault(poll, data) {
525
+ if (!poll.options.failOnUpstreamFault)
526
+ return null;
527
+ return data.upstreamFault ?? null;
528
+ }
1211
529
  /**
1212
530
  * Stage of a `ready` frame: an upstream fault on the frame, under
1213
- * `--fail-on-upstream-fault` (Issue #1839). Exit 11.
531
+ * `--fail-on-upstream-fault` (Issue #1839). Exit 11, with its diagnosis on
532
+ * stderr.
1214
533
  */
1215
534
  function upstreamFaultStage(poll, data) {
1216
535
  const { worktreeId, options } = poll;
@@ -1219,8 +538,8 @@ function upstreamFaultStage(poll, data) {
1219
538
  // because it is the answer to the question that gate can only ask: the
1220
539
  // turn did not end, and this is why. Without it the same session runs
1221
540
  // to --timeout and reports 124, which says nothing about the cause.
1222
- const fault = data.upstreamFault ?? null;
1223
- if (options.failOnUpstreamFault && fault) {
541
+ const fault = reportableUpstreamFault(poll, data);
542
+ if (fault) {
1224
543
  console.error(`Upstream fault on ${worktreeId}: id=${fault.id} — the agent is back at its ` +
1225
544
  'composer with an upstream API failure on screen, so this turn did not run. ' +
1226
545
  `Matched: ${JSON.stringify(fault.matchedText)}`);
@@ -1237,6 +556,32 @@ function upstreamFaultStage(poll, data) {
1237
556
  }
1238
557
  return { kind: 'next' };
1239
558
  }
559
+ /**
560
+ * The chat-ledger read of a poll, bounded by `--timeout` / `--stall-timeout`
561
+ * (Issue #3974).
562
+ *
563
+ * On an ordinary poll, a ledger that does not answer in time ends the wait
564
+ * ({@link DeadlineReached} back to {@link deadlineStage}, exit 124), not
565
+ * "unreadable". On the frame a settle returned (`judgingSettledFrame`) it does
566
+ * not: that frame was read inside the deadlines and is judged even after them
567
+ * (#3956), so the ledger is reported unreadable and the frame decides alone —
568
+ * as {@link faultFrameHasStop} treats a ledger cut by the same deadlines.
569
+ */
570
+ async function readLedgerWithinDeadlines(poll, state, data, judgingSettledFrame) {
571
+ const { client, worktreeId, options, startTime } = poll;
572
+ try {
573
+ // Quiet when aborted: what the deadline leads to is said here (settled
574
+ // frame) or by deadlineStage (124), not "judged from the frame alone".
575
+ return await (0, wait_timing_1.readWithinDeadlines)(options, startTime, state.lastActivityTime, signal => (0, wait_turn_boundary_1.readNewestPromptAt)(client, worktreeId, options, data, signal, true));
576
+ }
577
+ catch (error) {
578
+ if (!judgingSettledFrame || !(error instanceof wait_timing_1.DeadlineReached))
579
+ throw error;
580
+ console.error(`Note: the message ledger for ${worktreeId} could not be read within --timeout/--stall-timeout; ` +
581
+ 'judging the settled frame alone.');
582
+ return { readable: false };
583
+ }
584
+ }
1240
585
  /**
1241
586
  * How long `wait` holds an orphan turn — see {@link releaseOrphanTurn} — before
1242
587
  * completing on the `Stop` that answered the newest prompt (Issue #3429).
@@ -1247,7 +592,7 @@ function upstreamFaultStage(poll, data) {
1247
592
  * is restarted by any change to the frame, so a pane that is still drawing is
1248
593
  * never released. `--timeout` and `--stall-timeout` below it still win.
1249
594
  */
1250
- const ORPHAN_TURN_HOLD_MS = PENDING_PROMPT_HOLD_MS;
595
+ const ORPHAN_TURN_HOLD_MS = wait_turn_boundary_1.PENDING_PROMPT_HOLD_MS;
1251
596
  /**
1252
597
  * Whether the unsettled turn this wait adopted is an orphan the agent will never
1253
598
  * send a `Stop` for, held for {@link ORPHAN_TURN_HOLD_MS} (Issue #3429).
@@ -1268,13 +613,13 @@ const ORPHAN_TURN_HOLD_MS = PENDING_PROMPT_HOLD_MS;
1268
613
  * prompt has no `Stop` after it — that one keeps holding to `--timeout`;
1269
614
  * - the frame has not changed for {@link ORPHAN_TURN_HOLD_MS}.
1270
615
  */
1271
- async function releaseOrphanTurn(poll, state, data) {
1272
- const { client, worktreeId, options } = poll;
616
+ async function releaseOrphanTurn(poll, state, data, judgingSettledFrame) {
617
+ const { worktreeId } = poll;
1273
618
  const events = data.structuredEvents;
1274
619
  const closedByScreen = events?.closedBy === 'scraper_evidence' || events?.closedBy === 'stale';
1275
620
  if (!events ||
1276
- !publishesTurnRecord(data) ||
1277
- !reportsTurnBoundaries(data) ||
621
+ !(0, wait_turn_boundary_1.publishesTurnRecord)(data) ||
622
+ !(0, wait_turn_boundary_1.reportsTurnBoundaries)(data) ||
1278
623
  events.closedAt == null ||
1279
624
  events.openedAt == null ||
1280
625
  !closedByScreen ||
@@ -1283,9 +628,10 @@ async function releaseOrphanTurn(poll, state, data) {
1283
628
  state.orphanTurnHold = null;
1284
629
  return false;
1285
630
  }
1286
- const ledger = await readNewestPromptAt(client, worktreeId, options, data);
631
+ // Issue #3974: bounded by --timeout / --stall-timeout.
632
+ const ledger = await readLedgerWithinDeadlines(poll, state, data, judgingSettledFrame);
1287
633
  state.promptLedgerReadable = ledger.readable;
1288
- if (!ledger.readable || ledger.submittedAt === null || outstandingPrompt(data, ledger.submittedAt)) {
634
+ if (!ledger.readable || ledger.submittedAt === null || (0, wait_turn_boundary_1.outstandingPrompt)(data, ledger.submittedAt)) {
1289
635
  state.orphanTurnHold = null;
1290
636
  return false;
1291
637
  }
@@ -1298,7 +644,7 @@ async function releaseOrphanTurn(poll, state, data) {
1298
644
  return false;
1299
645
  console.error(`Note: ${worktreeId} answered its newest prompt with a stop ` +
1300
646
  `(lastStopEventAt=${data.lastStopEventAt}), and the turn opened after it ` +
1301
- `(turnStartedAt=${state.turnStartedAt}, ${describeTurnClose(data)}) has had no prompt, ` +
647
+ `(turnStartedAt=${state.turnStartedAt}, ${(0, wait_turn_boundary_1.describeTurnClose)(data)}) has had no prompt, ` +
1302
648
  `no stop and no new output for ${Math.round(quietMs / 1000)}s; completing on that stop.`);
1303
649
  return true;
1304
650
  }
@@ -1306,7 +652,7 @@ async function releaseOrphanTurn(poll, state, data) {
1306
652
  * Stage of a `ready` frame: the agent has not reported the end of the turn this
1307
653
  * wait adopted (Issue #1839). Held, except for an orphan turn (Issue #3429).
1308
654
  */
1309
- async function unsettledTurnStage(poll, state, data) {
655
+ async function unsettledTurnStage(poll, state, data, judgingSettledFrame) {
1310
656
  const { worktreeId } = poll;
1311
657
  // Issue #1839: `ready` off the terminal frame is the agent's composer,
1312
658
  // not the agent's verdict. Measured 2026-08-20 against a stub upstream
@@ -1315,12 +661,12 @@ async function unsettledTurnStage(poll, state, data) {
1315
661
  // hooks ARE reporting — the only case in which `turnStartedAt` is
1316
662
  // non-null — that missing `Stop` is the difference between "finished"
1317
663
  // and "never ran", and it is the only signal that carries it.
1318
- if (!turnSettled(data, state.turnStartedAt)) {
1319
- if (await releaseOrphanTurn(poll, state, data))
664
+ if (!(0, wait_turn_boundary_1.turnSettled)(data, state.turnStartedAt)) {
665
+ if (await releaseOrphanTurn(poll, state, data, judgingSettledFrame))
1320
666
  return { kind: 'next' };
1321
667
  console.error(`Waiting: ${worktreeId} is back at its composer, but its agent has not reported ` +
1322
668
  `the end of this turn (turnStartedAt=${state.turnStartedAt}, ` +
1323
- `lastStopEventAt=${data.lastStopEventAt ?? 'none'}, ${describeTurnClose(data)}). ` +
669
+ `lastStopEventAt=${data.lastStopEventAt ?? 'none'}, ${(0, wait_turn_boundary_1.describeTurnClose)(data)}). ` +
1324
670
  'Not reporting completion; inspect with ' +
1325
671
  `\`commandmate capture ${worktreeId} --json\`.`);
1326
672
  return { kind: 'wait' };
@@ -1352,13 +698,13 @@ function selfResumeHoldStage(poll, state, data, selfResumeStopAt) {
1352
698
  state.selfResumeHold = { stopAt: selfResumeStopAt, since: now };
1353
699
  const heldMs = now - state.selfResumeHold.since;
1354
700
  const elapsedMs = Math.max(heldMs, now - selfResumeStopAt);
1355
- if (elapsedMs < exports.SELF_RESUME_HOLD_MS) {
701
+ if (elapsedMs < wait_turn_boundary_1.SELF_RESUME_HOLD_MS) {
1356
702
  state.selfResumeHeld = true;
1357
703
  console.error(`Waiting: ${worktreeId} ended its turn with background work still running ` +
1358
704
  `(stoppedAt=${new Date(selfResumeStopAt).toISOString()}, ` +
1359
- `lastEventDetail=${exports.SELF_RESUME_PENDING_DETAIL}, ${describeTurnClose(data)}); ` +
705
+ `lastEventDetail=${wait_turn_boundary_1.SELF_RESUME_PENDING_DETAIL}, ${(0, wait_turn_boundary_1.describeTurnClose)(data)}); ` +
1360
706
  'it resumes by itself when that work finishes. Not reporting completion ' +
1361
- `(held ${Math.round(heldMs / 1000)}s, at most ${exports.SELF_RESUME_HOLD_MS / 1000}s ` +
707
+ `(held ${Math.round(heldMs / 1000)}s, at most ${wait_turn_boundary_1.SELF_RESUME_HOLD_MS / 1000}s ` +
1362
708
  'after the stop).');
1363
709
  return { kind: 'wait' };
1364
710
  }
@@ -1374,8 +720,8 @@ function selfResumeHoldStage(poll, state, data, selfResumeStopAt) {
1374
720
  * `next` carries whether the newest prompt was answered, which
1375
721
  * {@link completionStage} needs for its basis.
1376
722
  */
1377
- async function promptLedgerStage(poll, state, data) {
1378
- const { client, worktreeId, options, startTime } = poll;
723
+ async function promptLedgerStage(poll, state, data, judgingSettledFrame) {
724
+ const { worktreeId, startTime } = poll;
1379
725
  // Issue #1975: the same frame, one question further back. #1839's gate
1380
726
  // above can only fire once a turn has been ADOPTED, and `send` leaves a
1381
727
  // window ~1s wide in which nothing has been: the newest structured event
@@ -1393,18 +739,19 @@ async function promptLedgerStage(poll, state, data) {
1393
739
  // {@link reportsTurnBoundaries} for why a tool that posts no hooks never
1394
740
  // reaches it.
1395
741
  let answeredNewestPrompt = false;
1396
- if (state.turnStartedAt === null && state.promptLedgerReadable && reportsTurnBoundaries(data)) {
1397
- const ledger = await readNewestPromptAt(client, worktreeId, options, data);
742
+ if (state.turnStartedAt === null && state.promptLedgerReadable && (0, wait_turn_boundary_1.reportsTurnBoundaries)(data)) {
743
+ // Issue #3974: bounded by --timeout / --stall-timeout.
744
+ const ledger = await readLedgerWithinDeadlines(poll, state, data, judgingSettledFrame);
1398
745
  // One notice, then stop asking: a ledger that failed once will fail
1399
746
  // every poll, and the point of degrading is to stop paying for it.
1400
747
  state.promptLedgerReadable = ledger.readable;
1401
748
  if (ledger.readable && ledger.submittedAt !== null) {
1402
- if (outstandingPrompt(data, ledger.submittedAt)) {
749
+ if ((0, wait_turn_boundary_1.outstandingPrompt)(data, ledger.submittedAt)) {
1403
750
  const heldMs = Date.now() - startTime;
1404
- if (heldMs < PENDING_PROMPT_HOLD_MS) {
751
+ if (heldMs < wait_turn_boundary_1.PENDING_PROMPT_HOLD_MS) {
1405
752
  console.error(`Waiting: ${worktreeId} is at its composer, but the newest prompt sent to it ` +
1406
753
  `has no reported end (sentAt=${new Date(ledger.submittedAt).toISOString()}, ` +
1407
- `lastStopEventAt=${data.lastStopEventAt ?? 'none'}, ${describeTurnClose(data)}). ` +
754
+ `lastStopEventAt=${data.lastStopEventAt ?? 'none'}, ${(0, wait_turn_boundary_1.describeTurnClose)(data)}). ` +
1408
755
  'Not reporting completion: the agent has not started this turn yet.');
1409
756
  return { kind: 'wait' };
1410
757
  }
@@ -1419,25 +766,34 @@ async function promptLedgerStage(poll, state, data) {
1419
766
  }
1420
767
  return { kind: 'next', answeredNewestPrompt };
1421
768
  }
769
+ /**
770
+ * The basis of a completion on a `ready` frame (Issue #1839).
771
+ *
772
+ * `hook_stop` on both branches that have one, and they are the same statement
773
+ * made from two records: the agent reported the end of the turn this wait is
774
+ * about. `scraper_ready` keeps its documented meaning — "the screen said so and
775
+ * nothing corroborated it" — which is now exactly the set of cases that reach it.
776
+ */
777
+ function readyCompletionBasis(state, answeredNewestPrompt) {
778
+ return state.turnStartedAt !== null || answeredNewestPrompt
779
+ ? wait_turn_boundary_1.COMPLETION_BASIS.HOOK_STOP
780
+ : wait_turn_boundary_1.COMPLETION_BASIS.SCRAPER_READY;
781
+ }
1422
782
  /** Last stage of a `ready` frame: the completion line with its basis. Exit 0. */
1423
783
  function completionStage(poll, state, answeredNewestPrompt, selfResumeSuffix) {
1424
784
  const { worktreeId } = poll;
1425
- // `hook_stop` on both branches that have one, and they are the same
1426
- // statement made from two records: the agent reported the end of the
1427
- // turn this wait is about. `scraper_ready` keeps its documented meaning
1428
- // — "the screen said so and nothing corroborated it" — which is now
1429
- // exactly the set of cases that reach it.
1430
- const basis = state.turnStartedAt !== null || answeredNewestPrompt
1431
- ? COMPLETION_BASIS.HOOK_STOP
1432
- : COMPLETION_BASIS.SCRAPER_READY;
785
+ const basis = readyCompletionBasis(state, answeredNewestPrompt);
1433
786
  console.error(`Completed: ${worktreeId} (basis=${basis}${selfResumeSuffix()})`);
1434
787
  return exitWith({ exitCode: types_1.WaitExitCode.SUCCESS });
1435
788
  }
1436
789
  /**
1437
790
  * Stage: the agent is back at its composer on a frame that was understood. Asks
1438
791
  * the stages of a `ready` frame in order; the first that applies decides.
792
+ *
793
+ * `judgingSettledFrame` is true when `data` is the frame a settle returned
794
+ * (Issue #3956): it is judged as it stands and never settled again.
1439
795
  */
1440
- async function readyStage(poll, state, data, selfResumeStopAt, selfResumeSuffix) {
796
+ async function readyStage(poll, state, data, selfResumeStopAt, selfResumeSuffix, judgingSettledFrame) {
1441
797
  // Issue #1708 narrowed Path B: `ready` is only a completion when the frame
1442
798
  // was actually understood. A structured `hook_stop` over an unreadable
1443
799
  // pane is the degraded form of an overlay nobody could parse (see the note
@@ -1445,18 +801,41 @@ async function readyStage(poll, state, data, selfResumeStopAt, selfResumeSuffix)
1445
801
  // merged. Path A is untouched — a session that went away really is
1446
802
  // finished, and carries no flag anyway.
1447
803
  if (data.sessionStatus === 'ready' && data.isUnclassifiedActive !== true) {
1448
- const faultOutcome = upstreamFaultStage(poll, data);
1449
- if (faultOutcome.kind !== 'next')
1450
- return faultOutcome;
1451
- const turnOutcome = await unsettledTurnStage(poll, state, data);
804
+ // Issue #3956: one bound for everything a `Stop` poll's settle waits on —
805
+ // the ledger read that confirms the `Stop` and the re-reads — measured
806
+ // from this poll, so the verdict comes at most HOOK_STOP_SETTLE_MAX_MS
807
+ // after it (`--timeout` is applied on top, where each wait is bounded).
808
+ const settleDeadline = Date.now() + wait_hook_stop_settle_1.HOOK_STOP_SETTLE_MAX_MS;
809
+ if (reportableUpstreamFault(poll, data) !== null) {
810
+ // Issue #3956: a fault on the frame of a `Stop` poll is on a pane that
811
+ // may still be drawing, as much as a clean one is; it is judged on the
812
+ // settled frame too. Without a `Stop` it is #1839's case, reported now.
813
+ // Nothing is printed before that is decided: the diagnosis is for the
814
+ // frame the verdict is on.
815
+ if (!judgingSettledFrame && (await (0, wait_hook_stop_settle_1.faultFrameHasStop)(poll, state, data, settleDeadline))) {
816
+ return { kind: 'settled', data: await (0, wait_hook_stop_settle_1.settleAfterHookStop)(poll, state, data, settleDeadline) };
817
+ }
818
+ return upstreamFaultStage(poll, data);
819
+ }
820
+ const turnOutcome = await unsettledTurnStage(poll, state, data, judgingSettledFrame);
1452
821
  if (turnOutcome.kind !== 'next')
1453
822
  return turnOutcome;
1454
823
  const holdOutcome = selfResumeHoldStage(poll, state, data, selfResumeStopAt);
1455
824
  if (holdOutcome.kind !== 'next')
1456
825
  return holdOutcome;
1457
- const ledgerOutcome = await promptLedgerStage(poll, state, data);
826
+ const ledgerOutcome = await promptLedgerStage(poll, state, data, judgingSettledFrame);
1458
827
  if (ledgerOutcome.kind !== 'next')
1459
828
  return ledgerOutcome;
829
+ // Issue #3956: the `Stop` can land before the end of the reply is on the
830
+ // pane, so a `hook_stop` completion is judged again on the settled frame —
831
+ // as a poll of its own, so a prompt or a new turn drawn meanwhile is not
832
+ // read as this completion. Only under the flag: a plain `wait` reads no
833
+ // fault and waits no longer.
834
+ if (!judgingSettledFrame &&
835
+ poll.options.failOnUpstreamFault &&
836
+ readyCompletionBasis(state, ledgerOutcome.answeredNewestPrompt) === wait_turn_boundary_1.COMPLETION_BASIS.HOOK_STOP) {
837
+ return { kind: 'settled', data: await (0, wait_hook_stop_settle_1.settleAfterHookStop)(poll, state, data, settleDeadline) };
838
+ }
1460
839
  return completionStage(poll, state, ledgerOutcome.answeredNewestPrompt, selfResumeSuffix);
1461
840
  }
1462
841
  return { kind: 'next' };
@@ -1504,23 +883,34 @@ async function pollWorktree(client, worktreeId, options) {
1504
883
  const total = state.selfResumeHeldMs + (state.selfResumeHold ? Date.now() - state.selfResumeHold.since : 0);
1505
884
  return `, heldForSelfResume=${Math.round(total / 1000)}s`;
1506
885
  };
886
+ /**
887
+ * The frame a settle returned, judged as the next poll (Issue #3956). It was
888
+ * read inside the deadlines the settle kept to, so that poll does not ask
889
+ * {@link deadlineStage} again: a turn that completed in time is not a 124.
890
+ */
891
+ let settledFrame = null;
1507
892
  while (true) {
1508
- const deadlineOutcome = deadlineStage(poll, state);
1509
- if (deadlineOutcome.kind === 'exit')
1510
- return deadlineOutcome.result;
893
+ const judgingSettledFrame = settledFrame !== null;
894
+ if (!judgingSettledFrame) {
895
+ const deadlineOutcome = deadlineStage(poll, state);
896
+ if (deadlineOutcome.kind === 'exit')
897
+ return deadlineOutcome.result;
898
+ }
1511
899
  try {
1512
900
  // Issue #868: scope polling to a specific agent instance when provided.
1513
901
  // Issue #3755: `observe=1` so an exit 10 carries the observation of the
1514
902
  // very capture it was decided on (see {@link withObservation}).
1515
- const data = await client.get((0, prompt_1.observedCurrentOutputPath)(worktreeId, options.instance));
1516
- // Track content changes for stall detection
1517
- if (data.content !== state.lastContent) {
1518
- state.lastContent = data.content;
1519
- state.lastActivityTime = Date.now();
1520
- }
1521
- if (data.isRunning) {
1522
- state.everRunning = true;
1523
- }
903
+ const data = settledFrame ??
904
+ // Issue #3974: bounded by --timeout / --stall-timeout, so a server that
905
+ // does not answer cannot hold the wait past them.
906
+ (await (0, wait_timing_1.readWithinDeadlines)(options, startTime, state.lastActivityTime, signal => {
907
+ const path = (0, prompt_1.observedCurrentOutputPath)(worktreeId, options.instance);
908
+ return signal
909
+ ? client.get(path, { signal })
910
+ : client.get(path);
911
+ }));
912
+ settledFrame = null;
913
+ (0, wait_poll_bookkeeping_1.trackPollActivity)(state, data);
1524
914
  // Issue #3179: the agent is still launching. Work in progress, so keep
1525
915
  // polling: no prompt or selection list is read off the launch's frame,
1526
916
  // the unclassified dwell does not run, and a pane that does not exist yet
@@ -1529,220 +919,78 @@ async function pollWorktree(client, worktreeId, options) {
1529
919
  // completion. The server bounds the launch, so this cannot hold forever.
1530
920
  if (typeof data.startingSince === 'number') {
1531
921
  state.unclassifiedSince = null;
1532
- await sleep(POLL_INTERVAL_MS);
922
+ await (0, wait_timing_1.sleep)(wait_timing_1.POLL_INTERVAL_MS);
1533
923
  continue;
1534
924
  }
1535
- // Issue #1839: done before any exit path so the turn is adopted even on a
1536
- // poll that ends in a prompt — the same turn is still open when the human
1537
- // answers and `--on-prompt human` resumes polling.
1538
- state.turnStartedAt = adoptTurnStart(data, startTime, state.turnStartedAt);
925
+ (0, wait_poll_bookkeeping_1.adoptAndPublishTurn)(state, data, startTime, options);
1539
926
  // Issue #2614: a self-resume hold is about one `stop`, and ends the first
1540
927
  // time that `stop` is no longer the newest word — the agent woke (a
1541
928
  // turn-opening event) or stopped again. Checked on every poll, ahead of
1542
929
  // every exit, because the wake usually lands on a `running` frame that
1543
930
  // never reaches the hold itself.
1544
- const selfResumeStopAt = pendingSelfResumeStop(data);
1545
- if (state.selfResumeHold !== null && state.selfResumeHold.stopAt !== selfResumeStopAt) {
1546
- const heldMs = Date.now() - state.selfResumeHold.since;
1547
- state.selfResumeHeldMs += heldMs;
1548
- state.selfResumeHold = null;
1549
- console.error(`Note: ${worktreeId} has moved past the stop it said it would resume from ` +
1550
- `(held ${Math.round(heldMs / 1000)}s); judging its current state.`);
1551
- }
931
+ const selfResumeStopAt = (0, wait_turn_boundary_1.pendingSelfResumeStop)(data);
932
+ (0, wait_poll_bookkeeping_1.releaseMovedSelfResumeHold)(worktreeId, state, selfResumeStopAt);
1552
933
  const promptOutcome = promptStage(poll, state, data);
1553
934
  if (promptOutcome.kind === 'exit')
1554
935
  return withObservation(promptOutcome.result, data);
1555
936
  if (promptOutcome.kind === 'wait') {
1556
- await sleep(POLL_INTERVAL_MS);
937
+ await (0, wait_timing_1.sleep)(wait_timing_1.POLL_INTERVAL_MS);
1557
938
  continue;
1558
939
  }
1559
940
  // Issue #2463: the prompt the hold was waiting on has gone. Who answered it
1560
941
  // is not on the wire — Auto-Yes, or a human at the pane — so the line says
1561
942
  // only that it cleared; what the agent does next is for the checks below.
1562
- if (state.autoYesAnsweringSince !== null) {
1563
- console.error(`Prompt on ${worktreeId} cleared after ` +
1564
- `${Math.round((Date.now() - state.autoYesAnsweringSince) / 1000)}s; judging completion as usual.`);
1565
- state.autoYesAnsweringSince = null;
1566
- }
943
+ (0, wait_poll_bookkeeping_1.noteAutoYesPromptCleared)(worktreeId, state);
1567
944
  const selectionListOutcome = selectionListStage(poll, data);
1568
945
  if (selectionListOutcome.kind === 'exit')
1569
946
  return withObservation(selectionListOutcome.result, data);
1570
947
  if (selectionListOutcome.kind === 'wait') {
1571
- await sleep(POLL_INTERVAL_MS);
948
+ await (0, wait_timing_1.sleep)(wait_timing_1.POLL_INTERVAL_MS);
1572
949
  continue;
1573
950
  }
1574
951
  const unclassifiedOutcome = unclassifiedStage(poll, state, data);
1575
952
  if (unclassifiedOutcome.kind === 'exit')
1576
953
  return withObservation(unclassifiedOutcome.result, data);
1577
954
  if (unclassifiedOutcome.kind === 'wait') {
1578
- await sleep(POLL_INTERVAL_MS);
955
+ await (0, wait_timing_1.sleep)(wait_timing_1.POLL_INTERVAL_MS);
1579
956
  continue;
1580
957
  }
1581
958
  const notRunningOutcome = notRunningStage(poll, state, data, selfResumeSuffix);
1582
959
  if (notRunningOutcome.kind === 'exit')
1583
960
  return notRunningOutcome.result;
1584
- const readyOutcome = await readyStage(poll, state, data, selfResumeStopAt, selfResumeSuffix);
961
+ const readyOutcome = await readyStage(poll, state, data, selfResumeStopAt, selfResumeSuffix, judgingSettledFrame);
1585
962
  if (readyOutcome.kind === 'exit')
1586
963
  return readyOutcome.result;
964
+ if (readyOutcome.kind === 'settled') {
965
+ settledFrame = readyOutcome.data;
966
+ continue;
967
+ }
1587
968
  if (readyOutcome.kind === 'wait') {
1588
- await sleep(POLL_INTERVAL_MS);
969
+ // Issue #3974: the settled frame skipped deadlineStage, and its ledger
970
+ // read may have been cut by the deadline; ask it now rather than one
971
+ // interval late. With time left, the next poll comes as before.
972
+ if (judgingSettledFrame) {
973
+ const deadlineOutcome = deadlineStage(poll, state);
974
+ if (deadlineOutcome.kind === 'exit')
975
+ return deadlineOutcome.result;
976
+ }
977
+ await (0, wait_timing_1.sleep)(wait_timing_1.POLL_INTERVAL_MS);
1589
978
  continue;
1590
979
  }
1591
980
  // Progress indicator on stderr [DR1-05]
1592
981
  console.error(`Waiting: ${worktreeId} (status=${data.sessionStatus}, running=${data.isRunning}, prompt=${data.isPromptWaiting})`);
1593
982
  }
1594
983
  catch (error) {
984
+ // Issue #3974: a read ended by --timeout / --stall-timeout. Not a failed
985
+ // poll: straight back to deadlineStage, which exits 124.
986
+ if (error instanceof wait_timing_1.DeadlineReached)
987
+ continue;
1595
988
  if (error instanceof api_client_1.ApiError) {
1596
989
  throw error;
1597
990
  }
1598
991
  console.error(`Poll error for ${worktreeId}: ${error instanceof Error ? error.message : String(error)}`);
1599
992
  }
1600
- await sleep(POLL_INTERVAL_MS);
1601
- }
1602
- }
1603
- function sleep(ms) {
1604
- return new Promise(resolve => setTimeout(resolve, ms));
1605
- }
1606
- /** True when the caller asked for a verdict rather than "the agent stopped". */
1607
- function verifyRequested(options) {
1608
- return Boolean(options.verify || options.requireWork);
1609
- }
1610
- /**
1611
- * Whether this poll outcome should still be handed to the verification gates.
1612
- *
1613
- * A completion is the obvious case. NOT_STARTED joins it (Issue #1628) so the
1614
- * operator gets the gate results instead of a bare "no session": work committed
1615
- * by an agent whose session has since gone away is still worth reporting. The
1616
- * verdict is merged rather than substituted — mergeExitCode never lets a passing
1617
- * run overwrite NOT_STARTED, so "wait never saw this agent" survives to the exit
1618
- * code even when the gates are green.
1619
- */
1620
- function shouldVerify(exitCode, options) {
1621
- if (!verifyRequested(options))
1622
- return false;
1623
- return exitCode === types_1.WaitExitCode.SUCCESS || exitCode === types_1.VerifyExitCode.NOT_STARTED;
1624
- }
1625
- /**
1626
- * Task statuses that mean "this wait is about that task".
1627
- *
1628
- * Mirrors ACTIVE_TASK_STATUSES in src/lib/db/tasks-db.ts. Deliberately narrower
1629
- * than the set the server will attach a run to: this is a guess made from a
1630
- * worktree id alone, and a task that had already finished before the wait began
1631
- * is a different delegation, not this one.
1632
- */
1633
- const IN_FLIGHT_TASK_STATUSES = new Set([
1634
- 'running',
1635
- 'waiting_input',
1636
- 'verifying',
1637
- ]);
1638
- /**
1639
- * Read the task this wait is about, before waiting for it (Issue #1620).
1640
- *
1641
- * Timing is the whole point. Agents are asked to run the gates themselves
1642
- * before reporting completion, and doing so moves their task to a terminal
1643
- * status — after which a verification run started with only a worktree id has
1644
- * no contract to resolve, judges no scope, and still reports `passed`. Read
1645
- * while the task is still in flight, the id survives that transition and the
1646
- * run that follows is judged against the contract it was supposed to judge.
1647
- *
1648
- * Never throws: an unreadable ledger costs the attribution, and refusing to
1649
- * verify over it would cost every gate.
1650
- *
1651
- * @returns the task id, or undefined to leave resolution to the server
1652
- */
1653
- async function resolveWaitedTaskId(client, worktreeId) {
1654
- try {
1655
- const data = await client.get(`/api/worktrees/${worktreeId}/tasks?limit=1`);
1656
- const task = data?.tasks?.[0];
1657
- if (!task || !IN_FLIGHT_TASK_STATUSES.has(task.status))
1658
- return undefined;
1659
- return task.id;
1660
- }
1661
- catch (error) {
1662
- console.error(`Note: could not read the task ledger for ${worktreeId} ` +
1663
- `(${error instanceof Error ? error.message : String(error)}); ` +
1664
- 'verification will resolve its own task.');
1665
- return undefined;
1666
- }
1667
- }
1668
- /**
1669
- * Run verification for one worktree after its completion was detected.
1670
- *
1671
- * Swallows ApiError into an exit code: with several worktrees in flight, one
1672
- * unreachable run must not abort the verdicts of the others.
1673
- */
1674
- async function verifyAfterWait(client, worktreeId, options, taskId) {
1675
- // --verify runs every gate, and work-evidence is always part of "every gate",
1676
- // so combining it with --require-work is a superset rather than a conflict.
1677
- const gateIds = options.verify ? undefined : [verify_runner_1.WORK_EVIDENCE_GATE_ID];
1678
- try {
1679
- const outcome = await (0, verify_runner_1.runVerification)(client, {
1680
- worktreeId,
1681
- trigger: 'wait',
1682
- instanceId: options.instance,
1683
- taskId,
1684
- gateIds,
1685
- // stdout stays reserved for the prompt JSON contract.
1686
- resultStream: 'stderr',
1687
- });
1688
- return outcome.exitCode;
1689
- }
1690
- catch (error) {
1691
- if (error instanceof api_client_1.ApiError) {
1692
- console.error(`Error: ${error.message}`);
1693
- return error.exitCode;
1694
- }
1695
- console.error(`Error: verification of ${worktreeId} failed: ${error instanceof Error ? error.message : String(error)}`);
1696
- return types_1.ExitCode.UNEXPECTED_ERROR;
1697
- }
1698
- }
1699
- /**
1700
- * Fold one worktree's exit code into the aggregate.
1701
- *
1702
- * Ranked codes (see WAIT_EXIT_CODE_PRIORITY) beat unranked infrastructure
1703
- * codes, and among equals the first one observed stands.
1704
- */
1705
- function mergeExitCode(current, candidate) {
1706
- if (candidate === types_1.WaitExitCode.SUCCESS)
1707
- return current;
1708
- if (current === types_1.WaitExitCode.SUCCESS)
1709
- return candidate;
1710
- const rank = (code) => {
1711
- const index = types_1.WAIT_EXIT_CODE_PRIORITY.indexOf(code);
1712
- return index === -1 ? Number.MAX_SAFE_INTEGER : index;
1713
- };
1714
- return rank(candidate) < rank(current) ? candidate : current;
1715
- }
1716
- /**
1717
- * `options` with `--instance` resolved from a selector to an instance ID
1718
- * (Issue #2376).
1719
- *
1720
- * `wait` polls `/current-output?instance=`, which matches instance IDs and
1721
- * nothing else, so an alias that reached it would filter to no session and the
1722
- * wait would report on the worktree default instead — the exact silent
1723
- * wrong-session failure Issue #1638 catalogued for `--agent`.
1724
- *
1725
- * @param client - API client
1726
- * @param worktreeId - Worktree the selector is resolved against
1727
- * @param options - The options as given
1728
- */
1729
- async function resolveWaitInstance(client, worktreeId, options) {
1730
- if (!options.instance)
1731
- return options;
1732
- try {
1733
- const target = await (0, instances_1.resolveInstanceTarget)(client, worktreeId, options.instance, undefined);
1734
- return { ...options, instance: target.instanceId ?? options.instance };
1735
- }
1736
- catch (error) {
1737
- // Degrade to the pre-#2376 behaviour rather than failing the wait. An
1738
- // instance ID needs no resolution to reach `/current-output?instance=` —
1739
- // resolution exists here so that an ALIAS can — so a resolver that cannot
1740
- // be reached costs alias support for this call and nothing else. Failing
1741
- // instead would turn a reachable session into a non-zero exit for an
1742
- // orchestrator that has been waiting on it correctly for two years.
1743
- console.error(`Warning: could not resolve --instance '${options.instance}' `
1744
- + `(${(0, types_1.getErrorMessage)(error)}); using it as an instance id.`);
1745
- return options;
993
+ await (0, wait_timing_1.sleep)(wait_timing_1.POLL_INTERVAL_MS);
1746
994
  }
1747
995
  }
1748
996
  function createWaitCommand() {
@@ -1864,12 +1112,12 @@ The observation on exit 10 (Issue #3755):
1864
1112
  // "Codex 2"` is one alias against two rosters, and the id behind it can
1865
1113
  // legitimately differ — resolving once and reusing the answer would poll
1866
1114
  // the wrong session on the second worktree.
1867
- const perWorktreeOptions = await Promise.all(worktreeIds.map(id => resolveWaitInstance(client, id, options)));
1115
+ const perWorktreeOptions = await Promise.all(worktreeIds.map(id => (0, wait_instance_1.resolveWaitInstance)(client, id, options)));
1868
1116
  // Issue #1620: resolved before any polling starts. Once the agent stops
1869
1117
  // there is no reliable way left to tell which contract this wait was
1870
1118
  // about — the agent's own verification may have closed it by then.
1871
- const boundTaskIds = verifyRequested(options)
1872
- ? await Promise.all(worktreeIds.map(id => resolveWaitedTaskId(client, id)))
1119
+ const boundTaskIds = (0, wait_verify_1.verifyRequested)(options)
1120
+ ? await Promise.all(worktreeIds.map(id => (0, wait_verify_1.resolveWaitedTaskId)(client, id)))
1873
1121
  : worktreeIds.map(() => undefined);
1874
1122
  if (worktreeIds.length === 1) {
1875
1123
  // Single worktree
@@ -1880,8 +1128,8 @@ The observation on exit 10 (Issue #3755):
1880
1128
  }
1881
1129
  // Issue #1544: only a detected completion is worth verifying — a
1882
1130
  // prompt or a timeout means the agent never claimed to be done.
1883
- const exitCode = shouldVerify(result.exitCode, options)
1884
- ? mergeExitCode(result.exitCode, await verifyAfterWait(client, worktreeIds[0], options, boundTaskIds[0]))
1131
+ const exitCode = (0, wait_verify_1.shouldVerify)(result.exitCode, options)
1132
+ ? (0, wait_verify_1.mergeExitCode)(result.exitCode, await (0, wait_verify_1.verifyAfterWait)(client, worktreeIds[0], options, boundTaskIds[0]))
1885
1133
  : result.exitCode;
1886
1134
  process.exit(exitCode);
1887
1135
  return;
@@ -1897,25 +1145,25 @@ The observation on exit 10 (Issue #3755):
1897
1145
  if (result.value.output) {
1898
1146
  outputs.push(result.value.output);
1899
1147
  }
1900
- if (shouldVerify(result.value.exitCode, options)) {
1148
+ if ((0, wait_verify_1.shouldVerify)(result.value.exitCode, options)) {
1901
1149
  verifyTargets.push({ id: worktreeIds[index], taskId: boundTaskIds[index] });
1902
1150
  // Issue #1628: fold NOT_STARTED in before verification so a green
1903
1151
  // gate run cannot promote "no session was ever running" to success.
1904
- finalExitCode = mergeExitCode(finalExitCode, result.value.exitCode);
1152
+ finalExitCode = (0, wait_verify_1.mergeExitCode)(finalExitCode, result.value.exitCode);
1905
1153
  return;
1906
1154
  }
1907
- finalExitCode = mergeExitCode(finalExitCode, result.value.exitCode);
1155
+ finalExitCode = (0, wait_verify_1.mergeExitCode)(finalExitCode, result.value.exitCode);
1908
1156
  }
1909
1157
  else {
1910
1158
  const err = result.reason;
1911
- finalExitCode = mergeExitCode(finalExitCode, err instanceof api_client_1.ApiError ? err.exitCode : types_1.ExitCode.UNEXPECTED_ERROR);
1159
+ finalExitCode = (0, wait_verify_1.mergeExitCode)(finalExitCode, err instanceof api_client_1.ApiError ? err.exitCode : types_1.ExitCode.UNEXPECTED_ERROR);
1912
1160
  }
1913
1161
  });
1914
1162
  // Issue #1544: serial on purpose. The server caps concurrent runs
1915
1163
  // process-wide, so firing them together only queues them behind each
1916
1164
  // other while every gate competes for the same machine.
1917
1165
  for (const target of verifyTargets) {
1918
- finalExitCode = mergeExitCode(finalExitCode, await verifyAfterWait(client, target.id, options, target.taskId));
1166
+ finalExitCode = (0, wait_verify_1.mergeExitCode)(finalExitCode, await (0, wait_verify_1.verifyAfterWait)(client, target.id, options, target.taskId));
1919
1167
  }
1920
1168
  if (outputs.length > 0) {
1921
1169
  console.log(JSON.stringify(outputs));