commandmate 0.42.1 → 0.43.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 (435) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-build-manifest.json +144 -144
  3. package/.next/app-path-routes-manifest.json +23 -23
  4. package/.next/build-manifest.json +2 -2
  5. package/.next/prerender-manifest.json +9 -9
  6. package/.next/required-server-files.json +1 -1
  7. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  8. package/.next/server/app/api/agents/update/route_client-reference-manifest.js +1 -1
  9. package/.next/server/app/api/agents/versions/route_client-reference-manifest.js +1 -1
  10. package/.next/server/app/api/app/release-notes/route_client-reference-manifest.js +1 -1
  11. package/.next/server/app/api/app/update/route_client-reference-manifest.js +1 -1
  12. package/.next/server/app/api/app/update-check/route.js +1 -1
  13. package/.next/server/app/api/app/update-check/route_client-reference-manifest.js +1 -1
  14. package/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
  15. package/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
  16. package/.next/server/app/api/auth/status/route_client-reference-manifest.js +1 -1
  17. package/.next/server/app/api/capabilities/route.js +1 -1
  18. package/.next/server/app/api/capabilities/route_client-reference-manifest.js +1 -1
  19. package/.next/server/app/api/daily-summary/route.js +1 -1
  20. package/.next/server/app/api/daily-summary/route.js.nft.json +1 -1
  21. package/.next/server/app/api/daily-summary/route_client-reference-manifest.js +1 -1
  22. package/.next/server/app/api/daily-summary/status/route.js +1 -1
  23. package/.next/server/app/api/daily-summary/status/route.js.nft.json +1 -1
  24. package/.next/server/app/api/daily-summary/status/route_client-reference-manifest.js +1 -1
  25. package/.next/server/app/api/external-apps/[id]/health/route_client-reference-manifest.js +1 -1
  26. package/.next/server/app/api/external-apps/[id]/route_client-reference-manifest.js +1 -1
  27. package/.next/server/app/api/external-apps/route_client-reference-manifest.js +1 -1
  28. package/.next/server/app/api/fs/browse/route_client-reference-manifest.js +1 -1
  29. package/.next/server/app/api/fs/recent-paths/route_client-reference-manifest.js +1 -1
  30. package/.next/server/app/api/hooks/agent-event/route.js +103 -1
  31. package/.next/server/app/api/hooks/agent-event/route.js.nft.json +1 -1
  32. package/.next/server/app/api/hooks/agent-event/route_client-reference-manifest.js +1 -1
  33. package/.next/server/app/api/hooks/claude-done/route.js +2 -2
  34. package/.next/server/app/api/hooks/claude-done/route.js.nft.json +1 -1
  35. package/.next/server/app/api/hooks/claude-done/route_client-reference-manifest.js +1 -1
  36. package/.next/server/app/api/hooks/permission-request/route.js +1 -1
  37. package/.next/server/app/api/hooks/permission-request/route.js.nft.json +1 -1
  38. package/.next/server/app/api/hooks/permission-request/route_client-reference-manifest.js +1 -1
  39. package/.next/server/app/api/metrics/vibe/route_client-reference-manifest.js +1 -1
  40. package/.next/server/app/api/ollama/models/route_client-reference-manifest.js +1 -1
  41. package/.next/server/app/api/push/escalation/route_client-reference-manifest.js +1 -1
  42. package/.next/server/app/api/push/subscriptions/route_client-reference-manifest.js +1 -1
  43. package/.next/server/app/api/push/vapid/route_client-reference-manifest.js +1 -1
  44. package/.next/server/app/api/relays/[relayId]/cancel/route.js +1 -1
  45. package/.next/server/app/api/relays/[relayId]/cancel/route.js.nft.json +1 -1
  46. package/.next/server/app/api/relays/[relayId]/cancel/route_client-reference-manifest.js +1 -1
  47. package/.next/server/app/api/relays/route.js +1 -1
  48. package/.next/server/app/api/relays/route.js.nft.json +1 -1
  49. package/.next/server/app/api/relays/route_client-reference-manifest.js +1 -1
  50. package/.next/server/app/api/remote/pair/route_client-reference-manifest.js +1 -1
  51. package/.next/server/app/api/repositories/[id]/route_client-reference-manifest.js +1 -1
  52. package/.next/server/app/api/repositories/clone/[jobId]/route.js +1 -1
  53. package/.next/server/app/api/repositories/clone/[jobId]/route.js.nft.json +1 -1
  54. package/.next/server/app/api/repositories/clone/[jobId]/route_client-reference-manifest.js +1 -1
  55. package/.next/server/app/api/repositories/clone/route.js +1 -1
  56. package/.next/server/app/api/repositories/clone/route.js.nft.json +1 -1
  57. package/.next/server/app/api/repositories/clone/route_client-reference-manifest.js +1 -1
  58. package/.next/server/app/api/repositories/excluded/route_client-reference-manifest.js +1 -1
  59. package/.next/server/app/api/repositories/restore/route.js +1 -1
  60. package/.next/server/app/api/repositories/restore/route.js.nft.json +1 -1
  61. package/.next/server/app/api/repositories/restore/route_client-reference-manifest.js +1 -1
  62. package/.next/server/app/api/repositories/route.js +1 -1
  63. package/.next/server/app/api/repositories/route.js.nft.json +1 -1
  64. package/.next/server/app/api/repositories/route_client-reference-manifest.js +1 -1
  65. package/.next/server/app/api/repositories/scan/route.js +1 -1
  66. package/.next/server/app/api/repositories/scan/route.js.nft.json +1 -1
  67. package/.next/server/app/api/repositories/scan/route_client-reference-manifest.js +1 -1
  68. package/.next/server/app/api/repositories/sync/route.js +1 -1
  69. package/.next/server/app/api/repositories/sync/route.js.nft.json +1 -1
  70. package/.next/server/app/api/repositories/sync/route_client-reference-manifest.js +1 -1
  71. package/.next/server/app/api/repositories/validate-path/route_client-reference-manifest.js +1 -1
  72. package/.next/server/app/api/settings/default-agents/route.js +1 -1
  73. package/.next/server/app/api/settings/default-agents/route.js.nft.json +1 -1
  74. package/.next/server/app/api/settings/default-agents/route_client-reference-manifest.js +1 -1
  75. package/.next/server/app/api/settings/default-surface-mode/route_client-reference-manifest.js +1 -1
  76. package/.next/server/app/api/sidebar/group-order/route_client-reference-manifest.js +1 -1
  77. package/.next/server/app/api/skills/[id]/route.js +1 -1
  78. package/.next/server/app/api/skills/[id]/route_client-reference-manifest.js +1 -1
  79. package/.next/server/app/api/skills/installations/route_client-reference-manifest.js +1 -1
  80. package/.next/server/app/api/skills/operations/route_client-reference-manifest.js +1 -1
  81. package/.next/server/app/api/skills/reindex/route_client-reference-manifest.js +1 -1
  82. package/.next/server/app/api/skills/route.js +1 -1
  83. package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
  84. package/.next/server/app/api/slash-commands/route.js +1 -1
  85. package/.next/server/app/api/slash-commands/route_client-reference-manifest.js +1 -1
  86. package/.next/server/app/api/tasks/[taskId]/cancel/route_client-reference-manifest.js +1 -1
  87. package/.next/server/app/api/tasks/[taskId]/route_client-reference-manifest.js +1 -1
  88. package/.next/server/app/api/templates/[id]/route_client-reference-manifest.js +1 -1
  89. package/.next/server/app/api/templates/route_client-reference-manifest.js +1 -1
  90. package/.next/server/app/api/verification/runs/[runId]/route_client-reference-manifest.js +1 -1
  91. package/.next/server/app/api/verification/runs/route_client-reference-manifest.js +1 -1
  92. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js +1 -1
  93. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js.nft.json +1 -1
  94. package/.next/server/app/api/worktrees/[id]/auto-yes/route_client-reference-manifest.js +1 -1
  95. package/.next/server/app/api/worktrees/[id]/capture/route.js +1 -1
  96. package/.next/server/app/api/worktrees/[id]/capture/route.js.nft.json +1 -1
  97. package/.next/server/app/api/worktrees/[id]/capture/route_client-reference-manifest.js +1 -1
  98. package/.next/server/app/api/worktrees/[id]/clear-composer/route.js +1 -1
  99. package/.next/server/app/api/worktrees/[id]/clear-composer/route.js.nft.json +1 -1
  100. package/.next/server/app/api/worktrees/[id]/clear-composer/route_client-reference-manifest.js +1 -1
  101. package/.next/server/app/api/worktrees/[id]/cli-reference/route_client-reference-manifest.js +1 -1
  102. package/.next/server/app/api/worktrees/[id]/cli-tool/route_client-reference-manifest.js +1 -1
  103. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route.js +3 -1
  104. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route.js.nft.json +1 -1
  105. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route_client-reference-manifest.js +1 -1
  106. package/.next/server/app/api/worktrees/[id]/current-output/route.js +1 -1
  107. package/.next/server/app/api/worktrees/[id]/current-output/route.js.nft.json +1 -1
  108. package/.next/server/app/api/worktrees/[id]/current-output/route_client-reference-manifest.js +1 -1
  109. package/.next/server/app/api/worktrees/[id]/direct-input/route.js +1 -1
  110. package/.next/server/app/api/worktrees/[id]/direct-input/route.js.nft.json +1 -1
  111. package/.next/server/app/api/worktrees/[id]/direct-input/route_client-reference-manifest.js +1 -1
  112. package/.next/server/app/api/worktrees/[id]/env/route_client-reference-manifest.js +1 -1
  113. package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route.js +1 -1
  114. package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route_client-reference-manifest.js +1 -1
  115. package/.next/server/app/api/worktrees/[id]/execution-logs/route.js +3 -1
  116. package/.next/server/app/api/worktrees/[id]/execution-logs/route.js.nft.json +1 -1
  117. package/.next/server/app/api/worktrees/[id]/execution-logs/route_client-reference-manifest.js +1 -1
  118. package/.next/server/app/api/worktrees/[id]/files/[...path]/route_client-reference-manifest.js +1 -1
  119. package/.next/server/app/api/worktrees/[id]/git/branch/create/route_client-reference-manifest.js +1 -1
  120. package/.next/server/app/api/worktrees/[id]/git/branch/delete/route_client-reference-manifest.js +1 -1
  121. package/.next/server/app/api/worktrees/[id]/git/branches/route_client-reference-manifest.js +1 -1
  122. package/.next/server/app/api/worktrees/[id]/git/checkout/route_client-reference-manifest.js +1 -1
  123. package/.next/server/app/api/worktrees/[id]/git/commit/route_client-reference-manifest.js +1 -1
  124. package/.next/server/app/api/worktrees/[id]/git/diff/route_client-reference-manifest.js +1 -1
  125. package/.next/server/app/api/worktrees/[id]/git/fetch/route_client-reference-manifest.js +1 -1
  126. package/.next/server/app/api/worktrees/[id]/git/log/route_client-reference-manifest.js +1 -1
  127. package/.next/server/app/api/worktrees/[id]/git/pull/route_client-reference-manifest.js +1 -1
  128. package/.next/server/app/api/worktrees/[id]/git/push/route_client-reference-manifest.js +1 -1
  129. package/.next/server/app/api/worktrees/[id]/git/reset/route_client-reference-manifest.js +1 -1
  130. package/.next/server/app/api/worktrees/[id]/git/revert/route_client-reference-manifest.js +1 -1
  131. package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route_client-reference-manifest.js +1 -1
  132. package/.next/server/app/api/worktrees/[id]/git/stage/route_client-reference-manifest.js +1 -1
  133. package/.next/server/app/api/worktrees/[id]/git/staged/route_client-reference-manifest.js +1 -1
  134. package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route_client-reference-manifest.js +1 -1
  135. package/.next/server/app/api/worktrees/[id]/git/stash/apply/route_client-reference-manifest.js +1 -1
  136. package/.next/server/app/api/worktrees/[id]/git/stash/pop/route_client-reference-manifest.js +1 -1
  137. package/.next/server/app/api/worktrees/[id]/git/stash/push/route_client-reference-manifest.js +1 -1
  138. package/.next/server/app/api/worktrees/[id]/git/stash/route_client-reference-manifest.js +1 -1
  139. package/.next/server/app/api/worktrees/[id]/git/status/route_client-reference-manifest.js +1 -1
  140. package/.next/server/app/api/worktrees/[id]/git/unstage/route_client-reference-manifest.js +1 -1
  141. package/.next/server/app/api/worktrees/[id]/git/working-diff/route_client-reference-manifest.js +1 -1
  142. package/.next/server/app/api/worktrees/[id]/instances/notes/route_client-reference-manifest.js +1 -1
  143. package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js +1 -1
  144. package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js.nft.json +1 -1
  145. package/.next/server/app/api/worktrees/[id]/instances/opencode/route_client-reference-manifest.js +1 -1
  146. package/.next/server/app/api/worktrees/[id]/interrupt/route.js +1 -1
  147. package/.next/server/app/api/worktrees/[id]/interrupt/route.js.nft.json +1 -1
  148. package/.next/server/app/api/worktrees/[id]/interrupt/route_client-reference-manifest.js +1 -1
  149. package/.next/server/app/api/worktrees/[id]/kill-session/route.js +1 -1
  150. package/.next/server/app/api/worktrees/[id]/kill-session/route.js.nft.json +1 -1
  151. package/.next/server/app/api/worktrees/[id]/kill-session/route_client-reference-manifest.js +1 -1
  152. package/.next/server/app/api/worktrees/[id]/logs/[filename]/route_client-reference-manifest.js +1 -1
  153. package/.next/server/app/api/worktrees/[id]/logs/route_client-reference-manifest.js +1 -1
  154. package/.next/server/app/api/worktrees/[id]/marp-render/route_client-reference-manifest.js +1 -1
  155. package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route_client-reference-manifest.js +1 -1
  156. package/.next/server/app/api/worktrees/[id]/memos/route_client-reference-manifest.js +1 -1
  157. package/.next/server/app/api/worktrees/[id]/messages/route_client-reference-manifest.js +1 -1
  158. package/.next/server/app/api/worktrees/[id]/opencode/diff/route_client-reference-manifest.js +1 -1
  159. package/.next/server/app/api/worktrees/[id]/opencode/session/route.js +1 -1
  160. package/.next/server/app/api/worktrees/[id]/opencode/session/route.js.nft.json +1 -1
  161. package/.next/server/app/api/worktrees/[id]/opencode/session/route_client-reference-manifest.js +1 -1
  162. package/.next/server/app/api/worktrees/[id]/opencode/share/route.js +1 -1
  163. package/.next/server/app/api/worktrees/[id]/opencode/share/route.js.nft.json +1 -1
  164. package/.next/server/app/api/worktrees/[id]/opencode/share/route_client-reference-manifest.js +1 -1
  165. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js +1 -1
  166. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js.nft.json +1 -1
  167. package/.next/server/app/api/worktrees/[id]/prompt-response/route_client-reference-manifest.js +1 -1
  168. package/.next/server/app/api/worktrees/[id]/resolve-target/route_client-reference-manifest.js +1 -1
  169. package/.next/server/app/api/worktrees/[id]/respond/route.js +1 -1
  170. package/.next/server/app/api/worktrees/[id]/respond/route.js.nft.json +1 -1
  171. package/.next/server/app/api/worktrees/[id]/respond/route_client-reference-manifest.js +1 -1
  172. package/.next/server/app/api/worktrees/[id]/route.js +1 -103
  173. package/.next/server/app/api/worktrees/[id]/route.js.nft.json +1 -1
  174. package/.next/server/app/api/worktrees/[id]/route_client-reference-manifest.js +1 -1
  175. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route.js +3 -1
  176. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route.js.nft.json +1 -1
  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.js +3 -1
  179. package/.next/server/app/api/worktrees/[id]/schedules/active/route.js.nft.json +1 -1
  180. package/.next/server/app/api/worktrees/[id]/schedules/active/route_client-reference-manifest.js +1 -1
  181. package/.next/server/app/api/worktrees/[id]/schedules/route.js +3 -1
  182. package/.next/server/app/api/worktrees/[id]/schedules/route.js.nft.json +1 -1
  183. package/.next/server/app/api/worktrees/[id]/schedules/route_client-reference-manifest.js +1 -1
  184. package/.next/server/app/api/worktrees/[id]/search/route_client-reference-manifest.js +1 -1
  185. package/.next/server/app/api/worktrees/[id]/send/route.js +1 -103
  186. package/.next/server/app/api/worktrees/[id]/send/route.js.nft.json +1 -1
  187. package/.next/server/app/api/worktrees/[id]/send/route_client-reference-manifest.js +1 -1
  188. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js +104 -2
  189. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js.nft.json +1 -1
  190. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route_client-reference-manifest.js +1 -1
  191. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route_client-reference-manifest.js +1 -1
  192. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route_client-reference-manifest.js +1 -1
  193. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route_client-reference-manifest.js +1 -1
  194. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route_client-reference-manifest.js +1 -1
  195. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update/route_client-reference-manifest.js +1 -1
  196. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route_client-reference-manifest.js +1 -1
  197. package/.next/server/app/api/worktrees/[id]/skills/route_client-reference-manifest.js +1 -1
  198. package/.next/server/app/api/worktrees/[id]/slash-commands/route.js +1 -1
  199. package/.next/server/app/api/worktrees/[id]/slash-commands/route.js.nft.json +1 -1
  200. package/.next/server/app/api/worktrees/[id]/slash-commands/route_client-reference-manifest.js +1 -1
  201. package/.next/server/app/api/worktrees/[id]/special-keys/route.js +1 -1
  202. package/.next/server/app/api/worktrees/[id]/special-keys/route.js.nft.json +1 -1
  203. package/.next/server/app/api/worktrees/[id]/special-keys/route_client-reference-manifest.js +1 -1
  204. package/.next/server/app/api/worktrees/[id]/tasks/route.js +1 -1
  205. package/.next/server/app/api/worktrees/[id]/tasks/route_client-reference-manifest.js +1 -1
  206. package/.next/server/app/api/worktrees/[id]/terminal/route.js +1 -1
  207. package/.next/server/app/api/worktrees/[id]/terminal/route.js.nft.json +1 -1
  208. package/.next/server/app/api/worktrees/[id]/terminal/route_client-reference-manifest.js +1 -1
  209. package/.next/server/app/api/worktrees/[id]/timers/history/route_client-reference-manifest.js +1 -1
  210. package/.next/server/app/api/worktrees/[id]/timers/route.js +1 -1
  211. package/.next/server/app/api/worktrees/[id]/timers/route.js.nft.json +1 -1
  212. package/.next/server/app/api/worktrees/[id]/timers/route_client-reference-manifest.js +1 -1
  213. package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
  214. package/.next/server/app/api/worktrees/[id]/todos/route_client-reference-manifest.js +1 -1
  215. package/.next/server/app/api/worktrees/[id]/tree/[...path]/route_client-reference-manifest.js +1 -1
  216. package/.next/server/app/api/worktrees/[id]/tree/route_client-reference-manifest.js +1 -1
  217. package/.next/server/app/api/worktrees/[id]/upload/[...path]/route_client-reference-manifest.js +1 -1
  218. package/.next/server/app/api/worktrees/[id]/verify/config/route.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_client-reference-manifest.js +1 -1
  222. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route.js +1 -1
  223. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route_client-reference-manifest.js +1 -1
  224. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route_client-reference-manifest.js +1 -1
  225. package/.next/server/app/api/worktrees/[id]/verify/runs/route_client-reference-manifest.js +1 -1
  226. package/.next/server/app/api/worktrees/[id]/viewed/route_client-reference-manifest.js +1 -1
  227. package/.next/server/app/api/worktrees/apply-default-agents/route_client-reference-manifest.js +1 -1
  228. package/.next/server/app/api/worktrees/route.js +1 -1
  229. package/.next/server/app/api/worktrees/route.js.nft.json +1 -1
  230. package/.next/server/app/api/worktrees/route_client-reference-manifest.js +1 -1
  231. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  232. package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
  233. package/.next/server/app/more/page_client-reference-manifest.js +1 -1
  234. package/.next/server/app/offline/page_client-reference-manifest.js +1 -1
  235. package/.next/server/app/page_client-reference-manifest.js +1 -1
  236. package/.next/server/app/proxy/[...path]/route_client-reference-manifest.js +1 -1
  237. package/.next/server/app/repositories/page_client-reference-manifest.js +1 -1
  238. package/.next/server/app/review/page_client-reference-manifest.js +1 -1
  239. package/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  240. package/.next/server/app/skills/[skillId]/page_client-reference-manifest.js +1 -1
  241. package/.next/server/app/skills/installed/page_client-reference-manifest.js +1 -1
  242. package/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  243. package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -1
  244. package/.next/server/app/worktrees/[id]/page.js +9 -9
  245. package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -1
  246. package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
  247. package/.next/server/app-paths-manifest.json +23 -23
  248. package/.next/server/chunks/1068.js +1 -1
  249. package/.next/server/chunks/1210.js +1 -1
  250. package/.next/server/chunks/1501.js +4 -4
  251. package/.next/server/chunks/1990.js +1 -1
  252. package/.next/server/chunks/2119.js +1 -1
  253. package/.next/server/chunks/22.js +1 -1
  254. package/.next/server/chunks/2328.js +1 -1
  255. package/.next/server/chunks/2404.js +4 -3
  256. package/.next/server/chunks/2445.js +1 -1
  257. package/.next/server/chunks/252.js +1 -1
  258. package/.next/server/chunks/2816.js +1 -1
  259. package/.next/server/chunks/3543.js +1 -1
  260. package/.next/server/chunks/3730.js +1 -1
  261. package/.next/server/chunks/3945.js +1 -1
  262. package/.next/server/chunks/4207.js +3 -3
  263. package/.next/server/chunks/434.js +1 -1
  264. package/.next/server/chunks/5064.js +1 -1
  265. package/.next/server/chunks/5571.js +1 -1
  266. package/.next/server/chunks/5742.js +1 -1
  267. package/.next/server/chunks/5775.js +1 -1
  268. package/.next/server/chunks/611.js +1 -1
  269. package/.next/server/chunks/6130.js +1 -1
  270. package/.next/server/chunks/6285.js +1 -1
  271. package/.next/server/chunks/6491.js +103 -0
  272. package/.next/server/chunks/6661.js +1 -1
  273. package/.next/server/chunks/6781.js +1 -1
  274. package/.next/server/chunks/6793.js +1 -1
  275. package/.next/server/chunks/7491.js +3 -0
  276. package/.next/server/chunks/7685.js +1 -1
  277. package/.next/server/chunks/7905.js +1 -1
  278. package/.next/server/chunks/8581.js +2 -2
  279. package/.next/server/chunks/8583.js +1 -1
  280. package/.next/server/chunks/8673.js +6 -6
  281. package/.next/server/chunks/8728.js +2 -2
  282. package/.next/server/chunks/8791.js +1 -1
  283. package/.next/server/chunks/8800.js +4 -3
  284. package/.next/server/chunks/8918.js +5 -5
  285. package/.next/server/chunks/9130.js +3 -3
  286. package/.next/server/chunks/{8052.js → 9353.js} +4 -2
  287. package/.next/server/chunks/9390.js +3 -0
  288. package/.next/server/chunks/9627.js +4 -4
  289. package/.next/server/chunks/964.js +1 -1
  290. package/.next/server/chunks/967.js +1 -0
  291. package/.next/server/chunks/9731.js +3 -3
  292. package/.next/server/chunks/9882.js +3 -3
  293. package/.next/server/middleware-manifest.json +5 -5
  294. package/.next/server/pages/500.html +1 -1
  295. package/.next/server/server-reference-manifest.json +1 -1
  296. package/.next/static/chunks/{1642-fb2e176aaadbd137.js → 1642-767aed8e7c61ef7f.js} +1 -1
  297. package/.next/static/chunks/{2407-21fbf12d753b8d4d.js → 2407-940df9b11fadafc6.js} +1 -1
  298. package/.next/static/chunks/{2619-04bc32f026a0d946.js → 2619-a305ad4810f1393a.js} +1 -1
  299. package/.next/static/chunks/5449-6cb80bab2bd06b79.js +1 -0
  300. package/.next/static/chunks/7705-1f58d4c03d991fcf.js +1 -0
  301. package/.next/static/chunks/8165-3525fb42f1b4976e.js +1 -0
  302. package/.next/static/chunks/app/{layout-8ff4c7c08ef1f621.js → layout-057c850cd0df978e.js} +1 -1
  303. package/.next/static/chunks/app/review/page-ff9efae3f86eb840.js +1 -0
  304. package/.next/static/chunks/app/skills/[skillId]/page-74aac15286504ef4.js +1 -0
  305. package/.next/static/chunks/app/skills/page-182e16168b2fc098.js +1 -0
  306. package/.next/static/chunks/app/worktrees/[id]/page-eab0bf7564d3f9e2.js +1 -0
  307. package/.next/static/chunks/app/worktrees/[id]/terminal/{page-373ea37b16d930c7.js → page-c601f3b3ece6557e.js} +1 -1
  308. package/.next/trace +13 -13
  309. package/README.md +3 -3
  310. package/dist/cli/commands/ask.d.ts.map +1 -1
  311. package/dist/cli/commands/ask.js +23 -149
  312. package/dist/cli/commands/reply.d.ts +40 -0
  313. package/dist/cli/commands/reply.d.ts.map +1 -0
  314. package/dist/cli/commands/reply.js +133 -0
  315. package/dist/cli/commands/verify.d.ts.map +1 -1
  316. package/dist/cli/commands/verify.js +9 -0
  317. package/dist/cli/commands/wait.d.ts +5 -0
  318. package/dist/cli/commands/wait.d.ts.map +1 -1
  319. package/dist/cli/commands/wait.js +10 -1
  320. package/dist/cli/docs/agent-operations.d.ts +2 -2
  321. package/dist/cli/docs/agent-operations.d.ts.map +1 -1
  322. package/dist/cli/docs/agent-operations.js +13 -0
  323. package/dist/cli/program.d.ts.map +1 -1
  324. package/dist/cli/program.js +4 -0
  325. package/dist/cli/types/index.d.ts +2 -0
  326. package/dist/cli/types/index.d.ts.map +1 -1
  327. package/dist/cli/utils/reply-ledger.d.ts +95 -0
  328. package/dist/cli/utils/reply-ledger.d.ts.map +1 -0
  329. package/dist/cli/utils/reply-ledger.js +187 -0
  330. package/dist/lib/cli-tools/copilot-executable.d.ts +9 -0
  331. package/dist/lib/cli-tools/copilot-executable.d.ts.map +1 -1
  332. package/dist/lib/cli-tools/copilot-executable.js +21 -5
  333. package/dist/lib/cli-tools/opencode-executable.d.ts +103 -0
  334. package/dist/lib/cli-tools/opencode-executable.d.ts.map +1 -0
  335. package/dist/lib/cli-tools/opencode-executable.js +179 -0
  336. package/dist/lib/cli-tools/types.d.ts +1 -1
  337. package/dist/lib/cli-tools/types.d.ts.map +1 -1
  338. package/dist/lib/cli-tools/types.js +5 -1
  339. package/dist/lib/detection/tools/verified-against.d.ts +15 -0
  340. package/dist/lib/detection/tools/verified-against.d.ts.map +1 -1
  341. package/dist/lib/detection/tools/verified-against.js +17 -1
  342. package/dist/lib/detection/version-probes.d.ts.map +1 -1
  343. package/dist/lib/detection/version-probes.js +14 -1
  344. package/dist/lib/session/tmux-session-surface.d.ts.map +1 -1
  345. package/dist/lib/session/tmux-session-surface.js +1 -1
  346. package/dist/server/locales/en/worktree.json +44 -14
  347. package/dist/server/locales/ja/worktree.json +44 -14
  348. package/dist/server/server.js +23 -0
  349. package/dist/server/src/config/cli-tool-timing-config.js +19 -1
  350. package/dist/server/src/config/detection-evidence-config.js +3 -0
  351. package/dist/server/src/config/schedule-config.js +55 -1
  352. package/dist/server/src/lib/auto-yes-poller.js +47 -4
  353. package/dist/server/src/lib/cli-tools/agent-mode-spec.js +54 -2
  354. package/dist/server/src/lib/cli-tools/base.js +6 -2
  355. package/dist/server/src/lib/cli-tools/command-code.js +55 -1
  356. package/dist/server/src/lib/cli-tools/composer-spec.js +10 -0
  357. package/dist/server/src/lib/cli-tools/copilot-executable.js +21 -5
  358. package/dist/server/src/lib/cli-tools/graceful-exit.js +15 -1
  359. package/dist/server/src/lib/cli-tools/index.js +3 -1
  360. package/dist/server/src/lib/cli-tools/install-hints.js +9 -3
  361. package/dist/server/src/lib/cli-tools/liveness-spec.js +19 -0
  362. package/dist/server/src/lib/cli-tools/manager.js +2 -0
  363. package/dist/server/src/lib/cli-tools/opencode-executable.js +179 -0
  364. package/dist/server/src/lib/cli-tools/opencode-v2.js +369 -0
  365. package/dist/server/src/lib/cli-tools/opencode.js +29 -5
  366. package/dist/server/src/lib/cli-tools/types.js +5 -1
  367. package/dist/server/src/lib/cmate-cli-tool-parser.js +65 -7
  368. package/dist/server/src/lib/cmate-parser.js +12 -0
  369. package/dist/server/src/lib/cmate-validator.js +13 -1
  370. package/dist/server/src/lib/db/worktree-db.js +1 -1
  371. package/dist/server/src/lib/detection/cli-patterns.js +78 -2
  372. package/dist/server/src/lib/detection/model-info-extractor.js +79 -7
  373. package/dist/server/src/lib/detection/status-detector.js +10 -1
  374. package/dist/server/src/lib/detection/tools/codex/cli-patterns.js +2 -1
  375. package/dist/server/src/lib/detection/tools/opencode-v2/detect.js +253 -0
  376. package/dist/server/src/lib/detection/tools/opencode-v2/dialog-title.js +48 -0
  377. package/dist/server/src/lib/detection/tools/registry.js +2 -0
  378. package/dist/server/src/lib/detection/tools/run-detection.js +9 -0
  379. package/dist/server/src/lib/detection/tools/verified-against.js +17 -1
  380. package/dist/server/src/lib/detection/upstream-faults.js +8 -0
  381. package/dist/server/src/lib/detection/version-probes.js +14 -1
  382. package/dist/server/src/lib/hooks/agent-session-telemetry.js +36 -1
  383. package/dist/server/src/lib/hooks/sources/opencode/log-diagnosis.js +105 -0
  384. package/dist/server/src/lib/hooks/sources/opencode/source.js +7 -1
  385. package/dist/server/src/lib/hooks/sources/opencode-v2/client.js +422 -0
  386. package/dist/server/src/lib/hooks/sources/opencode-v2/decision-labels.js +24 -0
  387. package/dist/server/src/lib/hooks/sources/opencode-v2/history.js +421 -0
  388. package/dist/server/src/lib/hooks/sources/opencode-v2/ingest.js +271 -0
  389. package/dist/server/src/lib/hooks/sources/opencode-v2/mappers.js +165 -0
  390. package/dist/server/src/lib/hooks/sources/opencode-v2/payloads.js +351 -0
  391. package/dist/server/src/lib/hooks/sources/opencode-v2/ports.js +230 -0
  392. package/dist/server/src/lib/hooks/sources/opencode-v2/reattach.js +149 -0
  393. package/dist/server/src/lib/hooks/sources/opencode-v2/runtime.js +180 -0
  394. package/dist/server/src/lib/hooks/sources/opencode-v2/secrets.js +182 -0
  395. package/dist/server/src/lib/hooks/sources/opencode-v2/source.js +295 -0
  396. package/dist/server/src/lib/hooks/sources/opencode-v2/subscription.js +455 -0
  397. package/dist/server/src/lib/hooks/sources/opencode-v2/tool-id.js +18 -0
  398. package/dist/server/src/lib/hooks/sources/opencode-v2/usage.js +214 -0
  399. package/dist/server/src/lib/hooks/sources/registry.js +2 -0
  400. package/dist/server/src/lib/hooks/structured-decision-response.js +14 -5
  401. package/dist/server/src/lib/job-executor.js +2 -1
  402. package/dist/server/src/lib/polling/auto-yes-dialog-gate.js +15 -1
  403. package/dist/server/src/lib/polling/structured-history-gate.js +19 -5
  404. package/dist/server/src/lib/relay/relay-delivery.js +4 -1
  405. package/dist/server/src/lib/session/agent-event-state.js +24 -0
  406. package/dist/server/src/lib/session/claude-executor.js +184 -10
  407. package/dist/server/src/lib/session/current-output-builder.js +27 -3
  408. package/dist/server/src/lib/session/send-user-message.js +4 -0
  409. package/dist/server/src/lib/session/structured-prompt.js +54 -0
  410. package/dist/server/src/lib/session/tmux-session-surface.js +1 -1
  411. package/dist/server/src/lib/skills/compatibility-matrix.js +65 -0
  412. package/dist/server/src/lib/tmux/tmux.js +48 -2
  413. package/dist/server/src/lib/verification/env-clean-gate.js +228 -9
  414. package/dist/server/src/lib/verification/env-snapshot.js +65 -1
  415. package/dist/server/src/types/cli-tool-contracts.js +10 -2
  416. package/dist/types/cli-tool-contracts.d.ts +16 -5
  417. package/dist/types/cli-tool-contracts.d.ts.map +1 -1
  418. package/dist/types/cli-tool-contracts.js +10 -2
  419. package/package.json +2 -1
  420. package/release-notes/0.42.2.json +20 -0
  421. package/release-notes/0.43.0.json +130 -0
  422. package/scripts/hooks/cmate-agent-event.sh +14 -0
  423. package/scripts/opencode-v2/launch.sh +226 -0
  424. package/.next/server/chunks/4443.js +0 -3
  425. package/.next/server/chunks/5164.js +0 -1
  426. package/.next/server/chunks/650.js +0 -1
  427. package/.next/static/chunks/5449-550bd273dccc3ae4.js +0 -1
  428. package/.next/static/chunks/7705-2a2936551b0cf9a3.js +0 -1
  429. package/.next/static/chunks/8165-934ee7ff3b4ddfd4.js +0 -1
  430. package/.next/static/chunks/app/review/page-30616daa1dc595c2.js +0 -1
  431. package/.next/static/chunks/app/skills/[skillId]/page-ab7e432b69fccb3b.js +0 -1
  432. package/.next/static/chunks/app/skills/page-56b4fa11223e0cbd.js +0 -1
  433. package/.next/static/chunks/app/worktrees/[id]/page-3c946bd2875391fd.js +0 -1
  434. /package/.next/static/{3M_S0B7dhEDdVE2XSJz1Y → BVkBYdceLRvMROqQIqeBx}/_buildManifest.js +0 -0
  435. /package/.next/static/{3M_S0B7dhEDdVE2XSJz1Y → BVkBYdceLRvMROqQIqeBx}/_ssgManifest.js +0 -0
@@ -35,12 +35,15 @@
35
35
  */
36
36
  Object.defineProperty(exports, "__esModule", { value: true });
37
37
  exports.MAX_STRUCTURED_PROMPT_MESSAGE_LENGTH = exports.STRUCTURED_DECISION_OPTIONS = void 0;
38
+ exports.structuredDecisionOptionsFor = structuredDecisionOptionsFor;
38
39
  exports.isAddressableDecision = isAddressableDecision;
40
+ exports.hasApiAnswerableDecision = hasApiAnswerableDecision;
39
41
  exports.buildStructuredPromptQuestion = buildStructuredPromptQuestion;
40
42
  exports.buildStructuredPromptData = buildStructuredPromptData;
41
43
  exports.buildStructuredPromptHistoryRecord = buildStructuredPromptHistoryRecord;
42
44
  exports.isStructuredPromptWaitingData = isStructuredPromptWaitingData;
43
45
  const models_1 = require("../../types/models");
46
+ const decision_labels_1 = require("../../lib/hooks/sources/opencode-v2/decision-labels");
44
47
  /**
45
48
  * The three verdicts an approval dialog accepts, in the order `respond` numbers
46
49
  * them (Issue #1898).
@@ -67,6 +70,32 @@ exports.STRUCTURED_DECISION_OPTIONS = [
67
70
  // eslint-disable-next-line no-restricted-syntax -- CLI answer vocabulary, not display text
68
71
  { number: 3, label: 'Reject', reply: 'reject' },
69
72
  ];
73
+ /**
74
+ * A tool's own words for the approval verdicts, keyed by wire reply
75
+ * (Issue #2951). Only tools whose dialog words differ from
76
+ * {@link STRUCTURED_DECISION_OPTIONS} are here: OpenCode V2 draws `Always allow`
77
+ * where v1 draws `Allow always`.
78
+ */
79
+ const DECISION_LABELS_BY_TOOL = {
80
+ 'opencode-v2': decision_labels_1.OPENCODE_V2_DECISION_LABELS,
81
+ };
82
+ /**
83
+ * The approval verdicts in the words of the tool that asked (Issue #2951).
84
+ *
85
+ * What `capture --json` publishes as `decisionOptions` and what `respond`
86
+ * matches a label against, so both say what the tool's own dialog says. Only
87
+ * the LABEL differs per tool: the number and the wire reply are the shared
88
+ * list's, so `2` still means `always` everywhere. Every tool without its own
89
+ * words gets {@link STRUCTURED_DECISION_OPTIONS} itself (the same object).
90
+ *
91
+ * @param cliToolId - The tool the approval belongs to
92
+ */
93
+ function structuredDecisionOptionsFor(cliToolId) {
94
+ const labels = DECISION_LABELS_BY_TOOL[cliToolId];
95
+ if (!labels)
96
+ return exports.STRUCTURED_DECISION_OPTIONS;
97
+ return exports.STRUCTURED_DECISION_OPTIONS.map((option) => labels[option.reply] ? { ...option, label: labels[option.reply] } : option);
98
+ }
70
99
  /** Bound on the agent's `message`, which is prose and only ever displayed. */
71
100
  exports.MAX_STRUCTURED_PROMPT_MESSAGE_LENGTH = 500;
72
101
  /**
@@ -89,6 +118,31 @@ exports.MAX_STRUCTURED_PROMPT_MESSAGE_LENGTH = 500;
89
118
  function isAddressableDecision(value) {
90
119
  return typeof value === 'string' && value !== '';
91
120
  }
121
+ /**
122
+ * Whether the agent is holding a decision this server can answer over the
123
+ * agent's own API right now (Issue #2965).
124
+ *
125
+ * The gate on the two "the detection layer could not read this" rows — the
126
+ * unclassified-frame row and the structured-prompt row
127
+ * ({@link buildStructuredPromptQuestion}). Both exist to record a dialog nobody
128
+ * could answer; while this is true somebody can, by id, and the row is a
129
+ * meaningless line in the chat (OpenCode V2 approvals and questions, #2945;
130
+ * v1 opencode's approvals, which carry the same `permission-id`). All three
131
+ * conjuncts are required, and each failing one puts the row back — the safe
132
+ * side:
133
+ *
134
+ * - the source publishes per-decision ids (`eventIdentity: 'permission-id'`);
135
+ * - a pending decision carries one ({@link isAddressableDecision});
136
+ * - its delivery window has not expired (a verdict can still reach the agent).
137
+ *
138
+ * @param eventIdentity - `capabilities.eventIdentity` of the tool's event source
139
+ * @param pendingDecisions - the decisions the turn is holding, as published
140
+ */
141
+ function hasApiAnswerableDecision(eventIdentity, pendingDecisions) {
142
+ if (eventIdentity !== 'permission-id')
143
+ return false;
144
+ return pendingDecisions.some((decision) => isAddressableDecision(decision.id) && !decision.deliveryExpired);
145
+ }
92
146
  /** How each source reads in the one-line question. */
93
147
  const SOURCE_LABEL = {
94
148
  notification: 'Notification(permission_prompt)',
@@ -343,7 +343,7 @@ function isLiveAttachEligibleSession(sessionName) {
343
343
  * `tests/unit/tmux/session-surface-2317.test.ts`, so a tool moving in or out of
344
344
  * the alternate screen breaks a test rather than silently dropping the hint.
345
345
  */
346
- exports.ALT_SCREEN_TOOLS = ['claude', 'opencode', 'copilot'];
346
+ exports.ALT_SCREEN_TOOLS = ['claude', 'opencode', 'copilot', 'opencode-v2'];
347
347
  /** Whether `attach` should warn that a bare attach shows no transcript. */
348
348
  function usesAltScreen(cliToolId) {
349
349
  return exports.ALT_SCREEN_TOOLS.includes(cliToolId);
@@ -81,6 +81,7 @@ const NOT_MEASURED_SKIP_REASON_KEY = 'skills.compatibility.skipReason.notMeasure
81
81
  exports.AGENT_RELOAD_MESSAGE_KEYS = {
82
82
  SESSION_RESTART: 'skills.compatibility.reload.sessionRestart',
83
83
  SESSION_RESTART_NO_SLASH: 'skills.compatibility.reload.sessionRestartNoSlash',
84
+ PICKED_UP_LIVE: 'skills.compatibility.reload.pickedUpLive',
84
85
  UNKNOWN: 'skills.compatibility.reload.unknown',
85
86
  };
86
87
  /** Known limitation keys attached to an axis outcome. */
@@ -113,6 +114,15 @@ const MEASURED_DATE_2026_09_05 = '2026-09-05';
113
114
  * deliberately *not* recorded as a row — see the `gemini` entry below.
114
115
  */
115
116
  const OTHER_AGENTS_EVIDENCE_SOURCE = 'https://github.com/Kewton/CommandMate/blob/main/docs/reference/skill-agent-compatibility.md#9-gemini--copilot-probe-log-issue-2302';
117
+ /**
118
+ * Evidence reference for the OpenCode V2 (opencode2) 2.0.18 measurement
119
+ * (Issue #2975).
120
+ *
121
+ * The reference doc carries the harness, the controls and the raw
122
+ * `GET /api/skill` / message output.
123
+ */
124
+ const OPENCODE_V2_EVIDENCE_SOURCE = 'https://github.com/Kewton/CommandMate/blob/main/docs/reference/skill-agent-compatibility.md#10-opencode-v2-probe-log-issue-2975';
125
+ const MEASURED_DATE_2026_09_29 = '2026-09-29';
116
126
  function unmeasuredEntry(agent) {
117
127
  return {
118
128
  agent,
@@ -345,6 +355,61 @@ const AGENT_DISCOVERY_MATRIX = [
345
355
  reloadKey: exports.AGENT_RELOAD_MESSAGE_KEYS.SESSION_RESTART,
346
356
  skipReasonKey: null,
347
357
  },
358
+ {
359
+ agent: 'opencode-v2',
360
+ // Issue #2975, opencode2 2.0.18. Measured on its own rather than copied off
361
+ // the v1 row: the values happen to match v1's, but the release, the day and
362
+ // the route that makes invocation work are different.
363
+ //
364
+ // Ten probe Skills were planted, one per candidate root, each told to
365
+ // answer a unique token. `GET /api/skill` returned eight of them with their
366
+ // absolute SKILL.md paths — project `.opencode/skills`, `.opencode/skill`,
367
+ // `.claude/skills`, `.agents/skills`; home `.claude/skills`,
368
+ // `.agents/skills`, `.config/opencode/skills`, `.config/opencode/skill` —
369
+ // and not the two negative controls (`.github/skills`,
370
+ // `$HOME/.opencode/skills`). Both CommandMate install roots are among the
371
+ // eight, and the byte-identical dual-root install is listed once.
372
+ discoveryRoots: [constants_1.SKILL_INSTALL_ROOT_PREFIX, constants_1.SKILL_CLAUDE_INSTALL_ROOT_PREFIX],
373
+ discovery: {
374
+ outcome: 'verified',
375
+ evidenceKind: 'mechanical',
376
+ labelKey: exports.AGENT_AXIS_OUTCOME_LABEL_KEYS.verified,
377
+ evidenceKindKey: exports.AGENT_EVIDENCE_KIND_LABEL_KEYS.mechanical,
378
+ limitationKey: null,
379
+ },
380
+ invocation: {
381
+ // Submitting `/probe-agents-root ` produced a `skill` tool part with
382
+ // `input.id: "probe-agents-root"` and the Skill's absolute directory in
383
+ // its metadata, and the agent answered `PROBE_OK_probe-agents-root`;
384
+ // `.claude/skills` did the same with its own token. Unlike v1 the TUI
385
+ // does not expand the Skill — the user message is the literal
386
+ // `/probe-agents-root ` (a markdown command, by contrast, is replaced by
387
+ // its template) — so it is the model calling the `skill` tool. The tool
388
+ // part is the discriminator, not the token: `/probe-home-dotopencode-root`
389
+ // (never discovered) came back with a *different* Skill's token.
390
+ //
391
+ // The limitation is the same as v1's: typing the name after `/` shows
392
+ // "No matching commands" (positive control `/rev` → `/review`, negative
393
+ // control `/zzzznotacommand` → nothing), and the `ctrl+p` palette has no
394
+ // row for it either. What v2 adds is an `@` completion — `@probe` lists
395
+ // every discovered Skill tagged `skill`, and the `/skills` picker inserts
396
+ // `@name` — so v2 does have its own way in, just not a slash command.
397
+ outcome: 'verified',
398
+ evidenceKind: 'mechanical',
399
+ labelKey: exports.AGENT_AXIS_OUTCOME_LABEL_KEYS.verified,
400
+ evidenceKindKey: exports.AGENT_EVIDENCE_KIND_LABEL_KEYS.mechanical,
401
+ limitationKey: exports.AGENT_LIMITATION_MESSAGE_KEYS.NO_SLASH_COMMAND,
402
+ },
403
+ testedVersion: '2.0.18',
404
+ testedDate: MEASURED_DATE_2026_09_29,
405
+ evidenceSource: OPENCODE_V2_EVIDENCE_SOURCE,
406
+ // Also measured, and the opposite of v1: the server does NOT need a
407
+ // restart. A Skill planted while it ran appeared in `GET /api/skill` within
408
+ // seconds, and one planted into `$HOME/.agents/skills` mid-session was run
409
+ // in that same session — so the guidance is "no new session needed".
410
+ reloadKey: exports.AGENT_RELOAD_MESSAGE_KEYS.PICKED_UP_LIVE,
411
+ skipReasonKey: null,
412
+ },
348
413
  ];
349
414
  /** The measured matrix, in CLI-tool declaration order. */
350
415
  function getSkillAgentMatrix() {
@@ -254,6 +254,33 @@ async function listSessions() {
254
254
  return [];
255
255
  }
256
256
  }
257
+ /**
258
+ * Issue #2958: what window 0 of a new session runs until `createSession`
259
+ * replaces it with the login shell. Two words so tmux execs it directly (a
260
+ * single word would be run through `default-shell -c`); it never exits on its
261
+ * own and dies with the SIGHUP the replacement sends.
262
+ */
263
+ const PLACEHOLDER_PANE_COMMAND = ['sleep', '2147483647'];
264
+ /**
265
+ * Fallback for a failed window rebuild: swap the placeholder in window 0 for
266
+ * the login shell tmux would have started (`default-shell`, as a login shell).
267
+ *
268
+ * A bare `respawn-pane` would re-run the pane's creation command — the
269
+ * placeholder — so the shell is named explicitly.
270
+ */
271
+ async function respawnLoginShell(sessionName, workingDirectory) {
272
+ let shell = '';
273
+ try {
274
+ const { stdout } = await execFileAsync('tmux', ['show-options', '-gv', 'default-shell'], { timeout: DEFAULT_TIMEOUT });
275
+ shell = stdout.trim();
276
+ }
277
+ catch {
278
+ // Fall through to the environment's shell.
279
+ }
280
+ if (!shell)
281
+ shell = process.env.SHELL || '/bin/sh';
282
+ await execFileAsync('tmux', ['respawn-pane', '-k', '-t', `${exactTarget(sessionName)}0`, '-c', workingDirectory, shell, '-l'], { timeout: DEFAULT_TIMEOUT });
283
+ }
257
284
  /**
258
285
  * Create a new tmux session
259
286
  *
@@ -300,7 +327,23 @@ async function createSession(sessionNameOrOptions, cwd) {
300
327
  try {
301
328
  // Create session with explicit window size to avoid 80x24 default
302
329
  // This is critical for TUI tools (Copilot, OpenCode) that use alternate screen
303
- await execFileAsync('tmux', ['new-session', '-d', '-s', sessionName, '-c', workingDirectory, '-x', String(windowWidth), '-y', String(windowHeight)], { timeout: DEFAULT_TIMEOUT });
330
+ //
331
+ // Issue #2958: window 0 runs a PLACEHOLDER, not the login shell, because it
332
+ // is thrown away by the `new-window -k` below a few milliseconds later. A
333
+ // shell killed that early is still inside its rc files, and pyenv's
334
+ // `pyenv init -` (`command pyenv rehash`) can die holding its lock file
335
+ // (`$PYENV_ROOT/shims/.pyenv-shim`). The NEXT shell then spins in
336
+ // `pyenv rehash` for its 60s lock timeout before running the launch command,
337
+ // so the agent missed the 60s initialization wait (exit 99). Measured on tmux
338
+ // 3.5a / pyenv 2.6.0: 7 of 40 shell-first creations left the lock behind and
339
+ // the replacement pane ran its first command after 61s; 0 of 40 with the
340
+ // placeholder. Two argv words make tmux exec it directly, so no shell (and
341
+ // no rc file) is started for window 0 at all.
342
+ await execFileAsync('tmux', [
343
+ 'new-session', '-d', '-s', sessionName, '-c', workingDirectory,
344
+ '-x', String(windowWidth), '-y', String(windowHeight),
345
+ ...PLACEHOLDER_PANE_COMMAND,
346
+ ], { timeout: DEFAULT_TIMEOUT });
304
347
  // Issue #1624: `history-limit` must be set BEFORE the pane that uses it exists.
305
348
  //
306
349
  // It is a session option, but a pane sizes its scrollback buffer ONCE, from
@@ -324,7 +367,9 @@ async function createSession(sessionNameOrOptions, cwd) {
324
367
  // cwd instead). Omitting it silently launches every agent in the wrong repo.
325
368
  //
326
369
  // Best-effort, matching the geometry step below: if this fails the session is
327
- // still usable, just with tmux's default 2000-line scrollback.
370
+ // still usable, just with tmux's default 2000-line scrollback. Window 0 is
371
+ // only a placeholder (Issue #2958), so the fallback must still put the login
372
+ // shell into it — see respawnLoginShell().
328
373
  try {
329
374
  await execFileAsync('tmux', ['new-window', '-k', '-t', `${exactTarget(sessionName)}0`, '-c', workingDirectory], { timeout: DEFAULT_TIMEOUT });
330
375
  }
@@ -334,6 +379,7 @@ async function createSession(sessionNameOrOptions, cwd) {
334
379
  historyLimit,
335
380
  error: error instanceof Error ? error.message : String(error),
336
381
  });
382
+ await respawnLoginShell(sessionName, workingDirectory);
337
383
  }
338
384
  // Issue #1163: Pin the pane to a fixed height so alternate-screen TUIs
339
385
  // (Claude/Codex/etc.) keep enough visible rows for capture-pane.
@@ -17,7 +17,9 @@
17
17
  * counted, and it is the single failure this gate must not reproduce.
18
18
  * 2. **Additions and removals are judged asymmetrically.** Everything that
19
19
  * existed at task start must still exist, whoever it belonged to — that is
20
- * the pkill (#1739) and `kill-server` (#1624) case. New things are a
20
+ * the pkill (#1739) and `kill-server` (#1624) case — with one exception: a
21
+ * tmux session the baseline recorded as *another CommandMate server's*
22
+ * (#2627), which that server may close whenever it likes. New things are a
21
23
  * violation *unless they are attributable to another worker*, because
22
24
  * parallel delegations legitimately start their own sessions and servers
23
25
  * inside each other's measurement windows — or unless they are the one
@@ -29,17 +31,25 @@
29
31
  * @module lib/verification/env-clean-gate
30
32
  */
31
33
  Object.defineProperty(exports, "__esModule", { value: true });
32
- exports.ENV_CLEAN_GUIDANCE = exports.MAX_REPORTED_ENV_CHANGES = exports.REQUIRE_ENV_CLEAN_SOURCE_CONTRACT = exports.REQUIRE_ENV_CLEAN_SOURCE_CONFIG = void 0;
34
+ exports.ENV_CLEAN_GUIDANCE = exports.MAX_REPORTED_ENV_CHANGES = exports.readLivePidCwd = exports.REQUIRE_ENV_CLEAN_SOURCE_CONTRACT = exports.REQUIRE_ENV_CLEAN_SOURCE_CONFIG = void 0;
33
35
  exports.resolveRequireEnvClean = resolveRequireEnvClean;
34
36
  exports.attributeSessionName = attributeSessionName;
35
37
  exports.attributeAnchor = attributeAnchor;
38
+ exports.demoVitestPid = demoVitestPid;
39
+ exports.attributeHomeEntry = attributeHomeEntry;
36
40
  exports.resolveTaskSessionName = resolveTaskSessionName;
37
41
  exports.recordTaskSession = recordTaskSession;
38
42
  exports.readTaskSession = readTaskSession;
43
+ exports.currentSessionServer = currentSessionServer;
44
+ exports.isOtherServerSession = isOtherServerSession;
45
+ exports.recordOtherServerSessions = recordOtherServerSessions;
46
+ exports.readOtherServerSessions = readOtherServerSessions;
39
47
  exports.diffEnvSnapshots = diffEnvSnapshots;
40
48
  exports.formatEnvCleanReport = formatEnvCleanReport;
41
49
  exports.envCleanNoBaseline = envCleanNoBaseline;
42
50
  exports.evaluateEnvClean = evaluateEnvClean;
51
+ const child_process_1 = require("child_process");
52
+ const fs_1 = require("fs");
43
53
  const path_1 = require("path");
44
54
  const session_name_1 = require("../../lib/cli-tools/session-name");
45
55
  const types_1 = require("../../lib/cli-tools/types");
@@ -132,16 +142,92 @@ function attributeAnchor(anchor, worktreePath) {
132
142
  return 'other';
133
143
  return 'unattributed';
134
144
  }
135
- function attributeEntry(probeId, entry, context) {
145
+ /** Bounded like the snapshot probes: a hung `lsof` must not hold a run open. */
146
+ const PID_CWD_TIMEOUT_MS = 5_000;
147
+ /**
148
+ * Read a process's cwd from the machine: `/proc/<pid>/cwd` on Linux, `lsof` on
149
+ * macOS (which has no procfs). A dead pid, a process owned by someone this user
150
+ * cannot inspect, or a missing `lsof` all answer null — which leaves the entry
151
+ * unattributed, the strict verdict.
152
+ */
153
+ const readLivePidCwd = (pid) => {
154
+ try {
155
+ process.kill(pid, 0);
156
+ }
157
+ catch (error) {
158
+ // EPERM means the process exists but belongs to another user.
159
+ if (error.code !== 'EPERM')
160
+ return null;
161
+ }
162
+ if (process.platform === 'linux') {
163
+ try {
164
+ return (0, fs_1.readlinkSync)(`/proc/${pid}/cwd`);
165
+ }
166
+ catch {
167
+ return null;
168
+ }
169
+ }
170
+ try {
171
+ const out = (0, child_process_1.execFileSync)('lsof', ['-a', '-d', 'cwd', '-p', String(pid), '-F', 'n'], {
172
+ encoding: 'utf8',
173
+ timeout: PID_CWD_TIMEOUT_MS,
174
+ stdio: ['ignore', 'pipe', 'ignore'],
175
+ });
176
+ const line = out.split('\n').find((field) => field.startsWith('n'));
177
+ return line ? line.slice(1) : null;
178
+ }
179
+ catch {
180
+ return null;
181
+ }
182
+ };
183
+ exports.readLivePidCwd = readLivePidCwd;
184
+ /**
185
+ * `tests/unit/skills/demo-video/env-scripts.test.ts` creates
186
+ * `~/.commandmate-demo-vitest-<pid>` for the length of its run — in the real
187
+ * `$HOME`, because `env-up.sh` refuses `/tmp` and `/var` (#2954). The name
188
+ * carries the pid of the test process that made it, which is the one `$HOME`
189
+ * entry whose owner can be established.
190
+ */
191
+ const DEMO_VITEST_HOME_ENTRY = /^\.commandmate-demo-vitest-([1-9]\d*)$/;
192
+ /** The pid a `.commandmate-demo-vitest-<pid>` name carries; null for any other name. */
193
+ function demoVitestPid(name) {
194
+ const match = DEMO_VITEST_HOME_ENTRY.exec(name);
195
+ if (!match)
196
+ return null;
197
+ const pid = Number(match[1]);
198
+ return Number.isSafeInteger(pid) ? pid : null;
199
+ }
200
+ /**
201
+ * Attribute a `$HOME` entry (#2954).
202
+ *
203
+ * Only `.commandmate-demo-vitest-<pid>` can be attributed, and only while its
204
+ * pid is alive: the test process's cwd is then judged exactly as a listener's
205
+ * is ({@link attributeAnchor}), so a parallel worktree's test run is `other`.
206
+ * A dead pid, an unreadable cwd, or a cwd inside this worktree leave it
207
+ * unattributed — a directory this worker's own tests failed to remove is still
208
+ * caught.
209
+ */
210
+ function attributeHomeEntry(name, worktreePath, resolvePidCwd = exports.readLivePidCwd) {
211
+ const pid = demoVitestPid(name);
212
+ if (pid === null)
213
+ return 'unattributed';
214
+ const owner = attributeAnchor(resolvePidCwd(pid), worktreePath);
215
+ // `self` is not an excuse for an addition, and a file has no self to report.
216
+ return owner === 'other' ? 'other' : 'unattributed';
217
+ }
218
+ function attributeEntry(probeId, entry, context, resolvePidCwd) {
136
219
  switch (probeId) {
137
220
  case 'tmux-sessions':
138
221
  return attributeSessionName(entry.key, context.worktreeId);
139
222
  case 'listeners':
140
223
  return attributeAnchor(entry.anchor, context.worktreePath);
224
+ case 'home-entries':
225
+ return attributeHomeEntry(entry.key, context.worktreePath, resolvePidCwd);
141
226
  default:
142
227
  // A file has no owner. `$HOME` and `~/.commandmate` are shared, so an
143
228
  // entry appearing there is a violation for whoever is being judged — the
144
- // rule the Issue's incident list is made of.
229
+ // rule the Issue's incident list is made of. The one `$HOME` exception is
230
+ // above (#2954).
145
231
  return 'unattributed';
146
232
  }
147
233
  }
@@ -166,8 +252,12 @@ function resolveTaskSessionName(task) {
166
252
  }
167
253
  }
168
254
  /** A freshly captured baseline, stamped with its task's own agent session. */
169
- function recordTaskSession(snapshot, task) {
170
- return { ...snapshot, taskSession: resolveTaskSessionName(task) };
255
+ function recordTaskSession(snapshot, task, server = currentSessionServer()) {
256
+ return {
257
+ ...snapshot,
258
+ taskSession: resolveTaskSessionName(task),
259
+ otherServerSessions: recordOtherServerSessions(snapshot, server),
260
+ };
171
261
  }
172
262
  /**
173
263
  * The session a baseline excuses: its name, `null` when it was recorded as
@@ -180,6 +270,106 @@ function readTaskSession(baseline) {
180
270
  const recorded = baseline.taskSession;
181
271
  return typeof recorded === 'string' && recorded !== '' ? recorded : null;
182
272
  }
273
+ /**
274
+ * The identity of the server process this module runs in.
275
+ *
276
+ * The adoption table is read through `resolveSessionName`, which returns the
277
+ * adopted legacy name in place of the new-format one — this module may not
278
+ * reach into `lib/tmux` (#1922).
279
+ */
280
+ function currentSessionServer() {
281
+ return {
282
+ namespace: (0, session_name_1.getActiveSessionNamespace)(),
283
+ legacyAliasOf: (newName) => {
284
+ const parsed = (0, session_name_1.parseSessionName)(newName);
285
+ if (!parsed)
286
+ return undefined;
287
+ try {
288
+ const resolved = (0, session_name_1.resolveSessionName)(parsed.cliToolId, parsed.rest);
289
+ return resolved !== newName ? resolved : undefined;
290
+ }
291
+ catch {
292
+ return undefined;
293
+ }
294
+ },
295
+ };
296
+ }
297
+ /**
298
+ * Whether a session name positively belongs to a CommandMate server other than
299
+ * `server`.
300
+ *
301
+ * False whenever that cannot be shown: this server has no namespace (then every
302
+ * name could be its own), or the name is not a CommandMate session name at all.
303
+ */
304
+ function isOtherServerSession(name, server) {
305
+ if (server.namespace === null)
306
+ return false;
307
+ const parsed = (0, session_name_1.parseSessionName)(name);
308
+ if (!parsed)
309
+ return false;
310
+ if (parsed.namespace !== null)
311
+ return parsed.namespace !== server.namespace;
312
+ let ownName;
313
+ try {
314
+ ownName = (0, session_name_1.resolveNamespacedSessionName)(server.namespace, parsed.cliToolId, parsed.rest);
315
+ }
316
+ catch {
317
+ // A name this server could never have built is not one of its adoptions.
318
+ return true;
319
+ }
320
+ return server.legacyAliasOf(ownName) !== name;
321
+ }
322
+ /**
323
+ * The baseline's `mcbd-*` sessions that belonged to another CommandMate server
324
+ * at task creation.
325
+ *
326
+ * Recorded then, because only then is it knowable: this server's legacy
327
+ * adoptions are dropped when their session goes away, so by verification time
328
+ * a vanished adopted session would look like a stranger's.
329
+ *
330
+ * Why this is the line removals are excused on — the design note for #2627:
331
+ *
332
+ * - A removal is a violation because a worker may have killed someone else's
333
+ * session (#1624) or server (#1739). A session *of this server* — the
334
+ * sibling worktree in #1624, whose name carries this server's namespace —
335
+ * stays guarded exactly as before.
336
+ * - A session of *another server* is closed by that server's own lifecycle:
337
+ * the incident of 2026-09-17 was a global-install server's orchestrate
338
+ * finishing issue-107 and moving on to issue-108, with no kill of any kind
339
+ * in the three workers' transcripts. This task has no way to tell that
340
+ * from a worker's kill, and that server — not this gate — owns the fact.
341
+ * - The namespace is the designed marker of "which server" (#2866); nothing
342
+ * else here needs this server's database or a guess at the other
343
+ * repository's paths.
344
+ *
345
+ * Rejected: counting (`one other session gone is fine`) — that is the #1624
346
+ * shape, a sibling session disappearing while this worktree's stays; ignoring
347
+ * every `other` removal — that drops #1624 outright; the database's worktree
348
+ * table — the other server has a different database and the same worktree ids
349
+ * can exist in both, which is why #2866 exists; timing — the two snapshots do
350
+ * not say *when* inside the window something went away; the worker's command
351
+ * log — not recorded in a form the gate reads, and a kill run through a script
352
+ * would not name the session anyway.
353
+ *
354
+ * @returns the names, or null when `server` has no namespace to judge by
355
+ */
356
+ function recordOtherServerSessions(snapshot, server) {
357
+ if (server.namespace === null)
358
+ return null;
359
+ const sessions = snapshot.probes['tmux-sessions'];
360
+ if (!sessions || sessions.status !== 'ok')
361
+ return [];
362
+ return sessions.entries
363
+ .map((entry) => entry.key)
364
+ .filter((name) => isOtherServerSession(name, server));
365
+ }
366
+ /** The recorded other-server sessions of a baseline; empty when none was recorded. */
367
+ function readOtherServerSessions(baseline) {
368
+ const recorded = baseline.otherServerSessions;
369
+ if (!Array.isArray(recorded))
370
+ return new Set();
371
+ return new Set(recorded.filter((name) => typeof name === 'string'));
372
+ }
183
373
  function toChange(entry, owner) {
184
374
  return { key: entry.key, detail: entry.detail, owner };
185
375
  }
@@ -193,7 +383,9 @@ function toChange(entry, owner) {
193
383
  */
194
384
  function diffEnvSnapshots(baseline, final, context, options = {}) {
195
385
  const taskSession = readTaskSession(baseline);
386
+ const otherServerSessions = readOtherServerSessions(baseline);
196
387
  const ignoredHomeEntries = new Set(options.ignoreHomeEntries ?? []);
388
+ const resolvePidCwd = options.resolvePidCwd ?? exports.readLivePidCwd;
197
389
  const probes = env_snapshot_1.ENV_PROBE_IDS.map((probeId) => {
198
390
  const before = baseline.probes[probeId];
199
391
  const after = final.probes[probeId];
@@ -206,6 +398,7 @@ function diffEnvSnapshots(baseline, final, context, options = {}) {
206
398
  ignoredAdded: [],
207
399
  taskSessionAdded: [],
208
400
  removed: [],
401
+ removedByOtherServer: [],
209
402
  ignoredByConfig: [],
210
403
  };
211
404
  }
@@ -218,6 +411,7 @@ function diffEnvSnapshots(baseline, final, context, options = {}) {
218
411
  ignoredAdded: [],
219
412
  taskSessionAdded: [],
220
413
  removed: [],
414
+ removedByOtherServer: [],
221
415
  ignoredByConfig: [],
222
416
  };
223
417
  }
@@ -233,7 +427,7 @@ function diffEnvSnapshots(baseline, final, context, options = {}) {
233
427
  for (const entry of after.entries) {
234
428
  if (beforeKeys.has(entry.key))
235
429
  continue;
236
- const owner = attributeEntry(probeId, entry, context);
430
+ const owner = attributeEntry(probeId, entry, context, resolvePidCwd);
237
431
  if (isIgnoredByConfig(entry)) {
238
432
  ignoredByConfig.push(toChange(entry, owner));
239
433
  continue;
@@ -246,12 +440,29 @@ function diffEnvSnapshots(baseline, final, context, options = {}) {
246
440
  }
247
441
  (owner === 'other' ? ignoredAdded : added).push(toChange(entry, owner));
248
442
  }
443
+ // An excuse for another server's session presumes the tmux server lived
444
+ // through the task. When nothing from the baseline survived and the task's
445
+ // own session is gone too, the likeliest story is `kill-server` (#1624), and
446
+ // every removal is counted.
447
+ const tmuxServerSurvived = probeId === 'tmux-sessions' &&
448
+ after.entries.some((entry) => beforeKeys.has(entry.key) || (taskSession !== null && entry.key === taskSession));
249
449
  const removed = [];
450
+ const removedByOtherServer = [];
250
451
  for (const entry of before.entries) {
251
452
  if (afterKeys.has(entry.key))
252
453
  continue;
253
- const change = toChange(entry, attributeEntry(probeId, entry, context));
254
- (isIgnoredByConfig(entry) ? ignoredByConfig : removed).push(change);
454
+ const change = toChange(entry, attributeEntry(probeId, entry, context, resolvePidCwd));
455
+ if (isIgnoredByConfig(entry)) {
456
+ ignoredByConfig.push(change);
457
+ }
458
+ else if (tmuxServerSurvived &&
459
+ change.owner !== 'self' &&
460
+ otherServerSessions.has(entry.key)) {
461
+ removedByOtherServer.push(change);
462
+ }
463
+ else {
464
+ removed.push(change);
465
+ }
255
466
  }
256
467
  return {
257
468
  probeId,
@@ -261,6 +472,7 @@ function diffEnvSnapshots(baseline, final, context, options = {}) {
261
472
  ignoredAdded,
262
473
  taskSessionAdded,
263
474
  removed,
475
+ removedByOtherServer,
264
476
  ignoredByConfig,
265
477
  };
266
478
  });
@@ -318,6 +530,10 @@ function formatTaskSessionChanges(changes) {
318
530
  * session is: a verdict that silently discounted an entry would read exactly
319
531
  * like one that never saw it.
320
532
  */
533
+ /** Removals excused as another CommandMate server's sessions (#2627), one line each. */
534
+ function formatRemovedByOtherServer(changes) {
535
+ return changes.map((change) => ` · - ${change.key} (ignored: another CommandMate server's session, recorded at task start)`);
536
+ }
321
537
  function formatIgnoredByConfig(changes) {
322
538
  if (changes.length === 0)
323
539
  return [];
@@ -350,6 +566,7 @@ function formatEnvCleanReport(diff) {
350
566
  : '';
351
567
  lines.push(` ${probe.probeId} clean (${label})${excused}`);
352
568
  lines.push(...formatTaskSessionChanges(probe.taskSessionAdded));
569
+ lines.push(...formatRemovedByOtherServer(probe.removedByOtherServer));
353
570
  lines.push(...formatIgnoredByConfig(probe.ignoredByConfig));
354
571
  continue;
355
572
  }
@@ -357,6 +574,7 @@ function formatEnvCleanReport(diff) {
357
574
  lines.push(...formatChanges('+', probe.added));
358
575
  lines.push(...formatChanges('-', probe.removed));
359
576
  lines.push(...formatTaskSessionChanges(probe.taskSessionAdded));
577
+ lines.push(...formatRemovedByOtherServer(probe.removedByOtherServer));
360
578
  lines.push(...formatIgnoredByConfig(probe.ignoredByConfig));
361
579
  for (const excused of probe.ignoredAdded) {
362
580
  lines.push(` · ${excused.key} (ignored: belongs to another worktree)`);
@@ -415,6 +633,7 @@ async function evaluateEnvClean(input) {
415
633
  }
416
634
  const diff = diffEnvSnapshots(input.baseline, final, input, {
417
635
  ignoreHomeEntries: input.ignoreHomeEntries,
636
+ resolvePidCwd: input.resolvePidCwd,
418
637
  });
419
638
  const header = `${verify_config_1.ENV_CLEAN_GATE_ID}: baseline=${new Date(input.baseline.capturedAt).toISOString()} ` +
420
639
  `status=${diff.status} task-session=${describeTaskSession(diff.taskSession)}`;