commandmate 0.37.0 → 0.38.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (331) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-build-manifest.json +176 -176
  3. package/.next/app-path-routes-manifest.json +33 -33
  4. package/.next/build-manifest.json +2 -2
  5. package/.next/prerender-manifest.json +12 -12
  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.nft.json +1 -1
  14. package/.next/server/app/api/assistant/conversation/route_client-reference-manifest.js +1 -1
  15. package/.next/server/app/api/assistant/current-output/route.js.nft.json +1 -1
  16. package/.next/server/app/api/assistant/current-output/route_client-reference-manifest.js +1 -1
  17. package/.next/server/app/api/assistant/messages/route.js +1 -1
  18. package/.next/server/app/api/assistant/messages/route.js.nft.json +1 -1
  19. package/.next/server/app/api/assistant/messages/route_client-reference-manifest.js +1 -1
  20. package/.next/server/app/api/assistant/session/route.js +1 -1
  21. package/.next/server/app/api/assistant/session/route.js.nft.json +1 -1
  22. package/.next/server/app/api/assistant/session/route_client-reference-manifest.js +1 -1
  23. package/.next/server/app/api/assistant/start/route.js +1 -1
  24. package/.next/server/app/api/assistant/start/route.js.nft.json +1 -1
  25. package/.next/server/app/api/assistant/start/route_client-reference-manifest.js +1 -1
  26. package/.next/server/app/api/assistant/terminal/route.js +1 -1
  27. package/.next/server/app/api/assistant/terminal/route.js.nft.json +1 -1
  28. package/.next/server/app/api/assistant/terminal/route_client-reference-manifest.js +1 -1
  29. package/.next/server/app/api/assistant/tools/route.js.nft.json +1 -1
  30. package/.next/server/app/api/assistant/tools/route_client-reference-manifest.js +1 -1
  31. package/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
  32. package/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
  33. package/.next/server/app/api/auth/status/route_client-reference-manifest.js +1 -1
  34. package/.next/server/app/api/capabilities/route.js +1 -1
  35. package/.next/server/app/api/capabilities/route_client-reference-manifest.js +1 -1
  36. package/.next/server/app/api/daily-summary/route.js +1 -1
  37. package/.next/server/app/api/daily-summary/route.js.nft.json +1 -1
  38. package/.next/server/app/api/daily-summary/route_client-reference-manifest.js +1 -1
  39. package/.next/server/app/api/daily-summary/status/route.js +1 -1
  40. package/.next/server/app/api/daily-summary/status/route.js.nft.json +1 -1
  41. package/.next/server/app/api/daily-summary/status/route_client-reference-manifest.js +1 -1
  42. package/.next/server/app/api/external-apps/[id]/health/route_client-reference-manifest.js +1 -1
  43. package/.next/server/app/api/external-apps/[id]/route_client-reference-manifest.js +1 -1
  44. package/.next/server/app/api/external-apps/route_client-reference-manifest.js +1 -1
  45. package/.next/server/app/api/fs/browse/route_client-reference-manifest.js +1 -1
  46. package/.next/server/app/api/fs/recent-paths/route_client-reference-manifest.js +1 -1
  47. package/.next/server/app/api/hooks/agent-event/route.js +1 -1
  48. package/.next/server/app/api/hooks/agent-event/route.js.nft.json +1 -1
  49. package/.next/server/app/api/hooks/agent-event/route_client-reference-manifest.js +1 -1
  50. package/.next/server/app/api/hooks/claude-done/route.js +1 -1
  51. package/.next/server/app/api/hooks/claude-done/route.js.nft.json +1 -1
  52. package/.next/server/app/api/hooks/claude-done/route_client-reference-manifest.js +1 -1
  53. package/.next/server/app/api/hooks/permission-request/route.js +1 -1
  54. package/.next/server/app/api/hooks/permission-request/route.js.nft.json +1 -1
  55. package/.next/server/app/api/hooks/permission-request/route_client-reference-manifest.js +1 -1
  56. package/.next/server/app/api/metrics/vibe/route_client-reference-manifest.js +1 -1
  57. package/.next/server/app/api/ollama/models/route_client-reference-manifest.js +1 -1
  58. package/.next/server/app/api/push/escalation/route.js +1 -1
  59. package/.next/server/app/api/push/escalation/route.js.nft.json +1 -1
  60. package/.next/server/app/api/push/escalation/route_client-reference-manifest.js +1 -1
  61. package/.next/server/app/api/push/subscriptions/route_client-reference-manifest.js +1 -1
  62. package/.next/server/app/api/push/vapid/route.js +1 -1
  63. package/.next/server/app/api/push/vapid/route.js.nft.json +1 -1
  64. package/.next/server/app/api/push/vapid/route_client-reference-manifest.js +1 -1
  65. package/.next/server/app/api/relays/[relayId]/cancel/route.js.nft.json +1 -1
  66. package/.next/server/app/api/relays/[relayId]/cancel/route_client-reference-manifest.js +1 -1
  67. package/.next/server/app/api/relays/route.js.nft.json +1 -1
  68. package/.next/server/app/api/relays/route_client-reference-manifest.js +1 -1
  69. package/.next/server/app/api/remote/pair/route_client-reference-manifest.js +1 -1
  70. package/.next/server/app/api/repositories/[id]/route_client-reference-manifest.js +1 -1
  71. package/.next/server/app/api/repositories/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
  72. package/.next/server/app/api/repositories/[id]/todos/route_client-reference-manifest.js +1 -1
  73. package/.next/server/app/api/repositories/clone/[jobId]/route.js +1 -1
  74. package/.next/server/app/api/repositories/clone/[jobId]/route.js.nft.json +1 -1
  75. package/.next/server/app/api/repositories/clone/[jobId]/route_client-reference-manifest.js +1 -1
  76. package/.next/server/app/api/repositories/clone/route.js +1 -1
  77. package/.next/server/app/api/repositories/clone/route.js.nft.json +1 -1
  78. package/.next/server/app/api/repositories/clone/route_client-reference-manifest.js +1 -1
  79. package/.next/server/app/api/repositories/excluded/route_client-reference-manifest.js +1 -1
  80. package/.next/server/app/api/repositories/restore/route.js +1 -1
  81. package/.next/server/app/api/repositories/restore/route.js.nft.json +1 -1
  82. package/.next/server/app/api/repositories/restore/route_client-reference-manifest.js +1 -1
  83. package/.next/server/app/api/repositories/route.js +1 -1
  84. package/.next/server/app/api/repositories/route.js.nft.json +1 -1
  85. package/.next/server/app/api/repositories/route_client-reference-manifest.js +1 -1
  86. package/.next/server/app/api/repositories/scan/route.js +1 -1
  87. package/.next/server/app/api/repositories/scan/route.js.nft.json +1 -1
  88. package/.next/server/app/api/repositories/scan/route_client-reference-manifest.js +1 -1
  89. package/.next/server/app/api/repositories/sync/route.js +1 -1
  90. package/.next/server/app/api/repositories/sync/route.js.nft.json +1 -1
  91. package/.next/server/app/api/repositories/sync/route_client-reference-manifest.js +1 -1
  92. package/.next/server/app/api/repositories/validate-path/route_client-reference-manifest.js +1 -1
  93. package/.next/server/app/api/settings/default-agents/route.js.nft.json +1 -1
  94. package/.next/server/app/api/settings/default-agents/route_client-reference-manifest.js +1 -1
  95. package/.next/server/app/api/settings/default-surface-mode/route_client-reference-manifest.js +1 -1
  96. package/.next/server/app/api/sidebar/group-order/route_client-reference-manifest.js +1 -1
  97. package/.next/server/app/api/skills/[id]/route_client-reference-manifest.js +1 -1
  98. package/.next/server/app/api/skills/installations/route_client-reference-manifest.js +1 -1
  99. package/.next/server/app/api/skills/operations/route_client-reference-manifest.js +1 -1
  100. package/.next/server/app/api/skills/reindex/route_client-reference-manifest.js +1 -1
  101. package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
  102. package/.next/server/app/api/slash-commands/route_client-reference-manifest.js +1 -1
  103. package/.next/server/app/api/tasks/[taskId]/cancel/route_client-reference-manifest.js +1 -1
  104. package/.next/server/app/api/tasks/[taskId]/route_client-reference-manifest.js +1 -1
  105. package/.next/server/app/api/templates/[id]/route_client-reference-manifest.js +1 -1
  106. package/.next/server/app/api/templates/route_client-reference-manifest.js +1 -1
  107. package/.next/server/app/api/todos/route_client-reference-manifest.js +1 -1
  108. package/.next/server/app/api/verification/runs/[runId]/route_client-reference-manifest.js +1 -1
  109. package/.next/server/app/api/verification/runs/route_client-reference-manifest.js +1 -1
  110. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js +1 -1
  111. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js.nft.json +1 -1
  112. package/.next/server/app/api/worktrees/[id]/auto-yes/route_client-reference-manifest.js +1 -1
  113. package/.next/server/app/api/worktrees/[id]/capture/route.js.nft.json +1 -1
  114. package/.next/server/app/api/worktrees/[id]/capture/route_client-reference-manifest.js +1 -1
  115. package/.next/server/app/api/worktrees/[id]/clear-composer/route.js +1 -1
  116. package/.next/server/app/api/worktrees/[id]/clear-composer/route.js.nft.json +1 -1
  117. package/.next/server/app/api/worktrees/[id]/clear-composer/route_client-reference-manifest.js +1 -1
  118. package/.next/server/app/api/worktrees/[id]/cli-reference/route_client-reference-manifest.js +1 -1
  119. package/.next/server/app/api/worktrees/[id]/cli-tool/route_client-reference-manifest.js +1 -1
  120. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route.js +1 -1
  121. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route.js.nft.json +1 -1
  122. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route_client-reference-manifest.js +1 -1
  123. package/.next/server/app/api/worktrees/[id]/current-output/route.js +1 -1
  124. package/.next/server/app/api/worktrees/[id]/current-output/route.js.nft.json +1 -1
  125. package/.next/server/app/api/worktrees/[id]/current-output/route_client-reference-manifest.js +1 -1
  126. package/.next/server/app/api/worktrees/[id]/env/route_client-reference-manifest.js +1 -1
  127. package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route_client-reference-manifest.js +1 -1
  128. package/.next/server/app/api/worktrees/[id]/execution-logs/route.js +4 -3
  129. package/.next/server/app/api/worktrees/[id]/execution-logs/route.js.nft.json +1 -1
  130. package/.next/server/app/api/worktrees/[id]/execution-logs/route_client-reference-manifest.js +1 -1
  131. package/.next/server/app/api/worktrees/[id]/files/[...path]/route_client-reference-manifest.js +1 -1
  132. package/.next/server/app/api/worktrees/[id]/git/branch/create/route_client-reference-manifest.js +1 -1
  133. package/.next/server/app/api/worktrees/[id]/git/branch/delete/route_client-reference-manifest.js +1 -1
  134. package/.next/server/app/api/worktrees/[id]/git/branches/route_client-reference-manifest.js +1 -1
  135. package/.next/server/app/api/worktrees/[id]/git/checkout/route_client-reference-manifest.js +1 -1
  136. package/.next/server/app/api/worktrees/[id]/git/commit/route_client-reference-manifest.js +1 -1
  137. package/.next/server/app/api/worktrees/[id]/git/diff/route_client-reference-manifest.js +1 -1
  138. package/.next/server/app/api/worktrees/[id]/git/fetch/route_client-reference-manifest.js +1 -1
  139. package/.next/server/app/api/worktrees/[id]/git/log/route_client-reference-manifest.js +1 -1
  140. package/.next/server/app/api/worktrees/[id]/git/pull/route_client-reference-manifest.js +1 -1
  141. package/.next/server/app/api/worktrees/[id]/git/push/route_client-reference-manifest.js +1 -1
  142. package/.next/server/app/api/worktrees/[id]/git/reset/route_client-reference-manifest.js +1 -1
  143. package/.next/server/app/api/worktrees/[id]/git/revert/route_client-reference-manifest.js +1 -1
  144. package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route_client-reference-manifest.js +1 -1
  145. package/.next/server/app/api/worktrees/[id]/git/stage/route_client-reference-manifest.js +1 -1
  146. package/.next/server/app/api/worktrees/[id]/git/staged/route_client-reference-manifest.js +1 -1
  147. package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route_client-reference-manifest.js +1 -1
  148. package/.next/server/app/api/worktrees/[id]/git/stash/apply/route_client-reference-manifest.js +1 -1
  149. package/.next/server/app/api/worktrees/[id]/git/stash/pop/route_client-reference-manifest.js +1 -1
  150. package/.next/server/app/api/worktrees/[id]/git/stash/push/route_client-reference-manifest.js +1 -1
  151. package/.next/server/app/api/worktrees/[id]/git/stash/route_client-reference-manifest.js +1 -1
  152. package/.next/server/app/api/worktrees/[id]/git/status/route_client-reference-manifest.js +1 -1
  153. package/.next/server/app/api/worktrees/[id]/git/unstage/route_client-reference-manifest.js +1 -1
  154. package/.next/server/app/api/worktrees/[id]/git/working-diff/route_client-reference-manifest.js +1 -1
  155. package/.next/server/app/api/worktrees/[id]/instances/notes/route_client-reference-manifest.js +1 -1
  156. package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js.nft.json +1 -1
  157. package/.next/server/app/api/worktrees/[id]/instances/opencode/route_client-reference-manifest.js +1 -1
  158. package/.next/server/app/api/worktrees/[id]/interrupt/route.js.nft.json +1 -1
  159. package/.next/server/app/api/worktrees/[id]/interrupt/route_client-reference-manifest.js +1 -1
  160. package/.next/server/app/api/worktrees/[id]/kill-session/route.js.nft.json +1 -1
  161. package/.next/server/app/api/worktrees/[id]/kill-session/route_client-reference-manifest.js +1 -1
  162. package/.next/server/app/api/worktrees/[id]/logs/[filename]/route_client-reference-manifest.js +1 -1
  163. package/.next/server/app/api/worktrees/[id]/logs/route_client-reference-manifest.js +1 -1
  164. package/.next/server/app/api/worktrees/[id]/marp-render/route_client-reference-manifest.js +1 -1
  165. package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route_client-reference-manifest.js +1 -1
  166. package/.next/server/app/api/worktrees/[id]/memos/route_client-reference-manifest.js +1 -1
  167. package/.next/server/app/api/worktrees/[id]/messages/route_client-reference-manifest.js +1 -1
  168. package/.next/server/app/api/worktrees/[id]/opencode/diff/route_client-reference-manifest.js +1 -1
  169. package/.next/server/app/api/worktrees/[id]/opencode/session/route_client-reference-manifest.js +1 -1
  170. package/.next/server/app/api/worktrees/[id]/opencode/share/route_client-reference-manifest.js +1 -1
  171. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js +1 -1
  172. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js.nft.json +1 -1
  173. package/.next/server/app/api/worktrees/[id]/prompt-response/route_client-reference-manifest.js +1 -1
  174. package/.next/server/app/api/worktrees/[id]/resolve-target/route_client-reference-manifest.js +1 -1
  175. package/.next/server/app/api/worktrees/[id]/respond/route.js +1 -1
  176. package/.next/server/app/api/worktrees/[id]/respond/route.js.nft.json +1 -1
  177. package/.next/server/app/api/worktrees/[id]/respond/route_client-reference-manifest.js +1 -1
  178. package/.next/server/app/api/worktrees/[id]/route.js +1 -1
  179. package/.next/server/app/api/worktrees/[id]/route.js.nft.json +1 -1
  180. package/.next/server/app/api/worktrees/[id]/route_client-reference-manifest.js +1 -1
  181. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route.js +1 -6
  182. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route.js.nft.json +1 -1
  183. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route_client-reference-manifest.js +1 -1
  184. package/.next/server/app/api/worktrees/[id]/schedules/active/route.js +1 -1
  185. package/.next/server/app/api/worktrees/[id]/schedules/active/route.js.nft.json +1 -1
  186. package/.next/server/app/api/worktrees/[id]/schedules/active/route_client-reference-manifest.js +1 -1
  187. package/.next/server/app/api/worktrees/[id]/schedules/route.js +2 -7
  188. package/.next/server/app/api/worktrees/[id]/schedules/route.js.nft.json +1 -1
  189. package/.next/server/app/api/worktrees/[id]/schedules/route_client-reference-manifest.js +1 -1
  190. package/.next/server/app/api/worktrees/[id]/search/route_client-reference-manifest.js +1 -1
  191. package/.next/server/app/api/worktrees/[id]/send/route.js +1 -1
  192. package/.next/server/app/api/worktrees/[id]/send/route.js.nft.json +1 -1
  193. package/.next/server/app/api/worktrees/[id]/send/route_client-reference-manifest.js +1 -1
  194. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js.nft.json +1 -1
  195. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route_client-reference-manifest.js +1 -1
  196. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route_client-reference-manifest.js +1 -1
  197. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route_client-reference-manifest.js +1 -1
  198. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route_client-reference-manifest.js +1 -1
  199. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route_client-reference-manifest.js +1 -1
  200. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update/route_client-reference-manifest.js +1 -1
  201. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route_client-reference-manifest.js +1 -1
  202. package/.next/server/app/api/worktrees/[id]/skills/route_client-reference-manifest.js +1 -1
  203. package/.next/server/app/api/worktrees/[id]/slash-commands/route_client-reference-manifest.js +1 -1
  204. package/.next/server/app/api/worktrees/[id]/special-keys/route.js +1 -1
  205. package/.next/server/app/api/worktrees/[id]/special-keys/route.js.nft.json +1 -1
  206. package/.next/server/app/api/worktrees/[id]/special-keys/route_client-reference-manifest.js +1 -1
  207. package/.next/server/app/api/worktrees/[id]/tasks/route_client-reference-manifest.js +1 -1
  208. package/.next/server/app/api/worktrees/[id]/terminal/route.js.nft.json +1 -1
  209. package/.next/server/app/api/worktrees/[id]/terminal/route_client-reference-manifest.js +1 -1
  210. package/.next/server/app/api/worktrees/[id]/timers/history/route_client-reference-manifest.js +1 -1
  211. package/.next/server/app/api/worktrees/[id]/timers/route.js +1 -1
  212. package/.next/server/app/api/worktrees/[id]/timers/route.js.nft.json +1 -1
  213. package/.next/server/app/api/worktrees/[id]/timers/route_client-reference-manifest.js +1 -1
  214. package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
  215. package/.next/server/app/api/worktrees/[id]/todos/route_client-reference-manifest.js +1 -1
  216. package/.next/server/app/api/worktrees/[id]/tree/[...path]/route_client-reference-manifest.js +1 -1
  217. package/.next/server/app/api/worktrees/[id]/tree/route_client-reference-manifest.js +1 -1
  218. package/.next/server/app/api/worktrees/[id]/upload/[...path]/route_client-reference-manifest.js +1 -1
  219. package/.next/server/app/api/worktrees/[id]/verify/config/route_client-reference-manifest.js +1 -1
  220. package/.next/server/app/api/worktrees/[id]/verify/route.js +1 -1
  221. package/.next/server/app/api/worktrees/[id]/verify/route.js.nft.json +1 -1
  222. package/.next/server/app/api/worktrees/[id]/verify/route_client-reference-manifest.js +1 -1
  223. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route.js +1 -1
  224. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route.js.nft.json +1 -1
  225. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route_client-reference-manifest.js +1 -1
  226. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route_client-reference-manifest.js +1 -1
  227. package/.next/server/app/api/worktrees/[id]/verify/runs/route_client-reference-manifest.js +1 -1
  228. package/.next/server/app/api/worktrees/[id]/viewed/route_client-reference-manifest.js +1 -1
  229. package/.next/server/app/api/worktrees/apply-default-agents/route_client-reference-manifest.js +1 -1
  230. package/.next/server/app/api/worktrees/route.js +1 -1
  231. package/.next/server/app/api/worktrees/route.js.nft.json +1 -1
  232. package/.next/server/app/api/worktrees/route_client-reference-manifest.js +1 -1
  233. package/.next/server/app/chat/page_client-reference-manifest.js +1 -1
  234. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  235. package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
  236. package/.next/server/app/more/page_client-reference-manifest.js +1 -1
  237. package/.next/server/app/offline/page_client-reference-manifest.js +1 -1
  238. package/.next/server/app/page_client-reference-manifest.js +1 -1
  239. package/.next/server/app/proxy/[...path]/route_client-reference-manifest.js +1 -1
  240. package/.next/server/app/repositories/page_client-reference-manifest.js +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_client-reference-manifest.js +1 -1
  244. package/.next/server/app/skills/[skillId]/page_client-reference-manifest.js +1 -1
  245. package/.next/server/app/skills/installed/page_client-reference-manifest.js +1 -1
  246. package/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  247. package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -1
  248. package/.next/server/app/worktrees/[id]/page.js +11 -9
  249. package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -1
  250. package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
  251. package/.next/server/app-paths-manifest.json +33 -33
  252. package/.next/server/chunks/1467.js +1 -1
  253. package/.next/server/chunks/1707.js +1 -1
  254. package/.next/server/chunks/1886.js +2 -2
  255. package/.next/server/chunks/2119.js +1 -1
  256. package/.next/server/chunks/2445.js +1 -1
  257. package/.next/server/chunks/3480.js +1 -18
  258. package/.next/server/chunks/3730.js +1 -1
  259. package/.next/server/chunks/4207.js +5 -0
  260. package/.next/server/chunks/4443.js +1 -1
  261. package/.next/server/chunks/5164.js +1 -1
  262. package/.next/server/chunks/6130.js +1 -1
  263. package/.next/server/chunks/650.js +1 -1
  264. package/.next/server/chunks/6661.js +1 -1
  265. package/.next/server/chunks/6677.js +2 -2
  266. package/.next/server/chunks/6793.js +13 -0
  267. package/.next/server/chunks/7075.js +1 -1
  268. package/.next/server/chunks/8052.js +74 -0
  269. package/.next/server/chunks/8728.js +2 -2
  270. package/.next/server/chunks/9080.js +1 -1
  271. package/.next/server/middleware-manifest.json +5 -5
  272. package/.next/server/pages/500.html +1 -1
  273. package/.next/server/server-reference-manifest.json +1 -1
  274. package/.next/static/chunks/{2407-c4b1d2aae7e3f59b.js → 2407-be448eda70bc19b6.js} +1 -1
  275. package/.next/static/chunks/4388-a778968d9c4e9327.js +1 -0
  276. package/.next/static/chunks/4949-fa93029d6e05db0d.js +1 -0
  277. package/.next/static/chunks/998-292ebcd30f329eb1.js +1 -0
  278. package/.next/static/chunks/app/sessions/page-fe42c8f6fd59b9e7.js +1 -0
  279. package/.next/static/chunks/app/worktrees/[id]/page-1eb4297af22afac8.js +1 -0
  280. package/.next/static/css/ed092b853e52b5eb.css +1 -0
  281. package/.next/trace +14 -14
  282. package/dist/cli/commands/ls.d.ts +64 -0
  283. package/dist/cli/commands/ls.d.ts.map +1 -1
  284. package/dist/cli/commands/ls.js +238 -30
  285. package/dist/cli/commands/respond.d.ts.map +1 -1
  286. package/dist/cli/commands/respond.js +14 -0
  287. package/dist/cli/commands/status.d.ts.map +1 -1
  288. package/dist/cli/commands/status.js +154 -15
  289. package/dist/cli/docs/agent-operations.d.ts +1 -1
  290. package/dist/cli/docs/agent-operations.d.ts.map +1 -1
  291. package/dist/cli/docs/agent-operations.js +37 -1
  292. package/dist/cli/types/api-responses.d.ts.map +1 -1
  293. package/dist/cli/utils/server-url.d.ts +27 -0
  294. package/dist/cli/utils/server-url.d.ts.map +1 -1
  295. package/dist/cli/utils/server-url.js +48 -6
  296. package/dist/lib/cli-tools/types.d.ts +22 -1
  297. package/dist/lib/cli-tools/types.d.ts.map +1 -1
  298. package/dist/lib/detection/tools/verified-against.d.ts +8 -0
  299. package/dist/lib/detection/tools/verified-against.d.ts.map +1 -1
  300. package/dist/lib/detection/tools/verified-against.js +8 -0
  301. package/dist/server/locales/en/worktree.json +23 -1
  302. package/dist/server/locales/ja/worktree.json +23 -1
  303. package/dist/server/src/lib/cli-tools/agent-mode-spec.js +327 -0
  304. package/dist/server/src/lib/cli-tools/base.js +22 -0
  305. package/dist/server/src/lib/cmate-parser.js +26 -6
  306. package/dist/server/src/lib/cmate-validator.js +354 -0
  307. package/dist/server/src/lib/detection/cli-patterns.js +40 -2
  308. package/dist/server/src/lib/detection/model-info-extractor.js +40 -3
  309. package/dist/server/src/lib/detection/prompt-detect-multiple-choice.js +44 -0
  310. package/dist/server/src/lib/detection/tools/antigravity/detect.js +9 -0
  311. package/dist/server/src/lib/detection/tools/command-code/detect.js +14 -3
  312. package/dist/server/src/lib/detection/tools/command-code/permission.js +104 -0
  313. package/dist/server/src/lib/detection/tools/verified-against.js +8 -0
  314. package/dist/server/src/lib/polling/auto-yes-dialog-gate.js +20 -2
  315. package/dist/server/src/lib/prompt-answer-sender.js +339 -16
  316. package/dist/server/src/lib/session/claude-executor.js +190 -17
  317. package/dist/server/src/types/cli-tool-contracts.js +75 -1
  318. package/dist/types/cli-tool-contracts.d.ts +162 -0
  319. package/dist/types/cli-tool-contracts.d.ts.map +1 -1
  320. package/dist/types/cli-tool-contracts.js +75 -1
  321. package/package.json +1 -1
  322. package/.next/server/chunks/6337.js +0 -1
  323. package/.next/server/chunks/663.js +0 -79
  324. package/.next/static/chunks/4388-410b1d8ed0d8d98b.js +0 -1
  325. package/.next/static/chunks/4949-5b97d1eb769482d2.js +0 -1
  326. package/.next/static/chunks/998-ac0ded6d5eeb4dc0.js +0 -1
  327. package/.next/static/chunks/app/sessions/page-b8651c3f17c36800.js +0 -1
  328. package/.next/static/chunks/app/worktrees/[id]/page-f993ca88fe758599.js +0 -1
  329. package/.next/static/css/c511ecdf1e7f18a0.css +0 -1
  330. /package/.next/static/{0WNCXbrakAsDUEgDarN8N → DryXJ1-iHfWxfrHkkWVy8}/_buildManifest.js +0 -0
  331. /package/.next/static/{0WNCXbrakAsDUEgDarN8N → DryXJ1-iHfWxfrHkkWVy8}/_ssgManifest.js +0 -0
@@ -3,6 +3,70 @@
3
3
  * Issue #518: [DR1-08] Factory pattern with createLsCommand()
4
4
  */
5
5
  import { Command } from 'commander';
6
+ import type { WorktreeItem } from '../types/api-responses';
7
+ /** One entry of the per-CLI-tool status map the list API publishes. */
8
+ export type CliStatusEntry = NonNullable<WorktreeItem['sessionStatusByCli']>[string];
9
+ /**
10
+ * One instance's Auto-Yes arming, as `GET /api/worktrees` sends it (Issue #2512).
11
+ *
12
+ * Mirrors: src/types/auto-yes.ts AutoYesInstanceSummary.
13
+ *
14
+ * A copy rather than an import: `tsconfig.cli.json` sets `"paths": {}`, so
15
+ * nothing under `src/cli` can reach `@/types/auto-yes`. The copy is kept honest
16
+ * by a bidirectional `AssertAssignable` in
17
+ * `tests/unit/cli/commands/ls-auto-yes-2575.test.ts`, which `npx tsc --noEmit`
18
+ * evaluates — the same guard #1843 uses for the suppression-reason union.
19
+ *
20
+ * Only ARMED instances appear in the map: the server folds expired and
21
+ * turned-off states away as it reads them (`getEnabledAutoYesByWorktree`), so a
22
+ * missing key means "not armed right now" and carries no reason. Why it stopped
23
+ * lives in `commandmate capture --json`'s `autoYes.stopReason`.
24
+ */
25
+ export type AutoYesInstanceWire = {
26
+ enabled: boolean;
27
+ expiresAt: number | null;
28
+ };
29
+ /**
30
+ * A list row with the two maps this command reads and `WorktreeItem` does not
31
+ * declare (Issue #2575).
32
+ *
33
+ * `src/cli/types/api-responses.ts` declares only the fields the CLI reads, and
34
+ * until this column nothing read either of these. Widened HERE rather than
35
+ * there, on the precedent of `PeerWorktreeItem` in `peers.ts`: the shared mirror
36
+ * keeps meaning what its header says, and a row from a server that predates
37
+ * #2512 (no `autoYesByInstance`) or answered `?includeStatus=0` (no
38
+ * `sessionStatusByInstance`) is still a valid row — hence both optional.
39
+ *
40
+ * `sessionStatusByInstance` is the UN-aggregated map. `sessionStatusByCli` next
41
+ * to it is the logical-OR over every instance of a tool, which is the right
42
+ * input for REASON (#1926) and the wrong one here: Auto-Yes is armed per
43
+ * INSTANCE, so an aggregate cannot say whether it was `claude` or `claude-2`
44
+ * that raised the wait.
45
+ *
46
+ * Exported so tests can assert against the wire shape rather than restate it.
47
+ */
48
+ export interface LsWorktreeItem extends WorktreeItem {
49
+ autoYesByInstance?: Record<string, AutoYesInstanceWire>;
50
+ sessionStatusByInstance?: Partial<Record<string, CliStatusEntry>>;
51
+ }
52
+ /**
53
+ * `MM:SS`, or `H:MM:SS` from an hour up — the Web UI countdown's format.
54
+ *
55
+ * A second spelling of `formatTimeRemaining` (`src/config/auto-yes-config.ts`)
56
+ * on purpose, and the only duplication Issue #2575 accepts. That module imports
57
+ * `@/config/tmux-pane-config`, and `tsconfig.cli.json` sets `"paths": {}`, so a
58
+ * CLI module importing it compiles under lint / `tsc --noEmit` / vitest (all
59
+ * three resolve `@/`) and breaks only at `npm run build:cli` — a trap worth
60
+ * avoiding rather than walking into. The two are pinned to the same strings at
61
+ * the boundaries by `ls-auto-yes-2575.test.ts`, so an operator reads the same
62
+ * number in the browser and in the terminal.
63
+ *
64
+ * Takes a DURATION, not a deadline: the caller has already resolved `now` once
65
+ * for the whole table, and passing the deadline here would re-read the clock per
66
+ * row. Truncating means 0 < remaining < 1 s prints `00:00`, exactly as the
67
+ * browser countdown does one tick before it flips to OFF.
68
+ */
69
+ export declare function formatAutoYesRemaining(remainingMs: number): string;
6
70
  /**
7
71
  * Create the ls command.
8
72
  * [DR1-08] Factory pattern for addCommand() registration.
@@ -1 +1 @@
1
- {"version":3,"file":"ls.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/ls.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA6LpC;;;GAGG;AACH,wBAAgB,eAAe,IAAI,OAAO,CA8CzC"}
1
+ {"version":3,"file":"ls.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/ls.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,KAAK,EAAwB,YAAY,EAAE,MAAM,wBAAwB,CAAC;AA0BjF,uEAAuE;AACvE,MAAM,MAAM,cAAc,GAAG,WAAW,CAAC,YAAY,CAAC,oBAAoB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AAErF;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAEjF;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,cAAe,SAAQ,YAAY;IAClD,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IACxD,uBAAuB,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC;CACnE;AAoFD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAUlE;AAoOD;;;GAGG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAkFzC"}
@@ -4,6 +4,7 @@
4
4
  * Issue #518: [DR1-08] Factory pattern with createLsCommand()
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.formatAutoYesRemaining = formatAutoYesRemaining;
7
8
  exports.createLsCommand = createLsCommand;
8
9
  const commander_1 = require("commander");
9
10
  const api_client_1 = require("../utils/api-client");
@@ -31,6 +32,32 @@ function deriveStatus(wt) {
31
32
  return 'ready';
32
33
  return 'idle';
33
34
  }
35
+ /**
36
+ * Whether this status entry is one of the sessions that produced `status`.
37
+ *
38
+ * `deriveStatus` folds every session of the worktree into one word, so any cell
39
+ * that claims to be ABOUT that word has to be sourced from a session that
40
+ * produced it. Two columns need the predicate and must not drift apart: REASON
41
+ * (#1926) applies it per tool, AUTO_YES (#2575) applies it per instance.
42
+ *
43
+ * `idle` is explained by exactly one thing (Issue #2070): `exited`, the tmux
44
+ * session still there with no agent in it. Everything else idle is unexplained
45
+ * — no entry matches, REASON stays `-`, and AUTO_YES falls back to every armed
46
+ * instance.
47
+ */
48
+ function explainsStatus(entry, status) {
49
+ if (!entry)
50
+ return false;
51
+ if (status === 'waiting')
52
+ return entry.isWaitingForResponse;
53
+ if (status === 'running')
54
+ return entry.isProcessing;
55
+ if (status === 'ready')
56
+ return entry.isRunning;
57
+ if (status === 'idle')
58
+ return entry.sessionStatusReason === status_reason_1.STATUS_REASON.EXITED;
59
+ return false;
60
+ }
34
61
  /**
35
62
  * The per-tool status entry that explains this row's STATUS (Issue #1926).
36
63
  *
@@ -48,28 +75,10 @@ function pickStatusEntry(wt, status) {
48
75
  const byCli = wt.sessionStatusByCli;
49
76
  if (!byCli)
50
77
  return undefined;
51
- const explains = (entry) => {
52
- if (!entry)
53
- return false;
54
- if (status === 'waiting')
55
- return entry.isWaitingForResponse;
56
- if (status === 'running')
57
- return entry.isProcessing;
58
- if (status === 'ready')
59
- return entry.isRunning;
60
- // Issue #2070: `idle` gets an explanation for the first time, and only for
61
- // the one reason a stopped session can carry — `exited`. Everything else
62
- // about an idle row is unchanged: no entry is picked, so the REASON cell is
63
- // still `-`. That is what makes this additive rather than a fourth branch of
64
- // `deriveStatus` (DR3-005 keeps the STATUS vocabulary at four words).
65
- if (status === 'idle')
66
- return entry.sessionStatusReason === status_reason_1.STATUS_REASON.EXITED;
67
- return false;
68
- };
69
78
  const preferred = wt.cliToolId ? byCli[wt.cliToolId] : undefined;
70
- if (explains(preferred))
79
+ if (explainsStatus(preferred, status))
71
80
  return preferred;
72
- return Object.values(byCli).find(explains);
81
+ return Object.values(byCli).find((entry) => explainsStatus(entry, status));
73
82
  }
74
83
  /**
75
84
  * The REASON cell: why the STATUS beside it says what it says (Issue #1926).
@@ -100,25 +109,180 @@ function deriveReason(wt) {
100
109
  return '-';
101
110
  return entry?.statusEvidence === 'none' ? `${reason} (no evidence)` : reason;
102
111
  }
112
+ const MS_PER_SECOND = 1000;
113
+ const MS_PER_MINUTE = 60_000;
114
+ const MS_PER_HOUR = 3_600_000;
115
+ /**
116
+ * `MM:SS`, or `H:MM:SS` from an hour up — the Web UI countdown's format.
117
+ *
118
+ * A second spelling of `formatTimeRemaining` (`src/config/auto-yes-config.ts`)
119
+ * on purpose, and the only duplication Issue #2575 accepts. That module imports
120
+ * `@/config/tmux-pane-config`, and `tsconfig.cli.json` sets `"paths": {}`, so a
121
+ * CLI module importing it compiles under lint / `tsc --noEmit` / vitest (all
122
+ * three resolve `@/`) and breaks only at `npm run build:cli` — a trap worth
123
+ * avoiding rather than walking into. The two are pinned to the same strings at
124
+ * the boundaries by `ls-auto-yes-2575.test.ts`, so an operator reads the same
125
+ * number in the browser and in the terminal.
126
+ *
127
+ * Takes a DURATION, not a deadline: the caller has already resolved `now` once
128
+ * for the whole table, and passing the deadline here would re-read the clock per
129
+ * row. Truncating means 0 < remaining < 1 s prints `00:00`, exactly as the
130
+ * browser countdown does one tick before it flips to OFF.
131
+ */
132
+ function formatAutoYesRemaining(remainingMs) {
133
+ const remaining = Math.max(0, remainingMs);
134
+ const hours = Math.floor(remaining / MS_PER_HOUR);
135
+ const minutes = Math.floor((remaining % MS_PER_HOUR) / MS_PER_MINUTE);
136
+ const seconds = Math.floor((remaining % MS_PER_MINUTE) / MS_PER_SECOND);
137
+ if (hours > 0) {
138
+ return `${hours}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
139
+ }
140
+ return `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
141
+ }
142
+ /**
143
+ * Milliseconds of Auto-Yes left on one instance: 0 when it is not armed,
144
+ * Infinity when it is armed with no deadline.
145
+ *
146
+ * Everything that is not positively armed collapses to 0 — no key, `enabled`
147
+ * anything but true, or a deadline already past. A past `expiresAt` reaches us
148
+ * even though the server folds expired states away as it reads them: these are
149
+ * two machines' clocks, and #959's `displayEnabled = enabled && !hasExpired`
150
+ * falls the same way. The direction is the whole point — this cell may under-
151
+ * report arming, never over-report it, because over-reporting hides a prompt
152
+ * that only a human can clear.
153
+ *
154
+ * Infinity is not a shape the current server produces (`AutoYesState.expiresAt`
155
+ * is a number), but an explicit `null` beside `enabled: true` is the server
156
+ * saying armed-with-no-deadline, which is a fact, and the Sessions tile reads
157
+ * the same input as ON. Infinity also makes it lose every `min` against a real
158
+ * deadline, which is what "unknown expiry" should do.
159
+ *
160
+ * `null` EXACTLY, not "anything that is not a number": a row missing the key
161
+ * altogether is malformed rather than eternal, and the rule above decides which
162
+ * way malformed falls — towards `off`.
163
+ */
164
+ function remainingAutoYesMs(entry, now) {
165
+ if (!entry || entry.enabled !== true)
166
+ return 0;
167
+ if (entry.expiresAt === null)
168
+ return Number.POSITIVE_INFINITY;
169
+ if (typeof entry.expiresAt !== 'number')
170
+ return 0;
171
+ return entry.expiresAt > now ? entry.expiresAt - now : 0;
172
+ }
173
+ /**
174
+ * The AUTO_YES cell: how long before this row loses Auto-Yes (Issue #2575).
175
+ *
176
+ * In one sentence: the remaining time of the instance that will lose Auto-Yes
177
+ * FIRST, among the instances that explain this row's STATUS. One already without
178
+ * it makes the cell `off`.
179
+ *
180
+ * The minimum, rather than the longest or a list, is what closes the gap this
181
+ * Issue is about. On a row where `claude` is waiting unarmed and `codex` is
182
+ * waiting with ten minutes left, printing `10:00` buries a prompt nobody will
183
+ * answer under a countdown that has nothing to do with it; the minimum prints
184
+ * `off`. The cost is accepted and stated in `--help`: one unarmed instance
185
+ * sharing a `ready` row hides the armed one's countdown, which `ls --json` still
186
+ * has in full.
187
+ *
188
+ * `-` means "not known", and is deliberately not `off`:
189
+ * - no `autoYesByInstance` at all — a server older than #2512;
190
+ * - a non-idle row no instance explains. Impossible against the current
191
+ * server, whose row-level flags are the OR of the per-instance ones. It is a
192
+ * guard for the day that stops being true: falling back to "every armed
193
+ * instance" on a `waiting` row would print a countdown beside a prompt no
194
+ * instance is actually going to answer.
195
+ *
196
+ * The fallback to every armed instance is therefore `idle`-only, where nothing
197
+ * is running and there is no session whose wait could be misrepresented. An idle
198
+ * row with an `exited` instance is explained (#2070), so the fallback does not
199
+ * fire there.
200
+ *
201
+ * `status` and `now` are arguments rather than re-derived: `now` is read once
202
+ * per table so two rows cannot disagree about the time, and a test can freeze it.
203
+ */
204
+ function deriveAutoYesCell(wt, status, now) {
205
+ const armedByInstance = wt.autoYesByInstance;
206
+ if (!armedByInstance)
207
+ return '-';
208
+ const byInstance = wt.sessionStatusByInstance ?? {};
209
+ let targets = Object.keys(byInstance).filter(id => explainsStatus(byInstance[id], status));
210
+ if (targets.length === 0) {
211
+ if (status !== 'idle')
212
+ return '-';
213
+ targets = Object.keys(armedByInstance);
214
+ if (targets.length === 0)
215
+ return 'off';
216
+ }
217
+ // Deterministic order first, so the cell never depends on the key order the
218
+ // server happened to serialise: the worktree default's primary, then
219
+ // lexicographic. The first strict minimum in that order wins, which is what
220
+ // makes an equal-remaining tie resolve to the default (printed bare) rather
221
+ // than to whichever instance the JSON listed first.
222
+ const ordered = [...targets].sort((a, b) => {
223
+ if (a === wt.cliToolId)
224
+ return -1;
225
+ if (b === wt.cliToolId)
226
+ return 1;
227
+ return a < b ? -1 : 1;
228
+ });
229
+ let pick = ordered[0];
230
+ let remaining = remainingAutoYesMs(armedByInstance[pick], now);
231
+ for (const id of ordered.slice(1)) {
232
+ const candidate = remainingAutoYesMs(armedByInstance[id], now);
233
+ if (candidate < remaining) {
234
+ pick = id;
235
+ remaining = candidate;
236
+ }
237
+ }
238
+ const value = remaining === 0
239
+ ? 'off'
240
+ : remaining === Number.POSITIVE_INFINITY
241
+ ? 'on'
242
+ : formatAutoYesRemaining(remaining);
243
+ // The instance is named whenever it is not the default agent's primary — the
244
+ // row where a second agent raised the wait is exactly the row where REASON
245
+ // cannot say so (it is a per-tool aggregate and loses the reason for a tool
246
+ // with two instances), so this parenthesis is sometimes the only thing on the
247
+ // line that identifies the session. It is an `--instance` value verbatim.
248
+ return pick === wt.cliToolId ? value : `${value} (${pick})`;
249
+ }
103
250
  /**
104
251
  * Format worktrees as a table for terminal display.
105
252
  */
106
253
  function formatTable(worktrees) {
107
254
  if (worktrees.length === 0)
108
255
  return 'No worktrees found.';
109
- const headers = ['ID', 'NAME', 'STATUS', 'REASON', 'DEFAULT'];
110
- const rows = worktrees.map(wt => [
111
- wt.id,
112
- wt.name,
113
- deriveStatus(wt),
114
- deriveReason(wt),
115
- wt.cliToolId || '-',
116
- ]);
256
+ // Once per table, not once per row: two rows must not disagree about what
257
+ // "now" is, and a frozen clock in a test must produce one reading.
258
+ const now = Date.now();
259
+ // Issue #2575 APPENDS. The first five columns keep their order and their
260
+ // starting offsets, because operators (and the orchestrate recipes) read this
261
+ // table positionally — the same rule #1785 / #2038 / #2317 held for
262
+ // `commandmate instances`.
263
+ const headers = ['ID', 'NAME', 'STATUS', 'REASON', 'DEFAULT', 'AUTO_YES'];
264
+ const rows = worktrees.map(wt => {
265
+ const status = deriveStatus(wt);
266
+ return [
267
+ wt.id,
268
+ wt.name,
269
+ status,
270
+ deriveReason(wt),
271
+ wt.cliToolId || '-',
272
+ deriveAutoYesCell(wt, status, now),
273
+ ];
274
+ });
117
275
  // Calculate column widths
118
276
  const colWidths = headers.map((h, i) => Math.max(h.length, ...rows.map(r => r[i].length)));
119
- const headerLine = headers.map((h, i) => h.padEnd(colWidths[i])).join(' ');
277
+ // The LAST column is not padded. An instance id runs to 64 characters, so one
278
+ // row carrying `off (some-very-long-instance-id)` would otherwise pad every
279
+ // other row out to that width and wrap the whole table on a narrow terminal.
280
+ // Before #2575 the last column was DEFAULT and every line did end in padding.
281
+ const lastCol = headers.length - 1;
282
+ const pad = (cell, i) => (i === lastCol ? cell : cell.padEnd(colWidths[i]));
283
+ const headerLine = headers.map(pad).join(' ');
120
284
  const separator = colWidths.map(w => '-'.repeat(w)).join(' ');
121
- const dataLines = rows.map(r => r.map((cell, i) => cell.padEnd(colWidths[i])).join(' '));
285
+ const dataLines = rows.map(r => r.map(pad).join(' '));
122
286
  return [headerLine, separator, ...dataLines].join('\n');
123
287
  }
124
288
  /**
@@ -165,6 +329,14 @@ function deriveTmuxSession(wt) {
165
329
  * `WorktreeItem`, would need the same tool-picking rule the REASON column
166
330
  * applies for display, and would make `ls --json` disagree with
167
331
  * `GET /api/worktrees` — three costs for a shorter jq path.
332
+ *
333
+ * Issue #2575 adds a table column and nothing here, for the same reason plus
334
+ * one: the derived cell would be the LEAST accurate answer a machine can get.
335
+ * `autoYesByInstance` and `sessionStatusByInstance` are already in these rows
336
+ * verbatim, and a caller that needs "will anything answer this prompt" wants
337
+ * `commandmate wait`'s exit 10 or `capture --json`'s `autoYes`, both of which
338
+ * know about answers the contract policy withheld. The cell is a summary for a
339
+ * human reading a table.
168
340
  */
169
341
  function formatOutput(worktrees, options) {
170
342
  if (options.json) {
@@ -195,6 +367,42 @@ function createLsCommand() {
195
367
  .option('--branch <prefix>', 'Filter by branch name prefix')
196
368
  .option('--id <prefix>', 'Filter by worktree id prefix')
197
369
  .option('--token <token>', command_helpers_1.TOKEN_WARNING)
370
+ // Issue #2575: AUTO_YES is a derived cell with rules an operator can be
371
+ // surprised by (a `ready` row can read `off` while an instance is armed),
372
+ // and docs/** is outside this change's scope — so until the guides catch up,
373
+ // this is the only place a shipped build explains the column. Same reason
374
+ // `wait --help` carries the unclassified dwell (#1926).
375
+ .addHelpText('after', `
376
+ AUTO_YES column (Issue #2575):
377
+ How much Auto-Yes is left on the instance that will lose it FIRST, among the
378
+ instances that explain this row's STATUS (waiting: the ones waiting; running:
379
+ the ones processing; ready: the ones running; idle: the ones that exited. A
380
+ bare idle row falls back to every armed instance).
381
+
382
+ MM:SS time left, under an hour
383
+ H:MM:SS time left, an hour or more
384
+ on armed, with no expiry the server named
385
+ off at least one of those instances is NOT armed, so a prompt on this
386
+ row waits for a human. This is the cell to look for
387
+ - not known: the server predates the field, or this row is not idle
388
+ and no instance explains its STATUS
389
+
390
+ A time left is a fact about Auto-Yes, not a promise that the prompt gets
391
+ answered: a contract policy can withhold the answer, and a free-text prompt
392
+ has none to give. \`commandmate capture <id> --json --instance <instanceId>\`
393
+ carries autoYes.lastSuppression (what was withheld) and autoYes.stopReason
394
+ (why it stopped); \`commandmate wait <id>\` returns exit 10 for a prompt no
395
+ agent is going to clear.
396
+
397
+ The id in parentheses is the instance the cell is about, printed when that is
398
+ not the default agent's primary. Pass it to capture / send / respond as
399
+ --instance verbatim. It names an instance for THIS column only: REASON is
400
+ chosen per tool with the worktree default preferred (Issue #1926), so the two
401
+ cells on one row can be about different sessions.
402
+
403
+ Nothing here is derived in --json: it carries sessionStatusByInstance and
404
+ autoYesByInstance raw, which is where the per-instance breakdown is.
405
+ `)
198
406
  .action(async (options) => {
199
407
  try {
200
408
  const client = new api_client_1.ApiClient({ token: options.token });
@@ -1 +1 @@
1
- {"version":3,"file":"respond.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/respond.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA2JpC,wBAAgB,oBAAoB,IAAI,OAAO,CA4K9C"}
1
+ {"version":3,"file":"respond.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/respond.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA2JpC,wBAAgB,oBAAoB,IAAI,OAAO,CA4L9C"}
@@ -226,6 +226,20 @@ function createRespondCommand() {
226
226
  }
227
227
  if (refusedBeforeSending) {
228
228
  console.error(`Error: Answer was not sent. Reason: ${reason}${result.message ? ` (${result.message})` : ''}`);
229
+ // Issue #2583: the operator who lands here typed WORDS at a dialog
230
+ // that only takes a choice — a claude / agy Bash approval refused as
231
+ // free text, or #2573's "No, tell … what to do differently" row. The
232
+ // server's sentence ends with "answer with the option number", and
233
+ // this is that command with the ids already filled in, so the next
234
+ // step is a paste rather than a trip to the docs while a dialog sits
235
+ // open. Printed only for the reason that means "this answer could not
236
+ // be mapped onto a choice", and only when the answer was not already
237
+ // a number (where the number itself is what was wrong).
238
+ if (reason === 'unresolvable_answer' && answer !== undefined && !/^\d+$/.test(answer.trim())) {
239
+ const target = options.instance ? ` --instance ${options.instance}` : '';
240
+ console.error(`Hint: answer with the option number — \`commandmate respond ${worktreeId} <number>${target}\` ` +
241
+ `(\`commandmate capture ${worktreeId}${target}\` prints the dialog and its numbers).`);
242
+ }
229
243
  }
230
244
  else {
231
245
  console.error(`Warning: Response may not have been applied. Reason: ${reason}`);
@@ -1 +1 @@
1
- {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/status.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAA2C,aAAa,EAAE,MAAM,UAAU,CAAC;AA0PlF;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiG9E"}
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/status.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAA2C,aAAa,EAAE,MAAM,UAAU,CAAC;AAwZlF;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkG9E"}
@@ -13,6 +13,7 @@ const types_1 = require("../types");
13
13
  const logger_1 = require("../utils/logger");
14
14
  const daemon_1 = require("../utils/daemon");
15
15
  const env_setup_1 = require("../utils/env-setup");
16
+ const server_url_1 = require("../utils/server-url");
16
17
  const package_info_1 = require("../utils/package-info");
17
18
  const input_validators_1 = require("../utils/input-validators");
18
19
  const version_probes_1 = require("../../lib/detection/version-probes");
@@ -90,33 +91,166 @@ function printLocalhostConflict(status) {
90
91
  // Config dir unreadable, record unparsable: report the server, drop the hint.
91
92
  }
92
93
  }
94
+ /** `src/app/api/push/vapid/route.ts` — public key + a `configured` flag, no secrets. */
95
+ const VAPID_PROBE_PATH = '/api/push/vapid';
96
+ /**
97
+ * Budget for the probe below. A loopback round trip to a healthy server is ~2ms;
98
+ * anything near this bound is a server that cannot answer, and an unanswered
99
+ * probe costs nothing but the fallback.
100
+ */
101
+ const VAPID_PROBE_TIMEOUT_MS = 1000;
102
+ /**
103
+ * Ask the running server whether it actually holds a VAPID key pair (Issue #2585).
104
+ *
105
+ * The daemon is the only process that can answer: it was handed its environment at
106
+ * launch and has held it ever since, while every reader in this CLI is reconstructing
107
+ * that environment from the outside. `GET /api/push/vapid` already exists for the web
108
+ * client and returns `{configured, publicKey}` — the public key only, so this adds no
109
+ * exposure that the browser did not already have.
110
+ *
111
+ * @returns The server's verdict, or `null` when it did not give one — unreachable,
112
+ * unauthenticated, answered by something that is not this server (#2113), or not
113
+ * JSON. Every one of those is "I do not know", never "not configured": inventing a
114
+ * warning out of a failed probe is how a diagnostic starts lying.
115
+ */
116
+ async function probeServerVapid(baseUrl) {
117
+ const controller = new AbortController();
118
+ const timer = setTimeout(() => controller.abort(), VAPID_PROBE_TIMEOUT_MS);
119
+ try {
120
+ // The one `process.env` read this path keeps, and deliberately: a token is a fact
121
+ // about THIS invocation (the caller's credential), not about the daemon's
122
+ // configuration. Without it an authenticated server answers 302 to /login, which
123
+ // `redirect: 'manual'` keeps visible instead of following it to an HTML 200.
124
+ const token = process.env.CM_AUTH_TOKEN;
125
+ const response = await fetch(`${baseUrl}${VAPID_PROBE_PATH}`, {
126
+ method: 'GET',
127
+ headers: {
128
+ Accept: 'application/json',
129
+ ...(token ? { Authorization: `Bearer ${token}` } : {}),
130
+ },
131
+ redirect: 'manual',
132
+ signal: controller.signal,
133
+ });
134
+ if (!response.ok)
135
+ return null;
136
+ const payload = await response.json();
137
+ const configured = payload?.configured;
138
+ return typeof configured === 'boolean' ? configured : null;
139
+ }
140
+ catch {
141
+ return null;
142
+ }
143
+ finally {
144
+ clearTimeout(timer);
145
+ }
146
+ }
147
+ /**
148
+ * Fold the server's answer into the verdict read off its `.env` (Issue #2585).
149
+ *
150
+ * They disagree in exactly two ways, and both are real situations rather than
151
+ * defensive padding:
152
+ *
153
+ * - **Server has keys, `.env` names none.** They were exported into the daemon at
154
+ * launch. Unsupported (`commandmate init` writes the file), but real, and warning
155
+ * about push being off on a server that is demonstrably sending it would be wrong.
156
+ * - **Server has none, `.env` names both.** The file was edited after the daemon
157
+ * started. The warning stands — the running server still cannot send — and
158
+ * {@link explainVapidMismatch} adds the sentence that makes it actionable.
159
+ *
160
+ * The subject (#2124) is never reconciled, because the endpoint does not report it:
161
+ * it stays whatever the `.env` says, which is the only VAPID value a running server
162
+ * cannot be asked about.
163
+ */
164
+ function reconcileVapid(fileVerdict, serverConfigured) {
165
+ if (serverConfigured === null || serverConfigured === fileVerdict.configured) {
166
+ return fileVerdict;
167
+ }
168
+ if (serverConfigured) {
169
+ return {
170
+ ...fileVerdict,
171
+ configured: true,
172
+ status: fileVerdict.subjectIssue === null ? 'ok' : 'invalid-subject',
173
+ };
174
+ }
175
+ return { ...fileVerdict, configured: false, status: 'unconfigured' };
176
+ }
177
+ /**
178
+ * The sentence that closes the gap between "push is off" and "but I set those keys!"
179
+ * (Issue #2585) — appended to the shared lines, never replacing them.
180
+ *
181
+ * Both branches exist because both were measured: #2575 spent an investigation on a
182
+ * shell that exported the pair for a server that never had it, and a `.env` edited
183
+ * under a running daemon is the same confusion with the file in the shell's place.
184
+ *
185
+ * @returns Extra lines, or nothing at all when the report needs no qualifier.
186
+ */
187
+ function explainVapidMismatch(verdict, fileVerdict, serverConfigured, envPath) {
188
+ // Push works. Nothing is being reported, so there is nothing to qualify.
189
+ if (verdict.configured)
190
+ return [];
191
+ if (serverConfigured === false && fileVerdict.configured) {
192
+ return [
193
+ ` ${envPath} does set both keys, so the running server predates that edit:`,
194
+ ' restart it ("commandmate stop && commandmate start") to pick them up.',
195
+ ];
196
+ }
197
+ // Names only, never values — the same rule the shared lines follow.
198
+ const shellOnly = fileVerdict.missingKeys.filter((key) => (process.env[key] ?? '').trim() !== '');
199
+ if (shellOnly.length === 0)
200
+ return [];
201
+ const pronoun = shellOnly.length > 1 ? 'them' : 'it';
202
+ return [
203
+ ` This shell exports ${shellOnly.join(' and ')}, but the server was not started`,
204
+ ` with ${pronoun}: set ${pronoun} in ${envPath} and restart the server.`,
205
+ ];
206
+ }
93
207
  /**
94
208
  * Report the server's Web Push configuration, or nothing when it is healthy
95
- * (Issues #2123 / #2124).
209
+ * (Issues #2123 / #2124 / #2585).
96
210
  *
97
211
  * The Issues' acceptance condition is "the startup log OR `commandmate status`",
98
212
  * and this is the half that is still readable a week later — a daemon started in
99
213
  * the background writes its stdout wherever the launcher put it, and the reader
100
214
  * who notices "my phone stopped buzzing" reaches for `status`.
101
215
  *
102
- * Read from the env the DAEMON runs with (`getEffectiveEnv()`), not from this
103
- * process's own environment: `.env` outranks exported variables for the server
104
- * child (Issue #1266), so `process.env` here would report this shell's idea of
105
- * the configuration rather than the server's. Exactly what the `CM_ALLOWED_IPS`
106
- * line below already does.
216
+ * ## Who is asked, in order
217
+ *
218
+ * 1. **The running server**, over `GET /api/push/vapid`. It is the only party
219
+ * that knows what it was launched with, and #2585 is the proof that everything
220
+ * else is inference.
221
+ * 2. **Its `.env` files alone** ({@link loadEnvFileValues}) — for the subject,
222
+ * which the endpoint does not report, and for the whole verdict when the probe
223
+ * comes back `null`.
224
+ *
225
+ * `process.env` is NOT a layer under either, which is the fix. This used to read
226
+ * `getEffectiveEnv()`, whose `{...process.env, ...parsed}` reproduces what
227
+ * `daemon.start()` hands the child — exact for a key the `.env` defines, a guess
228
+ * for one it does not. `CM_VAPID_*` exported in the calling terminal therefore
229
+ * read as the daemon's own configuration and silenced this warning for a server
230
+ * that had none (#2575, measured 2026-09-16: `:60301` answered
231
+ * `{"configured":false}` while `status` said nothing).
107
232
  *
108
- * The residual imprecision is the same one that line carries: a variable exported
109
- * into the daemon's environment at launch and absent from `.env` is invisible
110
- * here. `commandmate init` writes all three VAPID variables into `.env`, so the
111
- * supported setup is covered; a hand-exported key pair would be reported as
112
- * unconfigured, which is why the startup log carries the same lines.
233
+ * ## When the server does not answer
234
+ *
235
+ * A stopped daemon never reaches this function — both callers return at
236
+ * "Not running". A *running* daemon that does not answer (auth on with no
237
+ * `CM_AUTH_TOKEN`, a wedged process, something else on the advertised port) falls
238
+ * back to the `.env` verdict, and never to the shell. The residual is then the
239
+ * mirror of the bug that was fixed: a pair exported into the daemon at launch and
240
+ * absent from `.env` reads as unconfigured, i.e. a warning that is not warranted.
241
+ * That direction is the deliberate one — a false warning names the variables and
242
+ * the file and can be checked in one command, whereas the silence it replaces is
243
+ * what #2575 could not diagnose at all.
113
244
  *
114
245
  * Silent on a healthy install — that silence is the negative control both Issues
115
246
  * ask for. Never throws: a diagnostic must not turn `status` into a failure.
116
247
  */
117
- function printVapidStatus(env) {
248
+ async function printVapidStatus(status, envPath) {
118
249
  try {
119
- const lines = (0, vapid_1.formatVapidReportLines)((0, vapid_1.inspectVapidConfig)(env));
250
+ const fileVerdict = (0, vapid_1.inspectVapidConfig)((0, server_url_1.loadEnvFileValues)(envPath));
251
+ const serverConfigured = status.url ? await probeServerVapid(status.url) : null;
252
+ const verdict = reconcileVapid(fileVerdict, serverConfigured);
253
+ const lines = (0, vapid_1.formatVapidReportLines)(verdict);
120
254
  if (lines.length === 0)
121
255
  return;
122
256
  console.log('');
@@ -124,6 +258,9 @@ function printVapidStatus(env) {
124
258
  for (const line of lines.slice(1)) {
125
259
  console.log(line);
126
260
  }
261
+ for (const line of explainVapidMismatch(verdict, fileVerdict, serverConfigured, envPath)) {
262
+ console.log(line);
263
+ }
127
264
  }
128
265
  catch {
129
266
  // Unreadable .env, unparsable value: report the server, drop the hint.
@@ -202,7 +339,8 @@ async function showSingleStatus(issueNo) {
202
339
  // Issue #2113: the advertised localhost URL may not reach this server at all
203
340
  printLocalhostConflict(status);
204
341
  // Issue #2123 / #2124: whether Web Push can work at all on this server
205
- printVapidStatus(daemonManager.getEffectiveEnv());
342
+ // Issue #2585: asked of the server, and read off its .env — never off this shell
343
+ await printVapidStatus(status, envPath);
206
344
  }
207
345
  /**
208
346
  * Show status for all servers (main + all worktrees)
@@ -295,7 +433,8 @@ async function statusCommand(options = {}) {
295
433
  // Issue #2113: the advertised localhost URL may not reach this server at all
296
434
  printLocalhostConflict(status);
297
435
  // Issue #2123 / #2124: whether Web Push can work at all on this server
298
- printVapidStatus(daemonManager.getEffectiveEnv());
436
+ // Issue #2585: asked of the server, and read off its .env — never off this shell
437
+ await printVapidStatus(status, envPath);
299
438
  // Issue #332: Show IP restriction status
300
439
  // Issue #1266: read the env the server actually runs with. An exported CM_ALLOWED_IPS
301
440
  // shadowed the .env one here, reporting an ACL the server does not enforce.