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
@@ -44,6 +44,8 @@ const assistant_response_saver_1 = require("../../lib/assistant-response-saver")
44
44
  const ws_server_1 = require("../../lib/ws-server");
45
45
  const types_2 = require("../../lib/realtime/types");
46
46
  const logger_1 = require("../../lib/logger");
47
+ const worktree_session_ownership_1 = require("../../lib/cli-tools/worktree-session-ownership");
48
+ const session_name_1 = require("../../lib/cli-tools/session-name");
47
49
  const prompt_waiting_guard_1 = require("../../lib/session/prompt-waiting-guard");
48
50
  const opencode_1 = require("../../lib/cli-tools/opencode");
49
51
  const logger = (0, logger_1.createLogger)('session/send-user-message');
@@ -108,6 +110,30 @@ async function sendUserMessage(db, params) {
108
110
  */
109
111
  const resolvedInstanceId = instanceId ?? cliToolId;
110
112
  const cliTool = manager_1.CLIToolManager.getInstance().getTool(cliToolId);
113
+ // Issue #2865: the send route checks ownership itself, but the timer manager
114
+ // and relay delivery reach tmux only through here. A session under this
115
+ // worktree's name that was created in another directory belongs to another
116
+ // CommandMate server; nothing is typed into it and no poller watches it.
117
+ // Checked before the prompt guard, which would otherwise read that pane.
118
+ const sessionName = (0, session_name_1.resolveSessionName)(cliToolId, worktreeId, instanceId);
119
+ const ownership = await (0, worktree_session_ownership_1.checkWorktreeSessionOwnership)(worktreeId, sessionName, db);
120
+ if (ownership === null || ownership.verdict === 'foreign') {
121
+ logger.warn('send-refused-foreign-session', {
122
+ worktreeId,
123
+ cliToolId,
124
+ instanceId: resolvedInstanceId,
125
+ sessionName,
126
+ sessionPath: ownership?.sessionPath ?? null,
127
+ reason: ownership ? 'foreign' : 'worktree_not_found',
128
+ });
129
+ return {
130
+ ok: false,
131
+ stage: 'foreign_session',
132
+ error: ownership
133
+ ? `tmux session "${sessionName}" belongs to another CommandMate server`
134
+ : `Worktree '${worktreeId}' not found; cannot confirm tmux session "${sessionName}" is this server's`,
135
+ };
136
+ }
111
137
  // Issue #1708: refuse before the first side effect. A prompt dialog does not
112
138
  // forward keystrokes to the agent — they accumulate in its own input line — so
113
139
  // the message is lost AND the next `respond` has to answer a prompt whose
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ /**
3
+ * Every (CLI tool, instance) pair whose tmux session could belong to a worktree
4
+ * (Issue #1621, extracted for #2866).
5
+ *
6
+ * Shared by the startup passes that predict session names from the database —
7
+ * `worktree-session-reconcile.ts` (ID moves) and `adopt-legacy-sessions.ts`
8
+ * (legacy-name adoption) — so both enumerate the same set.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.collectInstanceTargets = collectInstanceTargets;
12
+ const types_1 = require("../../lib/cli-tools/types");
13
+ const agent_instances_db_1 = require("../../lib/db/agent-instances-db");
14
+ /**
15
+ * The primary instance of every CLI tool, plus every roster row under any of
16
+ * `worktreeIds`.
17
+ *
18
+ * The primary instance of every CLI tool is always included — a worktree that
19
+ * predates the roster (#1000) has no `agent_instances` rows at all yet can
20
+ * absolutely have a running `mcbd-claude-<id>` session.
21
+ *
22
+ * @param db - Database instance (read for the agent roster)
23
+ * @param worktreeIds - The worktree IDs whose roster rows to include
24
+ */
25
+ function collectInstanceTargets(db, worktreeIds) {
26
+ const seen = new Set();
27
+ const targets = [];
28
+ const add = (cliToolId, instanceId) => {
29
+ const key = `${cliToolId}|${instanceId}`;
30
+ if (seen.has(key))
31
+ return;
32
+ seen.add(key);
33
+ targets.push({ cliToolId, instanceId });
34
+ };
35
+ for (const cliToolId of types_1.CLI_TOOL_IDS)
36
+ add(cliToolId, cliToolId);
37
+ for (const worktreeId of worktreeIds) {
38
+ let instances;
39
+ try {
40
+ instances = (0, agent_instances_db_1.getAgentInstances)(db, worktreeId);
41
+ }
42
+ catch {
43
+ // No agent_instances table (older database) — the primary instances above
44
+ // already cover the pre-roster shape.
45
+ continue;
46
+ }
47
+ for (const instance of instances) {
48
+ if ((0, types_1.isCliToolType)(instance.cliTool))
49
+ add(instance.cliTool, instance.id);
50
+ }
51
+ }
52
+ return targets;
53
+ }
@@ -3,9 +3,9 @@
3
3
  * The tmux "surface" CommandMate publishes on its own sessions (Issue #2317).
4
4
  *
5
5
  * Everything here is a pure argument builder or a pure predicate — no
6
- * `child_process`, no `@/` path alias, and one constants import. Three
7
- * constraints put it here rather than under `lib/tmux/`, and all three are
8
- * load-bearing:
6
+ * `child_process`, no `@/` path alias, one constants import and the pure
7
+ * session-name parser. Three constraints put it here rather than under
8
+ * `lib/tmux/`, and all three are load-bearing:
9
9
  *
10
10
  * 1. **`tsconfig.cli.json` sets `"paths": {}`.** The CLI bundle resolves nothing
11
11
  * through `@/…`, so a module the `attach` command needs may only reach the
@@ -67,6 +67,10 @@ exports.buildRemoveAutoPopupHookArgs = buildRemoveAutoPopupHookArgs;
67
67
  exports.buildDelegateGeometryCommands = buildDelegateGeometryCommands;
68
68
  exports.buildRestoreGeometryCommands = buildRestoreGeometryCommands;
69
69
  const tmux_pane_config_1 = require("../../config/tmux-pane-config");
70
+ // Relative on purpose (constraint 1 above). `session-name.ts` is already part of
71
+ // the CLI bundle (`commands/attach.ts` imports it) and reaches nothing through
72
+ // `@/…`, so it costs the bundle nothing new (Issue #2866).
73
+ const session_name_1 = require("../cli-tools/session-name");
70
74
  /**
71
75
  * Session-name prefix every CommandMate tmux session carries.
72
76
  *
@@ -308,8 +312,9 @@ function isLiveAttachSupported(cliToolId) {
308
312
  /**
309
313
  * Whether a tmux session's NAME says it runs a tool `--live` supports.
310
314
  *
311
- * The session name is `mcbd-<tool>-<worktree>` and no supported tool id is a
312
- * prefix of another, so this is exact rather than a guess. It exists because
315
+ * The session name is `mcbd-[<ns>-]<tool>-<worktree>` and `parseSessionName`
316
+ * reads the tool out of either form (Issue #2866), so this is exact rather
317
+ * than a guess. It exists because
313
318
  * the two callers that need the answer — the attach hook script's installer and
314
319
  * the response poller — hold a session name and nothing else: a hook fires with
315
320
  * tmux formats, and the poller must not pay a tmux round-trip to ask about a
@@ -320,7 +325,8 @@ function isLiveAttachSupported(cliToolId) {
320
325
  function isLiveAttachEligibleSession(sessionName) {
321
326
  if (!isCommandMateSession(sessionName))
322
327
  return false;
323
- return exports.LIVE_ATTACH_TOOLS.some((tool) => sessionName.startsWith(`${exports.MCBD_SESSION_PREFIX}${tool}-`));
328
+ const cliToolId = (0, session_name_1.parseSessionName)(sessionName)?.cliToolId;
329
+ return cliToolId !== undefined && exports.LIVE_ATTACH_TOOLS.includes(cliToolId);
324
330
  }
325
331
  /**
326
332
  * CLI tools that paint their transcript in the terminal's alternate screen.
@@ -331,8 +337,9 @@ function isLiveAttachEligibleSession(sessionName) {
331
337
  * else. `attach` prints its hint for exactly these.
332
338
  *
333
339
  * Deliberately a local list rather than an import of `usesAlternateScreen()`:
334
- * this module must stay free of `lib/cli-tools`, whose graph the CLI bundle
335
- * cannot afford (see the module docblock). The two are pinned to each other by
340
+ * this module must stay free of `lib/cli-tools` beyond the pure
341
+ * `session-name.ts`, whose tool graph the CLI bundle cannot afford (see the
342
+ * module docblock). The two are pinned to each other by
336
343
  * `tests/unit/tmux/session-surface-2317.test.ts`, so a tool moving in or out of
337
344
  * the alternate screen breaks a test rather than silently dropping the hint.
338
345
  */
@@ -74,11 +74,15 @@ exports.reconcileWorktreeSessions = reconcileWorktreeSessions;
74
74
  exports.reconcileWorktreeSessionsFromAliases = reconcileWorktreeSessionsFromAliases;
75
75
  const manager_1 = require("../../lib/cli-tools/manager");
76
76
  const types_1 = require("../../lib/cli-tools/types");
77
- const validation_1 = require("../../lib/cli-tools/validation");
78
77
  const agent_instances_db_1 = require("../../lib/db/agent-instances-db");
78
+ const validation_1 = require("../../lib/cli-tools/validation");
79
+ const session_name_1 = require("../../lib/cli-tools/session-name");
80
+ const session_namespace_1 = require("../../lib/cli-tools/session-namespace");
81
+ const session_instance_targets_1 = require("./session-instance-targets");
79
82
  const worktree_alias_db_1 = require("../../lib/db/worktree-alias-db");
80
83
  const path_validator_1 = require("../../lib/security/path-validator");
81
84
  const tmux_1 = require("../../lib/tmux/tmux");
85
+ const session_ownership_1 = require("../../lib/tmux/session-ownership");
82
86
  const control_mode_tmux_transport_1 = require("../../lib/tmux/control-mode-tmux-transport");
83
87
  const auto_yes_manager_1 = require("../../lib/polling/auto-yes-manager");
84
88
  const response_poller_1 = require("../../lib/polling/response-poller");
@@ -131,44 +135,16 @@ function normalizeRenames(renames) {
131
135
  * The roster is read for BOTH IDs because the caller may reconcile either side
132
136
  * of the DB move: after `migrateWorktreeIdPreservingChildren` the rows sit under
133
137
  * `newId`, but a caller reconciling ahead of the move still finds them under
134
- * `oldId`. The primary instance of every CLI tool is always included — a
135
- * worktree that predates the roster (#1000) has no `agent_instances` rows at all
136
- * yet can absolutely have a running `mcbd-claude-<id>` session.
138
+ * `oldId`.
137
139
  */
138
- function collectInstanceTargets(db, rename) {
139
- const seen = new Set();
140
- const targets = [];
141
- const add = (cliToolId, instanceId) => {
142
- const key = `${cliToolId}|${instanceId}`;
143
- if (seen.has(key))
144
- return;
145
- seen.add(key);
146
- targets.push({ cliToolId, instanceId });
147
- };
148
- for (const cliToolId of types_1.CLI_TOOL_IDS)
149
- add(cliToolId, cliToolId);
150
- for (const worktreeId of [rename.newId, rename.oldId]) {
151
- let instances;
152
- try {
153
- instances = (0, agent_instances_db_1.getAgentInstances)(db, worktreeId);
154
- }
155
- catch {
156
- // No agent_instances table (older database) — the primary instances above
157
- // already cover the pre-roster shape.
158
- continue;
159
- }
160
- for (const instance of instances) {
161
- if ((0, types_1.isCliToolType)(instance.cliTool))
162
- add(instance.cliTool, instance.id);
163
- }
164
- }
165
- return targets;
140
+ function collectRenameInstanceTargets(db, rename) {
141
+ return (0, session_instance_targets_1.collectInstanceTargets)(db, [rename.newId, rename.oldId]);
166
142
  }
167
143
  /** Build the (old session name → new session name) plan for one ID move. */
168
144
  function planSessionRenames(db, rename, errors) {
169
145
  const manager = manager_1.CLIToolManager.getInstance();
170
146
  const plans = [];
171
- for (const { cliToolId, instanceId } of collectInstanceTargets(db, rename)) {
147
+ for (const { cliToolId, instanceId } of collectRenameInstanceTargets(db, rename)) {
172
148
  try {
173
149
  const tool = manager.getTool(cliToolId);
174
150
  const oldName = tool.getSessionName(rename.oldId, instanceId);
@@ -243,27 +219,33 @@ function collectKnownWorktreeIds(db, renames) {
243
219
  * @param knownIds - Every worktree ID the database can vouch for
244
220
  * @returns The attribution, or `null` when nothing in `knownIds` explains the name
245
221
  */
246
- function attributeSessionName(name, knownIds) {
247
- for (const cliToolId of types_1.CLI_TOOL_IDS) {
248
- const prefix = `mcbd-${cliToolId}-`;
249
- if (!name.startsWith(prefix))
250
- continue;
251
- // No CLI tool id is a prefix of another, so at most one branch is entered
252
- // and the remainder is unambiguously `<id>[-<suffix>]`.
253
- const rest = name.slice(prefix.length);
254
- let candidate = rest;
255
- for (;;) {
256
- if (knownIds.has(candidate)) {
257
- const suffix = candidate.length === rest.length ? undefined : rest.slice(candidate.length + 1);
258
- return { cliToolId, worktreeId: candidate, suffix: suffix || undefined };
259
- }
260
- const cut = candidate.lastIndexOf('-');
261
- if (cut <= 0)
262
- return null;
263
- candidate = candidate.slice(0, cut);
222
+ function attributeSessionName(name, knownIds, namespace = (0, session_namespace_1.getSessionNamespace)()) {
223
+ // Issue #2866: legacy names and names in this server's namespace only. A name
224
+ // in another namespace is another server's session, whatever ID it carries.
225
+ const parsed = (0, session_name_1.parseSessionName)(name);
226
+ if (!parsed)
227
+ return null;
228
+ if (parsed.namespace !== null && parsed.namespace !== namespace)
229
+ return null;
230
+ // No CLI tool id is a prefix of another, so the remainder is unambiguously
231
+ // `<id>[-<suffix>]`.
232
+ const { cliToolId, rest } = parsed;
233
+ let candidate = rest;
234
+ for (;;) {
235
+ if (knownIds.has(candidate)) {
236
+ const suffix = candidate.length === rest.length ? undefined : rest.slice(candidate.length + 1);
237
+ return { cliToolId, worktreeId: candidate, suffix: suffix || undefined };
264
238
  }
239
+ const cut = candidate.lastIndexOf('-');
240
+ if (cut <= 0)
241
+ return null;
242
+ candidate = candidate.slice(0, cut);
265
243
  }
266
- return null;
244
+ }
245
+ /** Whether a live name is another server's namespaced session (Issue #2866). */
246
+ function isOtherNamespaceSession(name, namespace) {
247
+ const parsed = (0, session_name_1.parseSessionName)(name);
248
+ return parsed !== null && parsed.namespace !== null && parsed.namespace !== namespace;
267
249
  }
268
250
  /**
269
251
  * Read the live session list the other way round: attribute each name to a
@@ -277,10 +259,14 @@ function attributeSessionName(name, knownIds) {
277
259
  function discoverSessionRenames(renames, liveNames, knownIds, result) {
278
260
  const byOldId = new Map(renames.map((rename) => [rename.oldId, rename]));
279
261
  const plans = [];
262
+ const namespace = (0, session_namespace_1.getSessionNamespace)();
280
263
  for (const name of liveNames) {
281
264
  if (!name.startsWith('mcbd-'))
282
265
  continue;
283
- const attributed = attributeSessionName(name, knownIds);
266
+ // Issue #2866: another server's namespace — neither attributed nor reported.
267
+ if (isOtherNamespaceSession(name, namespace))
268
+ continue;
269
+ const attributed = attributeSessionName(name, knownIds, namespace);
284
270
  if (!attributed) {
285
271
  result.unaccountedSessions.push(name);
286
272
  continue;
@@ -291,7 +277,8 @@ function discoverSessionRenames(renames, liveNames, knownIds, result) {
291
277
  try {
292
278
  const tool = manager_1.CLIToolManager.getInstance().getTool(attributed.cliToolId);
293
279
  // Rebuilt through getSessionName rather than by string surgery so the
294
- // suffix convention stays owned by one place (`cli-tools/base.ts`).
280
+ // suffix convention stays owned by one place (`cli-tools/session-name.ts`).
281
+ // A legacy-form source lands on the current form (Issue #2866).
295
282
  const instanceId = attributed.suffix
296
283
  ? (0, types_1.buildInstanceId)(attributed.cliToolId, attributed.suffix)
297
284
  : attributed.cliToolId;
@@ -322,6 +309,58 @@ function mergeSessionPlans(predicted, discovered) {
322
309
  }
323
310
  return Array.from(byOldName.values());
324
311
  }
312
+ /**
313
+ * The path of a worktree row, or null. Queried directly for the same reason
314
+ * {@link collectKnownWorktreeIds} is (suites mock `worktree-db`).
315
+ */
316
+ function readWorktreePath(db, worktreeId) {
317
+ try {
318
+ const row = db.prepare('SELECT path FROM worktrees WHERE id = ?').get(worktreeId);
319
+ return row?.path ?? null;
320
+ }
321
+ catch {
322
+ return null;
323
+ }
324
+ }
325
+ /**
326
+ * Drop the plans whose live source session another CommandMate server created
327
+ * (Issue #2865).
328
+ *
329
+ * Session names carry no server identity, so a live `mcbd-claude-<old>` may be
330
+ * a different server's session that merely shares the worktree ID. Only a
331
+ * session whose `#{session_path}` is the worktree's own directory is renamed;
332
+ * the rest are reported in `skippedSessions`. The directory comes from the
333
+ * rename target's row, falling back to the source's row when the pass runs
334
+ * ahead of the DB move. A plan whose worktree has no row at all cannot be
335
+ * vouched for and is skipped too (fail safe).
336
+ */
337
+ function excludeForeignSessionPlans(db, plans, live, livePaths, deps, result) {
338
+ const owned = [];
339
+ for (const plan of plans) {
340
+ // Not live: renameSessionsTwoStage drops it without counting it.
341
+ if (!live.has(plan.oldName)) {
342
+ owned.push(plan);
343
+ continue;
344
+ }
345
+ const worktreePath = readWorktreePath(db, plan.rename.newId) ?? readWorktreePath(db, plan.rename.oldId);
346
+ const sessionPath = livePaths.get(plan.oldName) ?? null;
347
+ if (worktreePath !== null && deps.isSessionOwnedBy(sessionPath, worktreePath)) {
348
+ owned.push(plan);
349
+ continue;
350
+ }
351
+ result.skippedSessions.push({
352
+ oldName: plan.oldName,
353
+ newName: plan.newName,
354
+ reason: 'session owned by another server',
355
+ });
356
+ logger.warn('reconcile:foreign-session-skipped', {
357
+ sessionName: plan.oldName,
358
+ sessionPath,
359
+ worktreePath,
360
+ });
361
+ }
362
+ return owned;
363
+ }
325
364
  /** Mint a session name that is free both on the server and within this pass. */
326
365
  function allocateTempName(taken, ordinal) {
327
366
  let candidate = `${TEMP_SESSION_PREFIX}${ordinal}`;
@@ -501,13 +540,18 @@ async function reconcileWorktreeSessions(db, renamesOrOldId, newIdOrOptions, may
501
540
  const deps = {
502
541
  listSessions: options?.tmux?.listSessions ?? tmux_1.listSessions,
503
542
  renameSession: options?.tmux?.renameSession ?? tmux_1.renameSession,
543
+ isSessionOwnedBy: options?.tmux?.isSessionOwnedBy ?? (0, session_ownership_1.createCachedOwnershipMatcher)(),
504
544
  };
505
545
  // Listed once, up front: both the prediction pass and the attribution pass
506
546
  // need it, and it is what makes a startup with nothing stale cost exactly one
507
547
  // `tmux list-sessions`.
508
548
  let live = null;
549
+ const livePaths = new Map();
509
550
  try {
510
- live = new Set((await deps.listSessions()).map((session) => session.name));
551
+ const sessions = await deps.listSessions();
552
+ live = new Set(sessions.map((session) => session.name));
553
+ for (const session of sessions)
554
+ livePaths.set(session.name, session.path);
511
555
  }
512
556
  catch (error) {
513
557
  result.errors.push(`list tmux sessions: ${error instanceof Error ? error.message : String(error)}`);
@@ -527,7 +571,8 @@ async function reconcileWorktreeSessions(db, renamesOrOldId, newIdOrOptions, may
527
571
  else
528
572
  result.planSources.discovered++;
529
573
  }
530
- await renameSessionsTwoStage(plans, live, deps, result);
574
+ const ownedPlans = excludeForeignSessionPlans(db, plans, live, livePaths, deps, result);
575
+ await renameSessionsTwoStage(ownedPlans, live, deps, result);
531
576
  }
532
577
  // Runtime state moves after the sessions: a poller that ticks in between
533
578
  // fails one capture against a name that is briefly gone, which is a logged
@@ -12,6 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.cleanupWorktreeSessions = cleanupWorktreeSessions;
13
13
  exports.cleanupMultipleWorktrees = cleanupMultipleWorktrees;
14
14
  exports.killWorktreeSession = killWorktreeSession;
15
+ exports.createOwnedSessionKiller = createOwnedSessionKiller;
15
16
  exports.cleanupGlobalSessions = cleanupGlobalSessions;
16
17
  exports.syncWorktreesAndCleanup = syncWorktreesAndCleanup;
17
18
  const response_poller_1 = require("./polling/response-poller");
@@ -27,6 +28,8 @@ const logger_1 = require("../lib/logger");
27
28
  const manager_1 = require("./cli-tools/manager");
28
29
  const tmux_1 = require("./tmux/tmux");
29
30
  const worktrees_1 = require("./git/worktrees");
31
+ const worktree_db_1 = require("./db/worktree-db");
32
+ const session_ownership_1 = require("./cli-tools/session-ownership");
30
33
  const logger = (0, logger_1.createLogger)('session-cleanup');
31
34
  /**
32
35
  * Clean up all CLI tool sessions and pollers for a single worktree
@@ -164,26 +167,50 @@ async function cleanupMultipleWorktrees(worktreeIds, killSessionFn) {
164
167
  * MF-C01: getTool() throws Error if tool not found, wrapped in try-catch
165
168
  * SF-004: isRunning() correctly awaited
166
169
  *
170
+ * Issue #2865: only a session created in `worktreePath` is killed. A
171
+ * same-named session another CommandMate server created (the worktree ID is
172
+ * derived from the directory name, so two servers can share it) is left alone
173
+ * and `false` is returned.
174
+ *
167
175
  * @param worktreeId - Worktree ID
168
176
  * @param cliToolId - CLI tool type
177
+ * @param worktreePath - The worktree's directory, read from its row BEFORE the row is deleted
169
178
  * @returns true if session was killed, false otherwise
170
179
  */
171
- async function killWorktreeSession(worktreeId, cliToolId) {
180
+ async function killWorktreeSession(worktreeId, cliToolId, worktreePath) {
172
181
  try {
173
182
  const manager = manager_1.CLIToolManager.getInstance();
174
183
  const tool = manager.getTool(cliToolId); // throws Error if not found
175
184
  if (!await tool.isRunning(worktreeId))
176
185
  return false; // SF-004: await
186
+ const sessionName = tool.getSessionName(worktreeId);
187
+ const ownership = await (0, session_ownership_1.checkSessionOwnership)(sessionName, worktreePath);
188
+ if (ownership.verdict !== 'owned')
189
+ return false;
177
190
  // Issue #565: Clear prompt dedup cache on session kill
178
191
  const pollerKey = `${worktreeId}:${cliToolId}`;
179
192
  (0, response_poller_1.clearPromptHashCache)(pollerKey);
180
- const sessionName = tool.getSessionName(worktreeId);
181
193
  return (0, tmux_1.killSession)(sessionName);
182
194
  }
183
195
  catch {
184
196
  return false;
185
197
  }
186
198
  }
199
+ /**
200
+ * A {@link KillSessionFn} that kills through {@link killWorktreeSession} with
201
+ * each worktree's pre-deletion path (Issue #2865). A worktree with no known
202
+ * path cannot be vouched for, so nothing is killed for it.
203
+ *
204
+ * @param pathById - worktree ID -> path, captured before the rows are deleted
205
+ */
206
+ function createOwnedSessionKiller(pathById) {
207
+ return async (worktreeId, cliToolId) => {
208
+ const worktreePath = pathById.get(worktreeId);
209
+ if (worktreePath === undefined)
210
+ return false;
211
+ return killWorktreeSession(worktreeId, cliToolId, worktreePath);
212
+ };
213
+ }
187
214
  /**
188
215
  * Clean up all global assistant sessions.
189
216
  * Issue #649: Kill any orphaned mcbd-{cli_tool_id}-__global__ tmux sessions
@@ -233,6 +260,9 @@ async function cleanupGlobalSessions() {
233
260
  * @returns SyncResult and sanitized cleanupWarnings
234
261
  */
235
262
  async function syncWorktreesAndCleanup(db, worktrees) {
263
+ // Issue #2865: the rows sync deletes are gone afterwards, and their paths are
264
+ // what decides which sessions are this server's to kill.
265
+ const pathById = new Map((0, worktree_db_1.getAllWorktreePathIds)(db).map((row) => [row.id, row.path]));
236
266
  const syncResult = (0, worktrees_1.syncWorktreesToDB)(db, worktrees);
237
267
  // Issue #649: Clean up orphaned global assistant sessions
238
268
  try {
@@ -244,7 +274,7 @@ async function syncWorktreesAndCleanup(db, worktrees) {
244
274
  let cleanupWarnings = [];
245
275
  if (syncResult.deletedIds.length > 0) {
246
276
  try {
247
- const cleanupResult = await cleanupMultipleWorktrees(syncResult.deletedIds, killWorktreeSession);
277
+ const cleanupResult = await cleanupMultipleWorktrees(syncResult.deletedIds, createOwnedSessionKiller(pathById));
248
278
  if (cleanupResult.warnings.length > 0) {
249
279
  // SEC-MF-001: Log detailed warnings server-side only
250
280
  logger.warn('sync:cleanup-warnings', { warnings: cleanupResult.warnings });
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ /**
3
+ * Legacy tmux session adoption table (Issue #2866).
4
+ *
5
+ * Once the server has a session-name namespace, a session is named
6
+ * `mcbd-{ns}-{cli}-{worktreeId}[-{suffix}]`. Sessions the same server started
7
+ * before that (`mcbd-{cli}-{worktreeId}[-{suffix}]`) are NOT renamed — a rename
8
+ * would lose them for an older CommandMate running beside this one, or after a
9
+ * downgrade. Instead `adoptLegacySessions` records "the new-format name X is
10
+ * served by the legacy session Y", and `resolveSessionName` returns Y for X
11
+ * while the entry lives.
12
+ *
13
+ * An entry is dropped when its legacy session is killed or found gone
14
+ * (`tmux.ts` `killSession` / `hasSession`), so the next start uses the
15
+ * new-format name.
16
+ *
17
+ * Pure (no `@/` alias, no child_process): `cli-tools/session-name.ts` reads it,
18
+ * and that module is part of the CLI bundle (`tsconfig.cli.json` has no paths).
19
+ *
20
+ * Kept on `globalThis` rather than in module scope: under `next start` this
21
+ * module is evaluated once in the custom server's graph and again in each Next
22
+ * route bundle (see `tui-accumulator.ts`, Issue #2223), and the table is filled
23
+ * by the server at startup but read by the routes.
24
+ */
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.registerLegacyAlias = registerLegacyAlias;
27
+ exports.lookupLegacyAlias = lookupLegacyAlias;
28
+ exports.dropLegacyAliasByLegacyName = dropLegacyAliasByLegacyName;
29
+ exports.clearLegacyAliasesForTests = clearLegacyAliasesForTests;
30
+ function aliases() {
31
+ return (globalThis.__cmLegacySessionAliases ??= new Map());
32
+ }
33
+ /**
34
+ * Serve the new-format session name `newName` with the existing legacy session
35
+ * `legacyName`.
36
+ */
37
+ function registerLegacyAlias(newName, legacyName) {
38
+ aliases().set(newName, legacyName);
39
+ }
40
+ /** The legacy session name adopted for `newName`, if any. */
41
+ function lookupLegacyAlias(newName) {
42
+ return aliases().get(newName);
43
+ }
44
+ /**
45
+ * Forget every adoption served by the legacy session `legacyName`. A no-op for
46
+ * a name that is not an adopted legacy session.
47
+ *
48
+ * @returns true when an entry was removed
49
+ */
50
+ function dropLegacyAliasByLegacyName(legacyName) {
51
+ const table = aliases();
52
+ let dropped = false;
53
+ for (const [newName, legacy] of table) {
54
+ if (legacy === legacyName) {
55
+ table.delete(newName);
56
+ dropped = true;
57
+ }
58
+ }
59
+ return dropped;
60
+ }
61
+ /** Test-only: forget every adoption. */
62
+ function clearLegacyAliasesForTests() {
63
+ aliases().clear();
64
+ }
@@ -114,12 +114,20 @@ tmux set-option -u -t "=$SESSION:" @cm_delegated 2>/dev/null || true
114
114
  * `CM_LIVE_ATTACH_HOOK=on`.
115
115
  *
116
116
  * claude-only by session-name prefix, and that is not a shortcut. The session
117
- * name is `mcbd-<tool>-<worktree>`, no other CLI tool id begins with `claude`,
118
- * and the script has nothing but the name to go on — a hook fires with tmux
119
- * formats, not with CommandMate's roster. Widening it means widening
117
+ * name is `mcbd-<ns>-<tool>-<worktree>` or the legacy `mcbd-<tool>-<worktree>`
118
+ * (Issue #2866), no other CLI tool id begins with `claude`, and the script has
119
+ * nothing but the name to go on — a hook fires with tmux formats, not with
120
+ * CommandMate's roster. The namespace is matched as exactly eight hex digits
121
+ * (Issue #2867), not `*`: `mcbd-*-claude-*` would also match a legacy codex
122
+ * session of a worktree whose id starts with `claude-`. Widening it means widening
120
123
  * `LIVE_ATTACH_TOOLS` too, and that needs the per-tool re-measurement
121
124
  * Issue #2317 puts out of scope.
122
125
  */
126
+ /**
127
+ * A session-name namespace as a shell `case` glob: eight hex digits, the shape
128
+ * `SESSION_NAMESPACE_PATTERN` accepts (Issue #2866 / #2867).
129
+ */
130
+ const NAMESPACE_GLOB = '[0-9a-f]'.repeat(8);
123
131
  exports.LIVE_DELEGATE_SCRIPT = `#!/bin/sh
124
132
  # CommandMate live-attach delegate (Issue #2317) — generated file, edits are overwritten.
125
133
  #
@@ -141,7 +149,7 @@ SESSION="\${1:-}"
141
149
  CONTROL_MODE="\${2:-0}"
142
150
 
143
151
  case "$SESSION" in
144
- ${tmux_session_surface_1.MCBD_SESSION_PREFIX}claude-*) ;;
152
+ ${tmux_session_surface_1.MCBD_SESSION_PREFIX}claude-*|${tmux_session_surface_1.MCBD_SESSION_PREFIX}${NAMESPACE_GLOB}-claude-*) ;;
145
153
  *) exit 0 ;;
146
154
  esac
147
155