commandmate 0.47.2 → 0.49.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (434) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-build-manifest.json +180 -180
  3. package/.next/app-path-routes-manifest.json +30 -30
  4. package/.next/build-manifest.json +2 -2
  5. package/.next/prerender-manifest.json +9 -9
  6. package/.next/required-server-files.json +1 -1
  7. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  8. package/.next/server/app/api/agents/update/route_client-reference-manifest.js +1 -1
  9. package/.next/server/app/api/agents/versions/route_client-reference-manifest.js +1 -1
  10. package/.next/server/app/api/app/release-notes/route_client-reference-manifest.js +1 -1
  11. package/.next/server/app/api/app/update/route.js +3 -3
  12. package/.next/server/app/api/app/update/route_client-reference-manifest.js +1 -1
  13. package/.next/server/app/api/app/update-check/route_client-reference-manifest.js +1 -1
  14. package/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
  15. package/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
  16. package/.next/server/app/api/auth/status/route_client-reference-manifest.js +1 -1
  17. package/.next/server/app/api/capabilities/route.js +1 -1
  18. package/.next/server/app/api/capabilities/route_client-reference-manifest.js +1 -1
  19. package/.next/server/app/api/daily-summary/route_client-reference-manifest.js +1 -1
  20. package/.next/server/app/api/daily-summary/status/route_client-reference-manifest.js +1 -1
  21. package/.next/server/app/api/external-apps/[id]/health/route_client-reference-manifest.js +1 -1
  22. package/.next/server/app/api/external-apps/[id]/route_client-reference-manifest.js +1 -1
  23. package/.next/server/app/api/external-apps/route_client-reference-manifest.js +1 -1
  24. package/.next/server/app/api/fs/browse/route_client-reference-manifest.js +1 -1
  25. package/.next/server/app/api/fs/recent-paths/route_client-reference-manifest.js +1 -1
  26. package/.next/server/app/api/hooks/agent-event/route.js +2 -2
  27. package/.next/server/app/api/hooks/agent-event/route.js.nft.json +1 -1
  28. package/.next/server/app/api/hooks/agent-event/route_client-reference-manifest.js +1 -1
  29. package/.next/server/app/api/hooks/claude-done/route.js +2 -2
  30. package/.next/server/app/api/hooks/claude-done/route.js.nft.json +1 -1
  31. package/.next/server/app/api/hooks/claude-done/route_client-reference-manifest.js +1 -1
  32. package/.next/server/app/api/hooks/permission-request/route.js +1 -1
  33. package/.next/server/app/api/hooks/permission-request/route.js.nft.json +1 -1
  34. package/.next/server/app/api/hooks/permission-request/route_client-reference-manifest.js +1 -1
  35. package/.next/server/app/api/metrics/vibe/route_client-reference-manifest.js +1 -1
  36. package/.next/server/app/api/ollama/models/route_client-reference-manifest.js +1 -1
  37. package/.next/server/app/api/push/escalation/route.js +1 -1
  38. package/.next/server/app/api/push/escalation/route_client-reference-manifest.js +1 -1
  39. package/.next/server/app/api/push/subscriptions/route_client-reference-manifest.js +1 -1
  40. package/.next/server/app/api/push/vapid/route.js +1 -1
  41. package/.next/server/app/api/push/vapid/route_client-reference-manifest.js +1 -1
  42. package/.next/server/app/api/relays/[relayId]/cancel/route.js +1 -1
  43. package/.next/server/app/api/relays/[relayId]/cancel/route.js.nft.json +1 -1
  44. package/.next/server/app/api/relays/[relayId]/cancel/route_client-reference-manifest.js +1 -1
  45. package/.next/server/app/api/relays/route.js +1 -1
  46. package/.next/server/app/api/relays/route.js.nft.json +1 -1
  47. package/.next/server/app/api/relays/route_client-reference-manifest.js +1 -1
  48. package/.next/server/app/api/remote/pair/route_client-reference-manifest.js +1 -1
  49. package/.next/server/app/api/repositories/[id]/route_client-reference-manifest.js +1 -1
  50. package/.next/server/app/api/repositories/clone/[jobId]/route.js +1 -1
  51. package/.next/server/app/api/repositories/clone/[jobId]/route.js.nft.json +1 -1
  52. package/.next/server/app/api/repositories/clone/[jobId]/route_client-reference-manifest.js +1 -1
  53. package/.next/server/app/api/repositories/clone/route.js +1 -1
  54. package/.next/server/app/api/repositories/clone/route.js.nft.json +1 -1
  55. package/.next/server/app/api/repositories/clone/route_client-reference-manifest.js +1 -1
  56. package/.next/server/app/api/repositories/excluded/route_client-reference-manifest.js +1 -1
  57. package/.next/server/app/api/repositories/restore/route.js +1 -1
  58. package/.next/server/app/api/repositories/restore/route.js.nft.json +1 -1
  59. package/.next/server/app/api/repositories/restore/route_client-reference-manifest.js +1 -1
  60. package/.next/server/app/api/repositories/route.js +1 -1
  61. package/.next/server/app/api/repositories/route.js.nft.json +1 -1
  62. package/.next/server/app/api/repositories/route_client-reference-manifest.js +1 -1
  63. package/.next/server/app/api/repositories/scan/route.js +1 -1
  64. package/.next/server/app/api/repositories/scan/route.js.nft.json +1 -1
  65. package/.next/server/app/api/repositories/scan/route_client-reference-manifest.js +1 -1
  66. package/.next/server/app/api/repositories/sync/route.js +1 -1
  67. package/.next/server/app/api/repositories/sync/route.js.nft.json +1 -1
  68. package/.next/server/app/api/repositories/sync/route_client-reference-manifest.js +1 -1
  69. package/.next/server/app/api/repositories/validate-path/route_client-reference-manifest.js +1 -1
  70. package/.next/server/app/api/settings/default-agents/route.js +1 -1
  71. package/.next/server/app/api/settings/default-agents/route.js.nft.json +1 -1
  72. package/.next/server/app/api/settings/default-agents/route_client-reference-manifest.js +1 -1
  73. package/.next/server/app/api/settings/default-surface-mode/route_client-reference-manifest.js +1 -1
  74. package/.next/server/app/api/sidebar/group-order/route_client-reference-manifest.js +1 -1
  75. package/.next/server/app/api/skills/[id]/route_client-reference-manifest.js +1 -1
  76. package/.next/server/app/api/skills/installations/route_client-reference-manifest.js +1 -1
  77. package/.next/server/app/api/skills/operations/route_client-reference-manifest.js +1 -1
  78. package/.next/server/app/api/skills/reindex/route_client-reference-manifest.js +1 -1
  79. package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
  80. package/.next/server/app/api/slash-commands/route_client-reference-manifest.js +1 -1
  81. package/.next/server/app/api/tasks/[taskId]/cancel/route_client-reference-manifest.js +1 -1
  82. package/.next/server/app/api/tasks/[taskId]/route_client-reference-manifest.js +1 -1
  83. package/.next/server/app/api/templates/[id]/route_client-reference-manifest.js +1 -1
  84. package/.next/server/app/api/templates/route_client-reference-manifest.js +1 -1
  85. package/.next/server/app/api/verification/runs/[runId]/route_client-reference-manifest.js +1 -1
  86. package/.next/server/app/api/verification/runs/route_client-reference-manifest.js +1 -1
  87. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js +1 -1
  88. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js.nft.json +1 -1
  89. package/.next/server/app/api/worktrees/[id]/auto-yes/route_client-reference-manifest.js +1 -1
  90. package/.next/server/app/api/worktrees/[id]/capture/route.js +1 -1
  91. package/.next/server/app/api/worktrees/[id]/capture/route.js.nft.json +1 -1
  92. package/.next/server/app/api/worktrees/[id]/capture/route_client-reference-manifest.js +1 -1
  93. package/.next/server/app/api/worktrees/[id]/clear-composer/route.js +1 -1
  94. package/.next/server/app/api/worktrees/[id]/clear-composer/route.js.nft.json +1 -1
  95. package/.next/server/app/api/worktrees/[id]/clear-composer/route_client-reference-manifest.js +1 -1
  96. package/.next/server/app/api/worktrees/[id]/cli-reference/route_client-reference-manifest.js +1 -1
  97. package/.next/server/app/api/worktrees/[id]/cli-tool/route_client-reference-manifest.js +1 -1
  98. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route_client-reference-manifest.js +1 -1
  99. package/.next/server/app/api/worktrees/[id]/current-output/route.js +1 -1
  100. package/.next/server/app/api/worktrees/[id]/current-output/route.js.nft.json +1 -1
  101. package/.next/server/app/api/worktrees/[id]/current-output/route_client-reference-manifest.js +1 -1
  102. package/.next/server/app/api/worktrees/[id]/direct-input/route.js +1 -1
  103. package/.next/server/app/api/worktrees/[id]/direct-input/route.js.nft.json +1 -1
  104. package/.next/server/app/api/worktrees/[id]/direct-input/route_client-reference-manifest.js +1 -1
  105. package/.next/server/app/api/worktrees/[id]/env/route_client-reference-manifest.js +1 -1
  106. package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route_client-reference-manifest.js +1 -1
  107. package/.next/server/app/api/worktrees/[id]/execution-logs/route_client-reference-manifest.js +1 -1
  108. package/.next/server/app/api/worktrees/[id]/files/[...path]/route_client-reference-manifest.js +1 -1
  109. package/.next/server/app/api/worktrees/[id]/git/branch/create/route_client-reference-manifest.js +1 -1
  110. package/.next/server/app/api/worktrees/[id]/git/branch/delete/route_client-reference-manifest.js +1 -1
  111. package/.next/server/app/api/worktrees/[id]/git/branches/route_client-reference-manifest.js +1 -1
  112. package/.next/server/app/api/worktrees/[id]/git/checkout/route_client-reference-manifest.js +1 -1
  113. package/.next/server/app/api/worktrees/[id]/git/commit/route_client-reference-manifest.js +1 -1
  114. package/.next/server/app/api/worktrees/[id]/git/diff/route_client-reference-manifest.js +1 -1
  115. package/.next/server/app/api/worktrees/[id]/git/fetch/route_client-reference-manifest.js +1 -1
  116. package/.next/server/app/api/worktrees/[id]/git/log/route_client-reference-manifest.js +1 -1
  117. package/.next/server/app/api/worktrees/[id]/git/pull/route_client-reference-manifest.js +1 -1
  118. package/.next/server/app/api/worktrees/[id]/git/push/route_client-reference-manifest.js +1 -1
  119. package/.next/server/app/api/worktrees/[id]/git/reset/route_client-reference-manifest.js +1 -1
  120. package/.next/server/app/api/worktrees/[id]/git/revert/route_client-reference-manifest.js +1 -1
  121. package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route_client-reference-manifest.js +1 -1
  122. package/.next/server/app/api/worktrees/[id]/git/stage/route_client-reference-manifest.js +1 -1
  123. package/.next/server/app/api/worktrees/[id]/git/staged/route_client-reference-manifest.js +1 -1
  124. package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route_client-reference-manifest.js +1 -1
  125. package/.next/server/app/api/worktrees/[id]/git/stash/apply/route_client-reference-manifest.js +1 -1
  126. package/.next/server/app/api/worktrees/[id]/git/stash/pop/route_client-reference-manifest.js +1 -1
  127. package/.next/server/app/api/worktrees/[id]/git/stash/push/route_client-reference-manifest.js +1 -1
  128. package/.next/server/app/api/worktrees/[id]/git/stash/route_client-reference-manifest.js +1 -1
  129. package/.next/server/app/api/worktrees/[id]/git/status/route_client-reference-manifest.js +1 -1
  130. package/.next/server/app/api/worktrees/[id]/git/unstage/route_client-reference-manifest.js +1 -1
  131. package/.next/server/app/api/worktrees/[id]/git/working-diff/route_client-reference-manifest.js +1 -1
  132. package/.next/server/app/api/worktrees/[id]/instances/notes/route_client-reference-manifest.js +1 -1
  133. package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js +1 -1
  134. package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js.nft.json +1 -1
  135. package/.next/server/app/api/worktrees/[id]/instances/opencode/route_client-reference-manifest.js +1 -1
  136. package/.next/server/app/api/worktrees/[id]/interrupt/route.js +1 -1
  137. package/.next/server/app/api/worktrees/[id]/interrupt/route.js.nft.json +1 -1
  138. package/.next/server/app/api/worktrees/[id]/interrupt/route_client-reference-manifest.js +1 -1
  139. package/.next/server/app/api/worktrees/[id]/kill-session/route.js +1 -1
  140. package/.next/server/app/api/worktrees/[id]/kill-session/route.js.nft.json +1 -1
  141. package/.next/server/app/api/worktrees/[id]/kill-session/route_client-reference-manifest.js +1 -1
  142. package/.next/server/app/api/worktrees/[id]/logs/[filename]/route_client-reference-manifest.js +1 -1
  143. package/.next/server/app/api/worktrees/[id]/logs/route_client-reference-manifest.js +1 -1
  144. package/.next/server/app/api/worktrees/[id]/marp-render/route_client-reference-manifest.js +1 -1
  145. package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route_client-reference-manifest.js +1 -1
  146. package/.next/server/app/api/worktrees/[id]/memos/route_client-reference-manifest.js +1 -1
  147. package/.next/server/app/api/worktrees/[id]/messages/route_client-reference-manifest.js +1 -1
  148. package/.next/server/app/api/worktrees/[id]/opencode/diff/route_client-reference-manifest.js +1 -1
  149. package/.next/server/app/api/worktrees/[id]/opencode/session/route.js +1 -1
  150. package/.next/server/app/api/worktrees/[id]/opencode/session/route.js.nft.json +1 -1
  151. package/.next/server/app/api/worktrees/[id]/opencode/session/route_client-reference-manifest.js +1 -1
  152. package/.next/server/app/api/worktrees/[id]/opencode/share/route.js +1 -1
  153. package/.next/server/app/api/worktrees/[id]/opencode/share/route.js.nft.json +1 -1
  154. package/.next/server/app/api/worktrees/[id]/opencode/share/route_client-reference-manifest.js +1 -1
  155. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js +1 -1
  156. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js.nft.json +1 -1
  157. package/.next/server/app/api/worktrees/[id]/prompt-response/route_client-reference-manifest.js +1 -1
  158. package/.next/server/app/api/worktrees/[id]/prompt-response/strict/route.js +1 -1
  159. package/.next/server/app/api/worktrees/[id]/prompt-response/strict/route.js.nft.json +1 -1
  160. package/.next/server/app/api/worktrees/[id]/prompt-response/strict/route_client-reference-manifest.js +1 -1
  161. package/.next/server/app/api/worktrees/[id]/resolve-target/route_client-reference-manifest.js +1 -1
  162. package/.next/server/app/api/worktrees/[id]/respond/route.js +1 -1
  163. package/.next/server/app/api/worktrees/[id]/respond/route.js.nft.json +1 -1
  164. package/.next/server/app/api/worktrees/[id]/respond/route_client-reference-manifest.js +1 -1
  165. package/.next/server/app/api/worktrees/[id]/route.js +1 -1
  166. package/.next/server/app/api/worktrees/[id]/route.js.nft.json +1 -1
  167. package/.next/server/app/api/worktrees/[id]/route_client-reference-manifest.js +1 -1
  168. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route_client-reference-manifest.js +1 -1
  169. package/.next/server/app/api/worktrees/[id]/schedules/active/route_client-reference-manifest.js +1 -1
  170. package/.next/server/app/api/worktrees/[id]/schedules/route_client-reference-manifest.js +1 -1
  171. package/.next/server/app/api/worktrees/[id]/search/route_client-reference-manifest.js +1 -1
  172. package/.next/server/app/api/worktrees/[id]/send/route.js +1 -1
  173. package/.next/server/app/api/worktrees/[id]/send/route.js.nft.json +1 -1
  174. package/.next/server/app/api/worktrees/[id]/send/route_client-reference-manifest.js +1 -1
  175. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js +3 -3
  176. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js.nft.json +1 -1
  177. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route_client-reference-manifest.js +1 -1
  178. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route_client-reference-manifest.js +1 -1
  179. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route_client-reference-manifest.js +1 -1
  180. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route_client-reference-manifest.js +1 -1
  181. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route_client-reference-manifest.js +1 -1
  182. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update/route_client-reference-manifest.js +1 -1
  183. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route_client-reference-manifest.js +1 -1
  184. package/.next/server/app/api/worktrees/[id]/skills/route_client-reference-manifest.js +1 -1
  185. package/.next/server/app/api/worktrees/[id]/slash-commands/route_client-reference-manifest.js +1 -1
  186. package/.next/server/app/api/worktrees/[id]/special-keys/route.js +1 -1
  187. package/.next/server/app/api/worktrees/[id]/special-keys/route.js.nft.json +1 -1
  188. package/.next/server/app/api/worktrees/[id]/special-keys/route_client-reference-manifest.js +1 -1
  189. package/.next/server/app/api/worktrees/[id]/tasks/route_client-reference-manifest.js +1 -1
  190. package/.next/server/app/api/worktrees/[id]/terminal/route.js +1 -103
  191. package/.next/server/app/api/worktrees/[id]/terminal/route.js.nft.json +1 -1
  192. package/.next/server/app/api/worktrees/[id]/terminal/route_client-reference-manifest.js +1 -1
  193. package/.next/server/app/api/worktrees/[id]/timers/history/route_client-reference-manifest.js +1 -1
  194. package/.next/server/app/api/worktrees/[id]/timers/route.js +1 -1
  195. package/.next/server/app/api/worktrees/[id]/timers/route.js.nft.json +1 -1
  196. package/.next/server/app/api/worktrees/[id]/timers/route_client-reference-manifest.js +1 -1
  197. package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
  198. package/.next/server/app/api/worktrees/[id]/todos/route_client-reference-manifest.js +1 -1
  199. package/.next/server/app/api/worktrees/[id]/tree/[...path]/route_client-reference-manifest.js +1 -1
  200. package/.next/server/app/api/worktrees/[id]/tree/route_client-reference-manifest.js +1 -1
  201. package/.next/server/app/api/worktrees/[id]/upload/[...path]/route_client-reference-manifest.js +1 -1
  202. package/.next/server/app/api/worktrees/[id]/verify/config/route_client-reference-manifest.js +1 -1
  203. package/.next/server/app/api/worktrees/[id]/verify/route.js +1 -1
  204. package/.next/server/app/api/worktrees/[id]/verify/route_client-reference-manifest.js +1 -1
  205. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route.js +1 -1
  206. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route_client-reference-manifest.js +1 -1
  207. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route_client-reference-manifest.js +1 -1
  208. package/.next/server/app/api/worktrees/[id]/verify/runs/route_client-reference-manifest.js +1 -1
  209. package/.next/server/app/api/worktrees/[id]/viewed/route_client-reference-manifest.js +1 -1
  210. package/.next/server/app/api/worktrees/apply-default-agents/route_client-reference-manifest.js +1 -1
  211. package/.next/server/app/api/worktrees/route.js +1 -1
  212. package/.next/server/app/api/worktrees/route.js.nft.json +1 -1
  213. package/.next/server/app/api/worktrees/route_client-reference-manifest.js +1 -1
  214. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  215. package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
  216. package/.next/server/app/more/page_client-reference-manifest.js +1 -1
  217. package/.next/server/app/offline/page_client-reference-manifest.js +1 -1
  218. package/.next/server/app/page_client-reference-manifest.js +1 -1
  219. package/.next/server/app/proxy/[...path]/route_client-reference-manifest.js +1 -1
  220. package/.next/server/app/repositories/page_client-reference-manifest.js +1 -1
  221. package/.next/server/app/review/page_client-reference-manifest.js +1 -1
  222. package/.next/server/app/sessions/page.js +1 -1
  223. package/.next/server/app/sessions/page.js.nft.json +1 -1
  224. package/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  225. package/.next/server/app/skills/[skillId]/page.js +1 -1
  226. package/.next/server/app/skills/[skillId]/page.js.nft.json +1 -1
  227. package/.next/server/app/skills/[skillId]/page_client-reference-manifest.js +1 -1
  228. package/.next/server/app/skills/installed/page_client-reference-manifest.js +1 -1
  229. package/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  230. package/.next/server/app/worktrees/[id]/files/[...path]/page.js +2 -2
  231. package/.next/server/app/worktrees/[id]/files/[...path]/page.js.nft.json +1 -1
  232. package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -1
  233. package/.next/server/app/worktrees/[id]/page.js +12 -12
  234. package/.next/server/app/worktrees/[id]/page.js.nft.json +1 -1
  235. package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -1
  236. package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
  237. package/.next/server/app-paths-manifest.json +30 -30
  238. package/.next/server/chunks/1191.js +11 -4
  239. package/.next/server/chunks/1501.js +1 -1
  240. package/.next/server/chunks/1601.js +2 -2
  241. package/.next/server/chunks/1656.js +2 -2
  242. package/.next/server/chunks/1945.js +3 -3
  243. package/.next/server/chunks/1990.js +103 -0
  244. package/.next/server/chunks/2069.js +1 -0
  245. package/.next/server/chunks/2119.js +1 -1
  246. package/.next/server/chunks/2404.js +1 -1
  247. package/.next/server/chunks/2422.js +1 -1
  248. package/.next/server/chunks/2445.js +1 -1
  249. package/.next/server/chunks/2534.js +1 -1
  250. package/.next/server/chunks/255.js +1 -1
  251. package/.next/server/chunks/3241.js +1 -1
  252. package/.next/server/chunks/3505.js +2 -2
  253. package/.next/server/chunks/4243.js +1 -1
  254. package/.next/server/chunks/4248.js +1 -1
  255. package/.next/server/chunks/4280.js +1 -0
  256. package/.next/server/chunks/5209.js +1 -1
  257. package/.next/server/chunks/6119.js +1 -1
  258. package/.next/server/chunks/6130.js +1 -1
  259. package/.next/server/chunks/6401.js +1 -1
  260. package/.next/server/chunks/6486.js +9 -8
  261. package/.next/server/chunks/6781.js +1 -1
  262. package/.next/server/chunks/720.js +103 -0
  263. package/.next/server/chunks/7604.js +2 -0
  264. package/.next/server/chunks/7905.js +1 -1
  265. package/.next/server/chunks/8581.js +8 -8
  266. package/.next/server/chunks/8728.js +3 -3
  267. package/.next/server/chunks/8791.js +1 -1
  268. package/.next/server/chunks/8807.js +19 -18
  269. package/.next/server/chunks/8918.js +2 -104
  270. package/.next/server/chunks/936.js +1 -1
  271. package/.next/server/chunks/9390.js +1 -1
  272. package/.next/server/chunks/9540.js +1 -1
  273. package/.next/server/chunks/9627.js +5 -5
  274. package/.next/server/chunks/9731.js +2 -2
  275. package/.next/server/middleware-manifest.json +5 -5
  276. package/.next/server/pages/500.html +1 -1
  277. package/.next/server/server-reference-manifest.json +1 -1
  278. package/.next/static/chunks/1128-914c559913546bbc.js +1 -0
  279. package/.next/static/chunks/{2407-a6533805a86d05bd.js → 2407-ab92ae9837c39dce.js} +1 -1
  280. package/.next/static/chunks/{2863-6a07ec82fb52f4dd.js → 2863-7173dc305dffc4f6.js} +1 -1
  281. package/.next/static/chunks/6288-6fadbba6e84393b2.js +1 -0
  282. package/.next/static/chunks/7665-e9ef6e0a85b9fa49.js +1 -0
  283. package/.next/static/chunks/8407-35bbfc84793d7004.js +1 -0
  284. package/.next/static/chunks/9079-987939d231704218.js +1 -0
  285. package/.next/static/chunks/app/{layout-538d8d2746ad1588.js → layout-aa8e66164a4367af.js} +1 -1
  286. package/.next/static/chunks/app/sessions/page-cfd645305e25fd33.js +1 -0
  287. package/.next/static/chunks/app/skills/[skillId]/{page-52ba58712faf3378.js → page-cb6e74fd9a6a571d.js} +1 -1
  288. package/.next/static/chunks/app/worktrees/[id]/files/[...path]/page-704086656fb45699.js +1 -0
  289. package/.next/static/chunks/app/worktrees/[id]/page-a8d7886703ffc7b4.js +1 -0
  290. package/.next/static/css/{743f79ff19ab91e9.css → db8959555c3d9c96.css} +1 -1
  291. package/.next/trace +13 -13
  292. package/dist/cli/commands/auto-yes.d.ts +24 -0
  293. package/dist/cli/commands/auto-yes.d.ts.map +1 -1
  294. package/dist/cli/commands/auto-yes.js +76 -8
  295. package/dist/cli/commands/capture.d.ts.map +1 -1
  296. package/dist/cli/commands/capture.js +5 -0
  297. package/dist/cli/commands/instances.d.ts.map +1 -1
  298. package/dist/cli/commands/instances.js +10 -1
  299. package/dist/cli/commands/prompt.d.ts.map +1 -1
  300. package/dist/cli/commands/prompt.js +5 -3
  301. package/dist/cli/commands/send.d.ts.map +1 -1
  302. package/dist/cli/commands/send.js +19 -6
  303. package/dist/cli/commands/verify.d.ts.map +1 -1
  304. package/dist/cli/commands/verify.js +8 -1
  305. package/dist/cli/commands/wait.d.ts.map +1 -1
  306. package/dist/cli/commands/wait.js +101 -13
  307. package/dist/cli/config/duration-constants.d.ts +16 -13
  308. package/dist/cli/config/duration-constants.d.ts.map +1 -1
  309. package/dist/cli/config/duration-constants.js +21 -21
  310. package/dist/cli/docs/agent-operations.d.ts +2 -2
  311. package/dist/cli/docs/agent-operations.d.ts.map +1 -1
  312. package/dist/cli/docs/agent-operations.js +29 -1
  313. package/dist/cli/types/api-responses.d.ts +145 -3
  314. package/dist/cli/types/api-responses.d.ts.map +1 -1
  315. package/dist/cli/types/index.d.ts +4 -0
  316. package/dist/cli/types/index.d.ts.map +1 -1
  317. package/dist/cli/utils/resource-resolvers.d.ts +0 -18
  318. package/dist/cli/utils/resource-resolvers.d.ts.map +1 -1
  319. package/dist/cli/utils/resource-resolvers.js +1 -51
  320. package/dist/cli/utils/verify-runner.d.ts +24 -1
  321. package/dist/cli/utils/verify-runner.d.ts.map +1 -1
  322. package/dist/cli/utils/verify-runner.js +54 -1
  323. package/dist/config/auto-yes-duration.d.ts +56 -0
  324. package/dist/config/auto-yes-duration.d.ts.map +1 -0
  325. package/dist/config/auto-yes-duration.js +76 -0
  326. package/dist/lib/polling/auto-yes-suppression-reason.d.ts +54 -2
  327. package/dist/lib/polling/auto-yes-suppression-reason.d.ts.map +1 -1
  328. package/dist/lib/polling/auto-yes-suppression-reason.js +33 -2
  329. package/dist/lib/prompt-observation/types.d.ts +13 -0
  330. package/dist/lib/prompt-observation/types.d.ts.map +1 -1
  331. package/dist/server/locales/en/worktree.json +2 -1
  332. package/dist/server/locales/ja/worktree.json +2 -1
  333. package/dist/server/src/config/auto-yes-config.js +14 -19
  334. package/dist/server/src/config/auto-yes-duration.js +76 -0
  335. package/dist/server/src/lib/auto-yes-poller-answer-target.js +38 -0
  336. package/dist/server/src/lib/auto-yes-poller-keys.js +35 -0
  337. package/dist/server/src/lib/auto-yes-poller-session-presence.js +26 -0
  338. package/dist/server/src/lib/auto-yes-poller-tick.js +233 -0
  339. package/dist/server/src/lib/auto-yes-poller.js +337 -376
  340. package/dist/server/src/lib/auto-yes-state.js +59 -4
  341. package/dist/server/src/lib/cli-tools/submit-verified-sender.js +235 -19
  342. package/dist/server/src/lib/db/chat-db.js +5 -1
  343. package/dist/server/src/lib/db/verification-db.js +23 -2
  344. package/dist/server/src/lib/detection/composer-text.js +215 -11
  345. package/dist/server/src/lib/detection/option-recommendation.js +120 -0
  346. package/dist/server/src/lib/detection/prompt-detect-multiple-choice-approval-context.js +290 -0
  347. package/dist/server/src/lib/detection/prompt-detect-multiple-choice-chrome.js +193 -0
  348. package/dist/server/src/lib/detection/prompt-detect-multiple-choice.js +402 -539
  349. package/dist/server/src/lib/detection/prompt-detector.js +92 -21
  350. package/dist/server/src/lib/detection/prompt-screen-key.js +60 -0
  351. package/dist/server/src/lib/detection/tools/antigravity/dialog.js +158 -35
  352. package/dist/server/src/lib/detection/tools/claude/detect.js +111 -10
  353. package/dist/server/src/lib/detection/tools/command-code/dialog.js +67 -0
  354. package/dist/server/src/lib/detection/tools/dialog-block.js +16 -0
  355. package/dist/server/src/lib/detection/upstream-faults.js +19 -2
  356. package/dist/server/src/lib/detection/waiting-screen-reading.js +98 -0
  357. package/dist/server/src/lib/hooks/permission-decision-service.js +7 -0
  358. package/dist/server/src/lib/hooks/structured-decision-response.js +1 -1
  359. package/dist/server/src/lib/polling/auto-yes-confirm-page.js +2 -2
  360. package/dist/server/src/lib/polling/auto-yes-confirmation-ledger-types.js +3 -0
  361. package/dist/server/src/lib/polling/auto-yes-confirmation-ledger.js +34 -3
  362. package/dist/server/src/lib/polling/auto-yes-decision-state.js +195 -0
  363. package/dist/server/src/lib/polling/auto-yes-dialog-gate.js +139 -10
  364. package/dist/server/src/lib/polling/auto-yes-enter-fallback.js +14 -0
  365. package/dist/server/src/lib/polling/auto-yes-manual-answer.js +124 -0
  366. package/dist/server/src/lib/polling/auto-yes-option-effect.js +157 -0
  367. package/dist/server/src/lib/polling/auto-yes-policy.js +11 -5
  368. package/dist/server/src/lib/polling/auto-yes-poller-capture.js +15 -2
  369. package/dist/server/src/lib/polling/auto-yes-poller-generation.js +42 -1
  370. package/dist/server/src/lib/polling/auto-yes-poller-receipt-log.js +42 -5
  371. package/dist/server/src/lib/polling/auto-yes-poller-state.js +147 -49
  372. package/dist/server/src/lib/polling/auto-yes-poller-steps.js +172 -2
  373. package/dist/server/src/lib/polling/auto-yes-prompt-suppression.js +2 -2
  374. package/dist/server/src/lib/polling/auto-yes-question-choice.js +57 -0
  375. package/dist/server/src/lib/polling/auto-yes-resolver.js +96 -21
  376. package/dist/server/src/lib/polling/auto-yes-suppression-reason.js +33 -2
  377. package/dist/server/src/lib/polling/auto-yes-suppression-state.js +25 -1
  378. package/dist/server/src/lib/polling/prompt-screen-reading.js +232 -0
  379. package/dist/server/src/lib/polling/response-checker-dialog-gate.js +39 -0
  380. package/dist/server/src/lib/polling/response-checker.js +145 -58
  381. package/dist/server/src/lib/prompt-answer-sender.js +104 -10
  382. package/dist/server/src/lib/push/notification-dedup.js +15 -2
  383. package/dist/server/src/lib/push/prompt-card-state.js +140 -19
  384. package/dist/server/src/lib/push/prompt-push-gate.js +158 -12
  385. package/dist/server/src/lib/push/push-sender.js +23 -3
  386. package/dist/server/src/lib/push/resolution-push-notifier.js +14 -0
  387. package/dist/server/src/lib/push/waiting-push-notifier.js +139 -17
  388. package/dist/server/src/lib/realtime/terminal-broadcast.js +16 -0
  389. package/dist/server/src/lib/session/agent-event-state.js +25 -5
  390. package/dist/server/src/lib/session/agent-event-turn.js +140 -46
  391. package/dist/server/src/lib/session/cli-session.js +21 -2
  392. package/dist/server/src/lib/session/composer-clear.js +56 -4
  393. package/dist/server/src/lib/session/current-output-builder.js +66 -12
  394. package/dist/server/src/lib/session/send-attempt-state.js +24 -7
  395. package/dist/server/src/lib/session/waiting-episode-binding-observation.js +289 -0
  396. package/dist/server/src/lib/session/waiting-episode-binding-resolve.js +38 -0
  397. package/dist/server/src/lib/session/waiting-episode-binding.js +276 -0
  398. package/dist/server/src/lib/session/waiting-episode-state-ops.js +152 -0
  399. package/dist/server/src/lib/session/waiting-episode-state-store.js +202 -0
  400. package/dist/server/src/lib/session/waiting-episode-state-types.js +6 -0
  401. package/dist/server/src/lib/session/waiting-episode-state.js +68 -91
  402. package/dist/server/src/lib/session/waiting-episode-verdict.js +174 -0
  403. package/dist/server/src/lib/tmux/tmux-capture-cache.js +76 -11
  404. package/dist/server/src/lib/tmux/tmux.js +79 -9
  405. package/dist/server/src/lib/verification/gate-runner.js +172 -16
  406. package/dist/server/src/lib/verification/machine-lock.js +5 -0
  407. package/dist/server/src/lib/ws-server.js +18 -3
  408. package/dist/server/src/types/auto-yes-answer-mode.js +38 -0
  409. package/dist/server/src/types/auto-yes-decision.js +61 -0
  410. package/dist/server/src/types/auto-yes.js +6 -0
  411. package/dist/server/src/types/prompt-reading.js +32 -0
  412. package/dist/types/auto-yes-answer-mode.d.ts +35 -0
  413. package/dist/types/auto-yes-answer-mode.d.ts.map +1 -0
  414. package/dist/types/auto-yes-answer-mode.js +38 -0
  415. package/docs/en/user-guide/webapp-guide.md +47 -13
  416. package/package.json +1 -1
  417. package/public/sw.js +76 -4
  418. package/release-notes/0.48.0.json +57 -0
  419. package/release-notes/0.49.0.json +45 -0
  420. package/.next/server/chunks/1559.js +0 -2
  421. package/.next/server/chunks/2460.js +0 -1
  422. package/.next/server/chunks/5595.js +0 -1
  423. package/.next/server/chunks/610.js +0 -1
  424. package/.next/server/chunks/6722.js +0 -1
  425. package/.next/static/chunks/5371-a549a0d2c2044d41.js +0 -1
  426. package/.next/static/chunks/602-1c1488959215e140.js +0 -1
  427. package/.next/static/chunks/6288-09feba367cc2c65e.js +0 -1
  428. package/.next/static/chunks/8407-155f84e5ba05f1d5.js +0 -1
  429. package/.next/static/chunks/9079-24f9fa549ed298f1.js +0 -1
  430. package/.next/static/chunks/app/sessions/page-e02f1adb1d1c1ccc.js +0 -1
  431. package/.next/static/chunks/app/worktrees/[id]/files/[...path]/page-9cf1ecc59e36a004.js +0 -1
  432. package/.next/static/chunks/app/worktrees/[id]/page-46aced20b2b1c010.js +0 -1
  433. /package/.next/static/{etorRtpxbQqqOzdUeXdw2 → 3_JtAZaKMJEDFIIfkHv4n}/_buildManifest.js +0 -0
  434. /package/.next/static/{etorRtpxbQqqOzdUeXdw2 → 3_JtAZaKMJEDFIIfkHv4n}/_ssgManifest.js +0 -0
@@ -37,12 +37,17 @@
37
37
  *
38
38
  * A `yes_no` prompt is a different inference — `detectPrompt` requires an
39
39
  * explicit `(y/n)`-shaped token in the text rather than deriving it from layout
40
- * — and NO tool in the registry has a measured yes/no dialog rule to gate it
41
- * against. Gating an inference for which no positive rule exists is the failure
42
- * mode the rollout guidance is written to prevent: every such prompt would
43
- * become a suppression, and the operator would see a worker that had silently
44
- * gone quiet. When a tool's yes/no dialog is measured and fixtured, widen this
45
- * the same way a tool is added to the table.
40
+ * — and NO tool in the registry has a measured yes/no dialog rule. Until Issue
41
+ * #3822 that was the reason to leave it ungated. It is now the reason to refuse
42
+ * it on an `enforce` tool, in {@link evaluateAutoYesDialogGate} only: none of
43
+ * those tools draws a `(y/n)` dialog, so a `(y/n)` on their pane is text — a
44
+ * reply quoting one, a shell command's prompt — and typing `y` at it answers
45
+ * nothing the tool asked (the user's decision of 2026-10-20: a generic yes/no
46
+ * without the tool's own evidence is left to a human). The tool can still vouch
47
+ * for the frame through `detectDialog`, exactly as for a numbered list. The
48
+ * `legacy` tools are unchanged (#3823), and so is
49
+ * {@link evaluateDialogPresence}: a `(y/n)` row a human may answer still
50
+ * belongs in History.
46
51
  *
47
52
  * ## What "allowed" does NOT mean
48
53
  *
@@ -54,9 +59,12 @@
54
59
  * @module lib/polling/auto-yes-dialog-gate
55
60
  */
56
61
  Object.defineProperty(exports, "__esModule", { value: true });
57
- exports.COMMAND_CODE_UNSUPPORTED_QUESTION_MESSAGE = exports.UNSUPPORTED_DIALOG_LAYOUT_REASON = exports.PROMPT_NO_LONGER_ACTIVE_REASON = exports.AUTO_YES_DIALOG_GATE_ENV_VAR = exports.AUTO_YES_DIALOG_GATE_DEFAULT_MODE = exports.AUTO_YES_DIALOG_GATE_MODES = void 0;
62
+ exports.COMMAND_CODE_UNSUPPORTED_QUESTION_MESSAGE = exports.UNSUPPORTED_DIALOG_LAYOUT_REASON = exports.PROMPT_NO_LONGER_ACTIVE_REASON = exports.QUESTION_EVIDENCE_UNREAD_TOOLS = exports.AUTO_YES_QUESTION_DIALOG_KINDS = exports.AUTO_YES_DIALOG_GATE_ENV_VAR = exports.AUTO_YES_DIALOG_GATE_DEFAULT_MODE = exports.AUTO_YES_DIALOG_GATE_MODES = void 0;
58
63
  exports.resolveAutoYesDialogGateMode = resolveAutoYesDialogGateMode;
59
64
  exports.evaluateAutoYesDialogGate = evaluateAutoYesDialogGate;
65
+ exports.classifyAutoYesQuestion = classifyAutoYesQuestion;
66
+ exports.autoYesQuestionTreatment = autoYesQuestionTreatment;
67
+ exports.isAutoYesQuestionPrompt = isAutoYesQuestionPrompt;
60
68
  exports.evaluateDialogPresence = evaluateDialogPresence;
61
69
  exports.judgePromptResponse = judgePromptResponse;
62
70
  exports.assessPromptAnswerability = assessPromptAnswerability;
@@ -67,6 +75,7 @@ const prompt_detector_1 = require("../../lib/detection/prompt-detector");
67
75
  const cli_patterns_1 = require("../../lib/detection/cli-patterns");
68
76
  const dialog_1 = require("../../lib/detection/tools/antigravity/dialog");
69
77
  const dialog_2 = require("../../lib/detection/tools/command-code/dialog");
78
+ const auto_yes_option_effect_1 = require("./auto-yes-option-effect");
70
79
  /** Every accepted value of {@link AutoYesDialogGateMode}, for parsing and tests. */
71
80
  exports.AUTO_YES_DIALOG_GATE_MODES = ['enforce', 'legacy'];
72
81
  /**
@@ -193,7 +202,10 @@ function resolveAutoYesDialogGateMode(tool, env = process.env) {
193
202
  }
194
203
  return specific ?? wildcard ?? exports.AUTO_YES_DIALOG_GATE_DEFAULT_MODE[tool] ?? 'legacy';
195
204
  }
196
- /** The only prompt family this gate judges. See the module docstring. */
205
+ /**
206
+ * The only prompt family the presence gate judges. Auto-Yes's gate also judges
207
+ * `yes_no` (Issue #3822); see the module docstring.
208
+ */
197
209
  const GATED_PROMPT_TYPE = 'multiple_choice';
198
210
  /**
199
211
  * May Auto-Yes answer the prompt the generic inference found on this frame?
@@ -216,7 +228,10 @@ function evaluateAutoYesDialogGate(cliToolId, promptType, cleanOutput, env = pro
216
228
  // `judgeDialogPresence` holds that rule; Issue #2457 split it out so the
217
229
  // history-save and `/prompt-response` paths judge a frame the same way this
218
230
  // one does instead of re-deriving the rollout table.
219
- const presence = judgeDialogPresence(cliToolId, promptType, cleanOutput, resolveAutoYesDialogGateMode(cliToolId, env));
231
+ const mode = resolveAutoYesDialogGateMode(cliToolId, env);
232
+ const presence = promptType === 'yes_no'
233
+ ? judgeYesNoPresence(cliToolId, cleanOutput, mode)
234
+ : judgeDialogPresence(cliToolId, promptType, cleanOutput, mode);
220
235
  return {
221
236
  // `keys` is a dialog and still not answerable: opencode's button strip takes
222
237
  // ←/→ + Enter, so the digit is swallowed and the Enter confirms whatever is
@@ -245,6 +260,119 @@ function judgeDialogPresence(cliToolId, promptType, frame, mode) {
245
260
  const dialog = detector.detectDialog(typeof frame === 'string' ? (0, frame_1.normalizeFrame)(frame, cliToolId) : frame);
246
261
  return { present: dialog !== null, dialog, mode, gated: true };
247
262
  }
263
+ /**
264
+ * Issue #3822: the Auto-Yes gate's reading of a `yes_no` candidate. Judged on
265
+ * the same terms as a numbered one — the rollout table and the `hasDialogRules`
266
+ * cross-check — so a `legacy` tool, or one with no rules, stays ungated. An
267
+ * `enforce` tool answers only where its own `detectDialog` vouched for the
268
+ * frame; none of their rules reads a `(y/n)` row, so in practice it is refused.
269
+ */
270
+ function judgeYesNoPresence(cliToolId, frame, mode) {
271
+ const detector = (0, registry_1.getToolStatusDetector)(cliToolId);
272
+ if (!detector.hasDialogRules || mode === 'legacy') {
273
+ return { present: true, dialog: null, mode, gated: false };
274
+ }
275
+ const dialog = detector.detectDialog(typeof frame === 'string' ? (0, frame_1.normalizeFrame)(frame, cliToolId) : frame);
276
+ return { present: dialog !== null, dialog, mode, gated: true };
277
+ }
278
+ /**
279
+ * The dialog kinds that are a question to the operator, not a permission
280
+ * (Issue #3822): OpenCode V2's question form, read off its own key hints.
281
+ *
282
+ * Not Claude's `ask_user`: Claude classifies by the context rows above the
283
+ * options, which on a permission dialog are the command being approved — a
284
+ * `grep "Ready to submit your answers?"` approval reads `ask_user` (#3748's
285
+ * controls), and it is a permission.
286
+ */
287
+ exports.AUTO_YES_QUESTION_DIALOG_KINDS = new Set(['question']);
288
+ /**
289
+ * What kind of question to the operator a prompt is, if it is one (Issue
290
+ * #3863):
291
+ *
292
+ * - `'question-form'` — a question form the tool's own dialog rules read
293
+ * ({@link AUTO_YES_QUESTION_DIALOG_KINDS}: OpenCode V2's). Left to a human
294
+ * under every answer mode, as before; only on a gated frame, where those
295
+ * rules ran;
296
+ * - `'picker'` — a picker a question reader read: Claude's AskUserQuestion
297
+ * (the parser's own footer, `Enter to select · … navigate`) or Command
298
+ * Code's question screen (its reader). Both set `isAskUserQuestion`, off the
299
+ * picker's chrome rather than its text. Answered under the `recommended`
300
+ * answer mode, left to a human under `careful`;
301
+ * - null — not a question (a permission, a yes/no, a list).
302
+ *
303
+ * The picker is judged WITHOUT the dialog gate (#3863): the gate's mode
304
+ * (`enforce` / `legacy`, and the `CM_AUTOYES_DIALOG_GATE` kill switch) says
305
+ * whether a frame's numbered list may be answered at all, not whether it is a
306
+ * question, so `legacy` does not turn a question into something Auto-Yes
307
+ * answers under `careful`. Claude's dialog kind `ask_user` is not evidence:
308
+ * Claude classifies by the context rows above the options, which on a
309
+ * permission dialog are the command being approved (#3748).
310
+ *
311
+ * - `'unidentified'` (Issue #3881, the second half: finding 3) — given the
312
+ * tool, a numbered list on copilot or codex
313
+ * ({@link QUESTION_EVIDENCE_UNREAD_TOOLS}) that is neither of the above and
314
+ * whose rows do not read as a permission dialog
315
+ * (`auto-yes-option-effect`, the wording measured on their live captures).
316
+ * Copilot's question (`ask_user`) and codex's `request_user_input` draw the
317
+ * same picker as their menus: copilot calls anything without `do you want
318
+ * to` a `picker`, codex anything with a `?` above it a `permission`, and
319
+ * neither sets `isAskUserQuestion`. So such a list is not known to be a
320
+ * question, nor known not to be one. Left to a human under `careful`;
321
+ * under `recommended` it is answered exactly as before (not as a question).
322
+ *
323
+ * @param promptData - The prompt the tick read
324
+ * @param gate - {@link evaluateAutoYesDialogGate}'s verdict for the same frame, if it ran
325
+ * @param cliToolId - The tool that drew it; omitted, no list is `'unidentified'`
326
+ * (the reading before #3881's second half)
327
+ */
328
+ function classifyAutoYesQuestion(promptData, gate, cliToolId) {
329
+ if (gate?.gated === true && gate.dialog !== null && exports.AUTO_YES_QUESTION_DIALOG_KINDS.has(gate.dialog.kind)) {
330
+ return 'question-form';
331
+ }
332
+ if (promptData.type !== 'multiple_choice')
333
+ return null;
334
+ if (promptData.isAskUserQuestion === true)
335
+ return 'picker';
336
+ if (cliToolId !== undefined && exports.QUESTION_EVIDENCE_UNREAD_TOOLS.has(cliToolId)
337
+ && (0, auto_yes_option_effect_1.selectAllowOnceOption)(promptData.options, cliToolId).kind === 'not-a-permission-dialog') {
338
+ return 'unidentified';
339
+ }
340
+ return null;
341
+ }
342
+ /** See {@link AutoYesQuestionTreatment}. */
343
+ function autoYesQuestionTreatment(kind, answerMode) {
344
+ if (kind === null)
345
+ return 'base-rules';
346
+ if (kind === 'question-form')
347
+ return 'left-to-human';
348
+ if (answerMode === 'careful')
349
+ return 'left-to-human';
350
+ return kind === 'picker' ? 'recommended-choice' : 'base-rules';
351
+ }
352
+ /**
353
+ * The tools whose question screens nothing on the screen tells from their
354
+ * other pickers (Issue #3881, finding 3): copilot's `ask_user`, codex's
355
+ * `request_user_input`. Neither module reads a question's chrome; their dialog
356
+ * kinds are guesses from the words above the options
357
+ * (`tools/copilot/prompt.ts`, `tools/codex/prompt.ts`).
358
+ */
359
+ exports.QUESTION_EVIDENCE_UNREAD_TOOLS = new Set(['copilot', 'codex']);
360
+ /**
361
+ * Is the prompt a question to the operator rather than a permission, on a
362
+ * GATED frame? (Issue #3822.)
363
+ *
364
+ * The reading #3822 first shipped: a question only where the tool's own rules
365
+ * ran. Since Issue #3863 the poller reads {@link classifyAutoYesQuestion},
366
+ * which judges the picker without the gate (so the kill switch and the
367
+ * `legacy` tools do not change how a question is treated); this stays the
368
+ * gated half of that reading.
369
+ *
370
+ * @param promptData - The prompt the tick read
371
+ * @param gate - {@link evaluateAutoYesDialogGate}'s verdict for the same frame
372
+ */
373
+ function isAutoYesQuestionPrompt(promptData, gate) {
374
+ return gate.gated && classifyAutoYesQuestion(promptData, gate) !== null;
375
+ }
248
376
  /**
249
377
  * Does this frame POSITIVELY carry a dialog for the numbered-list candidate the
250
378
  * generic parser found on it? (Issue #2457)
@@ -395,8 +523,9 @@ function assessPromptAnswerability(cliToolId, frame) {
395
523
  // Issue #3808: a numbered agy screen agy's reader declines (the login-method
396
524
  // screen, a permission dialog whose `tab Amend` footer is cut or off the
397
525
  // pane) is no prompt — not the generic parser's reading of its `1. / 2.` rows.
526
+ // #3818: by default, so a run with a number missing is declined too.
398
527
  const declinedAgyScreen = cliToolId === 'antigravity' && toolDialog === null
399
- && (0, dialog_1.isAntigravityUnvouchedNumberedScreen)(cleanOutput);
528
+ && (0, dialog_1.isAntigravityUnansweredNumberedScreen)(cleanOutput);
400
529
  const isCommandCodeQuestion = commandCodeQuestion.kind === 'prompt';
401
530
  const candidate = (commandCodeQuestion.kind === 'prompt' ? commandCodeQuestion.prompt : null)
402
531
  ?? toolDialog
@@ -2,6 +2,20 @@
2
2
  /**
3
3
  * Auto-Yes's Enter on a choice screen CommandMate cannot read (Issue #3397).
4
4
  *
5
+ * ## Retired (Issue #3821)
6
+ *
7
+ * Nothing sends this Enter any more. The poller leaves every frame the dialog
8
+ * gate refuses to a human (`unclassified-frame`), whatever
9
+ * {@link judgeEnterFallback} would say and whatever
10
+ * {@link AUTO_YES_ENTER_FALLBACK_ENV_VAR} is set to: a bare Enter confirms
11
+ * whatever happens to be selected, and on a screen nothing here can read,
12
+ * nothing here can say what that is. {@link judgeEnterFallback} stays as a
13
+ * reading of the frame only; no sending path calls it. The session epoch the
14
+ * record was keyed on (`./auto-yes-enter-fallback-state`) is still what every
15
+ * send's generation check and the partial-answer record belong to.
16
+ *
17
+ * What follows is how the Enter was decided while it existed.
18
+ *
5
19
  * ## The screen
6
20
  *
7
21
  * `assessPromptAnswerability` refuses some frames that are plainly a choice
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ /**
3
+ * A person's answer through `/prompt-response`, as Auto-Yes's poller sees it
4
+ * (Issue #3821, review 2).
5
+ *
6
+ * Dropping the published decision is not enough to keep the poller's keys off
7
+ * a confirmation a person is answering: a tick already past its checks — the
8
+ * ownership check, a wait inside the send — acts for its generation (#3706),
9
+ * which a manual answer did not touch. So the start of a manual answer
10
+ *
11
+ * - moves the instance's manual-answer sequence on; a tick whose generation
12
+ * was taken under an earlier one is no longer current (`isTickCurrent`) and
13
+ * sends no further key;
14
+ * - holds the instance for {@link MANUAL_ANSWER_HOLD_MS}: a tick that reads a
15
+ * confirmation meanwhile leaves it to the person (`answered-by-human`)
16
+ * instead of answering what they may be answering right now;
17
+ * - drops the published decision.
18
+ *
19
+ * How the answer ENDED decides what happens to an answer the poller holds at
20
+ * that confirmation (Issue #3880, {@link settleManualAnswer}).
21
+ *
22
+ * Auto-Yes itself stays on: past the hold the poller answers again.
23
+ *
24
+ * In-memory and on `globalThis` (the route and the poller are bundled apart
25
+ * under `next dev`).
26
+ *
27
+ * @module lib/polling/auto-yes-manual-answer
28
+ */
29
+ Object.defineProperty(exports, "__esModule", { value: true });
30
+ exports.ANSWERED_BY_HUMAN_DECISION_REASON = exports.MANUAL_ANSWER_HOLD_MS = void 0;
31
+ exports.noteManualAnswerStarted = noteManualAnswerStarted;
32
+ exports.noteManualSendStarting = noteManualSendStarting;
33
+ exports.settleManualAnswer = settleManualAnswer;
34
+ exports.abandonManualSend = abandonManualSend;
35
+ exports.getManualAnswerSeq = getManualAnswerSeq;
36
+ exports.isManualAnswerHolding = isManualAnswerHolding;
37
+ exports.clearManualAnswers = clearManualAnswers;
38
+ const auto_yes_state_1 = require("../../lib/auto-yes-state");
39
+ const global_state_1 = require("../global-state");
40
+ const auto_yes_decision_state_1 = require("./auto-yes-decision-state");
41
+ const auto_yes_poller_state_1 = require("./auto-yes-poller-state");
42
+ /** How long a manual answer keeps the poller off the instance's confirmations. */
43
+ exports.MANUAL_ANSWER_HOLD_MS = auto_yes_state_1.DUPLICATE_RETRY_EXPIRY_MS;
44
+ /** The decision reason a tick withholds under while the hold lasts. */
45
+ exports.ANSWERED_BY_HUMAN_DECISION_REASON = 'answered-by-human';
46
+ const marks = (0, global_state_1.getOrInitGlobal)('__autoYesManualAnswers', () => new Map());
47
+ /** A person began answering on this instance (called before the first key or API call). */
48
+ function noteManualAnswerStarted(compositeKey, at = Date.now()) {
49
+ marks.set(compositeKey, { seq: (marks.get(compositeKey)?.seq ?? 0) + 1, at });
50
+ (0, auto_yes_decision_state_1.forgetAutoYesDecision)(compositeKey);
51
+ return { compositeKey, order: (0, auto_yes_poller_state_1.nextSendOrder)(), attempt: null };
52
+ }
53
+ /**
54
+ * The person's keys are about to go out (Issue #3880), at the confirmation
55
+ * `promptData` is — or, when no prompt could be read off the screen (the
56
+ * capture before the send failed), at an unidentified one. Registered as a
57
+ * send in flight, so a screen seen gone, a relaunch, or a worktree going away
58
+ * before it ends keeps its end from recording a hold.
59
+ */
60
+ function noteManualSendStarting(ticket, promptData) {
61
+ if (ticket.attempt !== null)
62
+ return;
63
+ const screenKey = promptData ? (0, auto_yes_poller_state_1.partialAnswerScreenKey)(promptData) : auto_yes_poller_state_1.UNIDENTIFIED_SCREEN_KEY;
64
+ ticket.attempt = (0, auto_yes_poller_state_1.beginManualSendAttempt)(ticket.compositeKey, screenKey);
65
+ }
66
+ /**
67
+ * A person's answer ended (Issue #3880). Starting one does not touch what
68
+ * Auto-Yes holds — the start only stops the tick under way and holds the
69
+ * poller off for {@link MANUAL_ANSWER_HOLD_MS} — so a manual send that fails
70
+ * cannot leave the confirmation free for Auto-Yes to type at again once that
71
+ * hold passes. Everything is matched to THIS answer (`ticket`), not to the
72
+ * instance's key alone:
73
+ *
74
+ * - `answered` / `not-sent`: the hold recorded before this answer began is
75
+ * released (the person answered, or saw the screen and nothing of theirs is
76
+ * on it). One recorded since — by another person's send that may be on the
77
+ * pane, or a tick's — stays.
78
+ * - `may-be-on-pane`: the send records a hold at its screen (unidentified
79
+ * when none was read), as Auto-Yes's own does: only for the session epoch it
80
+ * went to, never over a hold of a send registered after it, and not at all when
81
+ * the screen it typed at was seen gone since. And every tick under way stops
82
+ * (the manual-answer sequence moves on): one that read no hold before its
83
+ * last wait does not type over this one.
84
+ *
85
+ * An end nobody reports (a send that threw saying nothing of its keys, a
86
+ * verdict the agent's API gave no receipt for — both only abandoned; a
87
+ * structured verdict `/prompt-response` refused) leaves the hold as it was. A verdict delivered over the
88
+ * agent's API reports its receipt like a send (Issue #3925).
89
+ */
90
+ function settleManualAnswer(ticket, outcome, at = Date.now()) {
91
+ const { compositeKey, attempt } = ticket;
92
+ if (outcome !== 'may-be-on-pane') {
93
+ if (attempt !== null)
94
+ (0, auto_yes_poller_state_1.settleSendAttempt)(attempt, false, at);
95
+ (0, auto_yes_poller_state_1.releasePartialAnswerToHuman)(compositeKey, ticket.order);
96
+ return;
97
+ }
98
+ if (attempt !== null)
99
+ (0, auto_yes_poller_state_1.settleSendAttempt)(attempt, true, at);
100
+ const mark = marks.get(compositeKey);
101
+ if (mark !== undefined)
102
+ marks.set(compositeKey, { ...mark, seq: mark.seq + 1 });
103
+ }
104
+ /**
105
+ * A person's send ended in a way that says nothing of its keys (Issue #3880):
106
+ * it is no longer in flight, and the hold is left as it was.
107
+ */
108
+ function abandonManualSend(ticket) {
109
+ if (ticket.attempt !== null)
110
+ (0, auto_yes_poller_state_1.settleSendAttempt)(ticket.attempt, false);
111
+ }
112
+ /** The instance's manual-answer sequence (0 until a person answers there). */
113
+ function getManualAnswerSeq(compositeKey) {
114
+ return marks.get(compositeKey)?.seq ?? 0;
115
+ }
116
+ /** Whether a manual answer began on this instance less than {@link MANUAL_ANSWER_HOLD_MS} ago. */
117
+ function isManualAnswerHolding(compositeKey, now = Date.now()) {
118
+ const mark = marks.get(compositeKey);
119
+ return mark !== undefined && now - mark.at < exports.MANUAL_ANSWER_HOLD_MS;
120
+ }
121
+ /** Drop every mark: a test seam. The sequences only ever move forward otherwise. */
122
+ function clearManualAnswers() {
123
+ marks.clear();
124
+ }
@@ -0,0 +1,157 @@
1
+ "use strict";
2
+ /**
3
+ * Auto-Yes option effects - what picking one row of a permission dialog does
4
+ * (Issue #3822).
5
+ *
6
+ * Until #3822 the resolver picked the default row, or row 1, of any numbered
7
+ * dialog. On every tool measured here the rows of a permission dialog do not
8
+ * mean the same thing: one allows this call only, the others save a rule
9
+ * (`don't ask again`, `always allow`, `Persist to settings.json`), switch the
10
+ * permission mode for the session (`allow all edits`, `Full Access`), or deny.
11
+ * Where the cursor rests is the tool's choice, not a promise that the row is
12
+ * the narrow one — agy keeps the `>` where the operator left it — so Auto-Yes
13
+ * answers only the row that reads as "allow this call once", by its number,
14
+ * and nothing when no single row reads that way.
15
+ *
16
+ * ## Where the wording comes from
17
+ *
18
+ * Every rule below is a row read off a live capture in the repository, named
19
+ * next to it. Nothing is inferred from another tool's wording. A tool without
20
+ * a table (gemini, vibe-local, opencode, opencode-v2) keeps the pre-#3822
21
+ * reading: opencode's and OpenCode V2's permission strips are unnumbered and
22
+ * never reach the resolver as a prompt (they are answered through the hook,
23
+ * whose `allow` is `allowOnce`), and gemini / vibe-local have no captured
24
+ * permission dialog to read.
25
+ *
26
+ * ## When a dialog counts as a permission dialog
27
+ *
28
+ * When at least one of its rows reads as an allow — this call once, a saved
29
+ * rule, or a mode change. A `No` row alone does not make one: a launch dialog
30
+ * (`Yes, continue` / `No, quit`, `Yes, I trust this folder` / `No, exit`) is
31
+ * judged where it always was (the launch-dialog branch, the contract's deny
32
+ * patterns). A numbered list none of whose rows the tool's table recognises (a
33
+ * question's options, a dialog whose wording was never captured) keeps the
34
+ * pre-#3822 default-row reading — this module only narrows what a recognised
35
+ * permission dialog may be answered with, it does not decide which screens are
36
+ * dialogs.
37
+ *
38
+ * Client-safe: no server-only imports (the resolver is bundled into
39
+ * `hooks/useAutoYes.ts`).
40
+ */
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.OPTION_EFFECT_TOOLS = void 0;
43
+ exports.readOptionEffect = readOptionEffect;
44
+ exports.selectAllowOnceOption = selectAllowOnceOption;
45
+ /** `don't` with a straight or a typographic apostrophe. */
46
+ const DONT = "don['’]t";
47
+ /** `No`, alone or followed by its explanation (`No, cancel`, `No, and tell … differently`). */
48
+ const DENY_NO = ['deny', /^No(?:,|$)/];
49
+ /**
50
+ * Each tool's rows, first match wins. A rule is anchored at the start of the
51
+ * label and reads only the words that say what the row does, so the command or
52
+ * path a row quotes after them does not matter.
53
+ */
54
+ const OPTION_EFFECT_RULES = {
55
+ // tests/fixtures/canary/permission-dialog.raw.txt, permission-hook-no-decision.raw.txt,
56
+ // tests/unit/lib/detection/fixtures/claude-live-1708/bash-approval-taskpanel.txt,
57
+ // tests/fixtures/tui-frame-footer-2776/claude-2.1.278-bash-approval-task-panel.txt
58
+ claude: [
59
+ ['allow-once', /^Yes$/],
60
+ ['allow-persistent', /^Yes, and always allow\b/],
61
+ ['mode-change', /^Yes, allow all edits\b/],
62
+ ['mode-change', /^Yes, and switch to\b/],
63
+ DENY_NO,
64
+ ],
65
+ // tests/unit/lib/detection/fixtures/codex-live-1628/approval-{run-command,apply-patch}.txt,
66
+ // tests/fixtures/codex-dialogs-0157/approval.txt, codex-hooks-review-0148.ts,
67
+ // tests/fixtures/codex-browser-use-2609/approval-form-browser-use.txt (`Allow` /
68
+ // `Always allow` / `Cancel`, each followed by its description), and
69
+ // tests/fixtures/codex-live-2310/dialog-permissions-picker.txt (the approval modes)
70
+ codex: [
71
+ ['allow-once', /^Yes$/],
72
+ ['allow-once', /^Yes, proceed\b/],
73
+ ['allow-once', /^Allow(?:\s{2,}|$)/],
74
+ ['allow-persistent', new RegExp(`^Yes, and ${DONT} ask again\\b`)],
75
+ ['allow-persistent', /^Always allow\b/],
76
+ ['mode-change', /^Ask for approval\b/],
77
+ ['mode-change', /^Approve for me\b/],
78
+ ['mode-change', /^Full Access\b/],
79
+ ['deny', /^Cancel\b/],
80
+ DENY_NO,
81
+ ],
82
+ // tests/fixtures/antigravity-live-2364/dialog-bash-*.txt, dialog-create-file.txt,
83
+ // tests/fixtures/strict-respond-3812/permission-run-command.txt. `always allow in
84
+ // this conversation` is as much a saved rule as `(Persist to settings.json)`:
85
+ // neither is this call only.
86
+ antigravity: [
87
+ ['allow-once', /^Yes$/],
88
+ ['allow-once', /^Yes, run command$/],
89
+ ['allow-once', /^Yes, allow creation$/],
90
+ ['allow-persistent', /^Yes, and always allow\b/],
91
+ DENY_NO,
92
+ ],
93
+ // tests/fixtures/command-code-live-2250/dialog-shell-command.txt, dialog-create-file.txt,
94
+ // dialog-kill-task-1490.txt, tests/fixtures/command-code-plan-review-2763/after-approve.txt
95
+ 'command-code': [
96
+ ['allow-once', /^Yes$/],
97
+ ['allow-persistent', new RegExp(`^Yes, ${DONT} ask again\\b`)],
98
+ ['mode-change', /^Yes, allow all edits\b/],
99
+ DENY_NO,
100
+ ],
101
+ // tests/unit/lib/detection/fixtures/copilot-live-1885/permission-dialog.txt and
102
+ // copilot-picker-1895/picker-permissions.txt (`Manual ✓` / `Allow all`, the modes)
103
+ copilot: [
104
+ ['allow-once', /^Yes$/],
105
+ ['allow-persistent', new RegExp(`^Yes, and ${DONT} ask again\\b`)],
106
+ ['mode-change', /^Manual\b/],
107
+ ['mode-change', /^Allow all\b/],
108
+ DENY_NO,
109
+ ],
110
+ };
111
+ /** Every table, for a caller that does not say which tool drew the dialog. */
112
+ const ANY_TOOL_RULES = Object.values(OPTION_EFFECT_RULES).flat();
113
+ /** The tools whose permission rows are read (the others keep the pre-#3822 reading). */
114
+ exports.OPTION_EFFECT_TOOLS = Object.keys(OPTION_EFFECT_RULES);
115
+ function rulesFor(cliToolId) {
116
+ if (cliToolId === undefined)
117
+ return ANY_TOOL_RULES;
118
+ return OPTION_EFFECT_RULES[cliToolId] ?? null;
119
+ }
120
+ function readWith(rules, label) {
121
+ const text = label.trim();
122
+ for (const [effect, pattern] of rules) {
123
+ if (pattern.test(text))
124
+ return effect;
125
+ }
126
+ return 'unknown';
127
+ }
128
+ /**
129
+ * What choosing the row labelled `label` does on `cliToolId`'s dialog.
130
+ *
131
+ * @param cliToolId - The tool that drew the dialog. Omitted, every tool's
132
+ * table is read (the first rule that matches decides); a tool with no table
133
+ * reads every row as `unknown`.
134
+ */
135
+ function readOptionEffect(label, cliToolId) {
136
+ const rules = rulesFor(cliToolId);
137
+ return rules === null ? 'unknown' : readWith(rules, label);
138
+ }
139
+ /**
140
+ * Pick the one "allow this call once" row of a permission dialog.
141
+ *
142
+ * @param options - The dialog's rows, as parsed
143
+ * @param cliToolId - The tool that drew it; see {@link readOptionEffect}
144
+ */
145
+ function selectAllowOnceOption(options, cliToolId) {
146
+ const rules = rulesFor(cliToolId);
147
+ if (rules === null)
148
+ return { kind: 'not-a-permission-dialog' };
149
+ const effects = options.map((option) => readWith(rules, option.label));
150
+ if (!effects.some((effect) => effect === 'allow-once' || effect === 'allow-persistent' || effect === 'mode-change')) {
151
+ return { kind: 'not-a-permission-dialog' };
152
+ }
153
+ const once = options.filter((_option, index) => effects[index] === 'allow-once');
154
+ if (once.length === 1)
155
+ return { kind: 'allow-once', option: once[0] };
156
+ return { kind: 'unidentified', allowOnceCount: once.length };
157
+ }
@@ -95,11 +95,14 @@ function readPolicy(worktreeId, cliToolId, instanceId) {
95
95
  * the resolver reads {@link AUTO_YES_POLICY_UNKNOWN} as withholding (Issue #3822).
96
96
  *
97
97
  * @param instanceId - Agent instance id (defaults to the primary, i.e. cliToolId)
98
+ * @param options - `fresh: true` reads the task past the cache (and refreshes
99
+ * it): the poller's last look before a key (Issue #3822), where a contract
100
+ * switched or a deny pattern added within the TTL must already count
98
101
  * @returns The contract's autoYes block, null when no contract governs this
99
102
  * instance, or {@link AUTO_YES_POLICY_UNKNOWN} when the lookup failed
100
103
  */
101
- function getSessionAutoYesPolicy(worktreeId, cliToolId, instanceId) {
102
- return lookupEntry(worktreeId, cliToolId, instanceId).policy;
104
+ function getSessionAutoYesPolicy(worktreeId, cliToolId, instanceId, options) {
105
+ return lookupEntry(worktreeId, cliToolId, instanceId, options?.fresh === true).policy;
103
106
  }
104
107
  /**
105
108
  * The policy and the id of the task it came from, read in ONE lookup (Issue
@@ -162,17 +165,20 @@ function getSessionContractPolicySummary(worktreeId, cliToolId, instanceId) {
162
165
  denyPatternCount: policy.denyPatterns.length,
163
166
  };
164
167
  }
165
- function lookupEntry(worktreeId, cliToolId, instanceId) {
168
+ function lookupEntry(worktreeId, cliToolId, instanceId, fresh = false) {
166
169
  const resolvedInstanceId = instanceId ?? cliToolId;
167
170
  const key = (0, auto_yes_state_1.buildCompositeKey)(worktreeId, cliToolId, resolvedInstanceId);
168
171
  const now = Date.now();
169
172
  const cached = policyCache.get(key);
170
- if (cached && cached.expiresAt > now) {
173
+ if (!fresh && cached && cached.expiresAt > now) {
171
174
  return cached;
172
175
  }
173
176
  const { policy, taskId } = readPolicy(worktreeId, cliToolId, resolvedInstanceId);
174
177
  if ((0, auto_yes_resolver_1.isAutoYesPolicyUnknown)(policy)) {
175
- // Issue #3822: not cached, so the next lookup reads again.
178
+ // Issue #3822: not cached, so the next lookup reads again. A fresh read
179
+ // that failed also drops what was cached: it is no longer known to hold.
180
+ if (fresh)
181
+ policyCache.delete(key);
176
182
  return { policy, taskId, expiresAt: now };
177
183
  }
178
184
  if (policyCache.size >= MAX_CACHE_ENTRIES) {
@@ -13,9 +13,15 @@
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
14
  exports.capturePollerFrame = capturePollerFrame;
15
15
  exports.captureAndCleanOutput = captureAndCleanOutput;
16
+ const async_hooks_1 = require("async_hooks");
16
17
  const cli_session_1 = require("../session/cli-session");
18
+ const global_state_1 = require("../global-state");
17
19
  const cli_patterns_1 = require("../detection/cli-patterns");
18
20
  const auto_yes_config_1 = require("../../config/auto-yes-config");
21
+ /** Where `cli-session` reports whether the capture it runs inside cut the pane's top (Issue #3881 N4). */
22
+ function headCutSink() {
23
+ return (0, global_state_1.getOrInitGlobal)('__captureHeadCutSink', () => new async_hooks_1.AsyncLocalStorage());
24
+ }
19
25
  /**
20
26
  * Capture tmux session output once, keeping both spellings (Issue #2522).
21
27
  *
@@ -28,8 +34,15 @@ const auto_yes_config_1 = require("../../config/auto-yes-config");
28
34
  */
29
35
  async function capturePollerFrame(worktreeId, cliToolId, captureLines, instanceId) {
30
36
  const lines = captureLines ?? auto_yes_config_1.FULL_CAPTURE_LINES;
31
- const output = await (0, cli_session_1.captureSessionOutput)(worktreeId, cliToolId, lines, instanceId);
32
- return { raw: output, clean: (0, cli_patterns_1.stripBoxDrawing)((0, cli_patterns_1.stripAnsi)(output)) };
37
+ const reported = {};
38
+ const output = await headCutSink().run((headCut) => {
39
+ reported.headCut = headCut;
40
+ }, () => (0, cli_session_1.captureSessionOutput)(worktreeId, cliToolId, lines, instanceId));
41
+ return {
42
+ raw: output,
43
+ clean: (0, cli_patterns_1.stripBoxDrawing)((0, cli_patterns_1.stripAnsi)(output)),
44
+ ...(reported.headCut !== undefined ? { headCut: reported.headCut } : {}),
45
+ };
33
46
  }
34
47
  /**
35
48
  * Capture tmux session output and strip ANSI escape codes.
@@ -22,9 +22,13 @@ exports.isPollerCurrent = isPollerCurrent;
22
22
  exports.isTickCurrent = isTickCurrent;
23
23
  exports.isSameSession = isSameSession;
24
24
  exports.isDuplicatePrompt = isDuplicatePrompt;
25
+ exports.reserveDuplicateRetry = reserveDuplicateRetry;
26
+ exports.isDuplicateRetryOf = isDuplicateRetryOf;
27
+ exports.releaseDuplicateRetry = releaseDuplicateRetry;
25
28
  const auto_yes_enter_fallback_1 = require("./auto-yes-enter-fallback");
26
29
  const auto_yes_state_1 = require("../auto-yes-state");
27
30
  const global_state_1 = require("../global-state");
31
+ const auto_yes_manual_answer_1 = require("./auto-yes-manual-answer");
28
32
  /** In-memory storage for poller states (globalThis for hot reload persistence) */
29
33
  exports.autoYesPollerStates = (0, global_state_1.getOrInitGlobal)('__autoYesPollerStates', () => new Map());
30
34
  // =============================================================================
@@ -113,7 +117,8 @@ function isPollerCurrent(generation) {
113
117
  }
114
118
  /**
115
119
  * May the tick still act: its poller, its grant (the same enable, not expired)
116
- * and its session (no relaunch since) are all still the ones it started under.
120
+ * and its session (no relaunch since) are all still the ones it started under,
121
+ * and no person has begun answering on the instance since (Issue #3821).
117
122
  * Checked after capture, after each wait before a key, and inside the send.
118
123
  */
119
124
  function isTickCurrent(generation) {
@@ -124,6 +129,10 @@ function isTickCurrent(generation) {
124
129
  const grant = (0, auto_yes_state_1.getAutoYesState)(generation.worktreeId, generation.cliToolId, generation.instanceId);
125
130
  if (grant !== generation.grant || !grant.enabled)
126
131
  return false;
132
+ // Issue #3821: a person began answering on this instance since the tick started
133
+ // (Issue #3880: or a person's send ended with keys maybe on the pane, holding it).
134
+ if ((generation.manualAnswerSeq ?? 0) !== (0, auto_yes_manual_answer_1.getManualAnswerSeq)(generation.compositeKey))
135
+ return false;
127
136
  return isSameSession(generation);
128
137
  }
129
138
  /**
@@ -149,3 +158,35 @@ function isDuplicatePrompt(pollerState, promptKey) {
149
158
  return false;
150
159
  return (Date.now() - pollerState.lastAnsweredAt) < auto_yes_state_1.DUPLICATE_RETRY_EXPIRY_MS;
151
160
  }
161
+ /**
162
+ * Issue #3791 (review N1): publish that the duplicate guard held back the
163
+ * prompt on screen on this tick ({@link isDuplicatePrompt} was true), for the
164
+ * push gate to hold the wait until the guard's retry. Only the guard's own
165
+ * verdict sets it: an answer alone (`lastAnsweredAt`) says nothing about the
166
+ * screen now up — another prompt, or a failed tick, is not held by the guard.
167
+ */
168
+ function reserveDuplicateRetry(pollerState, promptKey, now) {
169
+ if (pollerState.lastAnsweredAt === null)
170
+ return;
171
+ pollerState.duplicateRetryReservation = { promptKey, answeredAt: pollerState.lastAnsweredAt, observedAt: now };
172
+ }
173
+ /**
174
+ * Issue #3791 (review N3): is `promptKey` the prompt the guard reserved, its
175
+ * guard since expired — the tick about to send the retry the reservation
176
+ * waited for? Its reservation is then kept until that send is settled.
177
+ */
178
+ function isDuplicateRetryOf(pollerState, promptKey) {
179
+ const reservation = pollerState.duplicateRetryReservation;
180
+ return (reservation !== undefined &&
181
+ reservation !== null &&
182
+ reservation.promptKey === promptKey &&
183
+ reservation.answeredAt === pollerState.lastAnsweredAt);
184
+ }
185
+ /**
186
+ * Issue #3791 (review N1): the tick did not hold the prompt back with the
187
+ * guard — another screen, no prompt, a failed tick, no session — so the wait
188
+ * is no longer the guard's retry to wait for.
189
+ */
190
+ function releaseDuplicateRetry(pollerState) {
191
+ pollerState.duplicateRetryReservation = null;
192
+ }