commandmate 0.44.2 → 0.44.3

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 (581) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-build-manifest.json +149 -149
  3. package/.next/app-path-routes-manifest.json +21 -21
  4. package/.next/build-manifest.json +2 -2
  5. package/.next/prerender-manifest.json +12 -12
  6. package/.next/react-loadable-manifest.json +0 -6
  7. package/.next/required-server-files.json +1 -1
  8. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  9. package/.next/server/app/api/agents/update/route.js +1 -1
  10. package/.next/server/app/api/agents/update/route_client-reference-manifest.js +1 -1
  11. package/.next/server/app/api/agents/versions/route.js +1 -1
  12. package/.next/server/app/api/agents/versions/route_client-reference-manifest.js +1 -1
  13. package/.next/server/app/api/app/release-notes/route_client-reference-manifest.js +1 -1
  14. package/.next/server/app/api/app/update/route.js +2 -2
  15. package/.next/server/app/api/app/update/route_client-reference-manifest.js +1 -1
  16. package/.next/server/app/api/app/update-check/route_client-reference-manifest.js +1 -1
  17. package/.next/server/app/api/auth/login/route.js +1 -1
  18. package/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
  19. package/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
  20. package/.next/server/app/api/auth/status/route_client-reference-manifest.js +1 -1
  21. package/.next/server/app/api/capabilities/route.js +1 -1
  22. package/.next/server/app/api/capabilities/route_client-reference-manifest.js +1 -1
  23. package/.next/server/app/api/daily-summary/route.js +1 -1
  24. package/.next/server/app/api/daily-summary/route.js.nft.json +1 -1
  25. package/.next/server/app/api/daily-summary/route_client-reference-manifest.js +1 -1
  26. package/.next/server/app/api/daily-summary/status/route.js +1 -1
  27. package/.next/server/app/api/daily-summary/status/route.js.nft.json +1 -1
  28. package/.next/server/app/api/daily-summary/status/route_client-reference-manifest.js +1 -1
  29. package/.next/server/app/api/external-apps/[id]/health/route_client-reference-manifest.js +1 -1
  30. package/.next/server/app/api/external-apps/[id]/route.js +1 -1
  31. package/.next/server/app/api/external-apps/[id]/route_client-reference-manifest.js +1 -1
  32. package/.next/server/app/api/external-apps/route.js +1 -1
  33. package/.next/server/app/api/external-apps/route_client-reference-manifest.js +1 -1
  34. package/.next/server/app/api/fs/browse/route_client-reference-manifest.js +1 -1
  35. package/.next/server/app/api/fs/recent-paths/route_client-reference-manifest.js +1 -1
  36. package/.next/server/app/api/hooks/agent-event/route.js +2 -2
  37. package/.next/server/app/api/hooks/agent-event/route.js.nft.json +1 -1
  38. package/.next/server/app/api/hooks/agent-event/route_client-reference-manifest.js +1 -1
  39. package/.next/server/app/api/hooks/claude-done/route.js +2 -2
  40. package/.next/server/app/api/hooks/claude-done/route.js.nft.json +1 -1
  41. package/.next/server/app/api/hooks/claude-done/route_client-reference-manifest.js +1 -1
  42. package/.next/server/app/api/hooks/permission-request/route.js +1 -1
  43. package/.next/server/app/api/hooks/permission-request/route.js.nft.json +1 -1
  44. package/.next/server/app/api/hooks/permission-request/route_client-reference-manifest.js +1 -1
  45. package/.next/server/app/api/metrics/vibe/route_client-reference-manifest.js +1 -1
  46. package/.next/server/app/api/ollama/models/route_client-reference-manifest.js +1 -1
  47. package/.next/server/app/api/push/escalation/route.js +1 -1
  48. package/.next/server/app/api/push/escalation/route_client-reference-manifest.js +1 -1
  49. package/.next/server/app/api/push/subscriptions/route.js +2 -2
  50. package/.next/server/app/api/push/subscriptions/route_client-reference-manifest.js +1 -1
  51. package/.next/server/app/api/push/vapid/route.js +1 -1
  52. package/.next/server/app/api/push/vapid/route_client-reference-manifest.js +1 -1
  53. package/.next/server/app/api/relays/[relayId]/cancel/route.js +1 -1
  54. package/.next/server/app/api/relays/[relayId]/cancel/route.js.nft.json +1 -1
  55. package/.next/server/app/api/relays/[relayId]/cancel/route_client-reference-manifest.js +1 -1
  56. package/.next/server/app/api/relays/route.js +1 -1
  57. package/.next/server/app/api/relays/route.js.nft.json +1 -1
  58. package/.next/server/app/api/relays/route_client-reference-manifest.js +1 -1
  59. package/.next/server/app/api/remote/pair/route_client-reference-manifest.js +1 -1
  60. package/.next/server/app/api/repositories/[id]/route.js +1 -1
  61. package/.next/server/app/api/repositories/[id]/route_client-reference-manifest.js +1 -1
  62. package/.next/server/app/api/repositories/clone/[jobId]/route.js +1 -1
  63. package/.next/server/app/api/repositories/clone/[jobId]/route.js.nft.json +1 -1
  64. package/.next/server/app/api/repositories/clone/[jobId]/route_client-reference-manifest.js +1 -1
  65. package/.next/server/app/api/repositories/clone/route.js +1 -1
  66. package/.next/server/app/api/repositories/clone/route.js.nft.json +1 -1
  67. package/.next/server/app/api/repositories/clone/route_client-reference-manifest.js +1 -1
  68. package/.next/server/app/api/repositories/excluded/route_client-reference-manifest.js +1 -1
  69. package/.next/server/app/api/repositories/restore/route.js +1 -1
  70. package/.next/server/app/api/repositories/restore/route.js.nft.json +1 -1
  71. package/.next/server/app/api/repositories/restore/route_client-reference-manifest.js +1 -1
  72. package/.next/server/app/api/repositories/route.js +1 -1
  73. package/.next/server/app/api/repositories/route.js.nft.json +1 -1
  74. package/.next/server/app/api/repositories/route_client-reference-manifest.js +1 -1
  75. package/.next/server/app/api/repositories/scan/route.js +1 -1
  76. package/.next/server/app/api/repositories/scan/route.js.nft.json +1 -1
  77. package/.next/server/app/api/repositories/scan/route_client-reference-manifest.js +1 -1
  78. package/.next/server/app/api/repositories/sync/route.js +1 -1
  79. package/.next/server/app/api/repositories/sync/route.js.nft.json +1 -1
  80. package/.next/server/app/api/repositories/sync/route_client-reference-manifest.js +1 -1
  81. package/.next/server/app/api/repositories/validate-path/route_client-reference-manifest.js +1 -1
  82. package/.next/server/app/api/settings/default-agents/route.js +1 -1
  83. package/.next/server/app/api/settings/default-agents/route.js.nft.json +1 -1
  84. package/.next/server/app/api/settings/default-agents/route_client-reference-manifest.js +1 -1
  85. package/.next/server/app/api/settings/default-surface-mode/route_client-reference-manifest.js +1 -1
  86. package/.next/server/app/api/sidebar/group-order/route.js +1 -1
  87. package/.next/server/app/api/sidebar/group-order/route_client-reference-manifest.js +1 -1
  88. package/.next/server/app/api/skills/[id]/route.js +1 -1
  89. package/.next/server/app/api/skills/[id]/route_client-reference-manifest.js +1 -1
  90. package/.next/server/app/api/skills/installations/route_client-reference-manifest.js +1 -1
  91. package/.next/server/app/api/skills/operations/route_client-reference-manifest.js +1 -1
  92. package/.next/server/app/api/skills/reindex/route_client-reference-manifest.js +1 -1
  93. package/.next/server/app/api/skills/route.js +1 -1
  94. package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
  95. package/.next/server/app/api/slash-commands/route_client-reference-manifest.js +1 -1
  96. package/.next/server/app/api/tasks/[taskId]/cancel/route_client-reference-manifest.js +1 -1
  97. package/.next/server/app/api/tasks/[taskId]/route_client-reference-manifest.js +1 -1
  98. package/.next/server/app/api/templates/[id]/route.js +2 -2
  99. package/.next/server/app/api/templates/[id]/route_client-reference-manifest.js +1 -1
  100. package/.next/server/app/api/templates/route.js +2 -2
  101. package/.next/server/app/api/templates/route_client-reference-manifest.js +1 -1
  102. package/.next/server/app/api/verification/runs/[runId]/route_client-reference-manifest.js +1 -1
  103. package/.next/server/app/api/verification/runs/route_client-reference-manifest.js +1 -1
  104. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js +1 -1
  105. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js.nft.json +1 -1
  106. package/.next/server/app/api/worktrees/[id]/auto-yes/route_client-reference-manifest.js +1 -1
  107. package/.next/server/app/api/worktrees/[id]/capture/route.js +1 -1
  108. package/.next/server/app/api/worktrees/[id]/capture/route.js.nft.json +1 -1
  109. package/.next/server/app/api/worktrees/[id]/capture/route_client-reference-manifest.js +1 -1
  110. package/.next/server/app/api/worktrees/[id]/clear-composer/route.js +1 -1
  111. package/.next/server/app/api/worktrees/[id]/clear-composer/route.js.nft.json +1 -1
  112. package/.next/server/app/api/worktrees/[id]/clear-composer/route_client-reference-manifest.js +1 -1
  113. package/.next/server/app/api/worktrees/[id]/cli-reference/route_client-reference-manifest.js +1 -1
  114. package/.next/server/app/api/worktrees/[id]/cli-tool/route.js +1 -1
  115. package/.next/server/app/api/worktrees/[id]/cli-tool/route_client-reference-manifest.js +1 -1
  116. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route.js +3 -3
  117. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route.js.nft.json +1 -1
  118. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route_client-reference-manifest.js +1 -1
  119. package/.next/server/app/api/worktrees/[id]/current-output/route.js +1 -1
  120. package/.next/server/app/api/worktrees/[id]/current-output/route.js.nft.json +1 -1
  121. package/.next/server/app/api/worktrees/[id]/current-output/route_client-reference-manifest.js +1 -1
  122. package/.next/server/app/api/worktrees/[id]/direct-input/route.js +1 -1
  123. package/.next/server/app/api/worktrees/[id]/direct-input/route.js.nft.json +1 -1
  124. package/.next/server/app/api/worktrees/[id]/direct-input/route_client-reference-manifest.js +1 -1
  125. package/.next/server/app/api/worktrees/[id]/env/route_client-reference-manifest.js +1 -1
  126. package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route_client-reference-manifest.js +1 -1
  127. package/.next/server/app/api/worktrees/[id]/execution-logs/route.js +2 -2
  128. package/.next/server/app/api/worktrees/[id]/execution-logs/route.js.nft.json +1 -1
  129. package/.next/server/app/api/worktrees/[id]/execution-logs/route_client-reference-manifest.js +1 -1
  130. package/.next/server/app/api/worktrees/[id]/files/[...path]/route.js +1 -1
  131. package/.next/server/app/api/worktrees/[id]/files/[...path]/route_client-reference-manifest.js +1 -1
  132. package/.next/server/app/api/worktrees/[id]/git/branch/create/route.js +1 -1
  133. package/.next/server/app/api/worktrees/[id]/git/branch/create/route_client-reference-manifest.js +1 -1
  134. package/.next/server/app/api/worktrees/[id]/git/branch/delete/route.js +1 -1
  135. package/.next/server/app/api/worktrees/[id]/git/branch/delete/route_client-reference-manifest.js +1 -1
  136. package/.next/server/app/api/worktrees/[id]/git/branches/route_client-reference-manifest.js +1 -1
  137. package/.next/server/app/api/worktrees/[id]/git/checkout/route.js +1 -1
  138. package/.next/server/app/api/worktrees/[id]/git/checkout/route_client-reference-manifest.js +1 -1
  139. package/.next/server/app/api/worktrees/[id]/git/commit/route.js +1 -1
  140. package/.next/server/app/api/worktrees/[id]/git/commit/route_client-reference-manifest.js +1 -1
  141. package/.next/server/app/api/worktrees/[id]/git/diff/route_client-reference-manifest.js +1 -1
  142. package/.next/server/app/api/worktrees/[id]/git/fetch/route.js +1 -1
  143. package/.next/server/app/api/worktrees/[id]/git/fetch/route_client-reference-manifest.js +1 -1
  144. package/.next/server/app/api/worktrees/[id]/git/log/route_client-reference-manifest.js +1 -1
  145. package/.next/server/app/api/worktrees/[id]/git/pull/route.js +1 -1
  146. package/.next/server/app/api/worktrees/[id]/git/pull/route_client-reference-manifest.js +1 -1
  147. package/.next/server/app/api/worktrees/[id]/git/push/route.js +1 -1
  148. package/.next/server/app/api/worktrees/[id]/git/push/route_client-reference-manifest.js +1 -1
  149. package/.next/server/app/api/worktrees/[id]/git/reset/route.js +1 -1
  150. package/.next/server/app/api/worktrees/[id]/git/reset/route_client-reference-manifest.js +1 -1
  151. package/.next/server/app/api/worktrees/[id]/git/revert/route.js +1 -1
  152. package/.next/server/app/api/worktrees/[id]/git/revert/route_client-reference-manifest.js +1 -1
  153. package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route_client-reference-manifest.js +1 -1
  154. package/.next/server/app/api/worktrees/[id]/git/stage/route.js +1 -1
  155. package/.next/server/app/api/worktrees/[id]/git/stage/route_client-reference-manifest.js +1 -1
  156. package/.next/server/app/api/worktrees/[id]/git/staged/route_client-reference-manifest.js +1 -1
  157. package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route_client-reference-manifest.js +1 -1
  158. package/.next/server/app/api/worktrees/[id]/git/stash/apply/route.js +1 -1
  159. package/.next/server/app/api/worktrees/[id]/git/stash/apply/route_client-reference-manifest.js +1 -1
  160. package/.next/server/app/api/worktrees/[id]/git/stash/pop/route.js +1 -1
  161. package/.next/server/app/api/worktrees/[id]/git/stash/pop/route_client-reference-manifest.js +1 -1
  162. package/.next/server/app/api/worktrees/[id]/git/stash/push/route.js +1 -1
  163. package/.next/server/app/api/worktrees/[id]/git/stash/push/route_client-reference-manifest.js +1 -1
  164. package/.next/server/app/api/worktrees/[id]/git/stash/route_client-reference-manifest.js +1 -1
  165. package/.next/server/app/api/worktrees/[id]/git/status/route_client-reference-manifest.js +1 -1
  166. package/.next/server/app/api/worktrees/[id]/git/unstage/route.js +1 -1
  167. package/.next/server/app/api/worktrees/[id]/git/unstage/route_client-reference-manifest.js +1 -1
  168. package/.next/server/app/api/worktrees/[id]/git/working-diff/route_client-reference-manifest.js +1 -1
  169. package/.next/server/app/api/worktrees/[id]/instances/notes/route.js +1 -1
  170. package/.next/server/app/api/worktrees/[id]/instances/notes/route_client-reference-manifest.js +1 -1
  171. package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js +1 -1
  172. package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js.nft.json +1 -1
  173. package/.next/server/app/api/worktrees/[id]/instances/opencode/route_client-reference-manifest.js +1 -1
  174. package/.next/server/app/api/worktrees/[id]/interrupt/route.js +1 -1
  175. package/.next/server/app/api/worktrees/[id]/interrupt/route.js.nft.json +1 -1
  176. package/.next/server/app/api/worktrees/[id]/interrupt/route_client-reference-manifest.js +1 -1
  177. package/.next/server/app/api/worktrees/[id]/kill-session/route.js +1 -1
  178. package/.next/server/app/api/worktrees/[id]/kill-session/route.js.nft.json +1 -1
  179. package/.next/server/app/api/worktrees/[id]/kill-session/route_client-reference-manifest.js +1 -1
  180. package/.next/server/app/api/worktrees/[id]/logs/[filename]/route_client-reference-manifest.js +1 -1
  181. package/.next/server/app/api/worktrees/[id]/logs/route_client-reference-manifest.js +1 -1
  182. package/.next/server/app/api/worktrees/[id]/marp-render/route.js +1 -1
  183. package/.next/server/app/api/worktrees/[id]/marp-render/route_client-reference-manifest.js +1 -1
  184. package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route.js +1 -1
  185. package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route_client-reference-manifest.js +1 -1
  186. package/.next/server/app/api/worktrees/[id]/memos/route.js +1 -1
  187. package/.next/server/app/api/worktrees/[id]/memos/route_client-reference-manifest.js +1 -1
  188. package/.next/server/app/api/worktrees/[id]/messages/route_client-reference-manifest.js +1 -1
  189. package/.next/server/app/api/worktrees/[id]/opencode/diff/route.js +1 -1
  190. package/.next/server/app/api/worktrees/[id]/opencode/diff/route_client-reference-manifest.js +1 -1
  191. package/.next/server/app/api/worktrees/[id]/opencode/session/route.js +1 -1
  192. package/.next/server/app/api/worktrees/[id]/opencode/session/route.js.nft.json +1 -1
  193. package/.next/server/app/api/worktrees/[id]/opencode/session/route_client-reference-manifest.js +1 -1
  194. package/.next/server/app/api/worktrees/[id]/opencode/share/route.js +1 -1
  195. package/.next/server/app/api/worktrees/[id]/opencode/share/route.js.nft.json +1 -1
  196. package/.next/server/app/api/worktrees/[id]/opencode/share/route_client-reference-manifest.js +1 -1
  197. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js +1 -1
  198. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js.nft.json +1 -1
  199. package/.next/server/app/api/worktrees/[id]/prompt-response/route_client-reference-manifest.js +1 -1
  200. package/.next/server/app/api/worktrees/[id]/resolve-target/route_client-reference-manifest.js +1 -1
  201. package/.next/server/app/api/worktrees/[id]/respond/route.js +1 -1
  202. package/.next/server/app/api/worktrees/[id]/respond/route.js.nft.json +1 -1
  203. package/.next/server/app/api/worktrees/[id]/respond/route_client-reference-manifest.js +1 -1
  204. package/.next/server/app/api/worktrees/[id]/route.js +1 -1
  205. package/.next/server/app/api/worktrees/[id]/route.js.nft.json +1 -1
  206. package/.next/server/app/api/worktrees/[id]/route_client-reference-manifest.js +1 -1
  207. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route.js +2 -2
  208. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route.js.nft.json +1 -1
  209. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route_client-reference-manifest.js +1 -1
  210. package/.next/server/app/api/worktrees/[id]/schedules/active/route.js +2 -2
  211. package/.next/server/app/api/worktrees/[id]/schedules/active/route.js.nft.json +1 -1
  212. package/.next/server/app/api/worktrees/[id]/schedules/active/route_client-reference-manifest.js +1 -1
  213. package/.next/server/app/api/worktrees/[id]/schedules/route.js +3 -3
  214. package/.next/server/app/api/worktrees/[id]/schedules/route.js.nft.json +1 -1
  215. package/.next/server/app/api/worktrees/[id]/schedules/route_client-reference-manifest.js +1 -1
  216. package/.next/server/app/api/worktrees/[id]/search/route_client-reference-manifest.js +1 -1
  217. package/.next/server/app/api/worktrees/[id]/send/route.js +1 -1
  218. package/.next/server/app/api/worktrees/[id]/send/route.js.nft.json +1 -1
  219. package/.next/server/app/api/worktrees/[id]/send/route_client-reference-manifest.js +1 -1
  220. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js +2 -2
  221. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js.nft.json +1 -1
  222. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route_client-reference-manifest.js +1 -1
  223. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route_client-reference-manifest.js +1 -1
  224. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route.js +1 -1
  225. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route_client-reference-manifest.js +1 -1
  226. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route_client-reference-manifest.js +1 -1
  227. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route_client-reference-manifest.js +1 -1
  228. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update/route_client-reference-manifest.js +1 -1
  229. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route.js +1 -1
  230. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route_client-reference-manifest.js +1 -1
  231. package/.next/server/app/api/worktrees/[id]/skills/route_client-reference-manifest.js +1 -1
  232. package/.next/server/app/api/worktrees/[id]/slash-commands/route.js +1 -1
  233. package/.next/server/app/api/worktrees/[id]/slash-commands/route_client-reference-manifest.js +1 -1
  234. package/.next/server/app/api/worktrees/[id]/special-keys/route.js +1 -1
  235. package/.next/server/app/api/worktrees/[id]/special-keys/route.js.nft.json +1 -1
  236. package/.next/server/app/api/worktrees/[id]/special-keys/route_client-reference-manifest.js +1 -1
  237. package/.next/server/app/api/worktrees/[id]/tasks/route.js +1 -1
  238. package/.next/server/app/api/worktrees/[id]/tasks/route_client-reference-manifest.js +1 -1
  239. package/.next/server/app/api/worktrees/[id]/terminal/route.js +2 -2
  240. package/.next/server/app/api/worktrees/[id]/terminal/route.js.nft.json +1 -1
  241. package/.next/server/app/api/worktrees/[id]/terminal/route_client-reference-manifest.js +1 -1
  242. package/.next/server/app/api/worktrees/[id]/timers/history/route_client-reference-manifest.js +1 -1
  243. package/.next/server/app/api/worktrees/[id]/timers/route.js +1 -1
  244. package/.next/server/app/api/worktrees/[id]/timers/route.js.nft.json +1 -1
  245. package/.next/server/app/api/worktrees/[id]/timers/route_client-reference-manifest.js +1 -1
  246. package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route.js +1 -1
  247. package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
  248. package/.next/server/app/api/worktrees/[id]/todos/route.js +1 -1
  249. package/.next/server/app/api/worktrees/[id]/todos/route_client-reference-manifest.js +1 -1
  250. package/.next/server/app/api/worktrees/[id]/tree/[...path]/route_client-reference-manifest.js +1 -1
  251. package/.next/server/app/api/worktrees/[id]/tree/route_client-reference-manifest.js +1 -1
  252. package/.next/server/app/api/worktrees/[id]/upload/[...path]/route_client-reference-manifest.js +1 -1
  253. package/.next/server/app/api/worktrees/[id]/verify/config/route.js +1 -1
  254. package/.next/server/app/api/worktrees/[id]/verify/config/route_client-reference-manifest.js +1 -1
  255. package/.next/server/app/api/worktrees/[id]/verify/route.js +1 -1
  256. package/.next/server/app/api/worktrees/[id]/verify/route_client-reference-manifest.js +1 -1
  257. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route.js +1 -1
  258. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route_client-reference-manifest.js +1 -1
  259. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route_client-reference-manifest.js +1 -1
  260. package/.next/server/app/api/worktrees/[id]/verify/runs/route_client-reference-manifest.js +1 -1
  261. package/.next/server/app/api/worktrees/[id]/viewed/route_client-reference-manifest.js +1 -1
  262. package/.next/server/app/api/worktrees/apply-default-agents/route_client-reference-manifest.js +1 -1
  263. package/.next/server/app/api/worktrees/route.js +1 -1
  264. package/.next/server/app/api/worktrees/route.js.nft.json +1 -1
  265. package/.next/server/app/api/worktrees/route_client-reference-manifest.js +1 -1
  266. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  267. package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
  268. package/.next/server/app/more/page_client-reference-manifest.js +1 -1
  269. package/.next/server/app/offline/page_client-reference-manifest.js +1 -1
  270. package/.next/server/app/page_client-reference-manifest.js +1 -1
  271. package/.next/server/app/proxy/[...path]/route_client-reference-manifest.js +1 -1
  272. package/.next/server/app/repositories/page_client-reference-manifest.js +1 -1
  273. package/.next/server/app/review/page_client-reference-manifest.js +1 -1
  274. package/.next/server/app/sessions/page.js +1 -1
  275. package/.next/server/app/sessions/page.js.nft.json +1 -1
  276. package/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  277. package/.next/server/app/skills/[skillId]/page_client-reference-manifest.js +1 -1
  278. package/.next/server/app/skills/installed/page_client-reference-manifest.js +1 -1
  279. package/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  280. package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -1
  281. package/.next/server/app/worktrees/[id]/page.js +11 -11
  282. package/.next/server/app/worktrees/[id]/page.js.nft.json +1 -1
  283. package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -1
  284. package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
  285. package/.next/server/app-paths-manifest.json +21 -21
  286. package/.next/server/chunks/1191.js +2 -2
  287. package/.next/server/chunks/1210.js +1 -1
  288. package/.next/server/chunks/1559.js +2 -0
  289. package/.next/server/chunks/1789.js +1 -0
  290. package/.next/server/chunks/2119.js +1 -1
  291. package/.next/server/chunks/2404.js +1 -1
  292. package/.next/server/chunks/2445.js +1 -1
  293. package/.next/server/chunks/2460.js +1 -1
  294. package/.next/server/chunks/2710.js +1 -1
  295. package/.next/server/chunks/2908.js +1 -1
  296. package/.next/server/chunks/2980.js +1 -1
  297. package/.next/server/chunks/3241.js +1 -1
  298. package/.next/server/chunks/3480.js +1 -1
  299. package/.next/server/chunks/3718.js +1 -1
  300. package/.next/server/chunks/4207.js +2 -2
  301. package/.next/server/chunks/450.js +1 -1
  302. package/.next/server/chunks/4672.js +5 -0
  303. package/.next/server/chunks/{9353.js → 4718.js} +2 -2
  304. package/.next/server/chunks/4837.js +14 -0
  305. package/.next/server/chunks/5048.js +1 -1
  306. package/.next/server/chunks/5209.js +1 -0
  307. package/.next/server/chunks/5595.js +1 -1
  308. package/.next/server/chunks/5625.js +25 -0
  309. package/.next/server/chunks/611.js +1 -1
  310. package/.next/server/chunks/6130.js +1 -1
  311. package/.next/server/chunks/6401.js +1 -1
  312. package/.next/server/chunks/6781.js +1 -1
  313. package/.next/server/chunks/6793.js +3 -3
  314. package/.next/server/chunks/7491.js +2 -2
  315. package/.next/server/chunks/7905.js +1 -1
  316. package/.next/server/chunks/850.js +1 -1
  317. package/.next/server/chunks/8728.js +3 -3
  318. package/.next/server/chunks/8791.js +1 -1
  319. package/.next/server/chunks/8800.js +1 -1
  320. package/.next/server/chunks/8918.js +7 -7
  321. package/.next/server/chunks/9130.js +1 -1
  322. package/.next/server/chunks/9390.js +2 -2
  323. package/.next/server/chunks/9584.js +1 -1
  324. package/.next/server/chunks/9627.js +6 -6
  325. package/.next/server/chunks/9731.js +3 -3
  326. package/.next/server/middleware-manifest.json +5 -5
  327. package/.next/server/middleware-react-loadable-manifest.js +1 -1
  328. package/.next/server/pages/500.html +1 -1
  329. package/.next/server/server-reference-manifest.json +1 -1
  330. package/.next/static/chunks/{1642-fb2e176aaadbd137.js → 1642-767aed8e7c61ef7f.js} +1 -1
  331. package/.next/static/chunks/{2407-051f6f84226a9f2c.js → 2407-06d35bb1aa02de80.js} +1 -1
  332. package/.next/static/chunks/{2619-04bc32f026a0d946.js → 2619-a305ad4810f1393a.js} +1 -1
  333. package/.next/static/chunks/4727-5d695d71e3fdf97b.js +1 -0
  334. package/.next/static/chunks/{8165-3853772f6ae1299b.js → 8165-3525fb42f1b4976e.js} +1 -1
  335. package/.next/static/chunks/app/{layout-9da1ab602bcb3051.js → layout-0d1750b833f5cc3e.js} +1 -1
  336. package/.next/static/chunks/app/sessions/page-2af68c63211c751f.js +1 -0
  337. package/.next/static/chunks/app/worktrees/[id]/page-e36898c3a80e7302.js +1 -0
  338. package/.next/static/chunks/app/worktrees/[id]/terminal/{page-373ea37b16d930c7.js → page-c601f3b3ece6557e.js} +1 -1
  339. package/.next/static/css/057f64a65726c439.css +1 -0
  340. package/.next/trace +13 -13
  341. package/dist/cli/commands/ask.d.ts.map +1 -1
  342. package/dist/cli/commands/ask.js +120 -119
  343. package/dist/cli/commands/attach.d.ts +94 -0
  344. package/dist/cli/commands/attach.d.ts.map +1 -1
  345. package/dist/cli/commands/attach.js +145 -7
  346. package/dist/cli/commands/auto-yes.js +1 -1
  347. package/dist/cli/commands/capture.d.ts.map +1 -1
  348. package/dist/cli/commands/capture.js +3 -5
  349. package/dist/cli/commands/command-target.d.ts +23 -0
  350. package/dist/cli/commands/command-target.d.ts.map +1 -0
  351. package/dist/cli/commands/command-target.js +25 -0
  352. package/dist/cli/commands/instances.d.ts.map +1 -1
  353. package/dist/cli/commands/instances.js +41 -2
  354. package/dist/cli/commands/message-dispatch.d.ts +36 -0
  355. package/dist/cli/commands/message-dispatch.d.ts.map +1 -0
  356. package/dist/cli/commands/message-dispatch.js +63 -0
  357. package/dist/cli/commands/reply.d.ts.map +1 -1
  358. package/dist/cli/commands/reply.js +2 -5
  359. package/dist/cli/commands/respond.d.ts.map +1 -1
  360. package/dist/cli/commands/respond.js +3 -6
  361. package/dist/cli/commands/send.d.ts.map +1 -1
  362. package/dist/cli/commands/send.js +149 -146
  363. package/dist/cli/commands/wait.d.ts.map +1 -1
  364. package/dist/cli/commands/wait.js +589 -431
  365. package/dist/cli/types/api-responses.d.ts +159 -27
  366. package/dist/cli/types/api-responses.d.ts.map +1 -1
  367. package/dist/cli/types/api-responses.js +4 -2
  368. package/dist/cli/utils/api-client.d.ts +25 -5
  369. package/dist/cli/utils/api-client.d.ts.map +1 -1
  370. package/dist/cli/utils/api-client.js +87 -55
  371. package/dist/cli/utils/server-url.d.ts +1 -0
  372. package/dist/cli/utils/server-url.d.ts.map +1 -1
  373. package/dist/cli/utils/server-url.js +7 -0
  374. package/dist/config/uat-isolation.d.ts +140 -0
  375. package/dist/config/uat-isolation.d.ts.map +1 -0
  376. package/dist/config/uat-isolation.js +246 -0
  377. package/dist/lib/global-state.d.ts +12 -0
  378. package/dist/lib/global-state.d.ts.map +1 -0
  379. package/dist/lib/global-state.js +16 -0
  380. package/dist/lib/polling/auto-yes-suppression-reason.d.ts +33 -0
  381. package/dist/lib/polling/auto-yes-suppression-reason.d.ts.map +1 -0
  382. package/dist/lib/polling/auto-yes-suppression-reason.js +2 -0
  383. package/dist/lib/session/prompt-view.d.ts +26 -3
  384. package/dist/lib/session/prompt-view.d.ts.map +1 -1
  385. package/dist/lib/session/prompt-view.js +26 -3
  386. package/dist/lib/session/status-evidence-type.d.ts +16 -0
  387. package/dist/lib/session/status-evidence-type.d.ts.map +1 -0
  388. package/dist/lib/session/status-evidence-type.js +2 -0
  389. package/dist/lib/tmux/legacy-session-alias.d.ts.map +1 -1
  390. package/dist/lib/tmux/legacy-session-alias.js +2 -1
  391. package/dist/server/locales/en/worktree.json +3 -1
  392. package/dist/server/locales/ja/worktree.json +3 -1
  393. package/dist/server/src/cli/types/api-responses.js +4 -2
  394. package/dist/server/src/config/cli-tool-timing-config.js +1 -6
  395. package/dist/server/src/config/uat-isolation.js +246 -0
  396. package/dist/server/src/lib/assistant-response-saver.js +62 -3
  397. package/dist/server/src/lib/auto-yes-lifecycle.js +6 -0
  398. package/dist/server/src/lib/auto-yes-poller.js +450 -160
  399. package/dist/server/src/lib/auto-yes-state.js +2 -2
  400. package/dist/server/src/lib/cli-tools/antigravity.js +38 -79
  401. package/dist/server/src/lib/cli-tools/base.js +151 -0
  402. package/dist/server/src/lib/cli-tools/codex.js +44 -80
  403. package/dist/server/src/lib/cli-tools/command-code.js +24 -56
  404. package/dist/server/src/lib/cli-tools/copilot.js +25 -67
  405. package/dist/server/src/lib/cli-tools/direct-input.js +8 -0
  406. package/dist/server/src/lib/cli-tools/gemini.js +23 -73
  407. package/dist/server/src/lib/cli-tools/opencode-pane-width.js +53 -0
  408. package/dist/server/src/lib/cli-tools/opencode-v2.js +9 -7
  409. package/dist/server/src/lib/cli-tools/opencode.js +21 -85
  410. package/dist/server/src/lib/cli-tools/submit-verified-sender.js +127 -4
  411. package/dist/server/src/lib/cli-tools/vibe-local.js +21 -66
  412. package/dist/server/src/lib/detection/cli-patterns.js +374 -3065
  413. package/dist/server/src/lib/detection/idle-evidence-observation.js +2 -2
  414. package/dist/server/src/lib/detection/prompt-detect-multiple-choice.js +7 -32
  415. package/dist/server/src/lib/detection/prompt-detector.js +2 -35
  416. package/dist/server/src/lib/detection/selection-shape-patterns.js +69 -0
  417. package/dist/server/src/lib/detection/selection-shape.js +32 -520
  418. package/dist/server/src/lib/detection/shared/pasted-text.js +41 -0
  419. package/dist/server/src/lib/detection/shared/shell-pane-command.js +16 -0
  420. package/dist/server/src/lib/detection/shared/strip-box-drawing.js +25 -0
  421. package/dist/server/src/lib/detection/tools/antigravity/detect.js +5 -29
  422. package/dist/server/src/lib/detection/tools/antigravity/dialog.js +2 -15
  423. package/dist/server/src/lib/detection/tools/antigravity/patterns.js +286 -0
  424. package/dist/server/src/lib/detection/tools/claude/detect.js +3 -14
  425. package/dist/server/src/lib/detection/tools/claude/patterns.js +264 -4
  426. package/dist/server/src/lib/detection/tools/claude/prompt.js +2 -10
  427. package/dist/server/src/lib/detection/tools/codex/detect.js +46 -85
  428. package/dist/server/src/lib/detection/tools/codex/live-region.js +33 -2
  429. package/dist/server/src/lib/detection/tools/codex/patterns.js +855 -0
  430. package/dist/server/src/lib/detection/tools/codex/prompt.js +2 -10
  431. package/dist/server/src/lib/detection/tools/command-code/detect.js +8 -50
  432. package/dist/server/src/lib/detection/tools/command-code/dialog.js +2 -18
  433. package/dist/server/src/lib/detection/tools/command-code/patterns.js +234 -0
  434. package/dist/server/src/lib/detection/tools/command-code/selection-shape.js +461 -0
  435. package/dist/server/src/lib/detection/tools/context-above.js +20 -0
  436. package/dist/server/src/lib/detection/tools/copilot/detect.js +10 -35
  437. package/dist/server/src/lib/detection/tools/copilot/patterns.js +640 -0
  438. package/dist/server/src/lib/detection/tools/copilot/prompt.js +2 -10
  439. package/dist/server/src/lib/detection/tools/gemini/patterns.js +29 -0
  440. package/dist/server/src/lib/detection/tools/live-region-specs.js +1 -1
  441. package/dist/server/src/lib/detection/tools/opencode/detect.js +8 -49
  442. package/dist/server/src/lib/detection/tools/opencode/patterns.js +508 -0
  443. package/dist/server/src/lib/detection/tools/opencode-v2/detect.js +7 -42
  444. package/dist/server/src/lib/detection/tools/opencode-v2/patterns.js +63 -0
  445. package/dist/server/src/lib/detection/tools/run-detection.js +6 -47
  446. package/dist/server/src/lib/detection/tools/verdicts.js +59 -0
  447. package/dist/server/src/lib/detection/tools/vibe-local/patterns.js +20 -0
  448. package/dist/server/src/lib/detection/truncate-raw-content.js +38 -0
  449. package/dist/server/src/lib/detection/turn-abandoned.js +66 -0
  450. package/dist/server/src/lib/detection/unclassified-frame-tracker.js +2 -2
  451. package/dist/server/src/lib/global-state.js +16 -0
  452. package/dist/server/src/lib/hooks/agent-session-telemetry.js +4 -6
  453. package/dist/server/src/lib/hooks/permission-decision-state.js +2 -2
  454. package/dist/server/src/lib/hooks/sources/antigravity/history.js +11 -76
  455. package/dist/server/src/lib/hooks/sources/antigravity/hooks-config.js +63 -1
  456. package/dist/server/src/lib/hooks/sources/antigravity/source.js +16 -0
  457. package/dist/server/src/lib/hooks/sources/antigravity/transcript.js +3 -12
  458. package/dist/server/src/lib/hooks/sources/claude/history.js +17 -156
  459. package/dist/server/src/lib/hooks/sources/claude/queued-notice.js +53 -0
  460. package/dist/server/src/lib/hooks/sources/claude/source.js +33 -3
  461. package/dist/server/src/lib/hooks/sources/claude/transcript.js +3 -13
  462. package/dist/server/src/lib/hooks/sources/codex/history.js +11 -74
  463. package/dist/server/src/lib/hooks/sources/codex/hooks-config.js +147 -11
  464. package/dist/server/src/lib/hooks/sources/codex/relay-install.js +64 -21
  465. package/dist/server/src/lib/hooks/sources/codex/transcript.js +5 -15
  466. package/dist/server/src/lib/hooks/sources/command-code/history.js +20 -121
  467. package/dist/server/src/lib/hooks/sources/command-code/transcript.js +3 -13
  468. package/dist/server/src/lib/hooks/sources/copilot/hook-settings.js +161 -31
  469. package/dist/server/src/lib/hooks/sources/define-source.js +40 -55
  470. package/dist/server/src/lib/hooks/sources/event-mapper.js +2 -1
  471. package/dist/server/src/lib/hooks/sources/opencode/diff.js +3 -4
  472. package/dist/server/src/lib/hooks/sources/opencode/history.js +2 -1
  473. package/dist/server/src/lib/hooks/sources/opencode/launch-settings.js +2 -1
  474. package/dist/server/src/lib/hooks/sources/opencode/payloads.js +2 -1
  475. package/dist/server/src/lib/hooks/sources/opencode/ports.js +2 -1
  476. package/dist/server/src/lib/hooks/sources/opencode/subscription.js +4 -3
  477. package/dist/server/src/lib/hooks/sources/opencode/transcript.js +3 -16
  478. package/dist/server/src/lib/hooks/sources/opencode-v2/history.js +2 -1
  479. package/dist/server/src/lib/hooks/sources/opencode-v2/mappers.js +5 -4
  480. package/dist/server/src/lib/hooks/sources/opencode-v2/ports.js +2 -1
  481. package/dist/server/src/lib/hooks/sources/opencode-v2/subscription.js +3 -7
  482. package/dist/server/src/lib/hooks/sources/opencode-v2/usage.js +2 -1
  483. package/dist/server/src/lib/hooks/sources/pending-decisions.js +2 -1
  484. package/dist/server/src/lib/hooks/sources/registry.js +3 -2
  485. package/dist/server/src/lib/hooks/sources/transcript-history.js +262 -0
  486. package/dist/server/src/lib/hooks/sources/turn-body.js +31 -0
  487. package/dist/server/src/lib/hooks/tool-input-normalization-state.js +2 -2
  488. package/dist/server/src/lib/polling/antigravity-permission-receipts.js +2 -2
  489. package/dist/server/src/lib/polling/auto-yes-enter-fallback-state.js +142 -0
  490. package/dist/server/src/lib/polling/auto-yes-enter-fallback.js +187 -0
  491. package/dist/server/src/lib/polling/auto-yes-resolver.js +9 -3
  492. package/dist/server/src/lib/polling/auto-yes-suppression-reason.js +2 -0
  493. package/dist/server/src/lib/polling/auto-yes-suppression-state.js +2 -2
  494. package/dist/server/src/lib/polling/pending-scraped-response.js +190 -0
  495. package/dist/server/src/lib/polling/prompt-dedup-state.js +2 -2
  496. package/dist/server/src/lib/polling/prompt-dedup.js +2 -2
  497. package/dist/server/src/lib/polling/response-checker-dialog-gate.js +95 -0
  498. package/dist/server/src/lib/polling/response-checker-extraction-result.js +50 -0
  499. package/dist/server/src/lib/polling/response-checker-extraction-steps.js +670 -0
  500. package/dist/server/src/lib/polling/response-checker.js +641 -1142
  501. package/dist/server/src/lib/polling/response-dedup.js +3 -4
  502. package/dist/server/src/lib/polling/response-poller-constants.js +17 -0
  503. package/dist/server/src/lib/polling/response-poller-core.js +54 -20
  504. package/dist/server/src/lib/polling/startup-screen.js +142 -0
  505. package/dist/server/src/lib/polling/structured-history-gate.js +3 -2
  506. package/dist/server/src/lib/prompt-answer-semantic.js +178 -0
  507. package/dist/server/src/lib/prompt-answer-sender.js +5 -4
  508. package/dist/server/src/lib/push/failure-episode-state.js +2 -2
  509. package/dist/server/src/lib/push/notification-dedup.js +3 -4
  510. package/dist/server/src/lib/push/prompt-card-state.js +2 -2
  511. package/dist/server/src/lib/push/waiting-push-notifier.js +3 -4
  512. package/dist/server/src/lib/realtime/publisher-registry.js +3 -2
  513. package/dist/server/src/lib/realtime/terminal-broadcast.js +38 -5
  514. package/dist/server/src/lib/realtime/terminal-session-ownership.js +45 -0
  515. package/dist/server/src/lib/relay/relay-delivery.js +3 -2
  516. package/dist/server/src/lib/relay/relay-readiness.js +38 -1
  517. package/dist/server/src/lib/response-cleaner.js +24 -1
  518. package/dist/server/src/lib/response-extractor.js +16 -0
  519. package/dist/server/src/lib/schedule-manager.js +8 -10
  520. package/dist/server/src/lib/session/agent-event-ask-user-question.js +168 -0
  521. package/dist/server/src/lib/session/agent-event-awaiting-instruction.js +104 -0
  522. package/dist/server/src/lib/session/agent-event-dedup.js +539 -0
  523. package/dist/server/src/lib/session/agent-event-model.js +562 -0
  524. package/dist/server/src/lib/session/agent-event-record.js +10 -0
  525. package/dist/server/src/lib/session/agent-event-state.js +106 -1854
  526. package/dist/server/src/lib/session/agent-event-structured-state.js +109 -0
  527. package/dist/server/src/lib/session/agent-event-turn.js +811 -0
  528. package/dist/server/src/lib/session/agent-session-lifecycle.js +11 -2
  529. package/dist/server/src/lib/session/chat-turn-progress.js +322 -0
  530. package/dist/server/src/lib/session/claude-executor.js +45 -5
  531. package/dist/server/src/lib/session/claude-session.js +21 -65
  532. package/dist/server/src/lib/session/cli-session.js +17 -0
  533. package/dist/server/src/lib/session/current-output-builder.js +450 -1103
  534. package/dist/server/src/lib/session/current-output-history-writers.js +255 -0
  535. package/dist/server/src/lib/session/current-output-types.js +9 -0
  536. package/dist/server/src/lib/session/detection-divergence.js +55 -0
  537. package/dist/server/src/lib/session/global-session-constants.js +2 -13
  538. package/dist/server/src/lib/session/hook-turn-hold.js +102 -0
  539. package/dist/server/src/lib/session/layer-disagreement.js +2 -2
  540. package/dist/server/src/lib/session/opencode-session-store.js +2 -1
  541. package/dist/server/src/lib/session/prompt-view.js +26 -3
  542. package/dist/server/src/lib/session/prompt-waiting-composition.js +3 -2
  543. package/dist/server/src/lib/session/provisional-turn.js +3 -1
  544. package/dist/server/src/lib/session/send-user-message.js +1 -1
  545. package/dist/server/src/lib/session/session-starting-state.js +4 -6
  546. package/dist/server/src/lib/session/status-evidence-type.js +2 -0
  547. package/dist/server/src/lib/session/status-evidence.js +2 -2
  548. package/dist/server/src/lib/session/structured-status-merge.js +335 -0
  549. package/dist/server/src/lib/session/waiting-episode-state.js +3 -4
  550. package/dist/server/src/lib/session-cleanup.js +1 -5
  551. package/dist/server/src/lib/skills/install-plan.js +2 -1
  552. package/dist/server/src/lib/skills/snapshot-store.js +2 -2
  553. package/dist/server/src/lib/skills/uninstall-plan.js +2 -2
  554. package/dist/server/src/lib/timer-manager.js +6 -8
  555. package/dist/server/src/lib/tmux/geometry-delegation.js +3 -4
  556. package/dist/server/src/lib/tmux/legacy-session-alias.js +2 -1
  557. package/dist/server/src/lib/tmux/session-hooks.js +2 -1
  558. package/dist/server/src/lib/tmux/session-status-options.js +3 -3
  559. package/dist/server/src/lib/tmux/tmux-capture-cache.js +3 -2
  560. package/dist/server/src/lib/tmux/tmux.js +33 -59
  561. package/dist/server/src/lib/tui-accumulator.js +2 -2
  562. package/dist/server/src/lib/version-checker.js +6 -6
  563. package/dist/server/src/lib/ws-server.js +47 -11
  564. package/docs/en/user-guide/webapp-guide.md +27 -3
  565. package/package.json +1 -1
  566. package/release-notes/0.44.3.json +82 -0
  567. package/scripts/hooks/cmate-agent-event.sh +18 -0
  568. package/.next/server/chunks/1068.js +0 -1
  569. package/.next/server/chunks/4372.js +0 -5
  570. package/.next/server/chunks/6474.js +0 -14
  571. package/.next/server/chunks/967.js +0 -1
  572. package/.next/server/chunks/9798.js +0 -2
  573. package/.next/server/chunks/9882.js +0 -25
  574. package/.next/static/chunks/591-539fec878c9dec5e.js +0 -1
  575. package/.next/static/chunks/app/sessions/page-049e06335187aa91.js +0 -1
  576. package/.next/static/chunks/app/worktrees/[id]/page-2a81397e60f17e63.js +0 -1
  577. package/.next/static/css/38070d879efa1371.css +0 -1
  578. package/dist/server/src/lib/cli-tools/index.js +0 -41
  579. package/dist/server/src/lib/polling/global-session-poller.js +0 -140
  580. /package/.next/static/{QlCqLjorauDDBXPa-C7TK → tWwHQzmvc-rv9KKUtDWfQ}/_buildManifest.js +0 -0
  581. /package/.next/static/{QlCqLjorauDDBXPa-C7TK → tWwHQzmvc-rv9KKUtDWfQ}/_ssgManifest.js +0 -0
@@ -218,6 +218,8 @@ function describePaneObstruction(data) {
218
218
  const SUPPRESSION_FRESH_MS = 60_000;
219
219
  /** The suppression currently blocking this session, or null. */
220
220
  function activeSuppression(data, now) {
221
+ // No `autoYes` at all (a session that is not running, Issue #3300) reads as
222
+ // "nothing was withheld", the same as a null record.
221
223
  const suppression = data.autoYes?.lastSuppression;
222
224
  if (!suppression)
223
225
  return null;
@@ -296,6 +298,33 @@ function formatSuppressionNotice(suppression, ageSeconds) {
296
298
  const cause = suppressionCause(suppression.reason);
297
299
  return ` auto-yes suppressed this prompt ${cause}: ${parts.join(' ')} (${ageSeconds}s ago)`;
298
300
  }
301
+ /**
302
+ * One stderr line saying Auto-Yes pressed Enter on THIS prompt (Issue #3397), or
303
+ * null when the record is absent or about another screen.
304
+ *
305
+ * The prompt is one CommandMate could not read (the window offers direct input
306
+ * for it). `sent` — Auto-Yes confirmed whatever was selected; `no-effect` — the
307
+ * same screen outlived the Enter, no second one was sent, and it is a human's
308
+ * again. An outcome this CLI does not know is named verbatim (#1843's rule).
309
+ * `currentPrompt` is the server's judgement that the record is about the
310
+ * `promptData` of the same response, so an Enter sent to an earlier screen is
311
+ * never reported against this one.
312
+ */
313
+ function formatEnterFallbackNotice(data, now) {
314
+ const record = data.autoYes?.lastEnterFallback;
315
+ if (!record || record.currentPrompt !== true)
316
+ return null;
317
+ const detail = `refusal=${record.refusalReason} promptType=${record.promptType}`;
318
+ const ago = `(${Math.max(0, Math.round((now - record.at) / 1000))}s ago)`;
319
+ if (record.outcome === 'sent') {
320
+ return ` auto-yes sent Enter to this prompt (CommandMate could not read it): ${detail} ${ago}`;
321
+ }
322
+ if (record.outcome === 'no-effect') {
323
+ return ` auto-yes sent Enter to this prompt, but the same screen is still up (no-effect); ` +
324
+ `answer it in the terminal: ${detail} ${ago}`;
325
+ }
326
+ return ` auto-yes Enter record for this prompt: outcome=${record.outcome} ${detail} ${ago}`;
327
+ }
299
328
  /**
300
329
  * Whether this server publishes a real turn record (Issue #1930).
301
330
  *
@@ -678,6 +707,508 @@ function nextPollWithinDeadlines(options, startTime, lastActivityTime, now) {
678
707
  }
679
708
  return true;
680
709
  }
710
+ /**
711
+ * The exit-10 payload for a prompt the detection layer parsed. `suppressed` is
712
+ * {@link activeSuppression}'s reading of the same poll.
713
+ */
714
+ function buildPromptOutput(worktreeId, data, promptData, suppressed) {
715
+ // Issue #1898: the degraded `unclassified` payload carries no `options`
716
+ // — by construction, because nothing parsed the screen — but for a
717
+ // source whose approvals are answered by decision id it does carry
718
+ // `decisionOptions`, which ARE answerable (`respond <id> 1`). Reporting
719
+ // an empty list there told the caller a dialog was open and gave it
720
+ // nothing to do about it, which is the whole of #1898-3 seen from the
721
+ // pipeline's side.
722
+ //
723
+ // Issue #3184: and a QUESTION answered by decision id (OpenCode V2,
724
+ // #2100) carries neither — its choices are `askUserQuestion.labels`,
725
+ // numbered by position. The panel offered them as buttons while this
726
+ // reported `[]`. Which of these applies is the shared view's call
727
+ // (`readPromptView`), not a third reading of the raw fields here.
728
+ const promptView = (0, prompt_view_1.readPromptView)(data);
729
+ const promptOptions = promptData.options?.length
730
+ ? promptData.options
731
+ : promptData.decisionOptions?.length
732
+ ? promptData.decisionOptions
733
+ : promptView?.apiTarget === 'question'
734
+ ? promptView.choices.map((choice) => ({
735
+ number: Number(choice.answer),
736
+ label: choice.label,
737
+ }))
738
+ : [];
739
+ const promptOutput = {
740
+ worktreeId,
741
+ cliToolId: data.cliToolId || 'claude',
742
+ type: promptData.type || 'unknown',
743
+ question: promptData.question || '',
744
+ options: promptOptions,
745
+ status: promptData.status || 'pending',
746
+ answerVia: waitAnswerVia(promptView),
747
+ ...(promptData.approvalTarget !== undefined && {
748
+ approvalTarget: promptData.approvalTarget,
749
+ }),
750
+ ...(suppressed && {
751
+ autoYesSuppression: {
752
+ reason: suppressed.suppression.reason,
753
+ mode: suppressed.suppression.mode,
754
+ promptType: suppressed.suppression.promptType,
755
+ ...(suppressed.suppression.pattern !== undefined && {
756
+ pattern: suppressed.suppression.pattern,
757
+ }),
758
+ ageSeconds: suppressed.ageSeconds,
759
+ },
760
+ }),
761
+ };
762
+ return promptOutput;
763
+ }
764
+ /** The exit-10 payload for an arrow-key selection list (Issue #1628). */
765
+ function buildSelectionListOutput(worktreeId, data) {
766
+ return {
767
+ worktreeId,
768
+ cliToolId: data.cliToolId || 'claude',
769
+ type: SELECTION_LIST_PROMPT_TYPE,
770
+ question: data.sessionStatusReason ?? SELECTION_LIST_PROMPT_TYPE,
771
+ options: [],
772
+ status: 'pending',
773
+ };
774
+ }
775
+ /**
776
+ * What `wait` says about a frame that stayed unclassified for the whole dwell
777
+ * (Issue #1708): the stderr line, and the `question` of its exit-10 payload.
778
+ */
779
+ function describeUnclassifiedFrame(worktreeId, data, dwellMs) {
780
+ const dwellSeconds = Math.round(dwellMs / 1000);
781
+ return (`Unclassified interactive frame on ${worktreeId} for ${dwellSeconds}s ` +
782
+ `(status=${data.sessionStatus ?? 'unknown'}/${data.sessionStatusReason ?? 'unknown'}). ` +
783
+ `The detection layer could not parse it; inspect the raw pane with ` +
784
+ `\`commandmate capture ${worktreeId} --pane\`.` +
785
+ // Issue #2095: the sidebar is exactly this frame's reason, and the
786
+ // one recovery is a keystroke in the pane. Riding the message keeps
787
+ // the exit-code table (10, `type: unclassified`) unchanged for every
788
+ // caller that already branches on it.
789
+ describePaneObstruction(data));
790
+ }
791
+ /** The exit-10 payload for a persistently unclassified frame (Issue #1708). */
792
+ function buildUnclassifiedOutput(worktreeId, data, question) {
793
+ return {
794
+ worktreeId,
795
+ cliToolId: data.cliToolId || 'claude',
796
+ type: UNCLASSIFIED_PROMPT_TYPE,
797
+ question,
798
+ options: [],
799
+ status: 'pending',
800
+ answerVia: 'terminal',
801
+ };
802
+ }
803
+ /** The stderr line for a session this wait never saw running (Issue #1628). */
804
+ function describeNotStarted(worktreeId, data, options) {
805
+ return (`Not started: ${worktreeId} has no running ${data.cliToolId ?? 'agent'} session` +
806
+ `${options.instance ? ` for instance ${options.instance}` : ''}` +
807
+ // Issue #1884: name the stage that chose the agent above. `wait` has
808
+ // no --agent to correct a mis-resolution with, so "no running claude
809
+ // session for instance opencode" was the entire evidence an operator
810
+ // got for a live agent reported as absent. `worktree-default` here
811
+ // means the instance is neither in the roster nor named after a
812
+ // tool; `client-fallback`, that the server is too old to resolve.
813
+ `${data.resolvedBy ? ` (resolvedBy=${data.resolvedBy})` : ''}.`);
814
+ }
815
+ /** The outcome that ends the wait with `result`. */
816
+ function exitWith(result) {
817
+ return { kind: 'exit', result };
818
+ }
819
+ /**
820
+ * Stage: `--timeout` and `--stall-timeout`, asked at the top of every poll,
821
+ * before its request. Exit 124.
822
+ */
823
+ function deadlineStage(poll, state) {
824
+ const { worktreeId, options, startTime } = poll;
825
+ // Check timeout
826
+ if (options.timeout) {
827
+ const elapsed = (Date.now() - startTime) / 1000;
828
+ if (elapsed >= options.timeout) {
829
+ console.error(`Timeout: ${worktreeId} exceeded ${options.timeout}s`);
830
+ return exitWith({ exitCode: types_1.WaitExitCode.TIMEOUT });
831
+ }
832
+ }
833
+ // Check stall-timeout
834
+ if (options.stallTimeout) {
835
+ const stallElapsed = (Date.now() - state.lastActivityTime) / 1000;
836
+ if (stallElapsed >= options.stallTimeout) {
837
+ console.error(`Stall timeout: ${worktreeId} no output for ${options.stallTimeout}s`);
838
+ return exitWith({ exitCode: types_1.WaitExitCode.TIMEOUT });
839
+ }
840
+ }
841
+ return { kind: 'next' };
842
+ }
843
+ /**
844
+ * Stage: a prompt the detection layer parsed. Exit 10, unless it is held for a
845
+ * human (`--on-prompt human`) or for the target's Auto-Yes (Issue #2463).
846
+ */
847
+ function promptStage(poll, state, data) {
848
+ const { worktreeId, options, startTime, autoYesGraceSeconds, autoYesGraceMs } = poll;
849
+ // Prompt detected
850
+ if (data.isPromptWaiting && data.promptData) {
851
+ // Issue #1699: report a policy suppression on both exits — the human one
852
+ // keeps polling and would otherwise say nothing about why nobody
853
+ // answered, and the agent one is read by pipelines that never see stderr.
854
+ const suppressed = activeSuppression(data, Date.now());
855
+ // [DR1-03] Prompt detection exit code
856
+ if (options.onPrompt === 'human') {
857
+ // Block and continue polling - user handles prompt manually
858
+ console.error(`Prompt detected on ${worktreeId}. Waiting for human response...`);
859
+ if (suppressed) {
860
+ console.error(formatSuppressionNotice(suppressed.suppression, suppressed.ageSeconds));
861
+ }
862
+ // Issue #3397: and whether Auto-Yes already pressed Enter on it.
863
+ const enterNotice = formatEnterFallbackNotice(data, Date.now());
864
+ if (enterNotice)
865
+ console.error(enterNotice);
866
+ return { kind: 'wait' };
867
+ }
868
+ // Issue #2463: the one case `decidePromptPush()` stays quiet about —
869
+ // Auto-Yes is on and has not withheld this answer — is a prompt Auto-Yes
870
+ // is about to answer, and exit 10 there hands a delegation back to a
871
+ // human for a dialog nobody had to see. Hold it for the grace window; a
872
+ // poll that shows no prompt ends the hold below and completion is judged
873
+ // as usual. A withheld answer (`suppressed`) and Auto-Yes being off are
874
+ // the gate's other two branches and still exit 10 at once.
875
+ if (!suppressed && data.autoYes?.enabled === true && autoYesGraceMs > 0) {
876
+ const now = Date.now();
877
+ if (state.autoYesAnsweringSince === null) {
878
+ state.autoYesAnsweringSince = now;
879
+ // stderr only: stdout is the exit-10 payload and nothing else.
880
+ console.error("Prompt detected; the target's Auto-Yes is answering, waiting up to " +
881
+ `${autoYesGraceSeconds}s… (${worktreeId})`);
882
+ }
883
+ const heldMs = now - state.autoYesAnsweringSince;
884
+ if (heldMs < autoYesGraceMs &&
885
+ nextPollWithinDeadlines(options, startTime, state.lastActivityTime, now)) {
886
+ return { kind: 'wait' };
887
+ }
888
+ console.error(heldMs < autoYesGraceMs
889
+ ? `Note: the prompt on ${worktreeId} is still open after ${Math.round(heldMs / 1000)}s ` +
890
+ 'under Auto-Yes, and the next poll would pass --timeout/--stall-timeout; reporting it now.'
891
+ : `Note: the target's Auto-Yes did not answer the prompt on ${worktreeId} within ` +
892
+ `${autoYesGraceSeconds}s; reporting it.`);
893
+ }
894
+ else if (state.autoYesAnsweringSince !== null && !suppressed) {
895
+ console.error(`Note: Auto-Yes is no longer enabled on ${worktreeId}; reporting the prompt.`);
896
+ }
897
+ // Default (agent mode): output prompt info and exit 10
898
+ const promptOutput = buildPromptOutput(worktreeId, data, data.promptData, suppressed);
899
+ if (suppressed) {
900
+ console.error(formatSuppressionNotice(suppressed.suppression, suppressed.ageSeconds));
901
+ }
902
+ // Issue #3397: stderr only, like the notice above; the exit-10 payload is unchanged.
903
+ const enterNotice = formatEnterFallbackNotice(data, Date.now());
904
+ if (enterNotice)
905
+ console.error(enterNotice);
906
+ return exitWith({ exitCode: types_1.WaitExitCode.PROMPT_DETECTED, output: promptOutput });
907
+ }
908
+ return { kind: 'next' };
909
+ }
910
+ /** Stage: an arrow-key selection list (Issue #1628). Exit 10, or held under `--on-prompt human`. */
911
+ function selectionListStage(poll, data) {
912
+ const { worktreeId, options } = poll;
913
+ // Issue #1628: an arrow-key menu is the agent blocked on a human just as much
914
+ // as a numbered prompt is, but it is published with isPromptWaiting=false so
915
+ // the UI can render NavigationButtons instead of PromptPanel. Treat it as a
916
+ // prompt here — otherwise `wait` polls a stopped agent until --timeout.
917
+ if (data.isSelectionListActive) {
918
+ if (options.onPrompt === 'human') {
919
+ console.error(`Selection list active on ${worktreeId} (${data.sessionStatusReason ?? 'selection_list'}). ` +
920
+ 'Waiting for human response...');
921
+ // Issue #1699: the poller parses frames status-detector publishes as
922
+ // selection lists, so a policy can be the reason this one is stuck too.
923
+ const suppressed = activeSuppression(data, Date.now());
924
+ if (suppressed) {
925
+ console.error(formatSuppressionNotice(suppressed.suppression, suppressed.ageSeconds));
926
+ }
927
+ return { kind: 'wait' };
928
+ }
929
+ return exitWith({
930
+ exitCode: types_1.WaitExitCode.PROMPT_DETECTED,
931
+ output: buildSelectionListOutput(worktreeId, data),
932
+ });
933
+ }
934
+ return { kind: 'next' };
935
+ }
936
+ /**
937
+ * Stage: an interactive frame nothing could parse, once it has stayed up for the
938
+ * whole dwell (Issue #1708). Exit 10, or held under `--on-prompt human`.
939
+ */
940
+ function unclassifiedStage(poll, state, data) {
941
+ const { worktreeId, options } = poll;
942
+ // Issue #1708: the frame is interactive but nothing could parse it. The
943
+ // detection layer is the single entry point every downstream safeguard
944
+ // hangs off, so a frame that slips past it disables Auto-Yes, the exit-10
945
+ // handoff and the contract's autoYes policy all at once — and `wait` used
946
+ // to burn its whole --timeout without ever mentioning it. Treat a
947
+ // PERSISTENT unclassified frame as a stop reason of its own.
948
+ //
949
+ // The dwell deliberately spans ALL THREE states that raise this flag, and
950
+ // the completion check below is suppressed while it is up. That is the
951
+ // whole point, and it is worth spelling out because the obvious reading is
952
+ // the wrong one. The server's definition (`isUnclassifiedFrame` in
953
+ // `src/lib/session/status-evidence.ts`, restated there by Issue #2011):
954
+ //
955
+ // isUnclassifiedActive =
956
+ // running && (default | unknown_frame | no_recent_output)
957
+ //
958
+ // `no_recent_output` is there because a static unrecognised overlay
959
+ // DEGRADES into it — once the Auto-Yes poller stamps
960
+ // lastServerResponseTimestamp, a frame that stopped changing flips from
961
+ // `running`/`default` after STALE_OUTPUT_THRESHOLD_MS (5s). `unknown_frame`
962
+ // is the same floor for a tool that opts out of the generic composer check
963
+ // (copilot, opencode), and says "this tool's own rules looked and read
964
+ // nothing". Both arrive about twelve times faster than this dwell. Letting
965
+ // the completion check claim one turned a stalled worker into `Completed`,
966
+ // which is worse than the timeout Issue #1708 complained about: exit 124
967
+ // stops a pipeline, exit 0 lets it merge. Measured before this guard: two
968
+ // unclassified polls followed by the degraded state returned SUCCESS.
969
+ //
970
+ // What is deliberately NOT in the set is `ready`/`input_prompt` with
971
+ // `statusEvidence: 'none'` — the agent back at its composer on a frame no
972
+ // tool-specific idle rule could vouch for. That frame WAS classified; what
973
+ // is missing is positive proof, which is a different question and §4 D1's
974
+ // to answer. Issue #1927 folded the two together and every idle Claude pane
975
+ // stopped completing (#2011). Whether `wait` should hold for evidence as
976
+ // well as classification is open, and any answer belongs in the same place
977
+ // as the rollout that produces the evidence — not here.
978
+ if (data.isUnclassifiedActive === true) {
979
+ if (state.unclassifiedSince === null)
980
+ state.unclassifiedSince = Date.now();
981
+ const dwellMs = Date.now() - state.unclassifiedSince;
982
+ if (dwellMs >= UNCLASSIFIED_DWELL_MS) {
983
+ const question = describeUnclassifiedFrame(worktreeId, data, dwellMs);
984
+ if (options.onPrompt === 'human') {
985
+ console.error(question);
986
+ console.error('Waiting for human response...');
987
+ return { kind: 'wait' };
988
+ }
989
+ console.error(question);
990
+ return exitWith({
991
+ exitCode: types_1.WaitExitCode.PROMPT_DETECTED,
992
+ output: buildUnclassifiedOutput(worktreeId, data, question),
993
+ });
994
+ }
995
+ }
996
+ else {
997
+ state.unclassifiedSince = null;
998
+ }
999
+ return { kind: 'next' };
1000
+ }
1001
+ /**
1002
+ * Stage: the session is not running (Path A). Exit 21 when this wait never saw
1003
+ * it alive (Issue #1628), exit 0 when it went away after it had been seen.
1004
+ */
1005
+ function notRunningStage(poll, state, data, selfResumeSuffix) {
1006
+ const { worktreeId, options } = poll;
1007
+ // Completion check [DR1-04]:
1008
+ // Path A: the tmux session went away after we had seen it alive — the agent
1009
+ // finished and its session was stopped.
1010
+ // Path B: agent completed task (sessionStatus === 'ready', input prompt detected)
1011
+ // Both indicate "no more work in progress" from wait command's perspective.
1012
+ // (This stage handles Path A only; Path B is checked in `readyStage`.)
1013
+ //
1014
+ // Issue #1628 narrowed Path A: a session that was NEVER seen running is
1015
+ // "nothing to wait for" (NOT_STARTED), not a completion. See `everRunning`.
1016
+ if (!data.isRunning && !state.everRunning) {
1017
+ console.error(describeNotStarted(worktreeId, data, options));
1018
+ return exitWith({ exitCode: types_1.VerifyExitCode.NOT_STARTED });
1019
+ }
1020
+ if (!data.isRunning) {
1021
+ console.error(`Completed: ${worktreeId} (basis=${COMPLETION_BASIS.SESSION_GONE}${selfResumeSuffix()})`);
1022
+ return exitWith({ exitCode: types_1.WaitExitCode.SUCCESS });
1023
+ }
1024
+ return { kind: 'next' };
1025
+ }
1026
+ /**
1027
+ * Stage of a `ready` frame: an upstream fault on the frame, under
1028
+ * `--fail-on-upstream-fault` (Issue #1839). Exit 11.
1029
+ */
1030
+ function upstreamFaultStage(poll, data) {
1031
+ const { worktreeId, options } = poll;
1032
+ // Issue #1839: the agent is back at its composer with an upstream
1033
+ // failure on the frame. Checked BEFORE the turn-boundary gate below,
1034
+ // because it is the answer to the question that gate can only ask: the
1035
+ // turn did not end, and this is why. Without it the same session runs
1036
+ // to --timeout and reports 124, which says nothing about the cause.
1037
+ const fault = data.upstreamFault ?? null;
1038
+ if (options.failOnUpstreamFault && fault) {
1039
+ console.error(`Upstream fault on ${worktreeId}: id=${fault.id} — the agent is back at its ` +
1040
+ 'composer with an upstream API failure on screen, so this turn did not run. ' +
1041
+ `Matched: ${JSON.stringify(fault.matchedText)}`);
1042
+ if (fault.id === 'context-limit') {
1043
+ // A retry into the same session hits the same wall (Issue #3011).
1044
+ console.error('The session\'s conversation is over the model\'s context limit. Start a fresh ' +
1045
+ `session and send again: commandmate instances ${worktreeId} kill ` +
1046
+ `${options.instance ?? '<instance>'}`);
1047
+ }
1048
+ return exitWith({
1049
+ exitCode: types_1.WaitExitCode.UPSTREAM_FAULT,
1050
+ upstreamFault: { id: fault.id, matchedText: fault.matchedText },
1051
+ });
1052
+ }
1053
+ return { kind: 'next' };
1054
+ }
1055
+ /**
1056
+ * Stage of a `ready` frame: the agent has not reported the end of the turn this
1057
+ * wait adopted (Issue #1839). Held.
1058
+ */
1059
+ function unsettledTurnStage(poll, state, data) {
1060
+ const { worktreeId } = poll;
1061
+ // Issue #1839: `ready` off the terminal frame is the agent's composer,
1062
+ // not the agent's verdict. Measured 2026-08-20 against a stub upstream
1063
+ // answering 529: Claude returns to the composer ~3 s after the send
1064
+ // having executed nothing, and never sends `Stop`. When this instance's
1065
+ // hooks ARE reporting — the only case in which `turnStartedAt` is
1066
+ // non-null — that missing `Stop` is the difference between "finished"
1067
+ // and "never ran", and it is the only signal that carries it.
1068
+ if (!turnSettled(data, state.turnStartedAt)) {
1069
+ console.error(`Waiting: ${worktreeId} is back at its composer, but its agent has not reported ` +
1070
+ `the end of this turn (turnStartedAt=${state.turnStartedAt}, ` +
1071
+ `lastStopEventAt=${data.lastStopEventAt ?? 'none'}, ${describeTurnClose(data)}). ` +
1072
+ 'Not reporting completion; inspect with ' +
1073
+ `\`commandmate capture ${worktreeId} --json\`.`);
1074
+ return { kind: 'wait' };
1075
+ }
1076
+ return { kind: 'next' };
1077
+ }
1078
+ /**
1079
+ * Stage of a `ready` frame: the turn ended on a `stop` that said the agent will
1080
+ * resume by itself (Issue #2614). Held, up to {@link SELF_RESUME_HOLD_MS}.
1081
+ */
1082
+ function selfResumeHoldStage(poll, state, data, selfResumeStopAt) {
1083
+ const { worktreeId } = poll;
1084
+ // Issue #2614: the turn did end — the agent said so — but it also said
1085
+ // that work of its own is still running in the background (a `schedule`
1086
+ // timer, a backgrounded command), and that work wakes it with nobody
1087
+ // typing anything. Measured 2026-09-17 on antigravity 1.2.4: four such
1088
+ // stops ~58 s before each self-wake, and the first one was reported as
1089
+ // `Completed (basis=hook_stop)` and verified five minutes before the
1090
+ // work was done. So this `stop` is held until it is no longer the newest
1091
+ // word (see `selfResumeStopAt` above), or until the bound.
1092
+ //
1093
+ // The bound is measured from whichever is further along: the `stop`
1094
+ // itself (server clock — a negative age is skew, and the max discards
1095
+ // it) or this wait's first sight of it. A session that said so hours ago
1096
+ // and never woke is not held again.
1097
+ if (selfResumeStopAt !== null) {
1098
+ const now = Date.now();
1099
+ if (state.selfResumeHold === null)
1100
+ state.selfResumeHold = { stopAt: selfResumeStopAt, since: now };
1101
+ const heldMs = now - state.selfResumeHold.since;
1102
+ const elapsedMs = Math.max(heldMs, now - selfResumeStopAt);
1103
+ if (elapsedMs < exports.SELF_RESUME_HOLD_MS) {
1104
+ state.selfResumeHeld = true;
1105
+ console.error(`Waiting: ${worktreeId} ended its turn with background work still running ` +
1106
+ `(stoppedAt=${new Date(selfResumeStopAt).toISOString()}, ` +
1107
+ `lastEventDetail=${exports.SELF_RESUME_PENDING_DETAIL}, ${describeTurnClose(data)}); ` +
1108
+ 'it resumes by itself when that work finishes. Not reporting completion ' +
1109
+ `(held ${Math.round(heldMs / 1000)}s, at most ${exports.SELF_RESUME_HOLD_MS / 1000}s ` +
1110
+ 'after the stop).');
1111
+ return { kind: 'wait' };
1112
+ }
1113
+ console.error(`Note: ${worktreeId} said at its stop ${Math.round(elapsedMs / 1000)}s ` +
1114
+ 'ago that background work was still running, and has not resumed since; ' +
1115
+ 'completing on that stop.');
1116
+ }
1117
+ return { kind: 'next' };
1118
+ }
1119
+ /**
1120
+ * Stage of a `ready` frame: the chat ledger shows a prompt the agent has not
1121
+ * reported the end of (Issue #1975). Held, up to {@link PENDING_PROMPT_HOLD_MS}.
1122
+ * `next` carries whether the newest prompt was answered, which
1123
+ * {@link completionStage} needs for its basis.
1124
+ */
1125
+ async function promptLedgerStage(poll, state, data) {
1126
+ const { client, worktreeId, options, startTime } = poll;
1127
+ // Issue #1975: the same frame, one question further back. #1839's gate
1128
+ // above can only fire once a turn has been ADOPTED, and `send` leaves a
1129
+ // window ~1s wide in which nothing has been: the newest structured event
1130
+ // is still the previous turn's `stop`, so `adoptTurnStart` takes nothing,
1131
+ // `turnSettled` reads null as "settled", and the composer the agent has
1132
+ // not touched yet is read as the composer it came back to. Measured
1133
+ // 2026-08-22 against copilot 1.0.80 on an isolated server: 3 of 5
1134
+ // send-then-wait runs came back in ~0.3s with `basis=scraper_ready` and
1135
+ // no artefact on disk.
1136
+ //
1137
+ // So ask the ledger instead of the clock: has this instance been handed
1138
+ // a prompt that the agent has not reported the end of? See
1139
+ // {@link outstandingPrompt} for why that comparison is the one that
1140
+ // separates "not started" from "finished", and
1141
+ // {@link reportsTurnBoundaries} for why a tool that posts no hooks never
1142
+ // reaches it.
1143
+ let answeredNewestPrompt = false;
1144
+ if (state.turnStartedAt === null && state.promptLedgerReadable && reportsTurnBoundaries(data)) {
1145
+ const ledger = await readNewestPromptAt(client, worktreeId, options, data);
1146
+ // One notice, then stop asking: a ledger that failed once will fail
1147
+ // every poll, and the point of degrading is to stop paying for it.
1148
+ state.promptLedgerReadable = ledger.readable;
1149
+ if (ledger.readable && ledger.submittedAt !== null) {
1150
+ if (outstandingPrompt(data, ledger.submittedAt)) {
1151
+ const heldMs = Date.now() - startTime;
1152
+ if (heldMs < PENDING_PROMPT_HOLD_MS) {
1153
+ console.error(`Waiting: ${worktreeId} is at its composer, but the newest prompt sent to it ` +
1154
+ `has no reported end (sentAt=${new Date(ledger.submittedAt).toISOString()}, ` +
1155
+ `lastStopEventAt=${data.lastStopEventAt ?? 'none'}, ${describeTurnClose(data)}). ` +
1156
+ 'Not reporting completion: the agent has not started this turn yet.');
1157
+ return { kind: 'wait' };
1158
+ }
1159
+ console.error(`Note: ${worktreeId} has been at its composer for ` +
1160
+ `${Math.round(heldMs / 1000)}s with the newest prompt still unreported by its ` +
1161
+ 'agent. Its hooks are not answering; completing on the frame alone.');
1162
+ }
1163
+ else {
1164
+ answeredNewestPrompt = true;
1165
+ }
1166
+ }
1167
+ }
1168
+ return { kind: 'next', answeredNewestPrompt };
1169
+ }
1170
+ /** Last stage of a `ready` frame: the completion line with its basis. Exit 0. */
1171
+ function completionStage(poll, state, answeredNewestPrompt, selfResumeSuffix) {
1172
+ const { worktreeId } = poll;
1173
+ // `hook_stop` on both branches that have one, and they are the same
1174
+ // statement made from two records: the agent reported the end of the
1175
+ // turn this wait is about. `scraper_ready` keeps its documented meaning
1176
+ // — "the screen said so and nothing corroborated it" — which is now
1177
+ // exactly the set of cases that reach it.
1178
+ const basis = state.turnStartedAt !== null || answeredNewestPrompt
1179
+ ? COMPLETION_BASIS.HOOK_STOP
1180
+ : COMPLETION_BASIS.SCRAPER_READY;
1181
+ console.error(`Completed: ${worktreeId} (basis=${basis}${selfResumeSuffix()})`);
1182
+ return exitWith({ exitCode: types_1.WaitExitCode.SUCCESS });
1183
+ }
1184
+ /**
1185
+ * Stage: the agent is back at its composer on a frame that was understood. Asks
1186
+ * the stages of a `ready` frame in order; the first that applies decides.
1187
+ */
1188
+ async function readyStage(poll, state, data, selfResumeStopAt, selfResumeSuffix) {
1189
+ // Issue #1708 narrowed Path B: `ready` is only a completion when the frame
1190
+ // was actually understood. A structured `hook_stop` over an unreadable
1191
+ // pane is the degraded form of an overlay nobody could parse (see the note
1192
+ // above), and reporting it as `Completed` is how a stalled worker gets
1193
+ // merged. Path A is untouched — a session that went away really is
1194
+ // finished, and carries no flag anyway.
1195
+ if (data.sessionStatus === 'ready' && data.isUnclassifiedActive !== true) {
1196
+ const faultOutcome = upstreamFaultStage(poll, data);
1197
+ if (faultOutcome.kind !== 'next')
1198
+ return faultOutcome;
1199
+ const turnOutcome = unsettledTurnStage(poll, state, data);
1200
+ if (turnOutcome.kind !== 'next')
1201
+ return turnOutcome;
1202
+ const holdOutcome = selfResumeHoldStage(poll, state, data, selfResumeStopAt);
1203
+ if (holdOutcome.kind !== 'next')
1204
+ return holdOutcome;
1205
+ const ledgerOutcome = await promptLedgerStage(poll, state, data);
1206
+ if (ledgerOutcome.kind !== 'next')
1207
+ return ledgerOutcome;
1208
+ return completionStage(poll, state, ledgerOutcome.answeredNewestPrompt, selfResumeSuffix);
1209
+ }
1210
+ return { kind: 'next' };
1211
+ }
681
1212
  /**
682
1213
  * Poll a single worktree until completion, prompt, or timeout.
683
1214
  *
@@ -694,81 +1225,36 @@ function nextPollWithinDeadlines(options, startTime, lastActivityTime, now) {
694
1225
  */
695
1226
  async function pollWorktree(client, worktreeId, options) {
696
1227
  const startTime = Date.now();
697
- let lastActivityTime = Date.now();
698
- let lastContent = '';
699
- /**
700
- * Issue #1628: whether this wait ever saw the session alive. `!isRunning` on the
701
- * FIRST poll is "there is nothing here to wait for", not "the agent finished" —
702
- * reporting SUCCESS for it is how a wait on a worktree whose agent never started
703
- * (wrong tool, wrong instance, session never created) came back `Completed` in
704
- * milliseconds and handed a `passed` verdict to whatever ran next.
705
- */
706
- let everRunning = false;
707
- /**
708
- * Epoch ms of the first poll in the current unbroken run of
709
- * `isUnclassifiedActive === true`, or null when the last poll cleared it
710
- * (Issue #1708).
711
- */
712
- let unclassifiedSince = null;
713
- /**
714
- * Epoch ms of the `user_prompt_submit` / `pre_tool_use` / `post_tool_use` this
715
- * wait adopted as "the turn I am waiting on", or null when the agent has
716
- * reported none (Issue #1839). See {@link adoptTurnStart}.
717
- */
718
- let turnStartedAt = null;
719
- /**
720
- * Whether the chat ledger is still worth asking (Issue #1975). Cleared by the
721
- * first read that fails, after which this wait judges completion from the
722
- * frame alone — the pre-#1975 behaviour — rather than re-reporting the same
723
- * unreachable endpoint on every poll.
724
- */
725
- let promptLedgerReadable = true;
726
- /**
727
- * Epoch ms of the first poll in the current unbroken run of an agent-mode
728
- * prompt the target's Auto-Yes is expected to answer, or null (Issue #2463).
729
- * Cleared by the first poll that shows no prompt, so every prompt Auto-Yes
730
- * answers gets a window of its own.
731
- */
732
- let autoYesAnsweringSince = null;
1228
+ const state = {
1229
+ lastActivityTime: Date.now(),
1230
+ lastContent: '',
1231
+ everRunning: false,
1232
+ unclassifiedSince: null,
1233
+ turnStartedAt: null,
1234
+ promptLedgerReadable: true,
1235
+ autoYesAnsweringSince: null,
1236
+ selfResumeHold: null,
1237
+ selfResumeHeldMs: 0,
1238
+ selfResumeHeld: false,
1239
+ };
733
1240
  const autoYesGraceSeconds = options.autoYesGrace ?? AUTO_YES_GRACE_DEFAULT_SECONDS;
734
1241
  const autoYesGraceMs = autoYesGraceSeconds * 1000;
735
- /**
736
- * The self-resume hold in progress: the `stop` it is about, and when this wait
737
- * first held on it (CLI clock). Null when none is (Issue #2614).
738
- */
739
- let selfResumeHold = null;
740
- /** Milliseconds spent in self-resume holds that have already ended (Issue #2614). */
741
- let selfResumeHeldMs = 0;
742
- /** Whether any poll of this wait was held for a self-resume (Issue #2614). */
743
- let selfResumeHeld = false;
1242
+ const poll = { client, worktreeId, options, startTime, autoYesGraceSeconds, autoYesGraceMs };
744
1243
  /**
745
1244
  * What the completion line adds when this wait held for a self-resume, or ''
746
1245
  * (Issue #2614). `basis=` keeps its word: the verdict is still the agent's own
747
1246
  * `Stop`, the hold only decided which one.
748
1247
  */
749
1248
  const selfResumeSuffix = () => {
750
- if (!selfResumeHeld)
1249
+ if (!state.selfResumeHeld)
751
1250
  return '';
752
- const total = selfResumeHeldMs + (selfResumeHold ? Date.now() - selfResumeHold.since : 0);
1251
+ const total = state.selfResumeHeldMs + (state.selfResumeHold ? Date.now() - state.selfResumeHold.since : 0);
753
1252
  return `, heldForSelfResume=${Math.round(total / 1000)}s`;
754
1253
  };
755
1254
  while (true) {
756
- // Check timeout
757
- if (options.timeout) {
758
- const elapsed = (Date.now() - startTime) / 1000;
759
- if (elapsed >= options.timeout) {
760
- console.error(`Timeout: ${worktreeId} exceeded ${options.timeout}s`);
761
- return { exitCode: types_1.WaitExitCode.TIMEOUT };
762
- }
763
- }
764
- // Check stall-timeout
765
- if (options.stallTimeout) {
766
- const stallElapsed = (Date.now() - lastActivityTime) / 1000;
767
- if (stallElapsed >= options.stallTimeout) {
768
- console.error(`Stall timeout: ${worktreeId} no output for ${options.stallTimeout}s`);
769
- return { exitCode: types_1.WaitExitCode.TIMEOUT };
770
- }
771
- }
1255
+ const deadlineOutcome = deadlineStage(poll, state);
1256
+ if (deadlineOutcome.kind === 'exit')
1257
+ return deadlineOutcome.result;
772
1258
  try {
773
1259
  // Issue #868: scope polling to a specific agent instance when provided.
774
1260
  const path = options.instance
@@ -776,12 +1262,12 @@ async function pollWorktree(client, worktreeId, options) {
776
1262
  : `/api/worktrees/${worktreeId}/current-output`;
777
1263
  const data = await client.get(path);
778
1264
  // Track content changes for stall detection
779
- if (data.content !== lastContent) {
780
- lastContent = data.content;
781
- lastActivityTime = Date.now();
1265
+ if (data.content !== state.lastContent) {
1266
+ state.lastContent = data.content;
1267
+ state.lastActivityTime = Date.now();
782
1268
  }
783
1269
  if (data.isRunning) {
784
- everRunning = true;
1270
+ state.everRunning = true;
785
1271
  }
786
1272
  // Issue #3179: the agent is still launching. Work in progress, so keep
787
1273
  // polling: no prompt or selection list is read off the launch's frame,
@@ -790,393 +1276,65 @@ async function pollWorktree(client, worktreeId, options) {
790
1276
  // launch that then fails leaves no session, which is NOT_STARTED, not a
791
1277
  // completion. The server bounds the launch, so this cannot hold forever.
792
1278
  if (typeof data.startingSince === 'number') {
793
- unclassifiedSince = null;
1279
+ state.unclassifiedSince = null;
794
1280
  await sleep(POLL_INTERVAL_MS);
795
1281
  continue;
796
1282
  }
797
1283
  // Issue #1839: done before any exit path so the turn is adopted even on a
798
1284
  // poll that ends in a prompt — the same turn is still open when the human
799
1285
  // answers and `--on-prompt human` resumes polling.
800
- turnStartedAt = adoptTurnStart(data, startTime, turnStartedAt);
1286
+ state.turnStartedAt = adoptTurnStart(data, startTime, state.turnStartedAt);
801
1287
  // Issue #2614: a self-resume hold is about one `stop`, and ends the first
802
1288
  // time that `stop` is no longer the newest word — the agent woke (a
803
1289
  // turn-opening event) or stopped again. Checked on every poll, ahead of
804
1290
  // every exit, because the wake usually lands on a `running` frame that
805
1291
  // never reaches the hold itself.
806
1292
  const selfResumeStopAt = pendingSelfResumeStop(data);
807
- if (selfResumeHold !== null && selfResumeHold.stopAt !== selfResumeStopAt) {
808
- const heldMs = Date.now() - selfResumeHold.since;
809
- selfResumeHeldMs += heldMs;
810
- selfResumeHold = null;
1293
+ if (state.selfResumeHold !== null && state.selfResumeHold.stopAt !== selfResumeStopAt) {
1294
+ const heldMs = Date.now() - state.selfResumeHold.since;
1295
+ state.selfResumeHeldMs += heldMs;
1296
+ state.selfResumeHold = null;
811
1297
  console.error(`Note: ${worktreeId} has moved past the stop it said it would resume from ` +
812
1298
  `(held ${Math.round(heldMs / 1000)}s); judging its current state.`);
813
1299
  }
814
- // Prompt detected
815
- if (data.isPromptWaiting && data.promptData) {
816
- // Issue #1699: report a policy suppression on both exits — the human one
817
- // keeps polling and would otherwise say nothing about why nobody
818
- // answered, and the agent one is read by pipelines that never see stderr.
819
- const suppressed = activeSuppression(data, Date.now());
820
- // [DR1-03] Prompt detection exit code
821
- if (options.onPrompt === 'human') {
822
- // Block and continue polling - user handles prompt manually
823
- console.error(`Prompt detected on ${worktreeId}. Waiting for human response...`);
824
- if (suppressed) {
825
- console.error(formatSuppressionNotice(suppressed.suppression, suppressed.ageSeconds));
826
- }
827
- await sleep(POLL_INTERVAL_MS);
828
- continue;
829
- }
830
- // Issue #2463: the one case `decidePromptPush()` stays quiet about —
831
- // Auto-Yes is on and has not withheld this answer — is a prompt Auto-Yes
832
- // is about to answer, and exit 10 there hands a delegation back to a
833
- // human for a dialog nobody had to see. Hold it for the grace window; a
834
- // poll that shows no prompt ends the hold below and completion is judged
835
- // as usual. A withheld answer (`suppressed`) and Auto-Yes being off are
836
- // the gate's other two branches and still exit 10 at once.
837
- if (!suppressed && data.autoYes?.enabled === true && autoYesGraceMs > 0) {
838
- const now = Date.now();
839
- if (autoYesAnsweringSince === null) {
840
- autoYesAnsweringSince = now;
841
- // stderr only: stdout is the exit-10 payload and nothing else.
842
- console.error("Prompt detected; the target's Auto-Yes is answering, waiting up to " +
843
- `${autoYesGraceSeconds}s… (${worktreeId})`);
844
- }
845
- const heldMs = now - autoYesAnsweringSince;
846
- if (heldMs < autoYesGraceMs &&
847
- nextPollWithinDeadlines(options, startTime, lastActivityTime, now)) {
848
- await sleep(POLL_INTERVAL_MS);
849
- continue;
850
- }
851
- console.error(heldMs < autoYesGraceMs
852
- ? `Note: the prompt on ${worktreeId} is still open after ${Math.round(heldMs / 1000)}s ` +
853
- 'under Auto-Yes, and the next poll would pass --timeout/--stall-timeout; reporting it now.'
854
- : `Note: the target's Auto-Yes did not answer the prompt on ${worktreeId} within ` +
855
- `${autoYesGraceSeconds}s; reporting it.`);
856
- }
857
- else if (autoYesAnsweringSince !== null && !suppressed) {
858
- console.error(`Note: Auto-Yes is no longer enabled on ${worktreeId}; reporting the prompt.`);
859
- }
860
- // Default (agent mode): output prompt info and exit 10
861
- //
862
- // Issue #1898: the degraded `unclassified` payload carries no `options`
863
- // — by construction, because nothing parsed the screen — but for a
864
- // source whose approvals are answered by decision id it does carry
865
- // `decisionOptions`, which ARE answerable (`respond <id> 1`). Reporting
866
- // an empty list there told the caller a dialog was open and gave it
867
- // nothing to do about it, which is the whole of #1898-3 seen from the
868
- // pipeline's side.
869
- //
870
- // Issue #3184: and a QUESTION answered by decision id (OpenCode V2,
871
- // #2100) carries neither — its choices are `askUserQuestion.labels`,
872
- // numbered by position. The panel offered them as buttons while this
873
- // reported `[]`. Which of these applies is the shared view's call
874
- // (`readPromptView`), not a third reading of the raw fields here.
875
- const promptView = (0, prompt_view_1.readPromptView)(data);
876
- const promptOptions = data.promptData.options?.length
877
- ? data.promptData.options
878
- : data.promptData.decisionOptions?.length
879
- ? data.promptData.decisionOptions
880
- : promptView?.apiTarget === 'question'
881
- ? promptView.choices.map((choice) => ({
882
- number: Number(choice.answer),
883
- label: choice.label,
884
- }))
885
- : [];
886
- const promptOutput = {
887
- worktreeId,
888
- cliToolId: data.cliToolId || 'claude',
889
- type: data.promptData.type || 'unknown',
890
- question: data.promptData.question || '',
891
- options: promptOptions,
892
- status: data.promptData.status || 'pending',
893
- answerVia: waitAnswerVia(promptView),
894
- ...(data.promptData.approvalTarget !== undefined && {
895
- approvalTarget: data.promptData.approvalTarget,
896
- }),
897
- ...(suppressed && {
898
- autoYesSuppression: {
899
- reason: suppressed.suppression.reason,
900
- mode: suppressed.suppression.mode,
901
- promptType: suppressed.suppression.promptType,
902
- ...(suppressed.suppression.pattern !== undefined && {
903
- pattern: suppressed.suppression.pattern,
904
- }),
905
- ageSeconds: suppressed.ageSeconds,
906
- },
907
- }),
908
- };
909
- if (suppressed) {
910
- console.error(formatSuppressionNotice(suppressed.suppression, suppressed.ageSeconds));
911
- }
912
- return { exitCode: types_1.WaitExitCode.PROMPT_DETECTED, output: promptOutput };
1300
+ const promptOutcome = promptStage(poll, state, data);
1301
+ if (promptOutcome.kind === 'exit')
1302
+ return promptOutcome.result;
1303
+ if (promptOutcome.kind === 'wait') {
1304
+ await sleep(POLL_INTERVAL_MS);
1305
+ continue;
913
1306
  }
914
1307
  // Issue #2463: the prompt the hold was waiting on has gone. Who answered it
915
1308
  // is not on the wire — Auto-Yes, or a human at the pane — so the line says
916
1309
  // only that it cleared; what the agent does next is for the checks below.
917
- if (autoYesAnsweringSince !== null) {
1310
+ if (state.autoYesAnsweringSince !== null) {
918
1311
  console.error(`Prompt on ${worktreeId} cleared after ` +
919
- `${Math.round((Date.now() - autoYesAnsweringSince) / 1000)}s; judging completion as usual.`);
920
- autoYesAnsweringSince = null;
921
- }
922
- // Issue #1628: an arrow-key menu is the agent blocked on a human just as much
923
- // as a numbered prompt is, but it is published with isPromptWaiting=false so
924
- // the UI can render NavigationButtons instead of PromptPanel. Treat it as a
925
- // prompt here — otherwise `wait` polls a stopped agent until --timeout.
926
- if (data.isSelectionListActive) {
927
- if (options.onPrompt === 'human') {
928
- console.error(`Selection list active on ${worktreeId} (${data.sessionStatusReason ?? 'selection_list'}). ` +
929
- 'Waiting for human response...');
930
- // Issue #1699: the poller parses frames status-detector publishes as
931
- // selection lists, so a policy can be the reason this one is stuck too.
932
- const suppressed = activeSuppression(data, Date.now());
933
- if (suppressed) {
934
- console.error(formatSuppressionNotice(suppressed.suppression, suppressed.ageSeconds));
935
- }
936
- await sleep(POLL_INTERVAL_MS);
937
- continue;
938
- }
939
- return {
940
- exitCode: types_1.WaitExitCode.PROMPT_DETECTED,
941
- output: {
942
- worktreeId,
943
- cliToolId: data.cliToolId || 'claude',
944
- type: SELECTION_LIST_PROMPT_TYPE,
945
- question: data.sessionStatusReason ?? SELECTION_LIST_PROMPT_TYPE,
946
- options: [],
947
- status: 'pending',
948
- },
949
- };
950
- }
951
- // Issue #1708: the frame is interactive but nothing could parse it. The
952
- // detection layer is the single entry point every downstream safeguard
953
- // hangs off, so a frame that slips past it disables Auto-Yes, the exit-10
954
- // handoff and the contract's autoYes policy all at once — and `wait` used
955
- // to burn its whole --timeout without ever mentioning it. Treat a
956
- // PERSISTENT unclassified frame as a stop reason of its own.
957
- //
958
- // The dwell deliberately spans ALL THREE states that raise this flag, and
959
- // the completion check below is suppressed while it is up. That is the
960
- // whole point, and it is worth spelling out because the obvious reading is
961
- // the wrong one. The server's definition (`isUnclassifiedFrame` in
962
- // `src/lib/session/status-evidence.ts`, restated there by Issue #2011):
963
- //
964
- // isUnclassifiedActive =
965
- // running && (default | unknown_frame | no_recent_output)
966
- //
967
- // `no_recent_output` is there because a static unrecognised overlay
968
- // DEGRADES into it — once the Auto-Yes poller stamps
969
- // lastServerResponseTimestamp, a frame that stopped changing flips from
970
- // `running`/`default` after STALE_OUTPUT_THRESHOLD_MS (5s). `unknown_frame`
971
- // is the same floor for a tool that opts out of the generic composer check
972
- // (copilot, opencode), and says "this tool's own rules looked and read
973
- // nothing". Both arrive about twelve times faster than this dwell. Letting
974
- // the completion check claim one turned a stalled worker into `Completed`,
975
- // which is worse than the timeout Issue #1708 complained about: exit 124
976
- // stops a pipeline, exit 0 lets it merge. Measured before this guard: two
977
- // unclassified polls followed by the degraded state returned SUCCESS.
978
- //
979
- // What is deliberately NOT in the set is `ready`/`input_prompt` with
980
- // `statusEvidence: 'none'` — the agent back at its composer on a frame no
981
- // tool-specific idle rule could vouch for. That frame WAS classified; what
982
- // is missing is positive proof, which is a different question and §4 D1's
983
- // to answer. Issue #1927 folded the two together and every idle Claude pane
984
- // stopped completing (#2011). Whether `wait` should hold for evidence as
985
- // well as classification is open, and any answer belongs in the same place
986
- // as the rollout that produces the evidence — not here.
987
- if (data.isUnclassifiedActive === true) {
988
- if (unclassifiedSince === null)
989
- unclassifiedSince = Date.now();
990
- const dwellMs = Date.now() - unclassifiedSince;
991
- if (dwellMs >= UNCLASSIFIED_DWELL_MS) {
992
- const dwellSeconds = Math.round(dwellMs / 1000);
993
- const question = `Unclassified interactive frame on ${worktreeId} for ${dwellSeconds}s ` +
994
- `(status=${data.sessionStatus ?? 'unknown'}/${data.sessionStatusReason ?? 'unknown'}). ` +
995
- `The detection layer could not parse it; inspect the raw pane with ` +
996
- `\`commandmate capture ${worktreeId} --pane\`.` +
997
- // Issue #2095: the sidebar is exactly this frame's reason, and the
998
- // one recovery is a keystroke in the pane. Riding the message keeps
999
- // the exit-code table (10, `type: unclassified`) unchanged for every
1000
- // caller that already branches on it.
1001
- describePaneObstruction(data);
1002
- if (options.onPrompt === 'human') {
1003
- console.error(question);
1004
- console.error('Waiting for human response...');
1005
- await sleep(POLL_INTERVAL_MS);
1006
- continue;
1007
- }
1008
- console.error(question);
1009
- return {
1010
- exitCode: types_1.WaitExitCode.PROMPT_DETECTED,
1011
- output: {
1012
- worktreeId,
1013
- cliToolId: data.cliToolId || 'claude',
1014
- type: UNCLASSIFIED_PROMPT_TYPE,
1015
- question,
1016
- options: [],
1017
- status: 'pending',
1018
- answerVia: 'terminal',
1019
- },
1020
- };
1021
- }
1312
+ `${Math.round((Date.now() - state.autoYesAnsweringSince) / 1000)}s; judging completion as usual.`);
1313
+ state.autoYesAnsweringSince = null;
1022
1314
  }
1023
- else {
1024
- unclassifiedSince = null;
1025
- }
1026
- // Completion check [DR1-04]:
1027
- // Path A: the tmux session went away after we had seen it alive — the agent
1028
- // finished and its session was stopped.
1029
- // Path B: agent completed task (sessionStatus === 'ready', input prompt detected)
1030
- // Both indicate "no more work in progress" from wait command's perspective.
1031
- //
1032
- // Issue #1628 narrowed Path A: a session that was NEVER seen running is
1033
- // "nothing to wait for" (NOT_STARTED), not a completion. See `everRunning`.
1034
- if (!data.isRunning && !everRunning) {
1035
- console.error(`Not started: ${worktreeId} has no running ${data.cliToolId ?? 'agent'} session` +
1036
- `${options.instance ? ` for instance ${options.instance}` : ''}` +
1037
- // Issue #1884: name the stage that chose the agent above. `wait` has
1038
- // no --agent to correct a mis-resolution with, so "no running claude
1039
- // session for instance opencode" was the entire evidence an operator
1040
- // got for a live agent reported as absent. `worktree-default` here
1041
- // means the instance is neither in the roster nor named after a
1042
- // tool; `client-fallback`, that the server is too old to resolve.
1043
- `${data.resolvedBy ? ` (resolvedBy=${data.resolvedBy})` : ''}.`);
1044
- return { exitCode: types_1.VerifyExitCode.NOT_STARTED };
1315
+ const selectionListOutcome = selectionListStage(poll, data);
1316
+ if (selectionListOutcome.kind === 'exit')
1317
+ return selectionListOutcome.result;
1318
+ if (selectionListOutcome.kind === 'wait') {
1319
+ await sleep(POLL_INTERVAL_MS);
1320
+ continue;
1045
1321
  }
1046
- // Issue #1708 narrowed Path B: `ready` is only a completion when the frame
1047
- // was actually understood. A structured `hook_stop` over an unreadable
1048
- // pane is the degraded form of an overlay nobody could parse (see the note
1049
- // above), and reporting it as `Completed` is how a stalled worker gets
1050
- // merged. Path A is untouched — a session that went away really is
1051
- // finished, and carries no flag anyway.
1052
- if (!data.isRunning) {
1053
- console.error(`Completed: ${worktreeId} (basis=${COMPLETION_BASIS.SESSION_GONE}${selfResumeSuffix()})`);
1054
- return { exitCode: types_1.WaitExitCode.SUCCESS };
1322
+ const unclassifiedOutcome = unclassifiedStage(poll, state, data);
1323
+ if (unclassifiedOutcome.kind === 'exit')
1324
+ return unclassifiedOutcome.result;
1325
+ if (unclassifiedOutcome.kind === 'wait') {
1326
+ await sleep(POLL_INTERVAL_MS);
1327
+ continue;
1055
1328
  }
1056
- if (data.sessionStatus === 'ready' && data.isUnclassifiedActive !== true) {
1057
- // Issue #1839: the agent is back at its composer with an upstream
1058
- // failure on the frame. Checked BEFORE the turn-boundary gate below,
1059
- // because it is the answer to the question that gate can only ask: the
1060
- // turn did not end, and this is why. Without it the same session runs
1061
- // to --timeout and reports 124, which says nothing about the cause.
1062
- const fault = data.upstreamFault ?? null;
1063
- if (options.failOnUpstreamFault && fault) {
1064
- console.error(`Upstream fault on ${worktreeId}: id=${fault.id} — the agent is back at its ` +
1065
- 'composer with an upstream API failure on screen, so this turn did not run. ' +
1066
- `Matched: ${JSON.stringify(fault.matchedText)}`);
1067
- if (fault.id === 'context-limit') {
1068
- // A retry into the same session hits the same wall (Issue #3011).
1069
- console.error('The session\'s conversation is over the model\'s context limit. Start a fresh ' +
1070
- `session and send again: commandmate instances ${worktreeId} kill ` +
1071
- `${options.instance ?? '<instance>'}`);
1072
- }
1073
- return {
1074
- exitCode: types_1.WaitExitCode.UPSTREAM_FAULT,
1075
- upstreamFault: { id: fault.id, matchedText: fault.matchedText },
1076
- };
1077
- }
1078
- // Issue #1839: `ready` off the terminal frame is the agent's composer,
1079
- // not the agent's verdict. Measured 2026-08-20 against a stub upstream
1080
- // answering 529: Claude returns to the composer ~3 s after the send
1081
- // having executed nothing, and never sends `Stop`. When this instance's
1082
- // hooks ARE reporting — the only case in which `turnStartedAt` is
1083
- // non-null — that missing `Stop` is the difference between "finished"
1084
- // and "never ran", and it is the only signal that carries it.
1085
- if (!turnSettled(data, turnStartedAt)) {
1086
- console.error(`Waiting: ${worktreeId} is back at its composer, but its agent has not reported ` +
1087
- `the end of this turn (turnStartedAt=${turnStartedAt}, ` +
1088
- `lastStopEventAt=${data.lastStopEventAt ?? 'none'}, ${describeTurnClose(data)}). ` +
1089
- 'Not reporting completion; inspect with ' +
1090
- `\`commandmate capture ${worktreeId} --json\`.`);
1091
- await sleep(POLL_INTERVAL_MS);
1092
- continue;
1093
- }
1094
- // Issue #2614: the turn did end — the agent said so — but it also said
1095
- // that work of its own is still running in the background (a `schedule`
1096
- // timer, a backgrounded command), and that work wakes it with nobody
1097
- // typing anything. Measured 2026-09-17 on antigravity 1.2.4: four such
1098
- // stops ~58 s before each self-wake, and the first one was reported as
1099
- // `Completed (basis=hook_stop)` and verified five minutes before the
1100
- // work was done. So this `stop` is held until it is no longer the newest
1101
- // word (see `selfResumeStopAt` above), or until the bound.
1102
- //
1103
- // The bound is measured from whichever is further along: the `stop`
1104
- // itself (server clock — a negative age is skew, and the max discards
1105
- // it) or this wait's first sight of it. A session that said so hours ago
1106
- // and never woke is not held again.
1107
- if (selfResumeStopAt !== null) {
1108
- const now = Date.now();
1109
- if (selfResumeHold === null)
1110
- selfResumeHold = { stopAt: selfResumeStopAt, since: now };
1111
- const heldMs = now - selfResumeHold.since;
1112
- const elapsedMs = Math.max(heldMs, now - selfResumeStopAt);
1113
- if (elapsedMs < exports.SELF_RESUME_HOLD_MS) {
1114
- selfResumeHeld = true;
1115
- console.error(`Waiting: ${worktreeId} ended its turn with background work still running ` +
1116
- `(stoppedAt=${new Date(selfResumeStopAt).toISOString()}, ` +
1117
- `lastEventDetail=${exports.SELF_RESUME_PENDING_DETAIL}, ${describeTurnClose(data)}); ` +
1118
- 'it resumes by itself when that work finishes. Not reporting completion ' +
1119
- `(held ${Math.round(heldMs / 1000)}s, at most ${exports.SELF_RESUME_HOLD_MS / 1000}s ` +
1120
- 'after the stop).');
1121
- await sleep(POLL_INTERVAL_MS);
1122
- continue;
1123
- }
1124
- console.error(`Note: ${worktreeId} said at its stop ${Math.round(elapsedMs / 1000)}s ` +
1125
- 'ago that background work was still running, and has not resumed since; ' +
1126
- 'completing on that stop.');
1127
- }
1128
- // Issue #1975: the same frame, one question further back. #1839's gate
1129
- // above can only fire once a turn has been ADOPTED, and `send` leaves a
1130
- // window ~1s wide in which nothing has been: the newest structured event
1131
- // is still the previous turn's `stop`, so `adoptTurnStart` takes nothing,
1132
- // `turnSettled` reads null as "settled", and the composer the agent has
1133
- // not touched yet is read as the composer it came back to. Measured
1134
- // 2026-08-22 against copilot 1.0.80 on an isolated server: 3 of 5
1135
- // send-then-wait runs came back in ~0.3s with `basis=scraper_ready` and
1136
- // no artefact on disk.
1137
- //
1138
- // So ask the ledger instead of the clock: has this instance been handed
1139
- // a prompt that the agent has not reported the end of? See
1140
- // {@link outstandingPrompt} for why that comparison is the one that
1141
- // separates "not started" from "finished", and
1142
- // {@link reportsTurnBoundaries} for why a tool that posts no hooks never
1143
- // reaches it.
1144
- let answeredNewestPrompt = false;
1145
- if (turnStartedAt === null && promptLedgerReadable && reportsTurnBoundaries(data)) {
1146
- const ledger = await readNewestPromptAt(client, worktreeId, options, data);
1147
- // One notice, then stop asking: a ledger that failed once will fail
1148
- // every poll, and the point of degrading is to stop paying for it.
1149
- promptLedgerReadable = ledger.readable;
1150
- if (ledger.readable && ledger.submittedAt !== null) {
1151
- if (outstandingPrompt(data, ledger.submittedAt)) {
1152
- const heldMs = Date.now() - startTime;
1153
- if (heldMs < PENDING_PROMPT_HOLD_MS) {
1154
- console.error(`Waiting: ${worktreeId} is at its composer, but the newest prompt sent to it ` +
1155
- `has no reported end (sentAt=${new Date(ledger.submittedAt).toISOString()}, ` +
1156
- `lastStopEventAt=${data.lastStopEventAt ?? 'none'}, ${describeTurnClose(data)}). ` +
1157
- 'Not reporting completion: the agent has not started this turn yet.');
1158
- await sleep(POLL_INTERVAL_MS);
1159
- continue;
1160
- }
1161
- console.error(`Note: ${worktreeId} has been at its composer for ` +
1162
- `${Math.round(heldMs / 1000)}s with the newest prompt still unreported by its ` +
1163
- 'agent. Its hooks are not answering; completing on the frame alone.');
1164
- }
1165
- else {
1166
- answeredNewestPrompt = true;
1167
- }
1168
- }
1169
- }
1170
- // `hook_stop` on both branches that have one, and they are the same
1171
- // statement made from two records: the agent reported the end of the
1172
- // turn this wait is about. `scraper_ready` keeps its documented meaning
1173
- // — "the screen said so and nothing corroborated it" — which is now
1174
- // exactly the set of cases that reach it.
1175
- const basis = turnStartedAt !== null || answeredNewestPrompt
1176
- ? COMPLETION_BASIS.HOOK_STOP
1177
- : COMPLETION_BASIS.SCRAPER_READY;
1178
- console.error(`Completed: ${worktreeId} (basis=${basis}${selfResumeSuffix()})`);
1179
- return { exitCode: types_1.WaitExitCode.SUCCESS };
1329
+ const notRunningOutcome = notRunningStage(poll, state, data, selfResumeSuffix);
1330
+ if (notRunningOutcome.kind === 'exit')
1331
+ return notRunningOutcome.result;
1332
+ const readyOutcome = await readyStage(poll, state, data, selfResumeStopAt, selfResumeSuffix);
1333
+ if (readyOutcome.kind === 'exit')
1334
+ return readyOutcome.result;
1335
+ if (readyOutcome.kind === 'wait') {
1336
+ await sleep(POLL_INTERVAL_MS);
1337
+ continue;
1180
1338
  }
1181
1339
  // Progress indicator on stderr [DR1-05]
1182
1340
  console.error(`Waiting: ${worktreeId} (status=${data.sessionStatus}, running=${data.isRunning}, prompt=${data.isPromptWaiting})`);