commandmate 0.41.1 → 0.42.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 (347) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-build-manifest.json +118 -118
  3. package/.next/app-path-routes-manifest.json +25 -25
  4. package/.next/build-manifest.json +2 -2
  5. package/.next/prerender-manifest.json +3 -3
  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.js +1 -1
  9. package/.next/server/app/api/agents/update/route_client-reference-manifest.js +1 -1
  10. package/.next/server/app/api/agents/versions/route.js +1 -1
  11. package/.next/server/app/api/agents/versions/route_client-reference-manifest.js +1 -1
  12. package/.next/server/app/api/app/release-notes/route_client-reference-manifest.js +1 -1
  13. package/.next/server/app/api/app/update/route_client-reference-manifest.js +1 -1
  14. package/.next/server/app/api/app/update-check/route.js +1 -1
  15. package/.next/server/app/api/app/update-check/route_client-reference-manifest.js +1 -1
  16. package/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
  17. package/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
  18. package/.next/server/app/api/auth/status/route_client-reference-manifest.js +1 -1
  19. package/.next/server/app/api/capabilities/route.js +1 -1
  20. package/.next/server/app/api/capabilities/route_client-reference-manifest.js +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_client-reference-manifest.js +1 -1
  23. package/.next/server/app/api/external-apps/[id]/health/route_client-reference-manifest.js +1 -1
  24. package/.next/server/app/api/external-apps/[id]/route_client-reference-manifest.js +1 -1
  25. package/.next/server/app/api/external-apps/route_client-reference-manifest.js +1 -1
  26. package/.next/server/app/api/fs/browse/route_client-reference-manifest.js +1 -1
  27. package/.next/server/app/api/fs/recent-paths/route_client-reference-manifest.js +1 -1
  28. package/.next/server/app/api/hooks/agent-event/route.js +1 -1
  29. package/.next/server/app/api/hooks/agent-event/route.js.nft.json +1 -1
  30. package/.next/server/app/api/hooks/agent-event/route_client-reference-manifest.js +1 -1
  31. package/.next/server/app/api/hooks/claude-done/route.js +2 -2
  32. package/.next/server/app/api/hooks/claude-done/route.js.nft.json +1 -1
  33. package/.next/server/app/api/hooks/claude-done/route_client-reference-manifest.js +1 -1
  34. package/.next/server/app/api/hooks/permission-request/route.js +1 -1
  35. package/.next/server/app/api/hooks/permission-request/route.js.nft.json +1 -1
  36. package/.next/server/app/api/hooks/permission-request/route_client-reference-manifest.js +1 -1
  37. package/.next/server/app/api/metrics/vibe/route_client-reference-manifest.js +1 -1
  38. package/.next/server/app/api/ollama/models/route_client-reference-manifest.js +1 -1
  39. package/.next/server/app/api/push/escalation/route_client-reference-manifest.js +1 -1
  40. package/.next/server/app/api/push/subscriptions/route_client-reference-manifest.js +1 -1
  41. package/.next/server/app/api/push/vapid/route_client-reference-manifest.js +1 -1
  42. package/.next/server/app/api/relays/[relayId]/cancel/route.js +1 -1
  43. package/.next/server/app/api/relays/[relayId]/cancel/route.js.nft.json +1 -1
  44. package/.next/server/app/api/relays/[relayId]/cancel/route_client-reference-manifest.js +1 -1
  45. package/.next/server/app/api/relays/route.js +1 -1
  46. package/.next/server/app/api/relays/route.js.nft.json +1 -1
  47. package/.next/server/app/api/relays/route_client-reference-manifest.js +1 -1
  48. package/.next/server/app/api/remote/pair/route_client-reference-manifest.js +1 -1
  49. package/.next/server/app/api/repositories/[id]/route_client-reference-manifest.js +1 -1
  50. package/.next/server/app/api/repositories/clone/[jobId]/route.js +1 -1
  51. package/.next/server/app/api/repositories/clone/[jobId]/route.js.nft.json +1 -1
  52. package/.next/server/app/api/repositories/clone/[jobId]/route_client-reference-manifest.js +1 -1
  53. package/.next/server/app/api/repositories/clone/route.js +1 -1
  54. package/.next/server/app/api/repositories/clone/route.js.nft.json +1 -1
  55. package/.next/server/app/api/repositories/clone/route_client-reference-manifest.js +1 -1
  56. package/.next/server/app/api/repositories/excluded/route_client-reference-manifest.js +1 -1
  57. package/.next/server/app/api/repositories/restore/route.js +1 -1
  58. package/.next/server/app/api/repositories/restore/route.js.nft.json +1 -1
  59. package/.next/server/app/api/repositories/restore/route_client-reference-manifest.js +1 -1
  60. package/.next/server/app/api/repositories/route.js +1 -1
  61. package/.next/server/app/api/repositories/route.js.nft.json +1 -1
  62. package/.next/server/app/api/repositories/route_client-reference-manifest.js +1 -1
  63. package/.next/server/app/api/repositories/scan/route.js +1 -1
  64. package/.next/server/app/api/repositories/scan/route.js.nft.json +1 -1
  65. package/.next/server/app/api/repositories/scan/route_client-reference-manifest.js +1 -1
  66. package/.next/server/app/api/repositories/sync/route.js +1 -1
  67. package/.next/server/app/api/repositories/sync/route.js.nft.json +1 -1
  68. package/.next/server/app/api/repositories/sync/route_client-reference-manifest.js +1 -1
  69. package/.next/server/app/api/repositories/validate-path/route_client-reference-manifest.js +1 -1
  70. package/.next/server/app/api/settings/default-agents/route.js +1 -1
  71. package/.next/server/app/api/settings/default-agents/route.js.nft.json +1 -1
  72. package/.next/server/app/api/settings/default-agents/route_client-reference-manifest.js +1 -1
  73. package/.next/server/app/api/settings/default-surface-mode/route_client-reference-manifest.js +1 -1
  74. package/.next/server/app/api/sidebar/group-order/route_client-reference-manifest.js +1 -1
  75. package/.next/server/app/api/skills/[id]/route_client-reference-manifest.js +1 -1
  76. package/.next/server/app/api/skills/installations/route_client-reference-manifest.js +1 -1
  77. package/.next/server/app/api/skills/operations/route_client-reference-manifest.js +1 -1
  78. package/.next/server/app/api/skills/reindex/route_client-reference-manifest.js +1 -1
  79. package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
  80. package/.next/server/app/api/slash-commands/route.js.nft.json +1 -1
  81. package/.next/server/app/api/slash-commands/route_client-reference-manifest.js +1 -1
  82. package/.next/server/app/api/tasks/[taskId]/cancel/route_client-reference-manifest.js +1 -1
  83. package/.next/server/app/api/tasks/[taskId]/route_client-reference-manifest.js +1 -1
  84. package/.next/server/app/api/templates/[id]/route_client-reference-manifest.js +1 -1
  85. package/.next/server/app/api/templates/route_client-reference-manifest.js +1 -1
  86. package/.next/server/app/api/verification/runs/[runId]/route_client-reference-manifest.js +1 -1
  87. package/.next/server/app/api/verification/runs/route_client-reference-manifest.js +1 -1
  88. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js +1 -1
  89. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js.nft.json +1 -1
  90. package/.next/server/app/api/worktrees/[id]/auto-yes/route_client-reference-manifest.js +1 -1
  91. package/.next/server/app/api/worktrees/[id]/capture/route.js +1 -1
  92. package/.next/server/app/api/worktrees/[id]/capture/route.js.nft.json +1 -1
  93. package/.next/server/app/api/worktrees/[id]/capture/route_client-reference-manifest.js +1 -1
  94. package/.next/server/app/api/worktrees/[id]/clear-composer/route.js +1 -1
  95. package/.next/server/app/api/worktrees/[id]/clear-composer/route.js.nft.json +1 -1
  96. package/.next/server/app/api/worktrees/[id]/clear-composer/route_client-reference-manifest.js +1 -1
  97. package/.next/server/app/api/worktrees/[id]/cli-reference/route_client-reference-manifest.js +1 -1
  98. package/.next/server/app/api/worktrees/[id]/cli-tool/route_client-reference-manifest.js +1 -1
  99. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route_client-reference-manifest.js +1 -1
  100. package/.next/server/app/api/worktrees/[id]/current-output/route.js +1 -1
  101. package/.next/server/app/api/worktrees/[id]/current-output/route.js.nft.json +1 -1
  102. package/.next/server/app/api/worktrees/[id]/current-output/route_client-reference-manifest.js +1 -1
  103. package/.next/server/app/api/worktrees/[id]/direct-input/route.js +1 -1
  104. package/.next/server/app/api/worktrees/[id]/direct-input/route.js.nft.json +1 -1
  105. package/.next/server/app/api/worktrees/[id]/direct-input/route_client-reference-manifest.js +1 -1
  106. package/.next/server/app/api/worktrees/[id]/env/route_client-reference-manifest.js +1 -1
  107. package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route_client-reference-manifest.js +1 -1
  108. package/.next/server/app/api/worktrees/[id]/execution-logs/route_client-reference-manifest.js +1 -1
  109. package/.next/server/app/api/worktrees/[id]/files/[...path]/route_client-reference-manifest.js +1 -1
  110. package/.next/server/app/api/worktrees/[id]/git/branch/create/route_client-reference-manifest.js +1 -1
  111. package/.next/server/app/api/worktrees/[id]/git/branch/delete/route_client-reference-manifest.js +1 -1
  112. package/.next/server/app/api/worktrees/[id]/git/branches/route_client-reference-manifest.js +1 -1
  113. package/.next/server/app/api/worktrees/[id]/git/checkout/route_client-reference-manifest.js +1 -1
  114. package/.next/server/app/api/worktrees/[id]/git/commit/route_client-reference-manifest.js +1 -1
  115. package/.next/server/app/api/worktrees/[id]/git/diff/route_client-reference-manifest.js +1 -1
  116. package/.next/server/app/api/worktrees/[id]/git/fetch/route_client-reference-manifest.js +1 -1
  117. package/.next/server/app/api/worktrees/[id]/git/log/route_client-reference-manifest.js +1 -1
  118. package/.next/server/app/api/worktrees/[id]/git/pull/route_client-reference-manifest.js +1 -1
  119. package/.next/server/app/api/worktrees/[id]/git/push/route_client-reference-manifest.js +1 -1
  120. package/.next/server/app/api/worktrees/[id]/git/reset/route_client-reference-manifest.js +1 -1
  121. package/.next/server/app/api/worktrees/[id]/git/revert/route_client-reference-manifest.js +1 -1
  122. package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route_client-reference-manifest.js +1 -1
  123. package/.next/server/app/api/worktrees/[id]/git/stage/route_client-reference-manifest.js +1 -1
  124. package/.next/server/app/api/worktrees/[id]/git/staged/route_client-reference-manifest.js +1 -1
  125. package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route_client-reference-manifest.js +1 -1
  126. package/.next/server/app/api/worktrees/[id]/git/stash/apply/route_client-reference-manifest.js +1 -1
  127. package/.next/server/app/api/worktrees/[id]/git/stash/pop/route_client-reference-manifest.js +1 -1
  128. package/.next/server/app/api/worktrees/[id]/git/stash/push/route_client-reference-manifest.js +1 -1
  129. package/.next/server/app/api/worktrees/[id]/git/stash/route_client-reference-manifest.js +1 -1
  130. package/.next/server/app/api/worktrees/[id]/git/status/route_client-reference-manifest.js +1 -1
  131. package/.next/server/app/api/worktrees/[id]/git/unstage/route_client-reference-manifest.js +1 -1
  132. package/.next/server/app/api/worktrees/[id]/git/working-diff/route_client-reference-manifest.js +1 -1
  133. package/.next/server/app/api/worktrees/[id]/instances/notes/route_client-reference-manifest.js +1 -1
  134. package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js.nft.json +1 -1
  135. package/.next/server/app/api/worktrees/[id]/instances/opencode/route_client-reference-manifest.js +1 -1
  136. package/.next/server/app/api/worktrees/[id]/interrupt/route.js +1 -1
  137. package/.next/server/app/api/worktrees/[id]/interrupt/route.js.nft.json +1 -1
  138. package/.next/server/app/api/worktrees/[id]/interrupt/route_client-reference-manifest.js +1 -1
  139. package/.next/server/app/api/worktrees/[id]/kill-session/route.js +1 -1
  140. package/.next/server/app/api/worktrees/[id]/kill-session/route.js.nft.json +1 -1
  141. package/.next/server/app/api/worktrees/[id]/kill-session/route_client-reference-manifest.js +1 -1
  142. package/.next/server/app/api/worktrees/[id]/logs/[filename]/route_client-reference-manifest.js +1 -1
  143. package/.next/server/app/api/worktrees/[id]/logs/route_client-reference-manifest.js +1 -1
  144. package/.next/server/app/api/worktrees/[id]/marp-render/route_client-reference-manifest.js +1 -1
  145. package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route_client-reference-manifest.js +1 -1
  146. package/.next/server/app/api/worktrees/[id]/memos/route_client-reference-manifest.js +1 -1
  147. package/.next/server/app/api/worktrees/[id]/messages/route_client-reference-manifest.js +1 -1
  148. package/.next/server/app/api/worktrees/[id]/opencode/diff/route_client-reference-manifest.js +1 -1
  149. package/.next/server/app/api/worktrees/[id]/opencode/session/route_client-reference-manifest.js +1 -1
  150. package/.next/server/app/api/worktrees/[id]/opencode/share/route_client-reference-manifest.js +1 -1
  151. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js +1 -1
  152. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js.nft.json +1 -1
  153. package/.next/server/app/api/worktrees/[id]/prompt-response/route_client-reference-manifest.js +1 -1
  154. package/.next/server/app/api/worktrees/[id]/resolve-target/route_client-reference-manifest.js +1 -1
  155. package/.next/server/app/api/worktrees/[id]/respond/route.js +1 -1
  156. package/.next/server/app/api/worktrees/[id]/respond/route.js.nft.json +1 -1
  157. package/.next/server/app/api/worktrees/[id]/respond/route_client-reference-manifest.js +1 -1
  158. package/.next/server/app/api/worktrees/[id]/route.js +103 -1
  159. package/.next/server/app/api/worktrees/[id]/route.js.nft.json +1 -1
  160. package/.next/server/app/api/worktrees/[id]/route_client-reference-manifest.js +1 -1
  161. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route_client-reference-manifest.js +1 -1
  162. package/.next/server/app/api/worktrees/[id]/schedules/active/route_client-reference-manifest.js +1 -1
  163. package/.next/server/app/api/worktrees/[id]/schedules/route_client-reference-manifest.js +1 -1
  164. package/.next/server/app/api/worktrees/[id]/search/route_client-reference-manifest.js +1 -1
  165. package/.next/server/app/api/worktrees/[id]/send/route.js +103 -1
  166. package/.next/server/app/api/worktrees/[id]/send/route.js.nft.json +1 -1
  167. package/.next/server/app/api/worktrees/[id]/send/route_client-reference-manifest.js +1 -1
  168. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js +1 -103
  169. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js.nft.json +1 -1
  170. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route_client-reference-manifest.js +1 -1
  171. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route_client-reference-manifest.js +1 -1
  172. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route_client-reference-manifest.js +1 -1
  173. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route_client-reference-manifest.js +1 -1
  174. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route_client-reference-manifest.js +1 -1
  175. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update/route_client-reference-manifest.js +1 -1
  176. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route_client-reference-manifest.js +1 -1
  177. package/.next/server/app/api/worktrees/[id]/skills/route_client-reference-manifest.js +1 -1
  178. package/.next/server/app/api/worktrees/[id]/slash-commands/route.js.nft.json +1 -1
  179. package/.next/server/app/api/worktrees/[id]/slash-commands/route_client-reference-manifest.js +1 -1
  180. package/.next/server/app/api/worktrees/[id]/special-keys/route.js +1 -1
  181. package/.next/server/app/api/worktrees/[id]/special-keys/route.js.nft.json +1 -1
  182. package/.next/server/app/api/worktrees/[id]/special-keys/route_client-reference-manifest.js +1 -1
  183. package/.next/server/app/api/worktrees/[id]/tasks/route.js +2 -2
  184. package/.next/server/app/api/worktrees/[id]/tasks/route_client-reference-manifest.js +1 -1
  185. package/.next/server/app/api/worktrees/[id]/terminal/route.js +1 -103
  186. package/.next/server/app/api/worktrees/[id]/terminal/route.js.nft.json +1 -1
  187. package/.next/server/app/api/worktrees/[id]/terminal/route_client-reference-manifest.js +1 -1
  188. package/.next/server/app/api/worktrees/[id]/timers/history/route_client-reference-manifest.js +1 -1
  189. package/.next/server/app/api/worktrees/[id]/timers/route.js +1 -1
  190. package/.next/server/app/api/worktrees/[id]/timers/route.js.nft.json +1 -1
  191. package/.next/server/app/api/worktrees/[id]/timers/route_client-reference-manifest.js +1 -1
  192. package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
  193. package/.next/server/app/api/worktrees/[id]/todos/route_client-reference-manifest.js +1 -1
  194. package/.next/server/app/api/worktrees/[id]/tree/[...path]/route_client-reference-manifest.js +1 -1
  195. package/.next/server/app/api/worktrees/[id]/tree/route_client-reference-manifest.js +1 -1
  196. package/.next/server/app/api/worktrees/[id]/upload/[...path]/route_client-reference-manifest.js +1 -1
  197. package/.next/server/app/api/worktrees/[id]/verify/config/route.js +1 -1
  198. package/.next/server/app/api/worktrees/[id]/verify/config/route_client-reference-manifest.js +1 -1
  199. package/.next/server/app/api/worktrees/[id]/verify/route.js +1 -1
  200. package/.next/server/app/api/worktrees/[id]/verify/route_client-reference-manifest.js +1 -1
  201. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route.js +1 -1
  202. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route_client-reference-manifest.js +1 -1
  203. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route_client-reference-manifest.js +1 -1
  204. package/.next/server/app/api/worktrees/[id]/verify/runs/route_client-reference-manifest.js +1 -1
  205. package/.next/server/app/api/worktrees/[id]/viewed/route_client-reference-manifest.js +1 -1
  206. package/.next/server/app/api/worktrees/apply-default-agents/route_client-reference-manifest.js +1 -1
  207. package/.next/server/app/api/worktrees/route.js +1 -1
  208. package/.next/server/app/api/worktrees/route.js.nft.json +1 -1
  209. package/.next/server/app/api/worktrees/route_client-reference-manifest.js +1 -1
  210. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  211. package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
  212. package/.next/server/app/more/page_client-reference-manifest.js +1 -1
  213. package/.next/server/app/offline/page_client-reference-manifest.js +1 -1
  214. package/.next/server/app/page_client-reference-manifest.js +1 -1
  215. package/.next/server/app/proxy/[...path]/route_client-reference-manifest.js +1 -1
  216. package/.next/server/app/repositories/page_client-reference-manifest.js +1 -1
  217. package/.next/server/app/review/page_client-reference-manifest.js +1 -1
  218. package/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  219. package/.next/server/app/skills/[skillId]/page_client-reference-manifest.js +1 -1
  220. package/.next/server/app/skills/installed/page_client-reference-manifest.js +1 -1
  221. package/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  222. package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -1
  223. package/.next/server/app/worktrees/[id]/page.js +9 -9
  224. package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -1
  225. package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
  226. package/.next/server/app-paths-manifest.json +25 -25
  227. package/.next/server/chunks/1068.js +1 -0
  228. package/.next/server/chunks/1210.js +1 -1
  229. package/.next/server/chunks/1501.js +5 -5
  230. package/.next/server/chunks/1990.js +103 -0
  231. package/.next/server/chunks/2119.js +1 -1
  232. package/.next/server/chunks/2445.js +1 -1
  233. package/.next/server/chunks/3241.js +1 -1
  234. package/.next/server/chunks/3707.js +1 -1
  235. package/.next/server/chunks/3718.js +1 -0
  236. package/.next/server/chunks/434.js +1 -1
  237. package/.next/server/chunks/4443.js +1 -1
  238. package/.next/server/chunks/5164.js +1 -1
  239. package/.next/server/chunks/5775.js +1 -0
  240. package/.next/server/chunks/611.js +1 -0
  241. package/.next/server/chunks/6130.js +1 -1
  242. package/.next/server/chunks/650.js +1 -1
  243. package/.next/server/chunks/6781.js +1 -1
  244. package/.next/server/chunks/7905.js +1 -1
  245. package/.next/server/chunks/8581.js +1 -1
  246. package/.next/server/chunks/8583.js +1 -1
  247. package/.next/server/chunks/8673.js +2 -2
  248. package/.next/server/chunks/8728.js +3 -3
  249. package/.next/server/chunks/8791.js +1 -0
  250. package/.next/server/chunks/8800.js +1 -1
  251. package/.next/server/chunks/8918.js +1 -103
  252. package/.next/server/chunks/9130.js +2 -2
  253. package/.next/server/chunks/964.js +1 -1
  254. package/.next/server/chunks/9731.js +3 -3
  255. package/.next/server/chunks/9882.js +3 -3
  256. package/.next/server/middleware-manifest.json +5 -5
  257. package/.next/server/pages/500.html +1 -1
  258. package/.next/server/server-reference-manifest.json +1 -1
  259. package/.next/static/chunks/{1642-fb2e176aaadbd137.js → 1642-767aed8e7c61ef7f.js} +1 -1
  260. package/.next/static/chunks/{2407-7bd75de2f6be3692.js → 2407-faae66d204748f7b.js} +1 -1
  261. package/.next/static/chunks/{2619-04bc32f026a0d946.js → 2619-a305ad4810f1393a.js} +1 -1
  262. package/.next/static/chunks/7705-2a2936551b0cf9a3.js +1 -0
  263. package/.next/static/chunks/8165-235859c6930f01b1.js +1 -0
  264. package/.next/static/chunks/app/{layout-51fa91ea833c97fc.js → layout-9a715043610e4e27.js} +1 -1
  265. package/.next/static/chunks/app/worktrees/[id]/page-61dd928d635db590.js +1 -0
  266. package/.next/static/chunks/app/worktrees/[id]/terminal/{page-373ea37b16d930c7.js → page-c601f3b3ece6557e.js} +1 -1
  267. package/.next/static/css/{974314e796232f53.css → b3f433d52b8ed5c8.css} +1 -1
  268. package/.next/trace +13 -13
  269. package/dist/cli/commands/attach.d.ts +6 -4
  270. package/dist/cli/commands/attach.d.ts.map +1 -1
  271. package/dist/cli/commands/attach.js +36 -5
  272. package/dist/cli/commands/instances.d.ts.map +1 -1
  273. package/dist/cli/commands/instances.js +5 -0
  274. package/dist/cli/commands/ls.d.ts.map +1 -1
  275. package/dist/cli/commands/ls.js +19 -9
  276. package/dist/cli/commands/whoami.d.ts +9 -25
  277. package/dist/cli/commands/whoami.d.ts.map +1 -1
  278. package/dist/cli/commands/whoami.js +18 -42
  279. package/dist/cli/types/api-responses.d.ts +37 -0
  280. package/dist/cli/types/api-responses.d.ts.map +1 -1
  281. package/dist/lib/cli-tools/session-name.d.ts +72 -4
  282. package/dist/lib/cli-tools/session-name.d.ts.map +1 -1
  283. package/dist/lib/cli-tools/session-name.js +115 -12
  284. package/dist/lib/detection/tools/verified-against.d.ts +11 -2
  285. package/dist/lib/detection/tools/verified-against.d.ts.map +1 -1
  286. package/dist/lib/detection/tools/verified-against.js +11 -2
  287. package/dist/lib/session/tmux-session-surface.d.ts +9 -7
  288. package/dist/lib/session/tmux-session-surface.d.ts.map +1 -1
  289. package/dist/lib/session/tmux-session-surface.js +15 -8
  290. package/dist/lib/tmux/legacy-session-alias.d.ts +43 -0
  291. package/dist/lib/tmux/legacy-session-alias.d.ts.map +1 -0
  292. package/dist/lib/tmux/legacy-session-alias.js +64 -0
  293. package/dist/lib/verification/verify-config.d.ts +21 -0
  294. package/dist/lib/verification/verify-config.d.ts.map +1 -1
  295. package/dist/lib/verification/verify-config.js +54 -1
  296. package/dist/server/locales/en/worktree.json +4 -1
  297. package/dist/server/locales/ja/worktree.json +4 -1
  298. package/dist/server/server.js +29 -0
  299. package/dist/server/src/lib/auto-yes-poller.js +15 -0
  300. package/dist/server/src/lib/cli-tools/antigravity.js +1 -1
  301. package/dist/server/src/lib/cli-tools/base.js +10 -1
  302. package/dist/server/src/lib/cli-tools/codex.js +1 -1
  303. package/dist/server/src/lib/cli-tools/command-code.js +1 -1
  304. package/dist/server/src/lib/cli-tools/copilot.js +1 -1
  305. package/dist/server/src/lib/cli-tools/gemini.js +1 -1
  306. package/dist/server/src/lib/cli-tools/legacy-session-adoption.js +19 -0
  307. package/dist/server/src/lib/cli-tools/opencode.js +1 -1
  308. package/dist/server/src/lib/cli-tools/session-name.js +115 -12
  309. package/dist/server/src/lib/cli-tools/session-namespace.js +55 -0
  310. package/dist/server/src/lib/cli-tools/session-ownership.js +21 -0
  311. package/dist/server/src/lib/cli-tools/vibe-local.js +1 -1
  312. package/dist/server/src/lib/cli-tools/worktree-session-ownership.js +28 -0
  313. package/dist/server/src/lib/db/app-settings-db.js +29 -0
  314. package/dist/server/src/lib/detection/cli-patterns.js +46 -8
  315. package/dist/server/src/lib/detection/tools/codex/cli-patterns.js +8 -2
  316. package/dist/server/src/lib/detection/tools/codex/detect.js +8 -1
  317. package/dist/server/src/lib/detection/tools/codex/prompt.js +6 -2
  318. package/dist/server/src/lib/detection/tools/verified-against.js +11 -2
  319. package/dist/server/src/lib/hooks/sources/codex/hooks-config.js +77 -2
  320. package/dist/server/src/lib/polling/auto-yes-dialog-gate.js +77 -1
  321. package/dist/server/src/lib/realtime/terminal-broadcast.js +11 -0
  322. package/dist/server/src/lib/session/adopt-legacy-sessions.js +89 -0
  323. package/dist/server/src/lib/session/claude-session.js +13 -10
  324. package/dist/server/src/lib/session/current-output-builder.js +18 -0
  325. package/dist/server/src/lib/session/send-user-message.js +26 -0
  326. package/dist/server/src/lib/session/session-instance-targets.js +53 -0
  327. package/dist/server/src/lib/session/tmux-session-surface.js +15 -8
  328. package/dist/server/src/lib/session/worktree-session-reconcile.js +101 -56
  329. package/dist/server/src/lib/session-cleanup.js +33 -3
  330. package/dist/server/src/lib/tmux/legacy-session-alias.js +64 -0
  331. package/dist/server/src/lib/tmux/session-hook-scripts.js +12 -4
  332. package/dist/server/src/lib/tmux/session-ownership.js +174 -0
  333. package/dist/server/src/lib/tmux/tmux.js +13 -3
  334. package/dist/server/src/lib/verification/env-clean-gate.js +46 -14
  335. package/dist/server/src/lib/verification/gate-runner.js +1 -0
  336. package/dist/server/src/lib/verification/verify-config.js +54 -1
  337. package/dist/server/src/lib/ws-server.js +11 -0
  338. package/package.json +1 -1
  339. package/release-notes/0.42.0.json +62 -0
  340. package/.next/server/chunks/3323.js +0 -1
  341. package/.next/server/chunks/7075.js +0 -1
  342. package/.next/server/chunks/9080.js +0 -1
  343. package/.next/static/chunks/7705-25076b57224da370.js +0 -1
  344. package/.next/static/chunks/8165-d3b7c8a7aa776bc7.js +0 -1
  345. package/.next/static/chunks/app/worktrees/[id]/page-1e6300dd50cd9a4d.js +0 -1
  346. /package/.next/static/{_fBjTkjoWfOqdjl2SeMIN → EbTDBXcXRpFNH4eom-HVv}/_buildManifest.js +0 -0
  347. /package/.next/static/{_fBjTkjoWfOqdjl2SeMIN → EbTDBXcXRpFNH4eom-HVv}/_ssgManifest.js +0 -0
@@ -0,0 +1,174 @@
1
+ "use strict";
2
+ /**
3
+ * tmux session ownership (Issue #2865)
4
+ *
5
+ * Session names (`mcbd-{cli}-{worktreeId}`) carry nothing that identifies the
6
+ * CommandMate server that created them, and worktree IDs are derived from the
7
+ * directory name — so two servers with different DBs and different worktree
8
+ * paths can resolve the SAME session name on the shared default tmux socket.
9
+ * Deciding "is it running?" by name alone then shows, types into, kills and
10
+ * adopts the OTHER server's session.
11
+ *
12
+ * CommandMate always creates sessions with `tmux new-session -c <worktree.path>`,
13
+ * so `#{session_path}` records which worktree a session belongs to. A session is
14
+ * "owned" only when the realpath of its `#{session_path}` equals the realpath of
15
+ * the worktree's path; anything else under the same name is "foreign" and is
16
+ * excluded from display, input, stop and reuse.
17
+ *
18
+ * A worktree whose directory has since moved therefore sees its old session as
19
+ * foreign. That is intentional (fail safe).
20
+ */
21
+ var __importDefault = (this && this.__importDefault) || function (mod) {
22
+ return (mod && mod.__esModule) ? mod : { "default": mod };
23
+ };
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.ForeignSessionError = exports.FOREIGN_SESSION_ERROR_CODE = void 0;
26
+ exports.normalizeOwnershipPath = normalizeOwnershipPath;
27
+ exports.isSessionPathOwnedBy = isSessionPathOwnedBy;
28
+ exports.createCachedOwnershipMatcher = createCachedOwnershipMatcher;
29
+ exports.reportForeignSession = reportForeignSession;
30
+ exports.resetForeignSessionWarningsForTesting = resetForeignSessionWarningsForTesting;
31
+ exports.checkSessionOwnership = checkSessionOwnership;
32
+ exports.assertSessionNotForeign = assertSessionNotForeign;
33
+ exports.foreignSessionErrorBody = foreignSessionErrorBody;
34
+ exports.ownedSessionNameSet = ownedSessionNameSet;
35
+ const fs_1 = __importDefault(require("fs"));
36
+ const path_1 = __importDefault(require("path"));
37
+ const logger_1 = require("../../lib/logger");
38
+ const tmux_1 = require("./tmux");
39
+ const logger = (0, logger_1.createLogger)('session-ownership');
40
+ exports.FOREIGN_SESSION_ERROR_CODE = 'session_owned_by_other_server';
41
+ /**
42
+ * Thrown when a code path would adopt / drive a session another server owns.
43
+ */
44
+ class ForeignSessionError extends Error {
45
+ sessionName;
46
+ sessionPath;
47
+ worktreePath;
48
+ code = exports.FOREIGN_SESSION_ERROR_CODE;
49
+ constructor(sessionName, sessionPath, worktreePath) {
50
+ super(`tmux session "${sessionName}" belongs to another server ` +
51
+ `(session_path=${sessionPath ?? 'unknown'}, worktree=${worktreePath})`);
52
+ this.sessionName = sessionName;
53
+ this.sessionPath = sessionPath;
54
+ this.worktreePath = worktreePath;
55
+ this.name = 'ForeignSessionError';
56
+ }
57
+ }
58
+ exports.ForeignSessionError = ForeignSessionError;
59
+ /**
60
+ * Normalize a path for ownership comparison: realpath when it resolves,
61
+ * otherwise `path.resolve()`; trailing `/` removed; case preserved.
62
+ */
63
+ function normalizeOwnershipPath(p) {
64
+ let resolved;
65
+ try {
66
+ resolved = fs_1.default.realpathSync.native(p);
67
+ }
68
+ catch {
69
+ resolved = path_1.default.resolve(p);
70
+ }
71
+ if (resolved.length > 1) {
72
+ resolved = resolved.replace(/\/+$/, '');
73
+ }
74
+ return resolved === '' ? '/' : resolved;
75
+ }
76
+ /**
77
+ * Pure comparison: is a session created in `sessionPath` owned by the worktree
78
+ * at `worktreePath`? `null` (tmux could not say) is never owned.
79
+ *
80
+ * @param normalize - Path normalizer; {@link createCachedOwnershipMatcher}
81
+ * passes a memoized one. Defaults to {@link normalizeOwnershipPath}.
82
+ */
83
+ function isSessionPathOwnedBy(sessionPath, worktreePath, normalize = normalizeOwnershipPath) {
84
+ if (sessionPath === null || sessionPath === '')
85
+ return false;
86
+ return normalize(sessionPath) === normalize(worktreePath);
87
+ }
88
+ /**
89
+ * Build an `isSessionPathOwnedBy` that memoizes realpath per input path. Meant
90
+ * to live for one request (e.g. the batch status listing), so a moved/created
91
+ * directory is picked up on the next request.
92
+ */
93
+ function createCachedOwnershipMatcher() {
94
+ const cache = new Map();
95
+ const norm = (p) => {
96
+ let v = cache.get(p);
97
+ if (v === undefined) {
98
+ v = normalizeOwnershipPath(p);
99
+ cache.set(p, v);
100
+ }
101
+ return v;
102
+ };
103
+ return (sessionPath, worktreePath) => isSessionPathOwnedBy(sessionPath, worktreePath, norm);
104
+ }
105
+ const warnedForeignSessions = new Set();
106
+ /**
107
+ * Log `session:foreign-detected` once per session name for the process lifetime.
108
+ */
109
+ function reportForeignSession(sessionName, sessionPath, worktreePath) {
110
+ if (warnedForeignSessions.has(sessionName))
111
+ return;
112
+ warnedForeignSessions.add(sessionName);
113
+ logger.warn('session:foreign-detected', { sessionName, sessionPath, worktreePath });
114
+ }
115
+ /** Test-only: forget which foreign sessions were already reported. */
116
+ function resetForeignSessionWarningsForTesting() {
117
+ warnedForeignSessions.clear();
118
+ }
119
+ /**
120
+ * Decide whether `sessionName` is absent, owned by the worktree at
121
+ * `worktreePath`, or foreign. A session that exists but whose
122
+ * `#{session_path}` cannot be read is treated as foreign (fail safe).
123
+ */
124
+ async function checkSessionOwnership(sessionName, worktreePath) {
125
+ if (!(await (0, tmux_1.hasSession)(sessionName))) {
126
+ return { verdict: 'absent', sessionPath: null };
127
+ }
128
+ const sessionPath = await (0, tmux_1.getSessionWorkingDirectory)(sessionName);
129
+ if (sessionPath !== null && isSessionPathOwnedBy(sessionPath, worktreePath)) {
130
+ return { verdict: 'owned', sessionPath };
131
+ }
132
+ reportForeignSession(sessionName, sessionPath, worktreePath);
133
+ return { verdict: 'foreign', sessionPath };
134
+ }
135
+ /**
136
+ * Throw `ForeignSessionError` when `sessionName` is foreign; otherwise return
137
+ * the ownership verdict (`owned` or `absent`).
138
+ */
139
+ async function assertSessionNotForeign(sessionName, worktreePath) {
140
+ const ownership = await checkSessionOwnership(sessionName, worktreePath);
141
+ if (ownership.verdict === 'foreign') {
142
+ throw new ForeignSessionError(sessionName, ownership.sessionPath, worktreePath);
143
+ }
144
+ return ownership;
145
+ }
146
+ /**
147
+ * JSON body for the HTTP 409 an API route returns for a foreign session.
148
+ */
149
+ function foreignSessionErrorBody(sessionName, sessionPath) {
150
+ return {
151
+ error: `tmux session "${sessionName}" belongs to another CommandMate server`,
152
+ code: exports.FOREIGN_SESSION_ERROR_CODE,
153
+ sessionName,
154
+ sessionPath,
155
+ };
156
+ }
157
+ /**
158
+ * From one batch `listSessions()` result, the names of the sessions the worktree
159
+ * at `worktreePath` owns. Feed this — not the raw name set — to status detection
160
+ * so a same-named foreign session never reads as "running". Other worktrees'
161
+ * sessions drop out too, which is harmless: status detection only looks up the
162
+ * worktree's own session names.
163
+ *
164
+ * @param matcher - Pass one `createCachedOwnershipMatcher()` across all worktrees
165
+ * of a request so each realpath is resolved once.
166
+ */
167
+ function ownedSessionNameSet(tmuxSessions, worktreePath, matcher = createCachedOwnershipMatcher()) {
168
+ const owned = new Set();
169
+ for (const session of tmuxSessions) {
170
+ if (matcher(session.path ?? null, worktreePath))
171
+ owned.add(session.name);
172
+ }
173
+ return owned;
174
+ }
@@ -30,6 +30,7 @@ const child_process_1 = require("child_process");
30
30
  const util_1 = require("util");
31
31
  const tmux_capture_cache_1 = require("./tmux-capture-cache");
32
32
  const geometry_delegation_1 = require("./geometry-delegation");
33
+ const legacy_session_alias_1 = require("./legacy-session-alias");
33
34
  const validation_1 = require("../../lib/cli-tools/validation");
34
35
  const tmux_pane_config_1 = require("../../config/tmux-pane-config");
35
36
  const logger_1 = require("../../lib/logger");
@@ -181,6 +182,9 @@ async function hasSession(sessionName) {
181
182
  }
182
183
  catch {
183
184
  // tmux has-session returns non-zero exit code if session doesn't exist
185
+ // Issue #2866: an adopted legacy session that is gone no longer serves its
186
+ // new-format name, so the next start uses the new-format name.
187
+ (0, legacy_session_alias_1.dropLegacyAliasByLegacyName)(sessionName);
184
188
  return false;
185
189
  }
186
190
  }
@@ -225,19 +229,23 @@ async function getSessionWorkingDirectory(sessionName) {
225
229
  */
226
230
  async function listSessions() {
227
231
  try {
228
- const { stdout } = await execFileAsync('tmux', ['list-sessions', '-F', '#{session_name}|#{session_windows}|#{session_attached}'], { timeout: DEFAULT_TIMEOUT });
232
+ // Issue #2865: `#{session_path}` is the LAST column and tab-separated, so a
233
+ // path containing `|` or spaces survives intact (everything after the third
234
+ // tab is the path).
235
+ const { stdout } = await execFileAsync('tmux', ['list-sessions', '-F', '#{session_name}\t#{session_windows}\t#{session_attached}\t#{session_path}'], { timeout: DEFAULT_TIMEOUT });
229
236
  if (!stdout || stdout.trim() === '') {
230
237
  return [];
231
238
  }
232
239
  return stdout
233
- .trim()
234
240
  .split('\n')
241
+ .filter(line => line.trim() !== '')
235
242
  .map(line => {
236
- const [name, windows, attached] = line.split('|');
243
+ const [name, windows, attached, ...rest] = line.split('\t');
237
244
  return {
238
245
  name,
239
246
  windows: parseInt(windows, 10) || 0,
240
247
  attached: attached === '1',
248
+ path: rest.join('\t'),
241
249
  };
242
250
  });
243
251
  }
@@ -628,6 +636,8 @@ async function killSession(sessionName) {
628
636
  await execFileAsync('tmux', ['kill-session', '-t', exactTarget(sessionName)], {
629
637
  timeout: DEFAULT_TIMEOUT,
630
638
  });
639
+ // Issue #2866: see hasSession.
640
+ (0, legacy_session_alias_1.dropLegacyAliasByLegacyName)(sessionName);
631
641
  return true;
632
642
  }
633
643
  catch (error) {
@@ -85,10 +85,13 @@ function resolveRequireEnvClean(contract, config) {
85
85
  sources.push(exports.REQUIRE_ENV_CLEAN_SOURCE_CONTRACT);
86
86
  return { required: sources.length > 0, sources };
87
87
  }
88
- /** CLI tool ids, longest first: `vibe-local` must not be stripped as `vibe`. */
89
- const CLI_PREFIXES = [...types_1.CLI_TOOL_IDS].sort((a, b) => b.length - a.length);
90
88
  /**
91
- * Attribute an `mcbd-<cli>-<worktreeId>[-suffix]` session name to a worktree.
89
+ * Attribute an `mcbd-[<ns>-]<cli>-<worktreeId>[-suffix]` session name to a
90
+ * worktree.
91
+ *
92
+ * The namespace (Issue #2866) is not consulted: the worktree ID is what ties a
93
+ * session to this task, and a session this task's agent started in any
94
+ * server's namespace is still this task's addition.
92
95
  *
93
96
  * Ambiguity resolves towards `self` on purpose. Worktree ids may contain
94
97
  * hyphens, so `mcbd-claude-foo-bar` is genuinely ambiguous between worktree
@@ -97,13 +100,10 @@ const CLI_PREFIXES = [...types_1.CLI_TOOL_IDS].sort((a, b) => b.length - a.lengt
97
100
  * rather than a missed leak.
98
101
  */
99
102
  function attributeSessionName(name, worktreeId) {
100
- if (!name.startsWith(env_snapshot_1.MCBD_SESSION_PREFIX))
101
- return 'unattributed';
102
- const rest = name.slice(env_snapshot_1.MCBD_SESSION_PREFIX.length);
103
- const cli = CLI_PREFIXES.find((id) => rest.startsWith(`${id}-`));
104
- if (!cli)
103
+ const parsed = (0, session_name_1.parseSessionName)(name);
104
+ if (!parsed)
105
105
  return 'unattributed';
106
- const tail = rest.slice(cli.length + 1);
106
+ const tail = parsed.rest;
107
107
  if (tail === worktreeId || tail.startsWith(`${worktreeId}-`))
108
108
  return 'self';
109
109
  return 'other';
@@ -191,8 +191,9 @@ function toChange(entry, owner) {
191
191
  * as an empty set — would report every entry as added or removed, which is worse
192
192
  * than useless, and treating it as equal would be the fail-open.
193
193
  */
194
- function diffEnvSnapshots(baseline, final, context) {
194
+ function diffEnvSnapshots(baseline, final, context, options = {}) {
195
195
  const taskSession = readTaskSession(baseline);
196
+ const ignoredHomeEntries = new Set(options.ignoreHomeEntries ?? []);
196
197
  const probes = env_snapshot_1.ENV_PROBE_IDS.map((probeId) => {
197
198
  const before = baseline.probes[probeId];
198
199
  const after = final.probes[probeId];
@@ -205,6 +206,7 @@ function diffEnvSnapshots(baseline, final, context) {
205
206
  ignoredAdded: [],
206
207
  taskSessionAdded: [],
207
208
  removed: [],
209
+ ignoredByConfig: [],
208
210
  };
209
211
  }
210
212
  if (!after || after.status !== 'ok') {
@@ -216,17 +218,26 @@ function diffEnvSnapshots(baseline, final, context) {
216
218
  ignoredAdded: [],
217
219
  taskSessionAdded: [],
218
220
  removed: [],
221
+ ignoredByConfig: [],
219
222
  };
220
223
  }
221
224
  const beforeKeys = new Set(before.entries.map((entry) => entry.key));
222
225
  const afterKeys = new Set(after.entries.map((entry) => entry.key));
226
+ // Only `home-entries`, and only by the whole name: the same string under
227
+ // `~/.commandmate` is a different directory and stays counted.
228
+ const isIgnoredByConfig = (entry) => probeId === 'home-entries' && ignoredHomeEntries.has(entry.key);
223
229
  const added = [];
224
230
  const ignoredAdded = [];
225
231
  const taskSessionAdded = [];
232
+ const ignoredByConfig = [];
226
233
  for (const entry of after.entries) {
227
234
  if (beforeKeys.has(entry.key))
228
235
  continue;
229
236
  const owner = attributeEntry(probeId, entry, context);
237
+ if (isIgnoredByConfig(entry)) {
238
+ ignoredByConfig.push(toChange(entry, owner));
239
+ continue;
240
+ }
230
241
  if (probeId === 'tmux-sessions' && taskSession && entry.key === taskSession) {
231
242
  // Additions only: a task session that existed at task start and is gone
232
243
  // falls through to `removed` below like everything else (#1624).
@@ -235,9 +246,13 @@ function diffEnvSnapshots(baseline, final, context) {
235
246
  }
236
247
  (owner === 'other' ? ignoredAdded : added).push(toChange(entry, owner));
237
248
  }
238
- const removed = before.entries
239
- .filter((entry) => !afterKeys.has(entry.key))
240
- .map((entry) => toChange(entry, attributeEntry(probeId, entry, context)));
249
+ const removed = [];
250
+ for (const entry of before.entries) {
251
+ if (afterKeys.has(entry.key))
252
+ continue;
253
+ const change = toChange(entry, attributeEntry(probeId, entry, context));
254
+ (isIgnoredByConfig(entry) ? ignoredByConfig : removed).push(change);
255
+ }
241
256
  return {
242
257
  probeId,
243
258
  status: added.length + removed.length > 0 ? 'violated' : 'clean',
@@ -246,6 +261,7 @@ function diffEnvSnapshots(baseline, final, context) {
246
261
  ignoredAdded,
247
262
  taskSessionAdded,
248
263
  removed,
264
+ ignoredByConfig,
249
265
  };
250
266
  });
251
267
  // A measured violation is a verdict and outranks an unmeasured probe; an
@@ -296,6 +312,18 @@ function formatTaskSessionChanges(changes) {
296
312
  return ` + ${change.key}${detail} [task session, excused]`;
297
313
  });
298
314
  }
315
+ /**
316
+ * `home-entries` changes dropped by `options.envCleanIgnoreHomeEntries`, on one
317
+ * line (#2890). Listed rather than dropped for the reason the excused task
318
+ * session is: a verdict that silently discounted an entry would read exactly
319
+ * like one that never saw it.
320
+ */
321
+ function formatIgnoredByConfig(changes) {
322
+ if (changes.length === 0)
323
+ return [];
324
+ const names = changes.map((change) => change.key).join(', ');
325
+ return [` ignored (options.envCleanIgnoreHomeEntries): ${names}`];
326
+ }
299
327
  /**
300
328
  * The header's account of what could be excused, so a report judged against a
301
329
  * baseline written before #2472 says why the task's own session was not.
@@ -322,12 +350,14 @@ function formatEnvCleanReport(diff) {
322
350
  : '';
323
351
  lines.push(` ${probe.probeId} clean (${label})${excused}`);
324
352
  lines.push(...formatTaskSessionChanges(probe.taskSessionAdded));
353
+ lines.push(...formatIgnoredByConfig(probe.ignoredByConfig));
325
354
  continue;
326
355
  }
327
356
  lines.push(` ${probe.probeId} VIOLATED (${label}): +${probe.added.length} -${probe.removed.length}`);
328
357
  lines.push(...formatChanges('+', probe.added));
329
358
  lines.push(...formatChanges('-', probe.removed));
330
359
  lines.push(...formatTaskSessionChanges(probe.taskSessionAdded));
360
+ lines.push(...formatIgnoredByConfig(probe.ignoredByConfig));
331
361
  for (const excused of probe.ignoredAdded) {
332
362
  lines.push(` · ${excused.key} (ignored: belongs to another worktree)`);
333
363
  }
@@ -383,7 +413,9 @@ async function evaluateEnvClean(input) {
383
413
  return done('error', `${verify_config_1.ENV_CLEAN_GATE_ID}: UNKNOWN — the current snapshot could not be taken: ` +
384
414
  `${error instanceof Error ? error.message : String(error)}`, null);
385
415
  }
386
- const diff = diffEnvSnapshots(input.baseline, final, input);
416
+ const diff = diffEnvSnapshots(input.baseline, final, input, {
417
+ ignoreHomeEntries: input.ignoreHomeEntries,
418
+ });
387
419
  const header = `${verify_config_1.ENV_CLEAN_GATE_ID}: baseline=${new Date(input.baseline.capturedAt).toISOString()} ` +
388
420
  `status=${diff.status} task-session=${describeTaskSession(diff.taskSession)}`;
389
421
  const report = `${header}\n${formatEnvCleanReport(diff)}`;
@@ -1154,6 +1154,7 @@ cancellation) {
1154
1154
  taskId: envClean.taskId,
1155
1155
  baseline: envClean.baseline,
1156
1156
  sources: envClean.decision.sources,
1157
+ ignoreHomeEntries: config.options.envCleanIgnoreHomeEntries,
1157
1158
  }));
1158
1159
  statuses.push(outcome.status);
1159
1160
  if (cancellation.cancelled) {
@@ -8,7 +8,7 @@
8
8
  * Server-only: reads from disk, so import this from API routes / CLI only.
9
9
  */
10
10
  Object.defineProperty(exports, "__esModule", { value: true });
11
- exports.VerifyConfigError = exports.MAX_RETRY_ON_FAIL = exports.MAX_GATE_MUTEX_LENGTH = exports.GATE_MUTEX_PATTERN = exports.GATE_ID_PATTERN = exports.DEFAULT_MAX_LOG_TAIL_BYTES = exports.DEFAULT_TIMEOUT_SEC = exports.VERIFY_CONFIG_RELATIVE_PATH = exports.RESERVED_GATE_IDS = exports.ENV_CLEAN_GATE_ID = exports.SCOPE_GATE_ID = exports.WORK_EVIDENCE_GATE_ID = void 0;
11
+ exports.VerifyConfigError = exports.MAX_ENV_CLEAN_IGNORE_HOME_ENTRIES = exports.MAX_RETRY_ON_FAIL = exports.MAX_GATE_MUTEX_LENGTH = exports.GATE_MUTEX_PATTERN = exports.GATE_ID_PATTERN = exports.DEFAULT_MAX_LOG_TAIL_BYTES = exports.DEFAULT_TIMEOUT_SEC = exports.VERIFY_CONFIG_RELATIVE_PATH = exports.RESERVED_GATE_IDS = exports.ENV_CLEAN_GATE_ID = exports.SCOPE_GATE_ID = exports.WORK_EVIDENCE_GATE_ID = void 0;
12
12
  exports.defaultPlannedGateIds = defaultPlannedGateIds;
13
13
  exports.validateGateEntries = validateGateEntries;
14
14
  exports.loadVerifyConfig = loadVerifyConfig;
@@ -110,6 +110,11 @@ exports.MAX_GATE_MUTEX_LENGTH = 64;
110
110
  * reports the machine's luck, not the work.
111
111
  */
112
112
  exports.MAX_RETRY_ON_FAIL = 1;
113
+ /**
114
+ * Most names `options.envCleanIgnoreHomeEntries` may list (Issue #2890). A list
115
+ * this long is already a repository papering over a machine it should fix.
116
+ */
117
+ exports.MAX_ENV_CLEAN_IGNORE_HOME_ENTRIES = 32;
113
118
  const TOP_LEVEL_KEYS = ['version', 'gates', 'options'];
114
119
  const GATE_KEYS = ['id', 'command', 'timeoutSec', 'mutex', 'retryOnFail', 'flakyIsPass'];
115
120
  const OPTION_KEYS = [
@@ -118,6 +123,7 @@ const OPTION_KEYS = [
118
123
  'maxLogTailBytes',
119
124
  'requireCommit',
120
125
  'requireEnvClean',
126
+ 'envCleanIgnoreHomeEntries',
121
127
  ];
122
128
  class VerifyConfigError extends Error {
123
129
  issues;
@@ -316,6 +322,47 @@ function validateGates(value, issues) {
316
322
  }
317
323
  return validateGateEntries(value, 'gates', issues);
318
324
  }
325
+ /**
326
+ * Validate `options.envCleanIgnoreHomeEntries` (Issue #2890).
327
+ *
328
+ * Each item must be usable as one exact `$HOME` directory-entry name: a string,
329
+ * non-empty, not `.` / `..`, and free of `/` and NUL. Anything with a separator
330
+ * could never equal a `readdir` result, so accepting it would be a rule that
331
+ * silently matches nothing.
332
+ *
333
+ * @returns the names, or null when the value was invalid (issues were pushed)
334
+ */
335
+ function validateHomeEntryNames(value, issues) {
336
+ const label = 'options.envCleanIgnoreHomeEntries';
337
+ if (!Array.isArray(value)) {
338
+ issues.push(`${label}: must be a list of $HOME entry names (got ${describe(value)})`);
339
+ return null;
340
+ }
341
+ const before = issues.length;
342
+ if (value.length > exports.MAX_ENV_CLEAN_IGNORE_HOME_ENTRIES) {
343
+ issues.push(`${label}: at most ${exports.MAX_ENV_CLEAN_IGNORE_HOME_ENTRIES} entries (got ${value.length})`);
344
+ }
345
+ const names = [];
346
+ value.forEach((item, index) => {
347
+ const at = `${label}[${index}]`;
348
+ if (typeof item !== 'string') {
349
+ issues.push(`${at}: must be a string (got ${describe(item)})`);
350
+ }
351
+ else if (item === '') {
352
+ issues.push(`${at}: must not be empty`);
353
+ }
354
+ else if (item === '.' || item === '..') {
355
+ issues.push(`${at}: must be an entry name, not ${JSON.stringify(item)}`);
356
+ }
357
+ else if (item.includes('/') || item.includes('\0')) {
358
+ issues.push(`${at}: must be a single $HOME entry name without "/" or NUL (got ${describe(item)})`);
359
+ }
360
+ else {
361
+ names.push(item);
362
+ }
363
+ });
364
+ return issues.length === before ? names : null;
365
+ }
319
366
  function validateOptions(value, issues) {
320
367
  const options = {
321
368
  baseRef: null,
@@ -323,6 +370,7 @@ function validateOptions(value, issues) {
323
370
  maxLogTailBytes: exports.DEFAULT_MAX_LOG_TAIL_BYTES,
324
371
  requireCommit: false,
325
372
  requireEnvClean: false,
373
+ envCleanIgnoreHomeEntries: [],
326
374
  };
327
375
  // A childless `options:` key parses as null and means "all defaults".
328
376
  if (value === undefined || value === null)
@@ -367,6 +415,11 @@ function validateOptions(value, issues) {
367
415
  options.requireEnvClean = parsed;
368
416
  }
369
417
  }
418
+ if (value.envCleanIgnoreHomeEntries !== undefined) {
419
+ const names = validateHomeEntryNames(value.envCleanIgnoreHomeEntries, issues);
420
+ if (names)
421
+ options.envCleanIgnoreHomeEntries = names;
422
+ }
370
423
  if (value.maxLogTailBytes !== undefined) {
371
424
  const parsed = asInteger(value.maxLogTailBytes);
372
425
  if (parsed === null) {
@@ -31,6 +31,7 @@ const db_instance_1 = require("./db/db-instance");
31
31
  const db_1 = require("./db");
32
32
  const tmux_control_mode_metrics_1 = require("./tmux/tmux-control-mode-metrics");
33
33
  const control_mode_tmux_transport_1 = require("./tmux/control-mode-tmux-transport");
34
+ const session_ownership_1 = require("./cli-tools/session-ownership");
34
35
  const tmux_control_mode_flags_1 = require("./tmux/tmux-control-mode-flags");
35
36
  const cache_1 = require("./external-apps/cache");
36
37
  const version_checker_1 = require("../lib/version-checker");
@@ -782,6 +783,16 @@ async function handleTerminalSubscribe(ws, message) {
782
783
  clientInfo.terminalSubscription = null;
783
784
  }
784
785
  const sessionName = (0, session_name_1.resolveSessionName)(cliToolId, worktreeId);
786
+ // Issue #2865: never stream a same-named session another CommandMate server
787
+ // created (its `#{session_path}` is not this worktree's directory).
788
+ const ownership = await (0, session_ownership_1.checkSessionOwnership)(sessionName, worktree.path);
789
+ if (ownership.verdict === 'foreign') {
790
+ sendTerminalEvent(ws, {
791
+ type: 'terminal_error',
792
+ error: 'Session belongs to another CommandMate server',
793
+ });
794
+ return;
795
+ }
785
796
  const transport = (0, control_mode_tmux_transport_1.getControlModeTmuxTransport)();
786
797
  if (transport.getSubscriberCount(sessionName) >= MAX_TERMINAL_SUBSCRIBERS_PER_SESSION) {
787
798
  sendTerminalEvent(ws, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "commandmate",
3
- "version": "0.41.1",
3
+ "version": "0.42.0",
4
4
  "description": "A local control plane for agent CLIs — orchestration and visibility for Claude Code, Codex, Gemini CLI, and more across Git worktrees",
5
5
  "keywords": [
6
6
  "claude-code",
@@ -0,0 +1,62 @@
1
+ {
2
+ "version": "0.42.0",
3
+ "date": "2026-09-27",
4
+ "highlight": {
5
+ "ja": "同じマシンで複数の CommandMate を動かしても、別のサーバのエージェントの画面が見えたり操作できたりしないようになりました。codex 0.157 の新しい画面にも対応しました。",
6
+ "en": "Running several CommandMate servers on one machine no longer lets one server see or drive another server's agents. The new screens in codex 0.157 are also supported."
7
+ },
8
+ "added": [
9
+ {
10
+ "ja": "選択画面で送信が続けて効かないとき、直接入力モードに切り替えるリンクが表示されるようになりました。",
11
+ "en": "When sending on a selection screen keeps having no effect, a link to switch to direct input mode is now shown."
12
+ },
13
+ {
14
+ "ja": "検証の環境チェックで、作業と無関係なホームディレクトリの項目を名前で除外できるようになりました。",
15
+ "en": "The environment check in verification can now ignore unrelated items in your home directory by name."
16
+ }
17
+ ],
18
+ "improved": [
19
+ {
20
+ "ja": "エージェントのセッション名にサーバごとの名前が付くようになり、別のサーバと同じ名前のプロジェクトでもセッションを起動できるようになりました。",
21
+ "en": "Agent session names now include a per-server name, so sessions can start even when another server has a project with the same name."
22
+ },
23
+ {
24
+ "ja": "CLI の attach・ls・whoami・instances が新しいセッション名に対応しました。",
25
+ "en": "The CLI attach, ls, whoami, and instances commands now work with the new session names."
26
+ }
27
+ ],
28
+ "fixed": [
29
+ {
30
+ "ja": "別のサーバが起動した同じ名前のセッションが表示され、送信や停止ができてしまう問題を直しました。",
31
+ "en": "Fixed sessions started by another server with the same name being shown and accepting messages or stop requests."
32
+ },
33
+ {
34
+ "ja": "codex 0.157 のモデル選択画面を選択画面として扱えず、送信しても反応しなかった問題を直しました。",
35
+ "en": "Fixed the codex 0.157 model picker not being recognized, so sending a choice did nothing."
36
+ },
37
+ {
38
+ "ja": "codex 0.157 のフォルダーの信頼確認画面を認識できなかった問題を直しました。",
39
+ "en": "Fixed the codex 0.157 folder trust screen not being recognized."
40
+ },
41
+ {
42
+ "ja": "CommandMate から答えられない画面に送信ボタンが出ていた問題を直しました。代わりに直接入力への案内が出ます。",
43
+ "en": "Fixed the Send button appearing on screens CommandMate cannot answer. A pointer to direct input is shown instead."
44
+ },
45
+ {
46
+ "ja": "「操作できません」の案内が表示されるまで最大で十数秒かかることがあった問題を直しました。",
47
+ "en": "Fixed the cannot-operate notice sometimes taking up to about fifteen seconds to appear."
48
+ },
49
+ {
50
+ "ja": "スマホでチャット表示のリンクから開いたとき、直接入力に切り替えるとチャット表示に戻ってしまう問題を直しました。",
51
+ "en": "Fixed switching to direct input on a phone going back to the chat view when the page was opened from a chat view link."
52
+ },
53
+ {
54
+ "ja": "codex を複数起動すると、別の codex の返答が最初に起動した codex の会話に入ってしまう問題を直しました。",
55
+ "en": "Fixed replies from one codex instance being saved into the conversation of the first codex that was started."
56
+ },
57
+ {
58
+ "ja": "承認への応答の後に、別のサーバのセッションの画面が会話履歴に取り込まれることがある問題を直しました。",
59
+ "en": "Fixed another server's session screen sometimes being saved into the conversation history after answering an approval."
60
+ }
61
+ ]
62
+ }
@@ -1 +0,0 @@
1
- "use strict";exports.id=3323,exports.ids=[3323],exports.modules={31517:(a,b,c)=>{c.d(b,{DL:()=>j,sD:()=>f});var d=c(2734);let e=(0,c(72626).h)("lib/hooks/stop-history-capture"),f=[150,500,2e3,5e3],g=new Set([d.c]);function h(a){return new Promise(b=>{setTimeout(b,a)})}async function i(a,b,c,d,f,g){let i=Date.now();try{for(let[j,k]of g.entries()){await h(k);let l={};if(await a.captureStructuredHistoryTurn(b.id,c,d,f,l))return e.info("stop-history-capture-deferred-captured",{worktreeId:b.id,cliToolId:c,instanceId:d,attempt:j+1,attempts:g.length,elapsedMs:Date.now()-i}),!0;e.debug("stop-history-capture-deferred-open",{worktreeId:b.id,cliToolId:c,instanceId:d,attempt:j+1,attempts:g.length,outcome:l.outcome??"unavailable",elapsedMs:Date.now()-i})}return e.info("stop-history-capture-deferred-exhausted",{worktreeId:b.id,cliToolId:c,instanceId:d,attempts:g.length,elapsedMs:Date.now()-i}),!1}catch(a){return e.warn("stop-history-capture-deferred-failed",{worktreeId:b.id,cliToolId:c,instanceId:d,error:a instanceof Error?a.message:String(a)}),!1}}async function j(a,b,d,k={}){try{let j=await Promise.all([c.e(1503),c.e(1719),c.e(9080),c.e(2119),c.e(2445),c.e(252),c.e(8800),c.e(8728),c.e(7905),c.e(9731),c.e(8918)]).then(c.bind(c,28918));if(!j.isPullTranscriptHistory(b))return{status:"unavailable"};let l={worktreePath:a.path,transcriptPathHint:null},m={};if(await j.captureStructuredHistoryTurn(a.id,b,d,l,m))return{status:"captured"};let n=()=>"not_yet_closed"===m.outcome?Promise.resolve(!0):j.hasStructuredHistoryTranscript(a.id,b,d,l);if(g.has(b)){let c=k.deferredDelaysMs??f;if(0===c.length||!await n())return{status:"unavailable"};let g=i(j,a,b,d,l,c);return e.info("stop-history-capture-deferred",{worktreeId:a.id,cliToolId:b,instanceId:d,delaysMs:c}),{status:"deferred",deferred:g}}let o=k.retryDelayMs??500;if(o<=0||!await n())return{status:"unavailable"};let p=Math.max(1,k.maxAttempts??3);for(let c=2;c<=p;c+=1){await h(o);let f={},g=await j.captureStructuredHistoryTurn(a.id,b,d,l,f);if(e.debug("stop-history-capture-retried",{worktreeId:a.id,cliToolId:b,instanceId:d,attempt:c,maxAttempts:p,captured:g,outcome:f.outcome??"unavailable"}),g)return{status:"captured"}}return{status:"unavailable"}}catch(c){return e.warn("stop-history-capture-failed",{worktreeId:a.id,cliToolId:b,instanceId:d,error:c instanceof Error?c.message:String(c)}),{status:"unavailable"}}}},52767:(a,b,c)=>{c.d(b,{r:()=>i,g:()=>h});var d=c(48524),e=c(87009),f=c(72626);let g=(0,f.h)("lib/tasks/task-transition-service");function h(a,b,c,f){let h=a.transaction(()=>{let g=(0,d.gg)(a,b);if(!g)return null;let h=g.status,i=function(a,b){switch(a){case"pending":switch(b){case"message_sent":return"running";case"send_failed":case"cancel":return"cancelled";default:return null}case"running":switch(b){case"prompt_detected":return"waiting_input";case"agent_idle":return"running";case"verify_started":return"verifying";case"send_failed":return"failed";case"cancel":return"cancelled";default:return null}case"waiting_input":switch(b){case"prompt_answered_auto":case"prompt_answered_human":case"agent_idle":return"running";case"verify_started":return"verifying";case"cancel":return"cancelled";default:return null}case"verifying":switch(b){case"verify_passed":return"succeeded";case"verify_failed":return"failed";case"verify_not_started":return"not_started";case"cancel":return"cancelled";default:return null}case"failed":case"not_started":switch(b){case"message_sent":return"running";case"verify_started":return"verifying";case"cancel":return"cancelled";default:return null}default:return null}}(h,c),j=Date.now(),k=(0,e.P)(a,{taskId:b,event:c,fromStatus:h,toStatus:i,payload:f,createdAt:j});return null===i?{task:g,fromStatus:h,toStatus:null,eventId:k}:{task:(0,d.xZ)(a,b,i,f?.runId===void 0?{}:{lastVerificationRunId:f.runId}),fromStatus:h,toStatus:i,eventId:k}})();return null===h?g.warn("task-event-unknown-task",{taskId:b,event:c}):null===h.toStatus&&g.warn("task-event-rejected",{taskId:b,event:c,fromStatus:h.fromStatus}),h}function i(a,b,c,e,f,i){try{let g=(0,d.MH)(a,b,c,e);if(!g)return null;return h(a,g.id,f,i)}catch(a){return g.warn("task-event-failed",{worktreeId:b,cliToolId:c,instanceId:e,event:f,error:a instanceof Error?a.message:String(a)}),null}}}};
@@ -1 +0,0 @@
1
- "use strict";exports.id=7075,exports.ids=[964,2839,5220,7075,8583],exports.modules={23197:(a,b,c)=>{c.d(b,{H1:()=>d});let d="__global__"},39687:(a,b,c)=>{c.d(b,{d:()=>q});var d=c(56791),e=c(43234),f=c(15194),g=c(95220),h=c(12462),i=c(43015),j=c(54325),k=c(72626),l=c(58707),m=c(41466);let n=(0,k.h)("session/send-user-message");function o(a){return a instanceof Error?a.message:String(a)}async function p(a,b){let c=`${a}:${b}`,d=Date.now()+5e3;for(;(0,g.getActivePollers)().includes(c);){if(Date.now()>=d)return!1;await new Promise(a=>setTimeout(a,100))}return!0}async function q(a,b){let{worktreeId:c,content:k,cliToolId:q,instanceId:r,absoluteImagePath:s,copilotModel:t}=b,u=b.messageType??"normal",v=r??q,w=e.CLIToolManager.getInstance().getTool(q),x=await (0,l.a3)(c,q,r,{ignoreStructured:b.ignoreStructuredPromptGuard});if(x.waiting)return n.info("send-refused-prompt-waiting",{worktreeId:c,cliToolId:q,reason:x.reason,blockedBy:x.blockedBy}),{ok:!1,stage:"prompt_waiting",error:(0,l.br)(c,x.blockedBy)};if(t&&"copilot"===q){try{await w.sendModelCommand(c,t,r),n.info("copilot-model-command-sent",{model:t})}catch(a){return n.error("failed-to-send-model-command:",{error:o(a)}),{ok:!1,stage:"model",error:o(a)}}await p(c,v)||n.warn("previous-turn-poller-still-running",{worktreeId:c,instanceId:v,waitedMs:5e3})}let y=new Date;try{await (0,h.o4)(a,c,q,y,r)}catch(a){n.error("failed-to-save-pending-assistant-response:",{error:o(a)})}let z=null;try{let b=(0,d.getMessages)(a,c,{limit:1,cliToolId:q,instanceId:v,matchResolvedInstance:!0});b.length>0&&"user"===b[0].role&&b[0].content===k&&(z=b[0].id)}catch(a){n.error("failed-to-detect-orphaned-messages:",{error:o(a)})}try{s?(0,f._J)(w)?await w.sendMessageWithImage(c,k,s,r):await w.sendMessage(c,(0,m.TZ)(k,s),r):await w.sendMessage(c,k,r)}catch(a){return n.error("failed-to-send-message-to:",{error:o(a)}),{ok:!1,stage:"send",error:o(a)}}let A=(0,d.createMessage)(a,{worktreeId:c,role:"user",content:k,messageType:u,timestamp:y,cliToolId:q,instanceId:r,requestId:b.requestId});try{(0,i.broadcastMessage)("message",{worktreeId:c,message:{...A,cliToolId:q,instanceId:v}})}catch(a){n.warn("user-message-broadcast-failed",{error:o(a)})}if(z)try{if((0,d.deleteMessageById)(a,z)){n.info("cleaned-up-orphaned-user");try{(0,i.broadcastMessage)(j.dz,{worktreeId:c,cliToolId:q,instanceId:v,reason:"orphan_cleanup"})}catch(a){n.warn("orphan-cleanup-broadcast-failed",{error:o(a)})}}}catch(a){n.error("failed-to-clean-up-orphaned-message:",{error:o(a)})}return(0,d.updateLastUserMessage)(a,c,k,y),(0,d.clearInProgressMessageId)(a,c,q,r),n.info("cleared-in-progress-message-for"),(0,g.startPolling)(c,q,r),{ok:!0,message:A}}},40964:(a,b,c)=>{c.d(b,{m:()=>g});var d=c(15194);let e=/^[a-zA-Z0-9_-]+$/;function f(a){if(!e.test(a))throw Error(`Invalid session name format: ${a}`)}function g(a,b,c){let e=`mcbd-${a}-${b}`;if(!c||c===a)return f(e),e;let g=(0,d.pL)(c,a),h=g?`${e}-${g}`:e;return f(h),h}},58707:(a,b,c)=>{c.d(b,{$n:()=>k,a3:()=>l,br:()=>m});var d=c(43234),e=c(31990),f=c(95595),g=c(34405),h=c(72626),i=c(30008);let j=(0,h.h)("prompt-waiting-guard"),k="PROMPT_WAITING";async function l(a,b,c,h){try{let k=d.CLIToolManager.getInstance().getTool(b);if(!await k.isRunning(a,c))return{waiting:!1};let l=await (0,e.Wh)(a,b,g._,c),m=(0,f.WC)(l,b),n=(0,i._G)({worktreeId:a,cliToolId:b,instanceId:c,scraper:{status:m.status,reason:m.reason,hasActivePrompt:m.hasActivePrompt},ignoreStructured:h?.ignoreStructured});if(!n.blocksSend)return null!==n.structuredSendBlockSuppressed&&j.info("structured-send-guard-not-applied",{worktreeId:a,cliToolId:b,instanceId:c,suppressed:n.structuredSendBlockSuppressed,promptWaitingSince:n.structured?.at??null}),{waiting:!1};return{waiting:!0,reason:n.blockReason??void 0,blockedBy:n.blockedBy??void 0}}catch(c){return j.warn("prompt-waiting-check-failed",{worktreeId:a,cliToolId:b,error:c instanceof Error?c.message:String(c)}),{waiting:!1}}}function m(a,b){let c=`${a} is waiting on a prompt. Sending now would type into the prompt's input line instead of reaching the agent, and would leave that text in place for the next answer. Answer the prompt first: \`commandmate respond ${a} <answer>\`.`;if("structured"!==b)return c;let d=Math.round(i.j0/6e4);return`${c} This dialog was reported by the agent's own hooks and is not visible to the terminal scraper, so if the pane looks idle the record has outlived its dialog: it stops blocking sends ${d} minutes after it was reported, or immediately with \`commandmate send ${a} <message> --ignore-structured-prompt\` (server-wide: ${i.F1}=off).`}},61068:(a,b,c)=>{c.d(b,{Nz:()=>u,EB:()=>v,l7:()=>x});var d=c(95220),e=c(5363),f=c(56793),g=c(85775),h=c(72626),i=c(43234),j=c(79892);let k=(0,h.h)("global-session-poller"),l=new Map,m=new Map;var n=c(93997),o=c(15194),p=c(23197),q=c(77093),r=c(82325);let s=(0,h.h)("session-cleanup");async function t(a,b){let c={worktreeId:a,sessionsKilled:[],sessionErrors:[],pollersStopped:[],pollerErrors:[]};for(let e of((0,n.pc)(),o.XH)){try{await b(a,e)&&(c.sessionsKilled.push(e),s.info("session:killed",{worktreeId:a,cliToolId:e}))}catch(d){let b=`${e}: ${(0,q.u1)(d)}`;c.sessionErrors.push(b),s.warn("session:kill-failed",{worktreeId:a,cliToolId:e,error:d instanceof Error?d.message:String(d)})}try{(0,d.stopPolling)(a,e),c.pollersStopped.push(`response-poller:${e}`)}catch(d){let b=`response-poller:${e}: ${(0,q.u1)(d)}`;c.pollerErrors.push(b),s.warn("response-poller:stop-failed",{worktreeId:a,cliToolId:e,error:d instanceof Error?d.message:String(d)})}}try{(0,e._C)(a),c.pollersStopped.push("auto-yes-poller")}catch(d){let b=`auto-yes-poller: ${(0,q.u1)(d)}`;c.pollerErrors.push(b),s.warn("auto-yes-poller:stop-failed",{worktreeId:a,error:d instanceof Error?d.message:String(d)})}try{(0,e.LP)(a),c.pollersStopped.push("auto-yes-state")}catch(d){let b=`auto-yes-state: ${(0,q.u1)(d)}`;c.pollerErrors.push(b),s.warn("auto-yes-state:delete-failed",{worktreeId:a,error:d instanceof Error?d.message:String(d)})}try{(0,f.Yg)(a),c.pollersStopped.push("schedule-manager")}catch(d){let b=`schedule-manager: ${(0,q.u1)(d)}`;c.pollerErrors.push(b),s.warn("schedule-manager:stop-failed",{worktreeId:a,error:d instanceof Error?d.message:String(d)})}try{(0,g.Tm)(a),c.pollersStopped.push("timer-manager")}catch(d){let b=`timer-manager: ${(0,q.u1)(d)}`;c.pollerErrors.push(b),s.warn("timer-manager:stop-failed",{worktreeId:a,error:d instanceof Error?d.message:String(d)})}return c}async function u(a,b){let c=await Promise.allSettled(a.map(a=>t(a,b))),d=[],e=[];for(let b=0;b<c.length;b++){let f=c[b],g=a[b];if("fulfilled"===f.status){let a=f.value;for(let b of(d.push(a),a.sessionErrors))e.push(`Session kill error (${g}): ${b}`);for(let b of a.pollerErrors)e.push(`Poller stop error (${g}): ${b}`)}else e.push(`Cleanup failed (${g}): ${(0,q.u1)(f.reason)}`)}return{results:d,warnings:e}}async function v(a,b){try{let c=i.CLIToolManager.getInstance().getTool(b);if(!await c.isRunning(a))return!1;let e=`${a}:${b}`;(0,d.clearPromptHashCache)(e);let f=c.getSessionName(a);return(0,j.fY)(f)}catch{return!1}}async function w(){for(let a of l.keys()){let b=l.get(a);b&&clearTimeout(b)}l.clear(),m.clear(),k.info("poll:all-stopped");let a=0,b=i.CLIToolManager.getInstance();for(let c of o.XH)try{let d=b.getTool(c).getSessionName(p.H1);await (0,j.N)(d)&&await (0,j.fY)(d)&&(a++,s.info("global-session:killed",{cliToolId:c,sessionName:d}))}catch(a){s.warn("global-session:kill-failed",{cliToolId:c,error:(0,q.u1)(a)})}return a}async function x(a,b){let c=(0,r.L0)(a,b);try{await w()}catch(a){s.warn("sync:global-cleanup-failed",{error:(0,q.u1)(a)})}let d=[];if(c.deletedIds.length>0)try{let a=await u(c.deletedIds,v);a.warnings.length>0&&(s.warn("sync:cleanup-warnings",{warnings:a.warnings}),d=[`${a.warnings.length} session cleanup warning(s) occurred`])}catch(a){s.error("sync:cleanup-failed",{error:(0,q.u1)(a)}),d=["Session cleanup encountered an error"]}return{syncResult:c,cleanupWarnings:d}}},82325:(a,b,c)=>{c.d(b,{Hz:()=>o,L0:()=>r,Mg:()=>s,YM:()=>p,Yp:()=>q});var d=c(79646),e=c(28354),f=c(29021),g=c.n(f),h=c(33873),i=c.n(h),j=c(23718),k=c(56791),l=c(72626),m=c(64185);let n=(0,l.h)("worktrees");function o(){let a=process.env.WORKTREE_REPOS;return a&&a.trim()?a.split(",").map(a=>a.trim()).filter(a=>a.length>0):[]}async function p(a){let b=(0,e.promisify)(d.exec);if(function(a){if(!a)return!1;try{return g().lstatSync(a),!1}catch(b){let a=b.code;return"ENOENT"===a||"ENOTDIR"===a}}(a))return n.warn("repository:scan-skipped-missing-dir",{repoPath:a}),[];try{let{stdout:c}=await b("git worktree list",{cwd:a}),d=function(a){if(!a||""===a.trim())return[];let b=a.trim().split("\n"),c=[];for(let a of b){let b=a.trim();if(!b)continue;let d=b.match(/^(.+?)\s+([a-z0-9]+)\s+(?:\[(.+?)\]|\(detached HEAD\))/);if(d){let[,a,b,e]=d;c.push({path:a.trim(),branch:e||`detached-${b}`,commit:b})}}return c}(c),e=i().resolve(a),f=i().basename(e);return(0,m.oZ)(e),d.map(a=>{let b=i().resolve(a.path);return{id:(0,j.ko)(b),name:a.branch,branch:a.branch,path:b,repositoryPath:e,repositoryName:f}}).filter(a=>["/etc","/root","/sys","/proc","/dev","/boot","/bin","/sbin","/usr/bin","/usr/sbin"].some(b=>a.path.startsWith(b))?(n.warn("worktree:unsafe-path-skipped",{path:a.path}),!1):!(a.path.includes("\0")||a.path.includes(".."))||(n.warn("worktree:malicious-path-skipped",{path:a.path}),!1))}catch(c){let a=c instanceof Error?c.message:String(c),b=c.code;if(a?.includes("not a git repository")||128===b)return[];throw c}}async function q(a){let b=await Promise.allSettled(a.map(async a=>{n.info("repository:scan-start",{repoPath:a});let b=await p(a);return n.info("repository:scan-complete",{repoPath:a,worktreeCount:b.length}),b})),c=[];for(let d=0;d<b.length;d++){let e=b[d];"fulfilled"===e.status?c.push(...e.value):n.error("repository:scan-failed",{repoPath:a[d],error:e.reason instanceof Error?e.reason.message:String(e.reason)})}return c}function r(a,b){if(0===b.length)return{deletedIds:[],upsertedCount:0};let c=[],d=0,e=new Map;for(let a of b){let b=a.repositoryPath||"";e.has(b)||e.set(b,[]),e.get(b).push(a)}let f=new Set([...(0,k.getAllWorktreeIds)(a),...(0,k.getAliasedWorktreeIds)(a)]),g=new Map((0,k.getAllWorktreePathIds)(a).map(a=>[i().resolve(a.path),a.id])),h=new Map,l=new Map;for(let[a,b]of g)h.set(a,new Set([b])),l.set(b,a);for(let b of(0,k.getAllWorktreeAliases)(a)){let a=l.get(b.worktreeId);a&&h.get(a)?.add(b.oldId)}let m=new Set(b.map(a=>i().resolve(a.path)));for(let[b,o]of e){if(!b)continue;let e=(0,k.getWorktreesByRepository)(a,b).filter(a=>!m.has(i().resolve(a.path))).map(a=>a.id);if(e.length>0){let b=(0,k.deleteWorktreesByIds)(a,e);for(let a of(c.push(...e),e)){f.delete(a);let b=l.get(a);void 0!==b&&(g.delete(b),h.delete(b))}n.info("worktree:cleanup",{deletedCount:b.deletedCount})}for(let b of o){let c=i().resolve(b.path),e=g.get(c),m=b.id,n=e??(m&&!f.has(m)?m:function(a,b,c){if(!c||0===c.size)return(0,j.ko)(a,b);let d=new Set(b);for(let a of c)d.delete(a);return(0,j.ko)(a,d)}(c,f,h.get(c)));f.add(n),g.set(c,n),l.set(n,c),(0,k.upsertWorktree)(a,{...b,id:n,name:b.branch??b.name}),d++}}return{deletedIds:c,upsertedCount:d}}function s(a,b){let c=new Set(b.map(a=>a.repositoryPath).filter(a=>!!a)),d=[];for(let b of(0,k.getRepositories)(a)){let e=b.path;if(!e||c.has(e)||function(a){if(!a)return!1;try{return g().existsSync(a)&&g().existsSync(i().join(a,".git"))}catch{return!0}}(e))continue;let f=(0,k.getWorktreesByRepository)(a,e).map(a=>a.id);if(0===f.length)continue;let h=(0,k.deleteWorktreesByIds)(a,f);d.push(...f),n.info("worktree:stale-repo-pruned",{repoPath:e,deletedCount:h.deletedCount})}return d}},85775:(a,b,c)=>{c.d(b,{Tm:()=>o,x4:()=>m,xJ:()=>n});var d=c(34129),e=c(43234),f=c(88807),g=c(72626),h=c(87374),i=c(39687);let j=(0,g.h)("timer-manager");function k(){return globalThis.__timerManagerState||(globalThis.__timerManagerState={timers:new Map,timerWorktrees:new Map,initialized:!1}),globalThis.__timerManagerState}async function l(a){let b=k(),c=(0,f.getDbInstance)();try{let b=(0,d.kx)(c,a);if(!b||"pending"!==b.status)return;let f=e.CLIToolManager.getInstance().getTool(b.cliToolId),g=b.instanceId;if(!await f.isRunning(b.worktreeId,g)){j.warn("timer:no-session",{timerId:a,worktreeId:b.worktreeId,instanceId:g}),(0,d.j2)(c,a,h.HR.NO_SESSION);return}(0,d.j2)(c,a,"sending");let k=await (0,i.d)(c,{worktreeId:b.worktreeId,content:b.message,cliToolId:b.cliToolId,instanceId:g});if(!k.ok){let b=`[${k.stage}] ${k.error}`;(0,d.j2)(c,a,"failed",void 0,b),j.error("timer:send-failed",{timerId:a,stage:k.stage,error:k.error});return}(0,d.j2)(c,a,"sent",Date.now()),j.info("timer:sent",{timerId:a,worktreeId:b.worktreeId})}catch(e){let b=e instanceof Error?e.message:String(e);try{(0,d.j2)(c,a,"failed",void 0,b)}catch{}j.error("timer:send-failed",{timerId:a,error:b})}finally{b.timers.delete(a),b.timerWorktrees.delete(a)}}function m(a,b,c){let d=k(),e=setTimeout(()=>{l(a)},c);d.timers.set(a,e),d.timerWorktrees.set(a,b)}function n(a){let b=k(),c=b.timers.get(a);c&&(clearTimeout(c),b.timers.delete(a),b.timerWorktrees.delete(a));let e=(0,f.getDbInstance)();(0,d.Ud)(e,a)}function o(a){let b=k(),c=(0,f.getDbInstance)();for(let[c,d]of b.timerWorktrees)if(d===a){let a=b.timers.get(c);a&&clearTimeout(a),b.timers.delete(c),b.timerWorktrees.delete(c)}(0,d.$$)(c,a)}},95220:(a,b,c)=>{c.r(b),c.d(b,{accumulateTuiContent:()=>g.IZ,cleanClaudeResponse:()=>f.NN,cleanCopilotResponse:()=>f.LH,cleanGeminiResponse:()=>f.IS,cleanOpenCodeResponse:()=>f.aW,clearPromptHashCache:()=>h.iX,clearTuiAccumulator:()=>g.q1,extractCopilotContentLines:()=>g.o0,extractTuiContentLines:()=>g.K0,findOverlapIndex:()=>g.vQ,getAccumulatedContent:()=>g.Uz,getActivePollers:()=>d.KQ,initTuiAccumulator:()=>g.tb,isDuplicatePrompt:()=>h.gv,isOpenCodeComplete:()=>e.bE,migrateResponsePollerWorktreeIds:()=>d.sR,normalizeCopilotLine:()=>g.IW,normalizePromptForDedup:()=>h.zm,renamePromptHashCacheKey:()=>h.i2,resolveExtractionStartIndex:()=>e.QM,startPolling:()=>d.g8,stopAllPolling:()=>d.fq,stopPolling:()=>d.Et,truncateMessage:()=>f.Sj});var d=c(45146),e=c(60),f=c(82450),g=c(13033),h=c(72457)}};