commandmate 0.30.2 → 0.31.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 (440) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-build-manifest.json +160 -160
  3. package/.next/app-path-routes-manifest.json +27 -27
  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/update/route_client-reference-manifest.js +1 -1
  11. package/.next/server/app/api/app/update-check/route.js +1 -1
  12. package/.next/server/app/api/app/update-check/route_client-reference-manifest.js +1 -1
  13. package/.next/server/app/api/assistant/conversation/route.js +1 -1
  14. package/.next/server/app/api/assistant/conversation/route.js.nft.json +1 -1
  15. package/.next/server/app/api/assistant/conversation/route_client-reference-manifest.js +1 -1
  16. package/.next/server/app/api/assistant/current-output/route.js +1 -1
  17. package/.next/server/app/api/assistant/current-output/route.js.nft.json +1 -1
  18. package/.next/server/app/api/assistant/current-output/route_client-reference-manifest.js +1 -1
  19. package/.next/server/app/api/assistant/messages/route.js +1 -1
  20. package/.next/server/app/api/assistant/messages/route.js.nft.json +1 -1
  21. package/.next/server/app/api/assistant/messages/route_client-reference-manifest.js +1 -1
  22. package/.next/server/app/api/assistant/session/route.js +1 -1
  23. package/.next/server/app/api/assistant/session/route.js.nft.json +1 -1
  24. package/.next/server/app/api/assistant/session/route_client-reference-manifest.js +1 -1
  25. package/.next/server/app/api/assistant/start/route.js +3 -3
  26. package/.next/server/app/api/assistant/start/route.js.nft.json +1 -1
  27. package/.next/server/app/api/assistant/start/route_client-reference-manifest.js +1 -1
  28. package/.next/server/app/api/assistant/terminal/route.js +4 -4
  29. package/.next/server/app/api/assistant/terminal/route.js.nft.json +1 -1
  30. package/.next/server/app/api/assistant/terminal/route_client-reference-manifest.js +1 -1
  31. package/.next/server/app/api/assistant/tools/route.js +1 -1
  32. package/.next/server/app/api/assistant/tools/route.js.nft.json +1 -1
  33. package/.next/server/app/api/assistant/tools/route_client-reference-manifest.js +1 -1
  34. package/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
  35. package/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
  36. package/.next/server/app/api/auth/status/route_client-reference-manifest.js +1 -1
  37. package/.next/server/app/api/capabilities/route.js +1 -1
  38. package/.next/server/app/api/capabilities/route_client-reference-manifest.js +1 -1
  39. package/.next/server/app/api/daily-summary/route_client-reference-manifest.js +1 -1
  40. package/.next/server/app/api/daily-summary/status/route_client-reference-manifest.js +1 -1
  41. package/.next/server/app/api/external-apps/[id]/health/route_client-reference-manifest.js +1 -1
  42. package/.next/server/app/api/external-apps/[id]/route_client-reference-manifest.js +1 -1
  43. package/.next/server/app/api/external-apps/route_client-reference-manifest.js +1 -1
  44. package/.next/server/app/api/fs/browse/route_client-reference-manifest.js +1 -1
  45. package/.next/server/app/api/fs/recent-paths/route_client-reference-manifest.js +1 -1
  46. package/.next/server/app/api/hooks/agent-event/route.js +1 -1
  47. package/.next/server/app/api/hooks/agent-event/route.js.nft.json +1 -1
  48. package/.next/server/app/api/hooks/agent-event/route_client-reference-manifest.js +1 -1
  49. package/.next/server/app/api/hooks/claude-done/route.js +1 -1
  50. package/.next/server/app/api/hooks/claude-done/route.js.nft.json +1 -1
  51. package/.next/server/app/api/hooks/claude-done/route_client-reference-manifest.js +1 -1
  52. package/.next/server/app/api/hooks/permission-request/route.js +1 -1
  53. package/.next/server/app/api/hooks/permission-request/route.js.nft.json +1 -1
  54. package/.next/server/app/api/hooks/permission-request/route_client-reference-manifest.js +1 -1
  55. package/.next/server/app/api/metrics/vibe/route_client-reference-manifest.js +1 -1
  56. package/.next/server/app/api/ollama/models/route_client-reference-manifest.js +1 -1
  57. package/.next/server/app/api/push/escalation/route_client-reference-manifest.js +1 -1
  58. package/.next/server/app/api/push/subscriptions/route_client-reference-manifest.js +1 -1
  59. package/.next/server/app/api/push/vapid/route_client-reference-manifest.js +1 -1
  60. package/.next/server/app/api/remote/pair/route_client-reference-manifest.js +1 -1
  61. package/.next/server/app/api/repositories/[id]/route_client-reference-manifest.js +1 -1
  62. package/.next/server/app/api/repositories/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
  63. package/.next/server/app/api/repositories/[id]/todos/route_client-reference-manifest.js +1 -1
  64. package/.next/server/app/api/repositories/clone/[jobId]/route.js +1 -1
  65. package/.next/server/app/api/repositories/clone/[jobId]/route.js.nft.json +1 -1
  66. package/.next/server/app/api/repositories/clone/[jobId]/route_client-reference-manifest.js +1 -1
  67. package/.next/server/app/api/repositories/clone/route.js +1 -1
  68. package/.next/server/app/api/repositories/clone/route.js.nft.json +1 -1
  69. package/.next/server/app/api/repositories/clone/route_client-reference-manifest.js +1 -1
  70. package/.next/server/app/api/repositories/excluded/route_client-reference-manifest.js +1 -1
  71. package/.next/server/app/api/repositories/restore/route.js +1 -1
  72. package/.next/server/app/api/repositories/restore/route.js.nft.json +1 -1
  73. package/.next/server/app/api/repositories/restore/route_client-reference-manifest.js +1 -1
  74. package/.next/server/app/api/repositories/route.js +1 -1
  75. package/.next/server/app/api/repositories/route.js.nft.json +1 -1
  76. package/.next/server/app/api/repositories/route_client-reference-manifest.js +1 -1
  77. package/.next/server/app/api/repositories/scan/route.js +1 -1
  78. package/.next/server/app/api/repositories/scan/route.js.nft.json +1 -1
  79. package/.next/server/app/api/repositories/scan/route_client-reference-manifest.js +1 -1
  80. package/.next/server/app/api/repositories/sync/route.js +1 -1
  81. package/.next/server/app/api/repositories/sync/route.js.nft.json +1 -1
  82. package/.next/server/app/api/repositories/sync/route_client-reference-manifest.js +1 -1
  83. package/.next/server/app/api/repositories/validate-path/route_client-reference-manifest.js +1 -1
  84. package/.next/server/app/api/settings/default-agents/route.js +1 -1
  85. package/.next/server/app/api/settings/default-agents/route.js.nft.json +1 -1
  86. package/.next/server/app/api/settings/default-agents/route_client-reference-manifest.js +1 -1
  87. package/.next/server/app/api/settings/default-surface-mode/route_client-reference-manifest.js +1 -1
  88. package/.next/server/app/api/sidebar/group-order/route_client-reference-manifest.js +1 -1
  89. package/.next/server/app/api/skills/[id]/route.js +1 -1
  90. package/.next/server/app/api/skills/[id]/route_client-reference-manifest.js +1 -1
  91. package/.next/server/app/api/skills/installations/route_client-reference-manifest.js +1 -1
  92. package/.next/server/app/api/skills/operations/route_client-reference-manifest.js +1 -1
  93. package/.next/server/app/api/skills/reindex/route_client-reference-manifest.js +1 -1
  94. package/.next/server/app/api/skills/route.js +1 -1
  95. package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
  96. package/.next/server/app/api/slash-commands/route.js +1 -1
  97. package/.next/server/app/api/slash-commands/route_client-reference-manifest.js +1 -1
  98. package/.next/server/app/api/tasks/[taskId]/cancel/route_client-reference-manifest.js +1 -1
  99. package/.next/server/app/api/tasks/[taskId]/route_client-reference-manifest.js +1 -1
  100. package/.next/server/app/api/templates/[id]/route_client-reference-manifest.js +1 -1
  101. package/.next/server/app/api/templates/route_client-reference-manifest.js +1 -1
  102. package/.next/server/app/api/todos/route_client-reference-manifest.js +1 -1
  103. package/.next/server/app/api/verification/runs/[runId]/route_client-reference-manifest.js +1 -1
  104. package/.next/server/app/api/verification/runs/route_client-reference-manifest.js +1 -1
  105. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js +1 -1
  106. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js.nft.json +1 -1
  107. package/.next/server/app/api/worktrees/[id]/auto-yes/route_client-reference-manifest.js +1 -1
  108. package/.next/server/app/api/worktrees/[id]/capture/route.js +1 -1
  109. package/.next/server/app/api/worktrees/[id]/capture/route.js.nft.json +1 -1
  110. package/.next/server/app/api/worktrees/[id]/capture/route_client-reference-manifest.js +1 -1
  111. package/.next/server/app/api/worktrees/[id]/clear-composer/route.js +1 -1
  112. package/.next/server/app/api/worktrees/[id]/clear-composer/route.js.nft.json +1 -1
  113. package/.next/server/app/api/worktrees/[id]/clear-composer/route_client-reference-manifest.js +1 -1
  114. package/.next/server/app/api/worktrees/[id]/cli-reference/route_client-reference-manifest.js +1 -1
  115. package/.next/server/app/api/worktrees/[id]/cli-tool/route_client-reference-manifest.js +1 -1
  116. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route_client-reference-manifest.js +1 -1
  117. package/.next/server/app/api/worktrees/[id]/current-output/route.js +1 -1
  118. package/.next/server/app/api/worktrees/[id]/current-output/route.js.nft.json +1 -1
  119. package/.next/server/app/api/worktrees/[id]/current-output/route_client-reference-manifest.js +1 -1
  120. package/.next/server/app/api/worktrees/[id]/env/route_client-reference-manifest.js +1 -1
  121. package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route.js +1 -1
  122. package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route_client-reference-manifest.js +1 -1
  123. package/.next/server/app/api/worktrees/[id]/execution-logs/route_client-reference-manifest.js +1 -1
  124. package/.next/server/app/api/worktrees/[id]/files/[...path]/route.js +1 -1
  125. package/.next/server/app/api/worktrees/[id]/files/[...path]/route_client-reference-manifest.js +1 -1
  126. package/.next/server/app/api/worktrees/[id]/git/branch/create/route_client-reference-manifest.js +1 -1
  127. package/.next/server/app/api/worktrees/[id]/git/branch/delete/route_client-reference-manifest.js +1 -1
  128. package/.next/server/app/api/worktrees/[id]/git/branches/route_client-reference-manifest.js +1 -1
  129. package/.next/server/app/api/worktrees/[id]/git/checkout/route_client-reference-manifest.js +1 -1
  130. package/.next/server/app/api/worktrees/[id]/git/commit/route_client-reference-manifest.js +1 -1
  131. package/.next/server/app/api/worktrees/[id]/git/diff/route_client-reference-manifest.js +1 -1
  132. package/.next/server/app/api/worktrees/[id]/git/fetch/route_client-reference-manifest.js +1 -1
  133. package/.next/server/app/api/worktrees/[id]/git/log/route_client-reference-manifest.js +1 -1
  134. package/.next/server/app/api/worktrees/[id]/git/pull/route_client-reference-manifest.js +1 -1
  135. package/.next/server/app/api/worktrees/[id]/git/push/route_client-reference-manifest.js +1 -1
  136. package/.next/server/app/api/worktrees/[id]/git/reset/route_client-reference-manifest.js +1 -1
  137. package/.next/server/app/api/worktrees/[id]/git/revert/route_client-reference-manifest.js +1 -1
  138. package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route_client-reference-manifest.js +1 -1
  139. package/.next/server/app/api/worktrees/[id]/git/stage/route_client-reference-manifest.js +1 -1
  140. package/.next/server/app/api/worktrees/[id]/git/staged/route_client-reference-manifest.js +1 -1
  141. package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route_client-reference-manifest.js +1 -1
  142. package/.next/server/app/api/worktrees/[id]/git/stash/apply/route_client-reference-manifest.js +1 -1
  143. package/.next/server/app/api/worktrees/[id]/git/stash/pop/route_client-reference-manifest.js +1 -1
  144. package/.next/server/app/api/worktrees/[id]/git/stash/push/route_client-reference-manifest.js +1 -1
  145. package/.next/server/app/api/worktrees/[id]/git/stash/route_client-reference-manifest.js +1 -1
  146. package/.next/server/app/api/worktrees/[id]/git/status/route_client-reference-manifest.js +1 -1
  147. package/.next/server/app/api/worktrees/[id]/git/unstage/route_client-reference-manifest.js +1 -1
  148. package/.next/server/app/api/worktrees/[id]/git/working-diff/route_client-reference-manifest.js +1 -1
  149. package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js.nft.json +1 -1
  150. package/.next/server/app/api/worktrees/[id]/instances/opencode/route_client-reference-manifest.js +1 -1
  151. package/.next/server/app/api/worktrees/[id]/interrupt/route.js +1 -1
  152. package/.next/server/app/api/worktrees/[id]/interrupt/route.js.nft.json +1 -1
  153. package/.next/server/app/api/worktrees/[id]/interrupt/route_client-reference-manifest.js +1 -1
  154. package/.next/server/app/api/worktrees/[id]/kill-session/route.js +1 -1
  155. package/.next/server/app/api/worktrees/[id]/kill-session/route.js.nft.json +1 -1
  156. package/.next/server/app/api/worktrees/[id]/kill-session/route_client-reference-manifest.js +1 -1
  157. package/.next/server/app/api/worktrees/[id]/logs/[filename]/route_client-reference-manifest.js +1 -1
  158. package/.next/server/app/api/worktrees/[id]/logs/route_client-reference-manifest.js +1 -1
  159. package/.next/server/app/api/worktrees/[id]/marp-render/route_client-reference-manifest.js +1 -1
  160. package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route_client-reference-manifest.js +1 -1
  161. package/.next/server/app/api/worktrees/[id]/memos/route_client-reference-manifest.js +1 -1
  162. package/.next/server/app/api/worktrees/[id]/messages/route_client-reference-manifest.js +1 -1
  163. package/.next/server/app/api/worktrees/[id]/opencode/diff/route_client-reference-manifest.js +1 -1
  164. package/.next/server/app/api/worktrees/[id]/opencode/session/route_client-reference-manifest.js +1 -1
  165. package/.next/server/app/api/worktrees/[id]/opencode/share/route_client-reference-manifest.js +1 -1
  166. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js +1 -1
  167. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js.nft.json +1 -1
  168. package/.next/server/app/api/worktrees/[id]/prompt-response/route_client-reference-manifest.js +1 -1
  169. package/.next/server/app/api/worktrees/[id]/resolve-target/route_client-reference-manifest.js +1 -1
  170. package/.next/server/app/api/worktrees/[id]/respond/route.js +1 -1
  171. package/.next/server/app/api/worktrees/[id]/respond/route.js.nft.json +1 -1
  172. package/.next/server/app/api/worktrees/[id]/respond/route_client-reference-manifest.js +1 -1
  173. package/.next/server/app/api/worktrees/[id]/route.js +1 -1
  174. package/.next/server/app/api/worktrees/[id]/route.js.nft.json +1 -1
  175. package/.next/server/app/api/worktrees/[id]/route_client-reference-manifest.js +1 -1
  176. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route.js +4 -3
  177. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route_client-reference-manifest.js +1 -1
  178. package/.next/server/app/api/worktrees/[id]/schedules/active/route_client-reference-manifest.js +1 -1
  179. package/.next/server/app/api/worktrees/[id]/schedules/route.js +4 -3
  180. package/.next/server/app/api/worktrees/[id]/schedules/route_client-reference-manifest.js +1 -1
  181. package/.next/server/app/api/worktrees/[id]/search/route_client-reference-manifest.js +1 -1
  182. package/.next/server/app/api/worktrees/[id]/send/route.js +1 -1
  183. package/.next/server/app/api/worktrees/[id]/send/route.js.nft.json +1 -1
  184. package/.next/server/app/api/worktrees/[id]/send/route_client-reference-manifest.js +1 -1
  185. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js +2 -2
  186. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js.nft.json +1 -1
  187. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route_client-reference-manifest.js +1 -1
  188. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route_client-reference-manifest.js +1 -1
  189. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route_client-reference-manifest.js +1 -1
  190. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route_client-reference-manifest.js +1 -1
  191. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route_client-reference-manifest.js +1 -1
  192. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update/route_client-reference-manifest.js +1 -1
  193. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route_client-reference-manifest.js +1 -1
  194. package/.next/server/app/api/worktrees/[id]/skills/route_client-reference-manifest.js +1 -1
  195. package/.next/server/app/api/worktrees/[id]/slash-commands/route.js +1 -1
  196. package/.next/server/app/api/worktrees/[id]/slash-commands/route_client-reference-manifest.js +1 -1
  197. package/.next/server/app/api/worktrees/[id]/special-keys/route.js +1 -1
  198. package/.next/server/app/api/worktrees/[id]/special-keys/route.js.nft.json +1 -1
  199. package/.next/server/app/api/worktrees/[id]/special-keys/route_client-reference-manifest.js +1 -1
  200. package/.next/server/app/api/worktrees/[id]/tasks/route_client-reference-manifest.js +1 -1
  201. package/.next/server/app/api/worktrees/[id]/terminal/route.js +1 -1
  202. package/.next/server/app/api/worktrees/[id]/terminal/route.js.nft.json +1 -1
  203. package/.next/server/app/api/worktrees/[id]/terminal/route_client-reference-manifest.js +1 -1
  204. package/.next/server/app/api/worktrees/[id]/timers/history/route_client-reference-manifest.js +1 -1
  205. package/.next/server/app/api/worktrees/[id]/timers/route.js +1 -1
  206. package/.next/server/app/api/worktrees/[id]/timers/route.js.nft.json +1 -1
  207. package/.next/server/app/api/worktrees/[id]/timers/route_client-reference-manifest.js +1 -1
  208. package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
  209. package/.next/server/app/api/worktrees/[id]/todos/route_client-reference-manifest.js +1 -1
  210. package/.next/server/app/api/worktrees/[id]/tree/[...path]/route_client-reference-manifest.js +1 -1
  211. package/.next/server/app/api/worktrees/[id]/tree/route_client-reference-manifest.js +1 -1
  212. package/.next/server/app/api/worktrees/[id]/upload/[...path]/route_client-reference-manifest.js +1 -1
  213. package/.next/server/app/api/worktrees/[id]/verify/config/route_client-reference-manifest.js +1 -1
  214. package/.next/server/app/api/worktrees/[id]/verify/route_client-reference-manifest.js +1 -1
  215. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route_client-reference-manifest.js +1 -1
  216. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route_client-reference-manifest.js +1 -1
  217. package/.next/server/app/api/worktrees/[id]/verify/runs/route_client-reference-manifest.js +1 -1
  218. package/.next/server/app/api/worktrees/[id]/viewed/route_client-reference-manifest.js +1 -1
  219. package/.next/server/app/api/worktrees/apply-default-agents/route_client-reference-manifest.js +1 -1
  220. package/.next/server/app/api/worktrees/route.js +1 -1
  221. package/.next/server/app/api/worktrees/route.js.nft.json +1 -1
  222. package/.next/server/app/api/worktrees/route_client-reference-manifest.js +1 -1
  223. package/.next/server/app/chat/page.js +2 -2
  224. package/.next/server/app/chat/page.js.nft.json +1 -1
  225. package/.next/server/app/chat/page_client-reference-manifest.js +1 -1
  226. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  227. package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
  228. package/.next/server/app/more/page.js +2 -2
  229. package/.next/server/app/more/page.js.nft.json +1 -1
  230. package/.next/server/app/more/page_client-reference-manifest.js +1 -1
  231. package/.next/server/app/offline/page_client-reference-manifest.js +1 -1
  232. package/.next/server/app/page.js +1 -1
  233. package/.next/server/app/page.js.nft.json +1 -1
  234. package/.next/server/app/page_client-reference-manifest.js +1 -1
  235. package/.next/server/app/proxy/[...path]/route_client-reference-manifest.js +1 -1
  236. package/.next/server/app/repositories/page.js +2 -2
  237. package/.next/server/app/repositories/page.js.nft.json +1 -1
  238. package/.next/server/app/repositories/page_client-reference-manifest.js +1 -1
  239. package/.next/server/app/review/page.js +1 -1
  240. package/.next/server/app/review/page.js.nft.json +1 -1
  241. package/.next/server/app/review/page_client-reference-manifest.js +1 -1
  242. package/.next/server/app/sessions/page.js +1 -1
  243. package/.next/server/app/sessions/page.js.nft.json +1 -1
  244. package/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  245. package/.next/server/app/skills/[skillId]/page.js +2 -2
  246. package/.next/server/app/skills/[skillId]/page.js.nft.json +1 -1
  247. package/.next/server/app/skills/[skillId]/page_client-reference-manifest.js +1 -1
  248. package/.next/server/app/skills/installed/page.js +2 -2
  249. package/.next/server/app/skills/installed/page.js.nft.json +1 -1
  250. package/.next/server/app/skills/installed/page_client-reference-manifest.js +1 -1
  251. package/.next/server/app/skills/page.js +1 -1
  252. package/.next/server/app/skills/page.js.nft.json +1 -1
  253. package/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  254. package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -1
  255. package/.next/server/app/worktrees/[id]/page.js +10 -10
  256. package/.next/server/app/worktrees/[id]/page.js.nft.json +1 -1
  257. package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -1
  258. package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
  259. package/.next/server/app-paths-manifest.json +27 -27
  260. package/.next/server/chunks/1058.js +1 -1
  261. package/.next/server/chunks/1068.js +1 -1
  262. package/.next/server/chunks/1262.js +1 -1
  263. package/.next/server/chunks/1886.js +3 -3
  264. package/.next/server/chunks/1990.js +103 -0
  265. package/.next/server/chunks/2119.js +1 -1
  266. package/.next/server/chunks/2328.js +1 -1
  267. package/.next/server/chunks/2404.js +1 -1
  268. package/.next/server/chunks/2445.js +1 -1
  269. package/.next/server/chunks/261.js +1 -1
  270. package/.next/server/chunks/3123.js +1 -1
  271. package/.next/server/chunks/3241.js +1 -1
  272. package/.next/server/chunks/3480.js +5 -4
  273. package/.next/server/chunks/4299.js +1 -1
  274. package/.next/server/chunks/4393.js +1 -1
  275. package/.next/server/chunks/4443.js +1 -5
  276. package/.next/server/chunks/5017.js +1 -1
  277. package/.next/server/chunks/5043.js +1 -1
  278. package/.next/server/chunks/5164.js +1 -1
  279. package/.next/server/chunks/552.js +2 -2
  280. package/.next/server/chunks/6072.js +1 -1
  281. package/.next/server/chunks/6130.js +1 -1
  282. package/.next/server/chunks/663.js +4 -3
  283. package/.next/server/chunks/6894.js +2 -2
  284. package/.next/server/chunks/7187.js +1 -0
  285. package/.next/server/chunks/7472.js +1 -1
  286. package/.next/server/chunks/{880.js → 7859.js} +6 -6
  287. package/.next/server/chunks/7905.js +1 -1
  288. package/.next/server/chunks/8800.js +2 -2
  289. package/.next/server/chunks/8918.js +7 -0
  290. package/.next/server/chunks/9123.js +2 -2
  291. package/.next/server/chunks/9130.js +4 -4
  292. package/.next/server/chunks/9627.js +1 -1
  293. package/.next/server/chunks/9696.js +1 -1
  294. package/.next/server/chunks/9798.js +1 -1
  295. package/.next/server/middleware-manifest.json +5 -5
  296. package/.next/server/pages/500.html +1 -1
  297. package/.next/server/pages-manifest.json +1 -1
  298. package/.next/server/server-reference-manifest.json +1 -1
  299. package/.next/static/chunks/1783-11c9b4d8a52ebd91.js +1 -0
  300. package/.next/static/chunks/4718-de1224c9e8a6e7fc.js +1 -0
  301. package/.next/static/chunks/6022-2fa0b5a82d4ce7b6.js +1 -0
  302. package/.next/static/chunks/{5229-6c89475b61bd2c8b.js → 6170-951b9f5fe6b4b3b5.js} +1 -1
  303. package/.next/static/chunks/app/chat/{page-9aa2011410895b0d.js → page-37d7615d17d7e2a0.js} +1 -1
  304. package/.next/static/chunks/app/layout-4c2f21e3f653ee4c.js +1 -0
  305. package/.next/static/chunks/app/more/{page-333bba1c8bbc9c11.js → page-353a3924e6d7968e.js} +1 -1
  306. package/.next/static/chunks/app/{page-214f7ffa13a0cf10.js → page-c2bf871d953a1d6f.js} +1 -1
  307. package/.next/static/chunks/app/repositories/{page-4951cac905e50224.js → page-7d0f26df0537254c.js} +1 -1
  308. package/.next/static/chunks/app/review/{page-a0899b2d285318c3.js → page-e3f141b2829973e9.js} +1 -1
  309. package/.next/static/chunks/app/sessions/{page-fb36145ec732092a.js → page-53f188ed9ca49e5f.js} +1 -1
  310. package/.next/static/chunks/app/skills/[skillId]/{page-9099e26b60442873.js → page-80569b720aea59cc.js} +1 -1
  311. package/.next/static/chunks/app/skills/installed/{page-182e32368696d824.js → page-dbd2690ad72da95b.js} +1 -1
  312. package/.next/static/chunks/app/skills/{page-d3fdc88239ebe0ab.js → page-dacd36f9c11aa7da.js} +1 -1
  313. package/.next/static/chunks/app/worktrees/[id]/page-97205088520255a5.js +1 -0
  314. package/.next/static/css/5c13ea243dfdcb66.css +1 -0
  315. package/.next/trace +13 -13
  316. package/README.md +37 -11
  317. package/dist/cli/commands/attach.d.ts +50 -0
  318. package/dist/cli/commands/attach.d.ts.map +1 -0
  319. package/dist/cli/commands/attach.js +204 -0
  320. package/dist/cli/commands/capture.d.ts.map +1 -1
  321. package/dist/cli/commands/capture.js +114 -0
  322. package/dist/cli/commands/instances.d.ts.map +1 -1
  323. package/dist/cli/commands/instances.js +23 -2
  324. package/dist/cli/commands/ls.d.ts.map +1 -1
  325. package/dist/cli/commands/ls.js +41 -1
  326. package/dist/cli/config/cli-dependencies.d.ts.map +1 -1
  327. package/dist/cli/config/cli-dependencies.js +34 -0
  328. package/dist/cli/program.d.ts.map +1 -1
  329. package/dist/cli/program.js +5 -0
  330. package/dist/cli/types/index.d.ts +36 -0
  331. package/dist/cli/types/index.d.ts.map +1 -1
  332. package/dist/config/tmux-pane-config.d.ts +153 -0
  333. package/dist/config/tmux-pane-config.d.ts.map +1 -0
  334. package/dist/config/tmux-pane-config.js +172 -0
  335. package/dist/lib/cli-tools/session-name.d.ts +44 -0
  336. package/dist/lib/cli-tools/session-name.d.ts.map +1 -0
  337. package/dist/lib/cli-tools/session-name.js +57 -0
  338. package/dist/lib/cli-tools/types.d.ts +1 -1
  339. package/dist/lib/cli-tools/types.d.ts.map +1 -1
  340. package/dist/lib/cli-tools/types.js +6 -1
  341. package/dist/lib/cli-tools/validation.d.ts +34 -0
  342. package/dist/lib/cli-tools/validation.d.ts.map +1 -0
  343. package/dist/lib/cli-tools/validation.js +41 -0
  344. package/dist/lib/detection/status-reason.d.ts +18 -0
  345. package/dist/lib/detection/status-reason.d.ts.map +1 -1
  346. package/dist/lib/detection/status-reason.js +18 -0
  347. package/dist/lib/detection/tools/verified-against.d.ts +57 -7
  348. package/dist/lib/detection/tools/verified-against.d.ts.map +1 -1
  349. package/dist/lib/detection/tools/verified-against.js +59 -8
  350. package/dist/lib/detection/version-probes.d.ts +26 -5
  351. package/dist/lib/detection/version-probes.d.ts.map +1 -1
  352. package/dist/lib/detection/version-probes.js +28 -6
  353. package/dist/lib/session/tmux-session-surface.d.ts +369 -0
  354. package/dist/lib/session/tmux-session-surface.d.ts.map +1 -0
  355. package/dist/lib/session/tmux-session-surface.js +525 -0
  356. package/dist/server/src/config/cli-tool-timing-config.js +12 -1
  357. package/dist/server/src/config/detection-evidence-config.js +5 -0
  358. package/dist/server/src/config/schedule-config.js +28 -1
  359. package/dist/server/src/lib/cli-tools/antigravity.js +2 -2
  360. package/dist/server/src/lib/cli-tools/base.js +13 -8
  361. package/dist/server/src/lib/cli-tools/claude.js +20 -0
  362. package/dist/server/src/lib/cli-tools/codex.js +205 -61
  363. package/dist/server/src/lib/cli-tools/command-code.js +349 -0
  364. package/dist/server/src/lib/cli-tools/composer-spec.js +6 -0
  365. package/dist/server/src/lib/cli-tools/copilot.js +2 -2
  366. package/dist/server/src/lib/cli-tools/gemini.js +2 -2
  367. package/dist/server/src/lib/cli-tools/graceful-exit.js +16 -1
  368. package/dist/server/src/lib/cli-tools/index.js +4 -1
  369. package/dist/server/src/lib/cli-tools/install-hints.js +131 -0
  370. package/dist/server/src/lib/cli-tools/liveness-spec.js +18 -0
  371. package/dist/server/src/lib/cli-tools/manager.js +2 -0
  372. package/dist/server/src/lib/cli-tools/opencode.js +2 -2
  373. package/dist/server/src/lib/cli-tools/start-availability.js +18 -11
  374. package/dist/server/src/lib/cli-tools/types.js +6 -1
  375. package/dist/server/src/lib/cli-tools/vibe-local.js +2 -2
  376. package/dist/server/src/lib/cmate-parser.js +6 -0
  377. package/dist/server/src/lib/detection/cli-patterns.js +441 -8
  378. package/dist/server/src/lib/detection/opencode-modal-overlay.js +66 -100
  379. package/dist/server/src/lib/detection/selection-shape.js +341 -0
  380. package/dist/server/src/lib/detection/sgr-background.js +210 -0
  381. package/dist/server/src/lib/detection/status-detector.js +6 -0
  382. package/dist/server/src/lib/detection/status-reason.js +18 -0
  383. package/dist/server/src/lib/detection/tools/antigravity/detect.js +38 -15
  384. package/dist/server/src/lib/detection/tools/codex/cli-patterns.js +392 -0
  385. package/dist/server/src/lib/detection/tools/codex/detect.js +83 -2
  386. package/dist/server/src/lib/detection/tools/command-code/detect.js +159 -0
  387. package/dist/server/src/lib/detection/tools/registry.js +6 -4
  388. package/dist/server/src/lib/detection/tools/verified-against.js +59 -8
  389. package/dist/server/src/lib/detection/version-probes.js +28 -6
  390. package/dist/server/src/lib/hooks/sources/antigravity/history.js +77 -16
  391. package/dist/server/src/lib/hooks/sources/claude/history.js +94 -18
  392. package/dist/server/src/lib/hooks/sources/codex/history.js +84 -15
  393. package/dist/server/src/lib/hooks/sources/codex/hooks-config.js +130 -17
  394. package/dist/server/src/lib/hooks/sources/codex/relay-install.js +145 -0
  395. package/dist/server/src/lib/hooks/sources/command-code/history.js +865 -0
  396. package/dist/server/src/lib/hooks/sources/command-code/hooks-config.js +390 -0
  397. package/dist/server/src/lib/hooks/sources/command-code/source.js +290 -0
  398. package/dist/server/src/lib/hooks/sources/command-code/tool-id.js +18 -0
  399. package/dist/server/src/lib/hooks/sources/command-code/transcript.js +604 -0
  400. package/dist/server/src/lib/hooks/sources/index.js +3 -1
  401. package/dist/server/src/lib/hooks/sources/opencode/history.js +57 -3
  402. package/dist/server/src/lib/hooks/sources/opencode/transcript.js +24 -28
  403. package/dist/server/src/lib/hooks/sources/registry.js +4 -0
  404. package/dist/server/src/lib/hooks/sources/turn-body.js +77 -19
  405. package/dist/server/src/lib/job-executor.js +12 -0
  406. package/dist/server/src/lib/polling/auto-yes-dialog-gate.js +6 -0
  407. package/dist/server/src/lib/polling/response-checker.js +112 -7
  408. package/dist/server/src/lib/polling/structured-history-gate.js +15 -8
  409. package/dist/server/src/lib/realtime/types.js +15 -5
  410. package/dist/server/src/lib/response-cleaner.js +24 -1
  411. package/dist/server/src/lib/response-extractor.js +11 -0
  412. package/dist/server/src/lib/session/claude-executor.js +223 -4
  413. package/dist/server/src/lib/session/cli-session.js +52 -0
  414. package/dist/server/src/lib/session/tmux-session-surface.js +525 -0
  415. package/dist/server/src/lib/skills/compatibility-matrix.js +117 -1
  416. package/dist/server/src/lib/tmux/geometry-delegation.js +143 -0
  417. package/dist/server/src/lib/tmux/read-mode-pager.js +76 -10
  418. package/dist/server/src/lib/tmux/read-mode.js +44 -2
  419. package/dist/server/src/lib/tmux/session-hook-scripts.js +249 -0
  420. package/dist/server/src/lib/tmux/session-hooks.js +122 -0
  421. package/dist/server/src/lib/tmux/session-status-options.js +213 -0
  422. package/dist/server/src/lib/tmux/tmux.js +79 -2
  423. package/dist/server/src/lib/version-checker.js +110 -0
  424. package/dist/server/src/lib/ws-server.js +16 -10
  425. package/dist/server/src/types/agent-transcript.js +73 -1
  426. package/dist/server/src/types/terminal-keys.js +131 -3
  427. package/dist/types/terminal-keys.d.ts +100 -3
  428. package/dist/types/terminal-keys.d.ts.map +1 -1
  429. package/dist/types/terminal-keys.js +131 -3
  430. package/package.json +1 -1
  431. package/.next/server/chunks/3099.js +0 -5
  432. package/.next/server/chunks/7824.js +0 -1
  433. package/.next/static/chunks/3916-0e929d089282dc5d.js +0 -1
  434. package/.next/static/chunks/6022-7a7d1760fc9814c7.js +0 -1
  435. package/.next/static/chunks/6381-147dde2a967e9458.js +0 -1
  436. package/.next/static/chunks/app/layout-6a26ea22d5cf03dc.js +0 -1
  437. package/.next/static/chunks/app/worktrees/[id]/page-2f73d69187936627.js +0 -1
  438. package/.next/static/css/23f9c40ecc458c77.css +0 -1
  439. /package/.next/static/{QXxQbXWoo7ldUyOcv7PCZ → nXW4dPkpE_9xUf_9ySRff}/_buildManifest.js +0 -0
  440. /package/.next/static/{QXxQbXWoo7ldUyOcv7PCZ → nXW4dPkpE_9xUf_9ySRff}/_ssgManifest.js +0 -0
@@ -0,0 +1,392 @@
1
+ "use strict";
2
+ /**
3
+ * Codex's dialog rules, read off the frame's STRUCTURE rather than its wording
4
+ * (Issue #2310).
5
+ *
6
+ * ## The defect these rules exist for
7
+ *
8
+ * Until #2310 the only thing that told `detect.ts` "a codex dialog is on screen"
9
+ * was a footer whitelist — `CODEX_SELECTION_LIST_PATTERN`, i.e. the literal
10
+ * words `press enter to confirm` / `press enter to select`. Every dialog codex
11
+ * closes with any other sentence fell straight through to the two branches that
12
+ * read `^›` as the idle composer (branch B of `afterThinking`, and the shared
13
+ * chain's step 3), and those publish **`ready`**. Two live captures of
14
+ * codex-cli 0.153.2 at the production 200x1000 geometry, both blocked on a
15
+ * keypress and both reported `ready` before this module existed
16
+ * (`tests/unit/lib/detection/fixtures/codex-live-2310/`):
17
+ *
18
+ * | screen | footer | why the whitelist missed it |
19
+ * |---|---|---|
20
+ * | `/experimental` | `Press space to select or enter to save for next conversation` | `press SPACE to select`, not `press enter to select` |
21
+ * | `/keymap` | `left/right group · enter edit shortcut · … · esc close` | no `press … to …` clause at all |
22
+ *
23
+ * A `ready` there is not cosmetic: Auto-Yes concludes there is nothing to
24
+ * answer, the sidebar dot goes green, and `commandmate wait` takes the frame as
25
+ * its `scraper_ready` completion — a false "Completed" on a session that has not
26
+ * moved since the operator's last keypress.
27
+ *
28
+ * Note what BOTH real leaks have in common and what the Issue's own analysis
29
+ * assumed they would not: **neither list is numbered.** A rule written only
30
+ * around `findNumberedOptionBlock` would still report both as `ready`, so the
31
+ * primary rule here is the attribute one below and the numbered block is the
32
+ * corroborating second reading, not the other way round.
33
+ *
34
+ * ## Why the attributes and not the text
35
+ *
36
+ * codex puts `›` (U+203A) at column 0 in three different places, and after
37
+ * `stripAnsi` all three are the same byte. The measured separation (0.153.2,
38
+ * cross-checked against the 0.148.0 / 0.151.0 captures already in the tree) is:
39
+ *
40
+ * ```text
41
+ * ESC[1m›ESC[0m ESC[2mAsk Codex to do anythingESC[0m composer, empty → composer
42
+ * ESC[1m›ESC[0m 1. buy milk composer, typed → composer
43
+ * ESC[1;2m› ESC[0mCreate a file scripts/greet.sh transcript echo → dim glyph
44
+ * ESC[1mESC[38;5;6m› 1. Yes, proceed (y)ESC[0m approval option → bold label
45
+ * ESC[1mESC[38;5;6m› [ ] Network proxy Apply network… /experimental → bold label
46
+ * ESC[1mESC[38;5;6m› Global - Open Agents unboundESC[0m /keymap → bold label
47
+ * ESC[38;5;6m› 1. Yes, continueESC[39m trust dialog → coloured glyph
48
+ * ```
49
+ *
50
+ * `composer-residual-leading-number.txt` is the frame that rules out the cheap
51
+ * text guard: it is a composer holding the hand-typed string `1. buy milk`, so
52
+ * "a `›` followed by a digit and a dot is an option" would call an idle session
53
+ * `waiting` — the shape #1883 turned into a send guard that rejected every send.
54
+ *
55
+ * {@link readCodexGlyphRowKind} therefore recognises an option **positively**
56
+ * (bold label, or a non-default foreground on the glyph) instead of defining it
57
+ * as "not the composer". Every unrecognised shape falls to `composer`, which is
58
+ * the direction that costs nothing: it is what the code did before #2310.
59
+ *
60
+ * ## Why this duplicates a little of `composer-text.ts`
61
+ *
62
+ * That module has the same SGR scan and the same three-way measurement, and it
63
+ * is the right module to share it from. It is outside this Issue's `scope.allow`
64
+ * and its `isCodexComposerRow` is not exported, so the scan is re-stated here.
65
+ * The two differ on purpose in one place — `composer-text.ts` accepts a row with
66
+ * a plain glyph and a plain label as the composer, which is right when the job
67
+ * is "find the input box near the bottom" and wrong here, where the same shape
68
+ * is the 0.151+ trust dialog's option. If they are ever merged, that difference
69
+ * is the one to carry across, not to smooth over.
70
+ */
71
+ Object.defineProperty(exports, "__esModule", { value: true });
72
+ exports.CODEX_DIALOG_FOOTER_PATTERN = exports.CODEX_DIALOG_RULES_VERIFIED_AGAINST = exports.CODEX_GLYPH = void 0;
73
+ exports.readCodexGlyphRowKind = readCodexGlyphRowKind;
74
+ exports.findCodexBottomGlyphRow = findCodexBottomGlyphRow;
75
+ exports.readCodexDialogFrame = readCodexDialogFrame;
76
+ exports.reportCodexDialogFooterDrift = reportCodexDialogFooterDrift;
77
+ exports.resetCodexDialogFooterDriftForTests = resetCodexDialogFooterDriftForTests;
78
+ const logger_1 = require("../../../../lib/logger");
79
+ const dialog_block_1 = require("../dialog-block");
80
+ const logger = (0, logger_1.createLogger)('codex-dialog-rules');
81
+ /** codex's selection-cursor / composer glyph, U+203A. */
82
+ exports.CODEX_GLYPH = '›';
83
+ /**
84
+ * The codex build these dialog rules were read off.
85
+ *
86
+ * Separate from `CODEX_VERIFIED_AGAINST` on purpose: that stamp is the whole
87
+ * detector's (`tools/verified-against.ts`, outside this Issue's scope) and still
88
+ * names 0.148.0, while the frames below are 0.153.2. Recording the newer
89
+ * measurement here rather than leaving it unrecorded keeps a later reader able
90
+ * to tell "this rule is wrong" from "this rule was right for 0.153.2"; the
91
+ * detector-wide stamp should be raised to match the next time that file is in
92
+ * scope.
93
+ */
94
+ exports.CODEX_DIALOG_RULES_VERIFIED_AGAINST = {
95
+ version: '0.153.2',
96
+ capturedAt: '2026-09-04',
97
+ paneGeometry: '200x1000',
98
+ };
99
+ /**
100
+ * The footer vocabulary codex closes its dialogs with — a SECONDARY signal.
101
+ *
102
+ * Deliberately not a gate. #2310 exists because a footer whitelist was load
103
+ * bearing, and widening the whitelist would only move the next wording change
104
+ * one sentence further away. What this pattern is for is the opposite: when
105
+ * {@link readCodexDialogFrame} recognises a dialog by structure and this pattern
106
+ * does NOT recognise its footer, that is a codex rewording worth a line in the
107
+ * log ({@link reportCodexDialogFooterDrift}) rather than a silent miss.
108
+ *
109
+ * Every measured footer matches one of the two alternatives:
110
+ *
111
+ * | footer | screen | alternative |
112
+ * |---|---|---|
113
+ * | `Press enter to confirm or esc to cancel` | approval | both |
114
+ * | `Press enter to confirm or esc to go back` | `/model`, `/permissions` | both |
115
+ * | `Press enter to continue` | trust, sign-in | 1st |
116
+ * | `Press t to trust all; enter to review hooks; esc to close` | hooks list | both |
117
+ * | `Press t to trust; esc to go back` | hooks detail | both |
118
+ * | `Press space to select or enter to save for next conversation` | `/experimental` | 1st |
119
+ * | `left/right group · enter edit shortcut · … · esc close` | `/keymap` | 2nd |
120
+ *
121
+ * No `/g` (keeps `.test()` stateless) and no nested quantifiers (ReDoS-safe).
122
+ */
123
+ exports.CODEX_DIALOG_FOOTER_PATTERN = /press\s+\S+\s+to\s+\S|esc\s+(?:to\s+)?(?:cancel|close|dismiss|quit|exit|back|go\s+back)/i;
124
+ const INITIAL_SGR = { bold: false, dim: false, coloured: false };
125
+ /**
126
+ * Apply one SGR parameter list to the running attribute state.
127
+ *
128
+ * The extended-colour introducers are consumed with their arguments because
129
+ * those arguments would otherwise be read as attributes: `ESC[38;5;2m` is
130
+ * "foreground = palette colour 2", and a naive scan sees the `2` and marks the
131
+ * rest of the row dim — which is exactly codex's own option colouring
132
+ * (`ESC[38;5;6m`) and would turn every dialog row into a transcript echo.
133
+ */
134
+ function applySgr(params, state) {
135
+ const parts = params === '' ? ['0'] : params.split(';');
136
+ let { bold, dim, coloured } = state;
137
+ for (let i = 0; i < parts.length; i++) {
138
+ const code = parts[i] === '' ? 0 : Number(parts[i]);
139
+ if (Number.isNaN(code))
140
+ continue;
141
+ if (code === 38) {
142
+ const mode = parts[i + 1] === '' || parts[i + 1] === undefined ? -1 : Number(parts[i + 1]);
143
+ // 5 = 256-colour (one argument), 2 = 24-bit RGB (three arguments).
144
+ if (mode === 5)
145
+ i += 2;
146
+ else if (mode === 2)
147
+ i += 4;
148
+ else
149
+ i += 1;
150
+ coloured = true;
151
+ continue;
152
+ }
153
+ if (code === 48 || code === 58) {
154
+ // Background / underline colour: same argument shapes, no bearing here.
155
+ const mode = parts[i + 1] === '' || parts[i + 1] === undefined ? -1 : Number(parts[i + 1]);
156
+ if (mode === 5)
157
+ i += 2;
158
+ else if (mode === 2)
159
+ i += 4;
160
+ else
161
+ i += 1;
162
+ continue;
163
+ }
164
+ if (code === 0) {
165
+ bold = false;
166
+ dim = false;
167
+ coloured = false;
168
+ }
169
+ else if (code === 1)
170
+ bold = true;
171
+ else if (code === 2)
172
+ dim = true;
173
+ else if (code === 22) {
174
+ bold = false;
175
+ dim = false;
176
+ }
177
+ else if (code === 39)
178
+ coloured = false;
179
+ else if ((code >= 30 && code <= 37) || (code >= 90 && code <= 97))
180
+ coloured = true;
181
+ }
182
+ return { bold, dim, coloured };
183
+ }
184
+ /**
185
+ * Split one raw pane row into rendered characters tagged with their attributes.
186
+ *
187
+ * Escape sequences are consumed, never emitted: CSI (`ESC[…letter`) updates the
188
+ * attribute state when it ends in `m` and is otherwise skipped, and OSC
189
+ * (`ESC]…BEL` or `ESC]…ESC\`, which tmux emits for hyperlinks) is skipped whole.
190
+ */
191
+ function scanAttributedChars(row) {
192
+ const out = [];
193
+ let state = INITIAL_SGR;
194
+ let i = 0;
195
+ while (i < row.length) {
196
+ const ch = row[i];
197
+ if (ch !== '\x1b') {
198
+ out.push({ ch, attrs: state });
199
+ i++;
200
+ continue;
201
+ }
202
+ const next = row[i + 1];
203
+ if (next === '[') {
204
+ let j = i + 2;
205
+ while (j < row.length && !/[A-Za-z]/.test(row[j]))
206
+ j++;
207
+ if (j >= row.length)
208
+ break; // truncated sequence: nothing renderable follows
209
+ if (row[j] === 'm')
210
+ state = applySgr(row.slice(i + 2, j), state);
211
+ i = j + 1;
212
+ continue;
213
+ }
214
+ if (next === ']') {
215
+ let j = i + 2;
216
+ while (j < row.length) {
217
+ if (row[j] === '\x07') {
218
+ j++;
219
+ break;
220
+ }
221
+ if (row[j] === '\x1b' && row[j + 1] === '\\') {
222
+ j += 2;
223
+ break;
224
+ }
225
+ j++;
226
+ }
227
+ i = j;
228
+ continue;
229
+ }
230
+ // Any other two-byte escape (charset switch, etc.): drop it.
231
+ i += 2;
232
+ }
233
+ return out;
234
+ }
235
+ /**
236
+ * Classify one RAW pane row whose first rendered glyph is `›`.
237
+ *
238
+ * @param rawRow - One row of the capture, ANSI intact
239
+ * @returns the row's kind, or `null` when the row is not a `›` row at all or
240
+ * carries no attributes to read it by
241
+ *
242
+ * `null` for an attribute-free row is the load-bearing case, not a formality:
243
+ * Auto-Yes hands the detection layer a capture that has already been through
244
+ * `stripAnsi`, and on that input every one of the three `›` uses is the same
245
+ * text. Answering `'option'` there would call an idle composer `waiting`, so the
246
+ * absence of attributes is reported as "cannot tell" and the callers fall back
247
+ * to the reading they had before #2310.
248
+ */
249
+ function readCodexGlyphRowKind(rawRow) {
250
+ if (!rawRow.includes('\x1b'))
251
+ return null;
252
+ const chars = scanAttributedChars(rawRow);
253
+ const glyphIndex = chars.findIndex(c => c.ch.trim() !== '');
254
+ if (glyphIndex < 0 || chars[glyphIndex].ch !== exports.CODEX_GLYPH)
255
+ return null;
256
+ const glyph = chars[glyphIndex].attrs;
257
+ // The transcript echo of a message the operator already sent. Checked first:
258
+ // codex draws it `ESC[1;2m`, so it is bold as well as dim.
259
+ if (glyph.dim)
260
+ return 'transcript-echo';
261
+ const label = chars.slice(glyphIndex + 1).find(c => c.ch.trim() !== '');
262
+ // Positively recognised: the two shapes every measured dialog row has.
263
+ if (label?.attrs.bold || glyph.coloured)
264
+ return 'option';
265
+ return 'composer';
266
+ }
267
+ /**
268
+ * Find and classify the bottom-most `›` row of a raw capture.
269
+ *
270
+ * "Bottom-most" is the whole point, and it is the same rule `isCodexPromptReady`
271
+ * and `codexActiveRegionLines` already apply for their own questions: codex
272
+ * draws on the normal screen, so a dialog the operator answered minutes ago is
273
+ * still in the frame with its options intact (Issue #1160). Only the LAST `›`
274
+ * row says what the pane is doing now — and when a turn is generating, that row
275
+ * is the composer, which is why this reads `running` frames as `composer` and
276
+ * leaves them to the thinking branches.
277
+ *
278
+ * @param raw - The capture exactly as it arrived, ANSI intact
279
+ */
280
+ function findCodexBottomGlyphRow(raw) {
281
+ const rows = raw.split('\n');
282
+ for (let i = rows.length - 1; i >= 0; i--) {
283
+ const kind = readCodexGlyphRowKind(rows[i]);
284
+ if (kind !== null)
285
+ return { kind, row: i };
286
+ }
287
+ return null;
288
+ }
289
+ /** How many non-blank rows below the dialog are read as its footer. */
290
+ const FOOTER_SCAN_ROWS = 8;
291
+ function readFooterBelow(contentLines, fromExclusive, endExclusive) {
292
+ const rows = [];
293
+ for (let i = fromExclusive + 1; i < endExclusive && rows.length < FOOTER_SCAN_ROWS; i++) {
294
+ const row = contentLines[i].trim();
295
+ if (row === '')
296
+ continue;
297
+ rows.push(row);
298
+ }
299
+ return rows.join('\n');
300
+ }
301
+ /**
302
+ * Does this frame show a codex dialog the operator has to answer?
303
+ *
304
+ * Two independent readings, either of which is enough:
305
+ *
306
+ * 1. **the glyph rule** — the bottom-most `›` row of the RAW capture is an
307
+ * option row ({@link readCodexGlyphRowKind}). This is the one that catches
308
+ * the unnumbered menus #2310 was raised for.
309
+ * 2. **the numbered block** — `findNumberedOptionBlock` found a `›`-selected
310
+ * run of options ending within a few rows of the content end. This is the
311
+ * reading that survives `stripAnsi`, and it is vetoed by the glyph rule when
312
+ * that positively says the row is the composer, so a composer holding the
313
+ * hand-typed text `1. buy milk` cannot be adopted as a dialog.
314
+ *
315
+ * Neither reading consults the footer. The footer is reported back so the caller
316
+ * can log a codex rewording; see {@link CODEX_DIALOG_FOOTER_PATTERN}.
317
+ *
318
+ * @param raw - The capture with ANSI intact (`NormalizedFrame.raw`)
319
+ * @param contentLines - The ANSI-stripped rows with trailing padding removed
320
+ * @param contentEnd - Exclusive end of the conversation region (the row above
321
+ * codex's status bar, or `contentLines.length` when the bar is not on screen)
322
+ */
323
+ function readCodexDialogFrame(raw, contentLines, contentEnd) {
324
+ const glyphRow = findCodexBottomGlyphRow(raw);
325
+ const block = (0, dialog_block_1.findNumberedOptionBlock)(contentLines, contentEnd);
326
+ const blockIsDialog = block !== null && block.selectedGlyph === exports.CODEX_GLYPH;
327
+ const by = glyphRow?.kind === 'option'
328
+ ? 'glyph'
329
+ : blockIsDialog && glyphRow?.kind !== 'composer' && glyphRow?.kind !== 'transcript-echo'
330
+ ? 'numbered-block'
331
+ : null;
332
+ if (by === null)
333
+ return null;
334
+ // The block's own footer when there is a block; otherwise the rows under the
335
+ // highlighted row. `block.lastRow` and the glyph row are indices into the same
336
+ // ANSI-stripped `contentLines`, so both spellings read the same rows.
337
+ const footer = block !== null
338
+ ? block.footer
339
+ : readFooterBelow(contentLines, findLastGlyphContentRow(contentLines, contentEnd), contentEnd);
340
+ return {
341
+ by,
342
+ options: block?.options ?? [],
343
+ footer,
344
+ footerRecognised: exports.CODEX_DIALOG_FOOTER_PATTERN.test(footer),
345
+ };
346
+ }
347
+ /** Index of the bottom-most `›` row within the content region, or -1. */
348
+ function findLastGlyphContentRow(contentLines, endExclusive) {
349
+ for (let i = Math.min(endExclusive, contentLines.length) - 1; i >= 0; i--) {
350
+ if (contentLines[i].trimStart().startsWith(exports.CODEX_GLYPH))
351
+ return i;
352
+ }
353
+ return -1;
354
+ }
355
+ /**
356
+ * Footers already reported, so a rewording costs one log line and not one per
357
+ * poll tick.
358
+ *
359
+ * Bounded because the key is frame text: a footer that varies (a countdown, a
360
+ * path) would otherwise grow the set without bound. At the cap the tracker stops
361
+ * recording rather than evicting — the point is the FIRST sighting of a new
362
+ * wording, and a process that has already seen 64 of them has been told.
363
+ */
364
+ const reportedFooters = new Set();
365
+ const REPORTED_FOOTER_CAP = 64;
366
+ /**
367
+ * Record that a structurally recognised codex dialog closed with a footer this
368
+ * layer does not know (Issue #2310).
369
+ *
370
+ * The detection still stands — that is the whole point of judging the structure
371
+ * — so this is not a warning about the verdict. It is the tripwire on the thing
372
+ * that actually rots: codex's wording. #2310 was reported months after
373
+ * `/experimental` and `/keymap` started falling through, because nothing in the
374
+ * pipeline said so out loud.
375
+ */
376
+ function reportCodexDialogFooterDrift(footer) {
377
+ const key = footer.slice(0, 200);
378
+ if (reportedFooters.has(key))
379
+ return;
380
+ if (reportedFooters.size >= REPORTED_FOOTER_CAP)
381
+ return;
382
+ reportedFooters.add(key);
383
+ logger.warn('codexDialogFooterUnrecognised', {
384
+ footer: key,
385
+ verifiedAgainst: exports.CODEX_DIALOG_RULES_VERIFIED_AGAINST.version,
386
+ hint: 'codex reworded a dialog footer; widen CODEX_DIALOG_FOOTER_PATTERN after re-capturing the frame',
387
+ });
388
+ }
389
+ /** Test-only: forget the footers already reported. */
390
+ function resetCodexDialogFooterDriftForTests() {
391
+ reportedFooters.clear();
392
+ }
@@ -19,6 +19,7 @@ exports.isCodexStalePrompt = isCodexStalePrompt;
19
19
  const cli_patterns_1 = require("../../cli-patterns");
20
20
  const prompt_detector_1 = require("../../prompt-detector");
21
21
  const status_reason_1 = require("../../status-reason");
22
+ const cli_patterns_2 = require("./cli-patterns");
22
23
  const prompt_1 = require("./prompt");
23
24
  const frame_1 = require("../frame");
24
25
  const run_detection_1 = require("../run-detection");
@@ -139,6 +140,19 @@ function isCodexApprovalRequest(promptDetection, selectionWindow) {
139
140
  const question = promptDetection.promptData?.question?.trim() ?? '';
140
141
  return question.endsWith('?') || cli_patterns_1.CODEX_APPROVAL_FOOTER_PATTERN.test(selectionWindow);
141
142
  }
143
+ /**
144
+ * Issue #2310: does the RAW frame positively show that its bottom-most `›` row
145
+ * is a dialog's highlighted row rather than the composer?
146
+ *
147
+ * The one question the ANSI-stripped `contentLines` cannot answer, asked in the
148
+ * two places that would otherwise publish `ready` off `CODEX_PROMPT_PATTERN`
149
+ * alone. False only means "not shown to be a dialog" — a stripped capture, a
150
+ * transcript echo and a genuine composer all answer false — so this can withhold
151
+ * an `ready` but never create one.
152
+ */
153
+ function isCodexDialogGlyphTail(raw) {
154
+ return (0, cli_patterns_2.findCodexBottomGlyphRow)(raw)?.kind === 'option';
155
+ }
142
156
  exports.codexStatusDetector = (0, run_detection_1.createToolStatusDetector)({
143
157
  tool: 'codex',
144
158
  verifiedAgainst: exports.VERIFIED_AGAINST,
@@ -240,6 +254,61 @@ exports.codexStatusDetector = (0, run_detection_1.createToolStatusDetector)({
240
254
  };
241
255
  }
242
256
  }
257
+ // 0.85. Codex: every OTHER dialog — recognised by structure (Issue #2310)
258
+ //
259
+ // Branch 0.8 above is a footer whitelist, and a dialog codex closes with any
260
+ // other sentence walks straight past it into the two branches that read `^›`
261
+ // as the idle composer (branch B below, and the shared chain's step 3), both
262
+ // of which publish `ready`. Measured on codex-cli 0.153.2 at 200x1000:
263
+ // `/experimental` ends on "Press space to select or enter to save for next
264
+ // conversation" and `/keymap` on "left/right group · enter edit shortcut · …
265
+ // · esc close"; both were reported `ready` while blocked on a keypress, which
266
+ // is what makes Auto-Yes see nothing to answer, the sidebar dot go green and
267
+ // `commandmate wait` close on `scraper_ready` mid-task.
268
+ //
269
+ // So this branch does not read the footer at all — `readCodexDialogFrame`
270
+ // judges the shape: the bottom-most `›` row of the RAW frame carrying a
271
+ // dialog's attributes rather than the composer's, or a `›`-selected numbered
272
+ // block at the foot of the content region (the reading that still answers
273
+ // once ANSI has been stripped). Neither of the two live leaks is numbered,
274
+ // which is why the attribute rule is the primary one.
275
+ //
276
+ // The verdict deliberately mirrors what the chain would have said one step
277
+ // later, so no frame that already resolved changes: a dialog `detectPrompt`
278
+ // can parse is still `PROMPT_DETECTED` with `hasActivePrompt` (step 1's
279
+ // answer — the trust dialog and any reworded approval keep exit 10 for
280
+ // `wait --on-prompt agent`), and everything else is a navigable selection
281
+ // list. The #1160 staleness guard applies as it does in 0.8: an answered
282
+ // block with codex working below it is scrollback, not a dialog — and the
283
+ // glyph rule agrees independently, because the bottom-most `›` on such a
284
+ // frame is the composer codex draws while it works.
285
+ const codexDialogFrame = (0, cli_patterns_2.readCodexDialogFrame)(frame.raw, contentLines, findCodexContentEnd(contentLines));
286
+ if (codexDialogFrame && !isCodexStalePrompt(contentLines)) {
287
+ // The footer is not consulted for the verdict; an unrecognised one means
288
+ // codex reworded a screen, which is worth saying out loud exactly once.
289
+ if (!codexDialogFrame.footerRecognised) {
290
+ (0, cli_patterns_2.reportCodexDialogFooterDrift)(codexDialogFrame.footer);
291
+ }
292
+ const codexPromptDetection = (0, prompt_detector_1.detectPrompt)((0, cli_patterns_1.stripBoxDrawing)(frame.clean), (0, cli_patterns_1.buildDetectPromptOptions)('codex'));
293
+ if (codexPromptDetection.isPrompt) {
294
+ return {
295
+ status: 'waiting',
296
+ confidence: 'high',
297
+ reason: status_reason_1.STATUS_REASON.PROMPT_DETECTED,
298
+ hasActivePrompt: true,
299
+ evidence: 'positive',
300
+ promptDetection: codexPromptDetection,
301
+ };
302
+ }
303
+ return {
304
+ status: 'waiting',
305
+ confidence: 'high',
306
+ reason: status_reason_1.STATUS_REASON.CODEX_SELECTION_LIST,
307
+ hasActivePrompt: false,
308
+ evidence: 'positive',
309
+ promptDetection: codexPromptDetection,
310
+ };
311
+ }
243
312
  return null;
244
313
  },
245
314
  isStalePrompt(frame) {
@@ -292,7 +361,17 @@ exports.codexStatusDetector = (0, run_detection_1.createToolStatusDetector)({
292
361
  //
293
362
  // The evidence stays `positive` here: codex has no measured idle rule yet
294
363
  // (see the module docstring), so DR2-002 keeps its pre-#1927 reading.
295
- if (cli_patterns_1.CODEX_PROMPT_PATTERN.test(contentLines[lastContentIdx].trim())) {
364
+ //
365
+ // Issue #2310: `^›` alone does not say "composer". codex draws the same
366
+ // glyph on a dialog's highlighted row, and reading one as the input line
367
+ // is what published `ready` for a session blocked on a keypress. Branch
368
+ // 0.85 already turns those frames back before the chain reaches here, so
369
+ // this is the second reading of the same fact rather than the only one —
370
+ // and it is written as a veto, not a test: only a RAW frame that
371
+ // positively shows a dialog row withholds `ready`, so a capture whose
372
+ // ANSI has been stripped still reports idle exactly as it did before.
373
+ if (cli_patterns_1.CODEX_PROMPT_PATTERN.test(contentLines[lastContentIdx].trim()) &&
374
+ !isCodexDialogGlyphTail(frame.raw)) {
296
375
  return {
297
376
  status: 'ready',
298
377
  confidence: 'high',
@@ -327,7 +406,9 @@ exports.codexStatusDetector = (0, run_detection_1.createToolStatusDetector)({
327
406
  while (codexTailIdx >= 0 && contentLines[codexTailIdx].trim() === '') {
328
407
  codexTailIdx--;
329
408
  }
330
- const codexTailIsIdlePrompt = codexTailIdx >= 0 && cli_patterns_1.CODEX_PROMPT_PATTERN.test(contentLines[codexTailIdx].trim());
409
+ const codexTailIsIdlePrompt = codexTailIdx >= 0 &&
410
+ cli_patterns_1.CODEX_PROMPT_PATTERN.test(contentLines[codexTailIdx].trim()) &&
411
+ !isCodexDialogGlyphTail(frame.raw);
331
412
  if (!codexTailIsIdlePrompt && (0, cli_patterns_1.detectThinking)('codex', frame.lastLines)) {
332
413
  return {
333
414
  status: 'running',
@@ -0,0 +1,159 @@
1
+ "use strict";
2
+ /**
3
+ * Command Code status detector (Issue #2250, 方針書 §4 D2).
4
+ *
5
+ * Command Code renders inline and pins a claude-shaped composer block to the
6
+ * bottom of the pane, so the shared chain does most of the work: the permission
7
+ * dialog is a numbered list with a `❯` cursor, which step 1's `detectPrompt`
8
+ * already reads, and the status row carries a spinner + `…` and `esc to
9
+ * interrupt`, which step 2's `detectThinking` already reads.
10
+ *
11
+ * What this module adds is `afterThinking`, and it exists because the generic
12
+ * composer check at step 3 would otherwise answer `ready` for a frame in which
13
+ * the composer is drawn and a turn is still in flight. That is not hypothetical
14
+ * on Command Code: the composer block stays on screen for the whole turn (see
15
+ * `turn-thinking.txt`, where `❯ Ask your question...` sits three rows under
16
+ * ` ⌘ Planning… esc to interrupt`). Step 2's window is
17
+ * `THINKING_TAIL_LINE_COUNT` = 5 lines, and the status row is 4 rows above the
18
+ * last content row on that frame, so it fits today — but a wrapped composer adds
19
+ * rows between them and pushes it out, which is exactly the #805 failure claude
20
+ * had to add a wider footer window for. Re-checking thinking here, against the
21
+ * 15-line `lastLines` window, is that wider window.
22
+ *
23
+ * No `readIdleEvidence`: per §4 D1 決定 1's tool-by-tool rollout (DR2-002) a rule
24
+ * has to be read off the tool's OWN frames before it can gate anything, and the
25
+ * five frames captured for this Issue cover launch / thinking / done / dialog /
26
+ * tool-use rather than the awkward idle states (after a `/clear`, after an Esc
27
+ * interrupt) a completion rule has to survive. `detection-evidence-config` ships
28
+ * `legacy` to match.
29
+ *
30
+ * **Issue #2304 captured both of those idle states, and pinned the cost of not
31
+ * having the rule.** `tests/unit/detection/tools/command-code/fixtures.test.ts`
32
+ * defuses the busy vocabulary on a running frame and measures the answer:
33
+ * `ready` / `input_prompt` / `evidence: 'positive'` — a completion declared on
34
+ * the *absence* of a busy marker, which is exactly what D1 forbids. It costs
35
+ * nothing in production while the rollout says `legacy`, because
36
+ * `resolveIdleEvidence` short-circuits before a tool rule is consulted; what it
37
+ * costs is the rollout itself. The two frames a rule needs are now in
38
+ * `tests/fixtures/command-code-live-2250/`:
39
+ *
40
+ * - after `/clear` — `boot-idle-1490.txt`, because the pane after `/clear` is
41
+ * **byte-identical** to the launch screen. Unlike claude, which leaves
42
+ * `new task? /clear to save …` behind and is the reason its own rule went
43
+ * back to `observe` (#2011), Command Code repaints the banner;
44
+ * - after an Esc interrupt — `idle-after-interrupt-1490.txt`, where Esc landed
45
+ * before the agent had written anything, so the newest turn is a prompt echo
46
+ * followed straight by `✻ Worked for 4s` with no `⠶` reply row at all.
47
+ *
48
+ * Building the rule, and measuring its `observe` rate before it enforces
49
+ * anything, is deliberately a separate Issue: the table it would have to move
50
+ * lives in `@/config/detection-evidence-config`, and `afterThinking`'s idle
51
+ * branch below publishes `'positive'` outright rather than through
52
+ * `resolveIdleEvidence`, so a rule added without changing that would never run.
53
+ *
54
+ * No `detectDialog` either: Epic #2249 決定 3 keeps Auto-Yes on the legacy
55
+ * numbered-response path, because Command Code fires `PreToolUse` AFTER the
56
+ * dialog is answered, so a hook-driven permission decision cannot dismiss it.
57
+ *
58
+ * `afterPrompt` arrived with Issue #2297, for the one screen the shared chain
59
+ * genuinely could not read: the picker `/model` opens. It is a provider-grouped
60
+ * list of model NAMES — no option numbers — over a `› Type to search models...`
61
+ * row, closed by `type to search · ↑/↓ navigate · shift+↑/↓ jump provider ·
62
+ * enter to select · esc to cancel`. None of `detectPrompt`, `detectThinking` or
63
+ * the composer check matches any of that, so the frame reached the `default`
64
+ * floor and the chat surface offered it the answer characters — into the search
65
+ * box. Measured live on v1.40.1 at the production 200x1000 geometry; the capture
66
+ * is `tests/fixtures/chat-dialog-card-2254/command-code-model-1-40-1.txt`.
67
+ *
68
+ * ## What #2304 re-measured, and what it did not change
69
+ *
70
+ * Nothing here changed, and that is the finding. Seven frames were captured
71
+ * live on **1.49.0** — nine minor versions past the build these rules were read
72
+ * off — at the same 200x1000 geometry, and every rule answers identically,
73
+ * state for state. `verifiedAgainst` therefore still records 1.40.1: that is
74
+ * the build the rules were *read off*, and
75
+ * `tests/unit/detection/tools/command-code/fixtures.test.ts` is the receipt that
76
+ * they still hold. It also pins the picker's verdict for the three 1.47.1
77
+ * captures, which had none before — `afterPrompt` reading one build's picker was
78
+ * an assumption about the next.
79
+ *
80
+ * Two 1.49.0 observations are worth carrying here because they bound what the
81
+ * rules rest on:
82
+ *
83
+ * - **A status verb can be three words with no `…`.** ` ✧ Shell command
84
+ * allowed esc to interrupt • 19s • ↓ 1.7k` is not read by
85
+ * `COMMAND_CODE_THINKING_PATTERN`'s spinner branch, which wants
86
+ * `[spinner] <one word>…`. Only the third alternative — the `esc to
87
+ * interrupt` tail — reads it, and the tool drops that tail below 42 columns.
88
+ * CommandMate panes are 200 wide, so it holds; a narrower pane would not.
89
+ * The capture is `turn-shell-running-1490.txt`.
90
+ * - **Evidence can be layered.** That same frame carries ` ✻ Thinking… (72
91
+ * lines) [ctrl+o to expand]` two rows above the status row, so it stays
92
+ * `running` when the status row alone is defused. The single-marker frames
93
+ * (`turn-thinking.txt`, `turn-thinking-1490.txt`) do not, which is the D1 gap
94
+ * described above.
95
+ */
96
+ Object.defineProperty(exports, "__esModule", { value: true });
97
+ exports.commandCodeStatusDetector = exports.VERIFIED_AGAINST = void 0;
98
+ const cli_patterns_1 = require("../../cli-patterns");
99
+ const selection_shape_1 = require("../../selection-shape");
100
+ const status_reason_1 = require("../../status-reason");
101
+ const run_detection_1 = require("../run-detection");
102
+ const verified_against_1 = require("../verified-against");
103
+ /** Command Code build these rules were read off (value in ../verified-against). */
104
+ exports.VERIFIED_AGAINST = verified_against_1.COMMAND_CODE_VERIFIED_AGAINST;
105
+ exports.commandCodeStatusDetector = (0, run_detection_1.createToolStatusDetector)({
106
+ tool: 'command-code',
107
+ verifiedAgainst: exports.VERIFIED_AGAINST,
108
+ afterPrompt(frame) {
109
+ // Issue #2297. Command Code's pickers (`/model` measured live on v1.40.1 at
110
+ // 200x1000) are arrow-driven overlays with a search box and a lower-case
111
+ // hint-bar footer. Nothing in the shared chain reads that footer, so before
112
+ // this branch the frame fell through to the `default` floor — which the chat
113
+ // surface renders as `unclassified`, i.e. with the `1`-`9` / `y` / `n`
114
+ // answer keys, and every one of those characters is typed into the picker's
115
+ // `Type to search models...` box rather than selecting anything.
116
+ //
117
+ // `waiting` + `positive`, exactly as claude's selection-list branch reports:
118
+ // a human has to move the highlight and press enter, and the frame says so
119
+ // in as many words.
120
+ if (selection_shape_1.COMMAND_CODE_SELECTION_LIST_FOOTER.test(frame.lastLines)) {
121
+ return {
122
+ status: 'waiting',
123
+ confidence: 'high',
124
+ reason: status_reason_1.STATUS_REASON.COMMAND_CODE_SELECTION_LIST,
125
+ hasActivePrompt: false,
126
+ evidence: 'positive',
127
+ };
128
+ }
129
+ return null;
130
+ },
131
+ afterThinking(frame) {
132
+ // The composer is drawn throughout a turn, so "running" has to be resolved
133
+ // before the generic composer check can say "ready". Widened window; see the
134
+ // module docblock.
135
+ if ((0, cli_patterns_1.detectThinking)('command-code', frame.lastLines)) {
136
+ return {
137
+ status: 'running',
138
+ confidence: 'high',
139
+ reason: status_reason_1.STATUS_REASON.THINKING_INDICATOR,
140
+ hasActivePrompt: false,
141
+ evidence: 'positive',
142
+ };
143
+ }
144
+ // Idle: the composer row is on screen and nothing is in flight. Same verdict
145
+ // the generic step 3 would reach, resolved here so the two cannot disagree
146
+ // about which window they read.
147
+ const { promptPattern } = (0, cli_patterns_1.getCliToolPatterns)('command-code');
148
+ if (promptPattern.test(frame.lastLines)) {
149
+ return {
150
+ status: 'ready',
151
+ confidence: 'high',
152
+ reason: status_reason_1.STATUS_REASON.INPUT_PROMPT,
153
+ hasActivePrompt: false,
154
+ evidence: 'positive',
155
+ };
156
+ }
157
+ return null;
158
+ },
159
+ });