commandmate 0.30.1 → 0.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (442) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-build-manifest.json +164 -164
  3. package/.next/app-path-routes-manifest.json +28 -28
  4. package/.next/build-manifest.json +2 -2
  5. package/.next/prerender-manifest.json +9 -9
  6. package/.next/required-server-files.json +1 -1
  7. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  8. package/.next/server/app/api/agents/update/route_client-reference-manifest.js +1 -1
  9. package/.next/server/app/api/agents/versions/route_client-reference-manifest.js +1 -1
  10. package/.next/server/app/api/app/update/route_client-reference-manifest.js +1 -1
  11. package/.next/server/app/api/app/update-check/route.js +1 -1
  12. package/.next/server/app/api/app/update-check/route_client-reference-manifest.js +1 -1
  13. package/.next/server/app/api/assistant/conversation/route.js +1 -1
  14. package/.next/server/app/api/assistant/conversation/route.js.nft.json +1 -1
  15. package/.next/server/app/api/assistant/conversation/route_client-reference-manifest.js +1 -1
  16. package/.next/server/app/api/assistant/current-output/route.js +1 -1
  17. package/.next/server/app/api/assistant/current-output/route.js.nft.json +1 -1
  18. package/.next/server/app/api/assistant/current-output/route_client-reference-manifest.js +1 -1
  19. package/.next/server/app/api/assistant/messages/route.js +1 -1
  20. package/.next/server/app/api/assistant/messages/route.js.nft.json +1 -1
  21. package/.next/server/app/api/assistant/messages/route_client-reference-manifest.js +1 -1
  22. package/.next/server/app/api/assistant/session/route.js +1 -1
  23. package/.next/server/app/api/assistant/session/route.js.nft.json +1 -1
  24. package/.next/server/app/api/assistant/session/route_client-reference-manifest.js +1 -1
  25. package/.next/server/app/api/assistant/start/route.js +3 -3
  26. package/.next/server/app/api/assistant/start/route.js.nft.json +1 -1
  27. package/.next/server/app/api/assistant/start/route_client-reference-manifest.js +1 -1
  28. package/.next/server/app/api/assistant/terminal/route.js +4 -4
  29. package/.next/server/app/api/assistant/terminal/route.js.nft.json +1 -1
  30. package/.next/server/app/api/assistant/terminal/route_client-reference-manifest.js +1 -1
  31. package/.next/server/app/api/assistant/tools/route.js +1 -1
  32. package/.next/server/app/api/assistant/tools/route.js.nft.json +1 -1
  33. package/.next/server/app/api/assistant/tools/route_client-reference-manifest.js +1 -1
  34. package/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
  35. package/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
  36. package/.next/server/app/api/auth/status/route_client-reference-manifest.js +1 -1
  37. package/.next/server/app/api/capabilities/route.js +1 -1
  38. package/.next/server/app/api/capabilities/route_client-reference-manifest.js +1 -1
  39. package/.next/server/app/api/daily-summary/route_client-reference-manifest.js +1 -1
  40. package/.next/server/app/api/daily-summary/status/route_client-reference-manifest.js +1 -1
  41. package/.next/server/app/api/external-apps/[id]/health/route_client-reference-manifest.js +1 -1
  42. package/.next/server/app/api/external-apps/[id]/route_client-reference-manifest.js +1 -1
  43. package/.next/server/app/api/external-apps/route_client-reference-manifest.js +1 -1
  44. package/.next/server/app/api/fs/browse/route_client-reference-manifest.js +1 -1
  45. package/.next/server/app/api/fs/recent-paths/route_client-reference-manifest.js +1 -1
  46. package/.next/server/app/api/hooks/agent-event/route.js +1 -1
  47. package/.next/server/app/api/hooks/agent-event/route.js.nft.json +1 -1
  48. package/.next/server/app/api/hooks/agent-event/route_client-reference-manifest.js +1 -1
  49. package/.next/server/app/api/hooks/claude-done/route.js +1 -1
  50. package/.next/server/app/api/hooks/claude-done/route.js.nft.json +1 -1
  51. package/.next/server/app/api/hooks/claude-done/route_client-reference-manifest.js +1 -1
  52. package/.next/server/app/api/hooks/permission-request/route.js +1 -1
  53. package/.next/server/app/api/hooks/permission-request/route.js.nft.json +1 -1
  54. package/.next/server/app/api/hooks/permission-request/route_client-reference-manifest.js +1 -1
  55. package/.next/server/app/api/metrics/vibe/route_client-reference-manifest.js +1 -1
  56. package/.next/server/app/api/ollama/models/route_client-reference-manifest.js +1 -1
  57. package/.next/server/app/api/push/escalation/route_client-reference-manifest.js +1 -1
  58. package/.next/server/app/api/push/subscriptions/route_client-reference-manifest.js +1 -1
  59. package/.next/server/app/api/push/vapid/route_client-reference-manifest.js +1 -1
  60. package/.next/server/app/api/remote/pair/route_client-reference-manifest.js +1 -1
  61. package/.next/server/app/api/repositories/[id]/route_client-reference-manifest.js +1 -1
  62. package/.next/server/app/api/repositories/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
  63. package/.next/server/app/api/repositories/[id]/todos/route_client-reference-manifest.js +1 -1
  64. package/.next/server/app/api/repositories/clone/[jobId]/route.js +1 -1
  65. package/.next/server/app/api/repositories/clone/[jobId]/route.js.nft.json +1 -1
  66. package/.next/server/app/api/repositories/clone/[jobId]/route_client-reference-manifest.js +1 -1
  67. package/.next/server/app/api/repositories/clone/route.js +1 -1
  68. package/.next/server/app/api/repositories/clone/route.js.nft.json +1 -1
  69. package/.next/server/app/api/repositories/clone/route_client-reference-manifest.js +1 -1
  70. package/.next/server/app/api/repositories/excluded/route_client-reference-manifest.js +1 -1
  71. package/.next/server/app/api/repositories/restore/route.js +1 -1
  72. package/.next/server/app/api/repositories/restore/route.js.nft.json +1 -1
  73. package/.next/server/app/api/repositories/restore/route_client-reference-manifest.js +1 -1
  74. package/.next/server/app/api/repositories/route.js +1 -1
  75. package/.next/server/app/api/repositories/route.js.nft.json +1 -1
  76. package/.next/server/app/api/repositories/route_client-reference-manifest.js +1 -1
  77. package/.next/server/app/api/repositories/scan/route.js +1 -1
  78. package/.next/server/app/api/repositories/scan/route.js.nft.json +1 -1
  79. package/.next/server/app/api/repositories/scan/route_client-reference-manifest.js +1 -1
  80. package/.next/server/app/api/repositories/sync/route.js +1 -1
  81. package/.next/server/app/api/repositories/sync/route.js.nft.json +1 -1
  82. package/.next/server/app/api/repositories/sync/route_client-reference-manifest.js +1 -1
  83. package/.next/server/app/api/repositories/validate-path/route_client-reference-manifest.js +1 -1
  84. package/.next/server/app/api/settings/default-agents/route.js +1 -1
  85. package/.next/server/app/api/settings/default-agents/route.js.nft.json +1 -1
  86. package/.next/server/app/api/settings/default-agents/route_client-reference-manifest.js +1 -1
  87. package/.next/server/app/api/settings/default-surface-mode/route_client-reference-manifest.js +1 -1
  88. package/.next/server/app/api/sidebar/group-order/route_client-reference-manifest.js +1 -1
  89. package/.next/server/app/api/skills/[id]/route.js +1 -1
  90. package/.next/server/app/api/skills/[id]/route_client-reference-manifest.js +1 -1
  91. package/.next/server/app/api/skills/installations/route_client-reference-manifest.js +1 -1
  92. package/.next/server/app/api/skills/operations/route_client-reference-manifest.js +1 -1
  93. package/.next/server/app/api/skills/reindex/route_client-reference-manifest.js +1 -1
  94. package/.next/server/app/api/skills/route.js +1 -1
  95. package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
  96. package/.next/server/app/api/slash-commands/route.js +1 -1
  97. package/.next/server/app/api/slash-commands/route_client-reference-manifest.js +1 -1
  98. package/.next/server/app/api/tasks/[taskId]/cancel/route_client-reference-manifest.js +1 -1
  99. package/.next/server/app/api/tasks/[taskId]/route_client-reference-manifest.js +1 -1
  100. package/.next/server/app/api/templates/[id]/route_client-reference-manifest.js +1 -1
  101. package/.next/server/app/api/templates/route_client-reference-manifest.js +1 -1
  102. package/.next/server/app/api/todos/route_client-reference-manifest.js +1 -1
  103. package/.next/server/app/api/verification/runs/[runId]/route_client-reference-manifest.js +1 -1
  104. package/.next/server/app/api/verification/runs/route_client-reference-manifest.js +1 -1
  105. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js +1 -1
  106. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js.nft.json +1 -1
  107. package/.next/server/app/api/worktrees/[id]/auto-yes/route_client-reference-manifest.js +1 -1
  108. package/.next/server/app/api/worktrees/[id]/capture/route.js +1 -1
  109. package/.next/server/app/api/worktrees/[id]/capture/route.js.nft.json +1 -1
  110. package/.next/server/app/api/worktrees/[id]/capture/route_client-reference-manifest.js +1 -1
  111. package/.next/server/app/api/worktrees/[id]/clear-composer/route.js +1 -1
  112. package/.next/server/app/api/worktrees/[id]/clear-composer/route.js.nft.json +1 -1
  113. package/.next/server/app/api/worktrees/[id]/clear-composer/route_client-reference-manifest.js +1 -1
  114. package/.next/server/app/api/worktrees/[id]/cli-reference/route_client-reference-manifest.js +1 -1
  115. package/.next/server/app/api/worktrees/[id]/cli-tool/route_client-reference-manifest.js +1 -1
  116. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route_client-reference-manifest.js +1 -1
  117. package/.next/server/app/api/worktrees/[id]/current-output/route.js +1 -1
  118. package/.next/server/app/api/worktrees/[id]/current-output/route.js.nft.json +1 -1
  119. package/.next/server/app/api/worktrees/[id]/current-output/route_client-reference-manifest.js +1 -1
  120. package/.next/server/app/api/worktrees/[id]/env/route_client-reference-manifest.js +1 -1
  121. package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route.js +1 -1
  122. package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route_client-reference-manifest.js +1 -1
  123. package/.next/server/app/api/worktrees/[id]/execution-logs/route_client-reference-manifest.js +1 -1
  124. package/.next/server/app/api/worktrees/[id]/files/[...path]/route.js +1 -1
  125. package/.next/server/app/api/worktrees/[id]/files/[...path]/route_client-reference-manifest.js +1 -1
  126. package/.next/server/app/api/worktrees/[id]/git/branch/create/route_client-reference-manifest.js +1 -1
  127. package/.next/server/app/api/worktrees/[id]/git/branch/delete/route_client-reference-manifest.js +1 -1
  128. package/.next/server/app/api/worktrees/[id]/git/branches/route_client-reference-manifest.js +1 -1
  129. package/.next/server/app/api/worktrees/[id]/git/checkout/route_client-reference-manifest.js +1 -1
  130. package/.next/server/app/api/worktrees/[id]/git/commit/route_client-reference-manifest.js +1 -1
  131. package/.next/server/app/api/worktrees/[id]/git/diff/route_client-reference-manifest.js +1 -1
  132. package/.next/server/app/api/worktrees/[id]/git/fetch/route_client-reference-manifest.js +1 -1
  133. package/.next/server/app/api/worktrees/[id]/git/log/route_client-reference-manifest.js +1 -1
  134. package/.next/server/app/api/worktrees/[id]/git/pull/route_client-reference-manifest.js +1 -1
  135. package/.next/server/app/api/worktrees/[id]/git/push/route_client-reference-manifest.js +1 -1
  136. package/.next/server/app/api/worktrees/[id]/git/reset/route_client-reference-manifest.js +1 -1
  137. package/.next/server/app/api/worktrees/[id]/git/revert/route_client-reference-manifest.js +1 -1
  138. package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route_client-reference-manifest.js +1 -1
  139. package/.next/server/app/api/worktrees/[id]/git/stage/route_client-reference-manifest.js +1 -1
  140. package/.next/server/app/api/worktrees/[id]/git/staged/route_client-reference-manifest.js +1 -1
  141. package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route_client-reference-manifest.js +1 -1
  142. package/.next/server/app/api/worktrees/[id]/git/stash/apply/route_client-reference-manifest.js +1 -1
  143. package/.next/server/app/api/worktrees/[id]/git/stash/pop/route_client-reference-manifest.js +1 -1
  144. package/.next/server/app/api/worktrees/[id]/git/stash/push/route_client-reference-manifest.js +1 -1
  145. package/.next/server/app/api/worktrees/[id]/git/stash/route_client-reference-manifest.js +1 -1
  146. package/.next/server/app/api/worktrees/[id]/git/status/route_client-reference-manifest.js +1 -1
  147. package/.next/server/app/api/worktrees/[id]/git/unstage/route_client-reference-manifest.js +1 -1
  148. package/.next/server/app/api/worktrees/[id]/git/working-diff/route_client-reference-manifest.js +1 -1
  149. package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js.nft.json +1 -1
  150. package/.next/server/app/api/worktrees/[id]/instances/opencode/route_client-reference-manifest.js +1 -1
  151. package/.next/server/app/api/worktrees/[id]/interrupt/route.js +1 -1
  152. package/.next/server/app/api/worktrees/[id]/interrupt/route.js.nft.json +1 -1
  153. package/.next/server/app/api/worktrees/[id]/interrupt/route_client-reference-manifest.js +1 -1
  154. package/.next/server/app/api/worktrees/[id]/kill-session/route.js +1 -1
  155. package/.next/server/app/api/worktrees/[id]/kill-session/route.js.nft.json +1 -1
  156. package/.next/server/app/api/worktrees/[id]/kill-session/route_client-reference-manifest.js +1 -1
  157. package/.next/server/app/api/worktrees/[id]/logs/[filename]/route_client-reference-manifest.js +1 -1
  158. package/.next/server/app/api/worktrees/[id]/logs/route_client-reference-manifest.js +1 -1
  159. package/.next/server/app/api/worktrees/[id]/marp-render/route_client-reference-manifest.js +1 -1
  160. package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route_client-reference-manifest.js +1 -1
  161. package/.next/server/app/api/worktrees/[id]/memos/route_client-reference-manifest.js +1 -1
  162. package/.next/server/app/api/worktrees/[id]/messages/route_client-reference-manifest.js +1 -1
  163. package/.next/server/app/api/worktrees/[id]/opencode/diff/route_client-reference-manifest.js +1 -1
  164. package/.next/server/app/api/worktrees/[id]/opencode/session/route_client-reference-manifest.js +1 -1
  165. package/.next/server/app/api/worktrees/[id]/opencode/share/route_client-reference-manifest.js +1 -1
  166. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js +1 -1
  167. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js.nft.json +1 -1
  168. package/.next/server/app/api/worktrees/[id]/prompt-response/route_client-reference-manifest.js +1 -1
  169. package/.next/server/app/api/worktrees/[id]/resolve-target/route_client-reference-manifest.js +1 -1
  170. package/.next/server/app/api/worktrees/[id]/respond/route.js +1 -1
  171. package/.next/server/app/api/worktrees/[id]/respond/route.js.nft.json +1 -1
  172. package/.next/server/app/api/worktrees/[id]/respond/route_client-reference-manifest.js +1 -1
  173. package/.next/server/app/api/worktrees/[id]/route.js +1 -1
  174. package/.next/server/app/api/worktrees/[id]/route.js.nft.json +1 -1
  175. package/.next/server/app/api/worktrees/[id]/route_client-reference-manifest.js +1 -1
  176. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route.js +4 -3
  177. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route_client-reference-manifest.js +1 -1
  178. package/.next/server/app/api/worktrees/[id]/schedules/active/route_client-reference-manifest.js +1 -1
  179. package/.next/server/app/api/worktrees/[id]/schedules/route.js +4 -3
  180. package/.next/server/app/api/worktrees/[id]/schedules/route_client-reference-manifest.js +1 -1
  181. package/.next/server/app/api/worktrees/[id]/search/route_client-reference-manifest.js +1 -1
  182. package/.next/server/app/api/worktrees/[id]/send/route.js +1 -1
  183. package/.next/server/app/api/worktrees/[id]/send/route.js.nft.json +1 -1
  184. package/.next/server/app/api/worktrees/[id]/send/route_client-reference-manifest.js +1 -1
  185. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js +2 -2
  186. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js.nft.json +1 -1
  187. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route_client-reference-manifest.js +1 -1
  188. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route_client-reference-manifest.js +1 -1
  189. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route_client-reference-manifest.js +1 -1
  190. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route_client-reference-manifest.js +1 -1
  191. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route_client-reference-manifest.js +1 -1
  192. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update/route_client-reference-manifest.js +1 -1
  193. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route_client-reference-manifest.js +1 -1
  194. package/.next/server/app/api/worktrees/[id]/skills/route_client-reference-manifest.js +1 -1
  195. package/.next/server/app/api/worktrees/[id]/slash-commands/route.js +1 -1
  196. package/.next/server/app/api/worktrees/[id]/slash-commands/route_client-reference-manifest.js +1 -1
  197. package/.next/server/app/api/worktrees/[id]/special-keys/route.js +1 -1
  198. package/.next/server/app/api/worktrees/[id]/special-keys/route.js.nft.json +1 -1
  199. package/.next/server/app/api/worktrees/[id]/special-keys/route_client-reference-manifest.js +1 -1
  200. package/.next/server/app/api/worktrees/[id]/tasks/route_client-reference-manifest.js +1 -1
  201. package/.next/server/app/api/worktrees/[id]/terminal/route.js +1 -1
  202. package/.next/server/app/api/worktrees/[id]/terminal/route.js.nft.json +1 -1
  203. package/.next/server/app/api/worktrees/[id]/terminal/route_client-reference-manifest.js +1 -1
  204. package/.next/server/app/api/worktrees/[id]/timers/history/route_client-reference-manifest.js +1 -1
  205. package/.next/server/app/api/worktrees/[id]/timers/route.js +1 -1
  206. package/.next/server/app/api/worktrees/[id]/timers/route.js.nft.json +1 -1
  207. package/.next/server/app/api/worktrees/[id]/timers/route_client-reference-manifest.js +1 -1
  208. package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
  209. package/.next/server/app/api/worktrees/[id]/todos/route_client-reference-manifest.js +1 -1
  210. package/.next/server/app/api/worktrees/[id]/tree/[...path]/route_client-reference-manifest.js +1 -1
  211. package/.next/server/app/api/worktrees/[id]/tree/route_client-reference-manifest.js +1 -1
  212. package/.next/server/app/api/worktrees/[id]/upload/[...path]/route_client-reference-manifest.js +1 -1
  213. package/.next/server/app/api/worktrees/[id]/verify/config/route_client-reference-manifest.js +1 -1
  214. package/.next/server/app/api/worktrees/[id]/verify/route_client-reference-manifest.js +1 -1
  215. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route_client-reference-manifest.js +1 -1
  216. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route_client-reference-manifest.js +1 -1
  217. package/.next/server/app/api/worktrees/[id]/verify/runs/route_client-reference-manifest.js +1 -1
  218. package/.next/server/app/api/worktrees/[id]/viewed/route_client-reference-manifest.js +1 -1
  219. package/.next/server/app/api/worktrees/apply-default-agents/route_client-reference-manifest.js +1 -1
  220. package/.next/server/app/api/worktrees/route.js +1 -1
  221. package/.next/server/app/api/worktrees/route.js.nft.json +1 -1
  222. package/.next/server/app/api/worktrees/route_client-reference-manifest.js +1 -1
  223. package/.next/server/app/chat/page.js +2 -2
  224. package/.next/server/app/chat/page.js.nft.json +1 -1
  225. package/.next/server/app/chat/page_client-reference-manifest.js +1 -1
  226. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  227. package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
  228. package/.next/server/app/more/page.js +2 -2
  229. package/.next/server/app/more/page.js.nft.json +1 -1
  230. package/.next/server/app/more/page_client-reference-manifest.js +1 -1
  231. package/.next/server/app/offline/page_client-reference-manifest.js +1 -1
  232. package/.next/server/app/page.js +1 -1
  233. package/.next/server/app/page.js.nft.json +1 -1
  234. package/.next/server/app/page_client-reference-manifest.js +1 -1
  235. package/.next/server/app/proxy/[...path]/route_client-reference-manifest.js +1 -1
  236. package/.next/server/app/repositories/page.js +2 -2
  237. package/.next/server/app/repositories/page.js.nft.json +1 -1
  238. package/.next/server/app/repositories/page_client-reference-manifest.js +1 -1
  239. package/.next/server/app/review/page.js +1 -1
  240. package/.next/server/app/review/page.js.nft.json +1 -1
  241. package/.next/server/app/review/page_client-reference-manifest.js +1 -1
  242. package/.next/server/app/sessions/page.js +1 -1
  243. package/.next/server/app/sessions/page.js.nft.json +1 -1
  244. package/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  245. package/.next/server/app/skills/[skillId]/page.js +2 -2
  246. package/.next/server/app/skills/[skillId]/page.js.nft.json +1 -1
  247. package/.next/server/app/skills/[skillId]/page_client-reference-manifest.js +1 -1
  248. package/.next/server/app/skills/installed/page.js +2 -2
  249. package/.next/server/app/skills/installed/page.js.nft.json +1 -1
  250. package/.next/server/app/skills/installed/page_client-reference-manifest.js +1 -1
  251. package/.next/server/app/skills/page.js +1 -1
  252. package/.next/server/app/skills/page.js.nft.json +1 -1
  253. package/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  254. package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -1
  255. package/.next/server/app/worktrees/[id]/page.js +10 -10
  256. package/.next/server/app/worktrees/[id]/page.js.nft.json +1 -1
  257. package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -1
  258. package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
  259. package/.next/server/app-paths-manifest.json +28 -28
  260. package/.next/server/chunks/1058.js +1 -1
  261. package/.next/server/chunks/1068.js +1 -1
  262. package/.next/server/chunks/1262.js +1 -1
  263. package/.next/server/chunks/1886.js +3 -3
  264. package/.next/server/chunks/1990.js +103 -0
  265. package/.next/server/chunks/2119.js +1 -1
  266. package/.next/server/chunks/2328.js +1 -1
  267. package/.next/server/chunks/2404.js +1 -1
  268. package/.next/server/chunks/2445.js +1 -1
  269. package/.next/server/chunks/261.js +1 -1
  270. package/.next/server/chunks/3123.js +1 -1
  271. package/.next/server/chunks/3241.js +1 -1
  272. package/.next/server/chunks/3480.js +5 -4
  273. package/.next/server/chunks/4299.js +1 -1
  274. package/.next/server/chunks/4393.js +1 -1
  275. package/.next/server/chunks/4443.js +1 -5
  276. package/.next/server/chunks/5017.js +1 -1
  277. package/.next/server/chunks/5043.js +1 -1
  278. package/.next/server/chunks/5164.js +1 -1
  279. package/.next/server/chunks/552.js +2 -2
  280. package/.next/server/chunks/6072.js +1 -1
  281. package/.next/server/chunks/6130.js +1 -1
  282. package/.next/server/chunks/663.js +4 -3
  283. package/.next/server/chunks/6894.js +2 -2
  284. package/.next/server/chunks/7187.js +1 -0
  285. package/.next/server/chunks/7472.js +1 -1
  286. package/.next/server/chunks/{880.js → 7859.js} +6 -6
  287. package/.next/server/chunks/7905.js +1 -1
  288. package/.next/server/chunks/8800.js +2 -2
  289. package/.next/server/chunks/8918.js +7 -0
  290. package/.next/server/chunks/9123.js +2 -2
  291. package/.next/server/chunks/9130.js +4 -4
  292. package/.next/server/chunks/9627.js +1 -1
  293. package/.next/server/chunks/9696.js +2 -2
  294. package/.next/server/chunks/9798.js +1 -1
  295. package/.next/server/middleware-manifest.json +5 -5
  296. package/.next/server/pages/500.html +1 -1
  297. package/.next/server/server-reference-manifest.json +1 -1
  298. package/.next/static/chunks/1783-11c9b4d8a52ebd91.js +1 -0
  299. package/.next/static/chunks/4718-de1224c9e8a6e7fc.js +1 -0
  300. package/.next/static/chunks/6022-2fa0b5a82d4ce7b6.js +1 -0
  301. package/.next/static/chunks/{5229-6c89475b61bd2c8b.js → 6170-951b9f5fe6b4b3b5.js} +1 -1
  302. package/.next/static/chunks/app/chat/{page-9aa2011410895b0d.js → page-37d7615d17d7e2a0.js} +1 -1
  303. package/.next/static/chunks/app/layout-4c2f21e3f653ee4c.js +1 -0
  304. package/.next/static/chunks/app/more/{page-333bba1c8bbc9c11.js → page-353a3924e6d7968e.js} +1 -1
  305. package/.next/static/chunks/app/{page-214f7ffa13a0cf10.js → page-c2bf871d953a1d6f.js} +1 -1
  306. package/.next/static/chunks/app/repositories/{page-4951cac905e50224.js → page-7d0f26df0537254c.js} +1 -1
  307. package/.next/static/chunks/app/review/{page-a0899b2d285318c3.js → page-e3f141b2829973e9.js} +1 -1
  308. package/.next/static/chunks/app/sessions/{page-fb36145ec732092a.js → page-53f188ed9ca49e5f.js} +1 -1
  309. package/.next/static/chunks/app/skills/[skillId]/{page-9099e26b60442873.js → page-80569b720aea59cc.js} +1 -1
  310. package/.next/static/chunks/app/skills/installed/{page-182e32368696d824.js → page-dbd2690ad72da95b.js} +1 -1
  311. package/.next/static/chunks/app/skills/{page-d3fdc88239ebe0ab.js → page-dacd36f9c11aa7da.js} +1 -1
  312. package/.next/static/chunks/app/worktrees/[id]/page-97205088520255a5.js +1 -0
  313. package/.next/static/css/5c13ea243dfdcb66.css +1 -0
  314. package/.next/trace +13 -13
  315. package/README.md +37 -11
  316. package/dist/cli/commands/attach.d.ts +50 -0
  317. package/dist/cli/commands/attach.d.ts.map +1 -0
  318. package/dist/cli/commands/attach.js +204 -0
  319. package/dist/cli/commands/capture.d.ts.map +1 -1
  320. package/dist/cli/commands/capture.js +114 -0
  321. package/dist/cli/commands/instances.d.ts.map +1 -1
  322. package/dist/cli/commands/instances.js +23 -2
  323. package/dist/cli/commands/ls.d.ts.map +1 -1
  324. package/dist/cli/commands/ls.js +41 -1
  325. package/dist/cli/config/cli-dependencies.d.ts.map +1 -1
  326. package/dist/cli/config/cli-dependencies.js +34 -0
  327. package/dist/cli/program.d.ts.map +1 -1
  328. package/dist/cli/program.js +5 -0
  329. package/dist/cli/types/index.d.ts +36 -0
  330. package/dist/cli/types/index.d.ts.map +1 -1
  331. package/dist/config/tmux-pane-config.d.ts +153 -0
  332. package/dist/config/tmux-pane-config.d.ts.map +1 -0
  333. package/dist/config/tmux-pane-config.js +172 -0
  334. package/dist/lib/cli-tools/session-name.d.ts +44 -0
  335. package/dist/lib/cli-tools/session-name.d.ts.map +1 -0
  336. package/dist/lib/cli-tools/session-name.js +57 -0
  337. package/dist/lib/cli-tools/types.d.ts +1 -1
  338. package/dist/lib/cli-tools/types.d.ts.map +1 -1
  339. package/dist/lib/cli-tools/types.js +6 -1
  340. package/dist/lib/cli-tools/validation.d.ts +34 -0
  341. package/dist/lib/cli-tools/validation.d.ts.map +1 -0
  342. package/dist/lib/cli-tools/validation.js +41 -0
  343. package/dist/lib/detection/status-reason.d.ts +18 -0
  344. package/dist/lib/detection/status-reason.d.ts.map +1 -1
  345. package/dist/lib/detection/status-reason.js +18 -0
  346. package/dist/lib/detection/tools/verified-against.d.ts +57 -7
  347. package/dist/lib/detection/tools/verified-against.d.ts.map +1 -1
  348. package/dist/lib/detection/tools/verified-against.js +59 -8
  349. package/dist/lib/detection/version-probes.d.ts +26 -5
  350. package/dist/lib/detection/version-probes.d.ts.map +1 -1
  351. package/dist/lib/detection/version-probes.js +28 -6
  352. package/dist/lib/session/tmux-session-surface.d.ts +369 -0
  353. package/dist/lib/session/tmux-session-surface.d.ts.map +1 -0
  354. package/dist/lib/session/tmux-session-surface.js +525 -0
  355. package/dist/server/src/config/cli-tool-timing-config.js +12 -1
  356. package/dist/server/src/config/detection-evidence-config.js +5 -0
  357. package/dist/server/src/config/schedule-config.js +28 -1
  358. package/dist/server/src/lib/cli-tools/antigravity.js +2 -2
  359. package/dist/server/src/lib/cli-tools/base.js +13 -8
  360. package/dist/server/src/lib/cli-tools/claude.js +20 -0
  361. package/dist/server/src/lib/cli-tools/codex.js +205 -61
  362. package/dist/server/src/lib/cli-tools/command-code.js +349 -0
  363. package/dist/server/src/lib/cli-tools/composer-spec.js +6 -0
  364. package/dist/server/src/lib/cli-tools/copilot.js +2 -2
  365. package/dist/server/src/lib/cli-tools/gemini.js +2 -2
  366. package/dist/server/src/lib/cli-tools/graceful-exit.js +16 -1
  367. package/dist/server/src/lib/cli-tools/index.js +4 -1
  368. package/dist/server/src/lib/cli-tools/install-hints.js +131 -0
  369. package/dist/server/src/lib/cli-tools/liveness-spec.js +18 -0
  370. package/dist/server/src/lib/cli-tools/manager.js +2 -0
  371. package/dist/server/src/lib/cli-tools/opencode.js +2 -2
  372. package/dist/server/src/lib/cli-tools/start-availability.js +18 -11
  373. package/dist/server/src/lib/cli-tools/types.js +6 -1
  374. package/dist/server/src/lib/cli-tools/vibe-local.js +2 -2
  375. package/dist/server/src/lib/cmate-parser.js +6 -0
  376. package/dist/server/src/lib/detection/cli-patterns.js +441 -8
  377. package/dist/server/src/lib/detection/opencode-modal-overlay.js +66 -100
  378. package/dist/server/src/lib/detection/selection-shape.js +341 -0
  379. package/dist/server/src/lib/detection/sgr-background.js +210 -0
  380. package/dist/server/src/lib/detection/status-detector.js +6 -0
  381. package/dist/server/src/lib/detection/status-reason.js +18 -0
  382. package/dist/server/src/lib/detection/tools/antigravity/detect.js +38 -15
  383. package/dist/server/src/lib/detection/tools/codex/cli-patterns.js +392 -0
  384. package/dist/server/src/lib/detection/tools/codex/detect.js +83 -2
  385. package/dist/server/src/lib/detection/tools/command-code/detect.js +159 -0
  386. package/dist/server/src/lib/detection/tools/registry.js +6 -4
  387. package/dist/server/src/lib/detection/tools/verified-against.js +59 -8
  388. package/dist/server/src/lib/detection/version-probes.js +28 -6
  389. package/dist/server/src/lib/hooks/sources/antigravity/history.js +101 -21
  390. package/dist/server/src/lib/hooks/sources/antigravity/transcript.js +39 -0
  391. package/dist/server/src/lib/hooks/sources/claude/history.js +245 -21
  392. package/dist/server/src/lib/hooks/sources/claude/transcript.js +175 -13
  393. package/dist/server/src/lib/hooks/sources/codex/history.js +84 -15
  394. package/dist/server/src/lib/hooks/sources/codex/hooks-config.js +130 -17
  395. package/dist/server/src/lib/hooks/sources/codex/relay-install.js +145 -0
  396. package/dist/server/src/lib/hooks/sources/command-code/history.js +865 -0
  397. package/dist/server/src/lib/hooks/sources/command-code/hooks-config.js +390 -0
  398. package/dist/server/src/lib/hooks/sources/command-code/source.js +290 -0
  399. package/dist/server/src/lib/hooks/sources/command-code/tool-id.js +18 -0
  400. package/dist/server/src/lib/hooks/sources/command-code/transcript.js +604 -0
  401. package/dist/server/src/lib/hooks/sources/index.js +3 -1
  402. package/dist/server/src/lib/hooks/sources/opencode/history.js +57 -3
  403. package/dist/server/src/lib/hooks/sources/opencode/transcript.js +24 -28
  404. package/dist/server/src/lib/hooks/sources/registry.js +4 -0
  405. package/dist/server/src/lib/hooks/sources/turn-body.js +77 -19
  406. package/dist/server/src/lib/hooks/stop-history-capture.js +58 -25
  407. package/dist/server/src/lib/job-executor.js +12 -0
  408. package/dist/server/src/lib/polling/auto-yes-dialog-gate.js +6 -0
  409. package/dist/server/src/lib/polling/response-checker.js +112 -7
  410. package/dist/server/src/lib/polling/structured-history-gate.js +15 -8
  411. package/dist/server/src/lib/realtime/types.js +15 -5
  412. package/dist/server/src/lib/response-cleaner.js +24 -1
  413. package/dist/server/src/lib/response-extractor.js +11 -0
  414. package/dist/server/src/lib/session/claude-executor.js +223 -4
  415. package/dist/server/src/lib/session/cli-session.js +52 -0
  416. package/dist/server/src/lib/session/tmux-session-surface.js +525 -0
  417. package/dist/server/src/lib/skills/compatibility-matrix.js +117 -1
  418. package/dist/server/src/lib/tmux/geometry-delegation.js +143 -0
  419. package/dist/server/src/lib/tmux/read-mode-pager.js +76 -10
  420. package/dist/server/src/lib/tmux/read-mode.js +44 -2
  421. package/dist/server/src/lib/tmux/session-hook-scripts.js +249 -0
  422. package/dist/server/src/lib/tmux/session-hooks.js +122 -0
  423. package/dist/server/src/lib/tmux/session-status-options.js +213 -0
  424. package/dist/server/src/lib/tmux/tmux.js +79 -2
  425. package/dist/server/src/lib/version-checker.js +110 -0
  426. package/dist/server/src/lib/ws-server.js +16 -10
  427. package/dist/server/src/types/agent-transcript.js +73 -1
  428. package/dist/server/src/types/terminal-keys.js +131 -3
  429. package/dist/types/terminal-keys.d.ts +100 -3
  430. package/dist/types/terminal-keys.d.ts.map +1 -1
  431. package/dist/types/terminal-keys.js +131 -3
  432. package/package.json +1 -1
  433. package/.next/server/chunks/3099.js +0 -5
  434. package/.next/server/chunks/7824.js +0 -1
  435. package/.next/static/chunks/3916-0e929d089282dc5d.js +0 -1
  436. package/.next/static/chunks/6022-7a7d1760fc9814c7.js +0 -1
  437. package/.next/static/chunks/6381-dbf04a99647f6018.js +0 -1
  438. package/.next/static/chunks/app/layout-6a26ea22d5cf03dc.js +0 -1
  439. package/.next/static/chunks/app/worktrees/[id]/page-aac399392ec8c273.js +0 -1
  440. package/.next/static/css/23f9c40ecc458c77.css +0 -1
  441. /package/.next/static/{pcpB4K6KreMzu2qbhvuRY → nXW4dPkpE_9xUf_9ySRff}/_buildManifest.js +0 -0
  442. /package/.next/static/{pcpB4K6KreMzu2qbhvuRY → nXW4dPkpE_9xUf_9ySRff}/_ssgManifest.js +0 -0
@@ -4,7 +4,7 @@
4
4
  * Provides functions to manage tmux sessions for Claude CLI integration
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.NAVIGATION_KEY_VALUES = exports.SPECIAL_KEY_VALUES = void 0;
7
+ exports.REPAINT_INVALIDATE_DELAY_MS = exports.NAVIGATION_KEY_VALUES = exports.SPECIAL_KEY_VALUES = void 0;
8
8
  exports.exactTarget = exactTarget;
9
9
  exports.reconcileSessionGeometry = reconcileSessionGeometry;
10
10
  exports.isTmuxAvailable = isTmuxAvailable;
@@ -28,6 +28,7 @@ exports.sendSpecialKeysAndInvalidate = sendSpecialKeysAndInvalidate;
28
28
  const child_process_1 = require("child_process");
29
29
  const util_1 = require("util");
30
30
  const tmux_capture_cache_1 = require("./tmux-capture-cache");
31
+ const geometry_delegation_1 = require("./geometry-delegation");
31
32
  const validation_1 = require("../../lib/cli-tools/validation");
32
33
  const tmux_pane_config_1 = require("../../config/tmux-pane-config");
33
34
  const logger_1 = require("../../lib/logger");
@@ -77,6 +78,24 @@ function exactTarget(sessionName) {
77
78
  * Failures are intentionally non-fatal: geometry improves capture fidelity but
78
79
  * must never make an otherwise healthy CLI session unusable.
79
80
  *
81
+ * ## It stands down while a human is attached (Issue #2317, Phase D)
82
+ *
83
+ * `commandmate attach --live` hands the window to the terminal looking at it so
84
+ * the transcript is readable at all; every `send` to a running session reaches
85
+ * here through `reconcileExistingSession()`, and snapping the canvas back to
86
+ * 200x1000 mid-read would undo that under the reader's hands. So when the
87
+ * geometry does NOT already match, this asks whether a NON-control-mode client
88
+ * is attached and leaves the window alone if one is.
89
+ *
90
+ * Two properties of that ordering are load-bearing:
91
+ *
92
+ * - the question is asked only on the path that would actually resize, so the
93
+ * overwhelmingly common "already correct" call still costs exactly the two
94
+ * tmux round-trips it always has;
95
+ * - it keys off a live client rather than off `@cm_delegated`, so a flag left
96
+ * behind by a CLI that was killed can never pin a window open forever — the
97
+ * next reconcile with nobody attached repairs it.
98
+ *
80
99
  * @returns true when at least one tmux option was changed.
81
100
  */
82
101
  async function reconcileSessionGeometry(sessionName, options = {}) {
@@ -103,6 +122,13 @@ async function reconcileSessionGeometry(sessionName, options = {}) {
103
122
  const sizeMatches = currentWidth === windowWidth && currentHeight === windowHeight;
104
123
  if (modeMatches && sizeMatches)
105
124
  return false;
125
+ // Issue #2317: a human is reading this pane at their terminal's size. See the
126
+ // docblock — asked here, after the cheap match, so the ordinary call is
127
+ // unchanged.
128
+ if ((options.respectAttachedClient ?? true) && (await (0, geometry_delegation_1.hasHumanClientAttached)(sessionName))) {
129
+ logger.info('session-geometry:delegated-to-client', { sessionName });
130
+ return false;
131
+ }
106
132
  try {
107
133
  if (!modeMatches) {
108
134
  await execFileAsync('tmux', ['set-window-option', '-t', target, 'window-size', 'manual'], { timeout: DEFAULT_TIMEOUT });
@@ -316,7 +342,13 @@ async function createSession(sessionNameOrOptions, cwd) {
316
342
  // replaced (verified: `show-window-options -v window-size` came back empty),
317
343
  // so reconciling first would have the setting thrown away and leave the pane
318
344
  // tracking the latest client again.
319
- await reconcileSessionGeometry(sessionName, { windowWidth, windowHeight });
345
+ await reconcileSessionGeometry(sessionName, {
346
+ windowWidth,
347
+ windowHeight,
348
+ // Nothing can be attached to a session this call is still creating, so the
349
+ // Phase D client probe would be a round-trip with one possible answer.
350
+ respectAttachedClient: false,
351
+ });
320
352
  }
321
353
  catch (error) {
322
354
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -433,6 +465,20 @@ const ALLOWED_SPECIAL_KEYS = new Set([
433
465
  // are tmux named keys; 'q' is the pager's literal "quit" character (sent verbatim by
434
466
  // `tmux send-keys`, no injection risk — single fixed char via execFile, not a shell).
435
467
  'PageUp', 'PageDown', 'Home', 'End', 'q',
468
+ // Issue #2254: the answer characters `1`-`9` / `y` / `n`, so a dialog nobody
469
+ // could parse can be answered from the chat surface's dialog card instead of
470
+ // only from the terminal. Literal characters on the wire like `q` above.
471
+ // `n` was already deliverable as an opencode chord letter and is not repeated.
472
+ '1', '2', '3', '4', '5', '6', '7', '8', '9', 'y',
473
+ // Issue #2297: claude's "use this session only" key. Its `/model` footer reads
474
+ // `Enter to set as default · s to use this session only · Esc to cancel`, and
475
+ // `Enter` there rewrites `model` in ~/.claude/settings.json (#1495) — so
476
+ // without this the chat surface could deliver the destructive half of that
477
+ // footer and not the safe half. A literal character like `q` / `y` above.
478
+ // Deliverable here for every session; only claude and Command Code DECLARE it
479
+ // (`CLAUDE_NAVIGATION_KEY_VALUES`), so the route answers 400 for anyone else —
480
+ // which matters, because `s` is `sort:relevance` on copilot's session picker.
481
+ 's',
436
482
  // Issue #2046: opencode's own chords. `C-x` is its leader prefix (measured
437
483
  // default of 1.18.22, 2000 ms window), `C-p` opens the command palette and
438
484
  // `C-t` cycles the model variant. The lower-case letters complete a leader
@@ -802,6 +848,36 @@ async function clearComposerLine(sessionName) {
802
848
  function isAllowedSpecialKey(key, vocabulary = terminal_keys_1.NAVIGATION_KEY_VALUES) {
803
849
  return vocabulary.includes(key) && isSendableSpecialKey(key);
804
850
  }
851
+ /**
852
+ * How long after a key lands the TUI is still allowed to be repainting
853
+ * (Issue #2297).
854
+ *
855
+ * `invalidateCache()` fires the instant `tmux send-keys` returns, which is
856
+ * BEFORE the CLI has drawn the consequence of the key. The next capture — the
857
+ * chat surface's own `onKeysSent` refresh, or any of the pollers that share this
858
+ * cache (the sidebar status probe, the global session poller) — therefore has a
859
+ * good chance of storing the PRE-repaint frame, and {@link CACHE_TTL_MS} then
860
+ * serves that stale frame for five seconds. That is the "the highlight does not
861
+ * move" report in Issue #2297: the send worked, the cache was invalidated, and
862
+ * the surface still drew the old dialog.
863
+ *
864
+ * 250 ms is comfortably past an ink/bubbletea repaint (`SPECIAL_KEY_DELAY_MS`,
865
+ * the gap this transport already leaves BETWEEN keys of one chord, is 100 ms)
866
+ * and comfortably inside the 1-second budget the Issue sets for seeing the
867
+ * highlight move.
868
+ */
869
+ exports.REPAINT_INVALIDATE_DELAY_MS = 250;
870
+ /**
871
+ * Drop the cached frame again once the TUI has had time to repaint.
872
+ *
873
+ * Fire-and-forget on purpose: the route must not wait 250 ms to answer, and the
874
+ * work is one `Map.delete`. The timer is `unref()`ed where the runtime supports
875
+ * it so a pending invalidation can never hold a process (or a test runner) open.
876
+ */
877
+ function scheduleRepaintInvalidation(sessionName) {
878
+ const timer = setTimeout(() => (0, tmux_capture_cache_1.invalidateCache)(sessionName), exports.REPAINT_INVALIDATE_DELAY_MS);
879
+ timer.unref?.();
880
+ }
805
881
  /**
806
882
  * Send special keys to a tmux session and invalidate the capture cache.
807
883
  * Wrapper combining sendSpecialKeys() + invalidateCache() for DRY (DR1-003).
@@ -812,4 +888,5 @@ function isAllowedSpecialKey(key, vocabulary = terminal_keys_1.NAVIGATION_KEY_VA
812
888
  async function sendSpecialKeysAndInvalidate(sessionName, keys) {
813
889
  await sendSpecialKeys(sessionName, keys);
814
890
  (0, tmux_capture_cache_1.invalidateCache)(sessionName);
891
+ scheduleRepaintInvalidation(sessionName);
815
892
  }
@@ -20,12 +20,15 @@ exports.isNewerVersion = isNewerVersion;
20
20
  exports.getClientVersion = getClientVersion;
21
21
  exports.getServerVersion = getServerVersion;
22
22
  exports.getCurrentVersion = getCurrentVersion;
23
+ exports.getServedBundleVersion = getServedBundleVersion;
24
+ exports.resolveBundleDrift = resolveBundleDrift;
23
25
  exports.validateReleaseUrl = validateReleaseUrl;
24
26
  exports.sanitizeReleaseName = sanitizeReleaseName;
25
27
  exports.checkForUpdate = checkForUpdate;
26
28
  exports.resetCacheForTesting = resetCacheForTesting;
27
29
  const fs_1 = require("fs");
28
30
  const path_1 = require("path");
31
+ const types_1 = require("../lib/realtime/types");
29
32
  // =============================================================================
30
33
  // Constants
31
34
  // =============================================================================
@@ -60,6 +63,17 @@ const FETCH_TIMEOUT_MS = 5000;
60
63
  * project directory) leaking a foreign version.
61
64
  */
62
65
  const PACKAGE_NAME = 'commandmate';
66
+ /**
67
+ * The manifest `next build` writes beside the client bundle, relative to the
68
+ * package root. [Issue #2271]
69
+ *
70
+ * It snapshots the *resolved* next.config — the `env` block included — so
71
+ * `config.env.NEXT_PUBLIC_APP_VERSION` is literally the string that build
72
+ * inlined into every browser bundle it emitted. That makes it the only file on
73
+ * disk that can answer "which version is the bundle we are serving?" without
74
+ * asking the bundle itself.
75
+ */
76
+ const NEXT_BUILD_MANIFEST_PATH = ['.next', 'required-server-files.json'];
63
77
  const cache = globalThis.__versionCheckCache ??
64
78
  (globalThis.__versionCheckCache = {
65
79
  result: null,
@@ -162,6 +176,99 @@ function getServerVersion() {
162
176
  function getCurrentVersion() {
163
177
  return getServerVersion();
164
178
  }
179
+ // =============================================================================
180
+ // Served bundle identity (Issue #2271)
181
+ // =============================================================================
182
+ /**
183
+ * Memoised answer of {@link getServedBundleVersion}, resolved on first use and
184
+ * then frozen for the life of the process. [Issue #2271]
185
+ *
186
+ * Frozen on purpose. The question is "which build is this process serving?",
187
+ * and a running Next production server answers that once — at startup, from the
188
+ * `.next` it opened. Re-reading the manifest on every call would let a
189
+ * `next build` performed *underneath* the running server rename the served
190
+ * build without the server having reloaded a single byte of it, which is the
191
+ * false positive this Issue exists to remove, in a new disguise.
192
+ */
193
+ let servedBundleVersion = null;
194
+ /**
195
+ * Read the version `next build` inlined into the client bundle, from the build
196
+ * manifest it left on disk. [Issue #2271]
197
+ *
198
+ * @returns The baked version, or null when the manifest is absent, unreadable,
199
+ * malformed, or predates the `env` block.
200
+ */
201
+ function readServedBundleVersionFromBuild() {
202
+ try {
203
+ const raw = (0, fs_1.readFileSync)((0, path_1.join)(process.cwd(), ...NEXT_BUILD_MANIFEST_PATH), 'utf-8');
204
+ const parsed = JSON.parse(raw);
205
+ const baked = parsed.config?.env?.NEXT_PUBLIC_APP_VERSION;
206
+ if (typeof baked === 'string' && baked.length > 0)
207
+ return baked;
208
+ return null;
209
+ }
210
+ catch {
211
+ return null;
212
+ }
213
+ }
214
+ /** First-use resolution behind {@link getServedBundleVersion}'s memo. */
215
+ function resolveServedBundleVersion() {
216
+ // `next dev` compiles on demand and never writes the build manifest, but a
217
+ // stale one left by an earlier `npm run build` is still sitting in `.next` —
218
+ // and it names a version the dev bundle was never built from. Under dev the
219
+ // live next.config populates `process.env` for the server too, so the baked
220
+ // value already *is* the honest answer and the manifest must not be consulted.
221
+ if (process.env.NODE_ENV === 'production') {
222
+ const built = readServedBundleVersionFromBuild();
223
+ if (built)
224
+ return built;
225
+ }
226
+ return getClientVersion();
227
+ }
228
+ /**
229
+ * The version of the **client bundle this server is serving**. [Issue #2271]
230
+ *
231
+ * Deliberately *not* {@link getServerVersion}. That one reads package.json at
232
+ * runtime, which is the right answer for "is there a newer release on GitHub?"
233
+ * and the wrong one for "should this tab reload?": the release procedure bumps
234
+ * package.json on `develop` and never rebuilds the primary checkout (doing so
235
+ * would swap `.next` out from under the running server — see the release
236
+ * skill's Phase 2-3), so `package.json > bundle` is the steady state after
237
+ * every release. Comparing against it therefore told **every** tab, forever,
238
+ * that it was out of date.
239
+ *
240
+ * The honest comparand is the build the bundle came from, so this reads the
241
+ * `next build` manifest and falls back — never to package.json — to the baked
242
+ * `NEXT_PUBLIC_APP_VERSION`, and finally to `'0.0.0'`, which
243
+ * {@link isVersionMismatch} treats as "unknown" and never reports as drift.
244
+ *
245
+ * @returns Served bundle version string (e.g., "0.2.3"), or "0.0.0" as fallback
246
+ */
247
+ function getServedBundleVersion() {
248
+ servedBundleVersion ??= resolveServedBundleVersion();
249
+ return servedBundleVersion;
250
+ }
251
+ /**
252
+ * Decide whether a tab running `clientBundleVersion` is on a stale build.
253
+ * [Issue #2271]
254
+ *
255
+ * The single seam the WebSocket version handshake calls, so "what counts as
256
+ * drift" has exactly one definition and one place to test it. Both sides are
257
+ * build identities: the client sends the `NEXT_PUBLIC_APP_VERSION` its bundle
258
+ * was compiled with, and this compares it against the version of the bundle
259
+ * being served — so a bare `package.json` bump moves neither side, and only a
260
+ * rebuild does.
261
+ *
262
+ * @param clientBundleVersion - The version the tab's bundle was built from
263
+ * @returns The drifted pair, or null when the two builds agree or either side
264
+ * is an unknown/fallback version
265
+ */
266
+ function resolveBundleDrift(clientBundleVersion) {
267
+ const serverVersion = getServedBundleVersion();
268
+ if (!(0, types_1.isVersionMismatch)(serverVersion, clientBundleVersion))
269
+ return null;
270
+ return { serverVersion, clientVersion: clientBundleVersion };
271
+ }
165
272
  /**
166
273
  * Validate that a URL is a legitimate GitHub Releases URL.
167
274
  * [SEC-SF-001] OWASP A03:2021 - Prevents injection via DNS pollution/MITM.
@@ -259,6 +366,9 @@ function resetCacheForTesting() {
259
366
  cache.result = null;
260
367
  cache.fetchedAt = 0;
261
368
  cache.rateLimitResetAt = null;
369
+ // Issue #2271: the served-bundle memo is frozen for the life of a process, so
370
+ // a suite that moves process.cwd() between cases must be able to thaw it.
371
+ servedBundleVersion = null;
262
372
  }
263
373
  // =============================================================================
264
374
  // Internal Functions
@@ -426,28 +426,34 @@ function handleMessage(ws, message) {
426
426
  }
427
427
  }
428
428
  /**
429
- * Handle a client-version hello (#1338/#1356).
429
+ * Handle a client-version hello (#1338/#1356/#2271).
430
430
  *
431
- * The client announces its baked bundle version on every (re)connect. If the
432
- * server's actually-running version (runtime package.json, resolved by
433
- * getServerVersion) has drifted from it, reply with a version_mismatch event so
434
- * the tab can surface a reload nudge. Stays silent when the versions match or
435
- * either side is an unknown/fallback version (受入条件: 誤検知しない).
431
+ * The client announces the version its bundle was built from on every
432
+ * (re)connect. `resolveBundleDrift` compares that against the version of the
433
+ * bundle **this server is serving** and answers null unless the two builds
434
+ * really differ; on drift, reply with a version_mismatch event so the tab can
435
+ * surface a reload nudge.
436
+ *
437
+ * Issue #2271: this used to ask `getServerVersion()`, i.e. the installed
438
+ * package.json. Releases bump that file without rebuilding the running server's
439
+ * `.next` — by design — so the comparison was permanently unequal and every tab
440
+ * carried an undismissable banner. The resolver, not this handler, is where
441
+ * "what counts as drift" is defined; keep it that way.
436
442
  */
437
443
  function handleClientVersion(ws, message) {
438
444
  const clientVersion = typeof message.version === 'string' ? message.version : '';
439
445
  if (!clientVersion)
440
446
  return;
441
- const serverVersion = (0, version_checker_1.getServerVersion)();
442
- if (!(0, types_2.isVersionMismatch)(serverVersion, clientVersion))
447
+ const drift = (0, version_checker_1.resolveBundleDrift)(clientVersion);
448
+ if (!drift)
443
449
  return;
444
450
  if (ws.readyState !== ws_1.WebSocket.OPEN)
445
451
  return;
446
452
  try {
447
453
  ws.send(JSON.stringify({
448
454
  type: types_2.VERSION_MISMATCH_EVENT_TYPE,
449
- serverVersion,
450
- clientVersion,
455
+ serverVersion: drift.serverVersion,
456
+ clientVersion: drift.clientVersion,
451
457
  }));
452
458
  }
453
459
  catch (error) {
@@ -39,7 +39,7 @@
39
39
  * @module types/agent-transcript
40
40
  */
41
41
  Object.defineProperty(exports, "__esModule", { value: true });
42
- exports.AGENT_MARKDOWN_REQUEST_ID_PREFIXES = exports.ANTIGRAVITY_PROMPT_REQUEST_ID_PREFIX = exports.ANTIGRAVITY_MARKDOWN_REQUEST_ID_PREFIX = exports.CODEX_PROMPT_REQUEST_ID_PREFIX = exports.CODEX_MARKDOWN_REQUEST_ID_PREFIX = exports.CLAUDE_PROMPT_REQUEST_ID_PREFIX = exports.CLAUDE_MARKDOWN_REQUEST_ID_PREFIX = exports.AGENT_MARKDOWN_REQUEST_ID_PREFIX = void 0;
42
+ exports.AGENT_MARKDOWN_REQUEST_ID_PREFIXES = exports.COMMAND_CODE_PROMPT_REQUEST_ID_PREFIX = exports.COMMAND_CODE_MARKDOWN_REQUEST_ID_PREFIX = exports.ANTIGRAVITY_PROMPT_REQUEST_ID_PREFIX = exports.ANTIGRAVITY_MARKDOWN_REQUEST_ID_PREFIX = exports.CODEX_PROMPT_REQUEST_ID_PREFIX = exports.CODEX_MARKDOWN_REQUEST_ID_PREFIX = exports.CLAUDE_PROMPT_REQUEST_ID_PREFIX = exports.CLAUDE_MARKDOWN_REQUEST_ID_PREFIX = exports.AGENT_MARKDOWN_REQUEST_ID_PREFIX = void 0;
43
43
  exports.isAgentAuthoredMarkdown = isAgentAuthoredMarkdown;
44
44
  exports.opencodeTurnRequestId = opencodeTurnRequestId;
45
45
  exports.claudeTurnRequestId = claudeTurnRequestId;
@@ -48,6 +48,8 @@ exports.codexTurnRequestId = codexTurnRequestId;
48
48
  exports.codexPromptRequestId = codexPromptRequestId;
49
49
  exports.antigravityTurnRequestId = antigravityTurnRequestId;
50
50
  exports.antigravityPromptRequestId = antigravityPromptRequestId;
51
+ exports.commandCodeTurnRequestId = commandCodeTurnRequestId;
52
+ exports.commandCodePromptRequestId = commandCodePromptRequestId;
51
53
  /**
52
54
  * Prefix on `chat_messages.request_id` for a row whose `content` is opencode's
53
55
  * own Markdown rather than a scrape of its terminal.
@@ -152,6 +154,40 @@ exports.ANTIGRAVITY_MARKDOWN_REQUEST_ID_PREFIX = 'antigravity-turn:';
152
154
  * a codex turn can.
153
155
  */
154
156
  exports.ANTIGRAVITY_PROMPT_REQUEST_ID_PREFIX = 'antigravity-prompt:';
157
+ /**
158
+ * The same, for a turn read out of Command Code's transcript JSONL (Issue #2252).
159
+ *
160
+ * A fifth namespace for the fifth reader, for the reason
161
+ * {@link CLAUDE_MARKDOWN_REQUEST_ID_PREFIX} gives: the value is an idempotency
162
+ * key as well as a marker, and Command Code names its records with an **8-hex
163
+ * short id of its own minting** (`cb06ab09`), which is a far smaller space than
164
+ * claude's uuids. Sharing a prefix with claude would therefore not merely be
165
+ * untidy — a `command-code` id is exactly the shape a claude uuid's first
166
+ * segment has, and a collision between two tools' ids reads as "already saved",
167
+ * which is the one failure a key must not have.
168
+ *
169
+ * `command-code-` and not `cc-`: the string is what an operator reads in the row
170
+ * when they ask why History shows Markdown, and the tool id is what they will
171
+ * search the codebase for.
172
+ */
173
+ exports.COMMAND_CODE_MARKDOWN_REQUEST_ID_PREFIX = 'command-code-turn:';
174
+ /**
175
+ * Prefix on a **user** row whose text was read out of Command Code's transcript
176
+ * JSONL (Issue #2252).
177
+ *
178
+ * Deliberately absent from {@link AGENT_MARKDOWN_REQUEST_ID_PREFIXES}, for the
179
+ * whole of the reason {@link CLAUDE_PROMPT_REQUEST_ID_PREFIX} states: the
180
+ * operator's own text is drawn verbatim and must not change shape because it
181
+ * happened to contain a `#` or a `|`.
182
+ *
183
+ * Keyed on the same record id as the turn's assistant row, which is claude's
184
+ * arrangement rather than codex's. It is the right one here because Command
185
+ * Code opens a turn with exactly one fresh `role: "user"` record — its own
186
+ * `isFreshUserTurn` is `role === 'user' && no tool_result block`, and a prompt
187
+ * typed while a turn is running is appended as a `meta.source: "steering"`
188
+ * record that opens a turn of its own rather than joining the one in flight.
189
+ */
190
+ exports.COMMAND_CODE_PROMPT_REQUEST_ID_PREFIX = 'command-code-prompt:';
155
191
  /**
156
192
  * Every prefix that means "this row holds source, not a rendering".
157
193
  *
@@ -166,6 +202,7 @@ exports.AGENT_MARKDOWN_REQUEST_ID_PREFIXES = [
166
202
  exports.CLAUDE_MARKDOWN_REQUEST_ID_PREFIX,
167
203
  exports.CODEX_MARKDOWN_REQUEST_ID_PREFIX,
168
204
  exports.ANTIGRAVITY_MARKDOWN_REQUEST_ID_PREFIX,
205
+ exports.COMMAND_CODE_MARKDOWN_REQUEST_ID_PREFIX,
169
206
  ];
170
207
  /**
171
208
  * Whether this row's `content` may be rendered as Markdown.
@@ -314,3 +351,38 @@ function antigravityTurnRequestId(conversationId, stepIndex) {
314
351
  function antigravityPromptRequestId(conversationId, stepIndex) {
315
352
  return `${exports.ANTIGRAVITY_PROMPT_REQUEST_ID_PREFIX}${antigravityTurnKey(conversationId, stepIndex)}`;
316
353
  }
354
+ /**
355
+ * The row id for one Command Code turn (Issue #2252).
356
+ *
357
+ * The turn is named by the **prompt record it answers** — the `id` of the fresh
358
+ * `role: "user"` record the operator's text arrived on. That is claude's
359
+ * arrangement (#2121) and antigravity's (#2198) rather than codex's, because
360
+ * Command Code writes nothing that closes a turn and nothing that links a reply
361
+ * back to its prompt: `parentId` chains one record to the previous one in file
362
+ * order, not a reply to its question, so what opens the turn is the only
363
+ * boundary in the file.
364
+ *
365
+ * Deliberately not the assistant record's own `id`: one turn produces one
366
+ * assistant record per round of the agent loop — the captured two-tool turn has
367
+ * two — and keying on those would split one reply into several History rows.
368
+ *
369
+ * @param promptId - `id` of the user record that opened the turn
370
+ */
371
+ function commandCodeTurnRequestId(promptId) {
372
+ return `${exports.COMMAND_CODE_MARKDOWN_REQUEST_ID_PREFIX}${promptId}`;
373
+ }
374
+ /**
375
+ * The row id for the **prompt** that opened one Command Code turn (Issue #2252).
376
+ *
377
+ * Same `id`, different prefix, and therefore a different row — exactly the
378
+ * relationship {@link claudePromptRequestId} has with {@link claudeTurnRequestId},
379
+ * and for the same reason: one record names one turn, and a turn is a user row
380
+ * plus an assistant row, so keying both on the record that opened it is what
381
+ * makes the pair reconstructible from the transcript alone, including on a
382
+ * re-read where both halves must resolve to "already there" independently.
383
+ *
384
+ * @param promptId - `id` of the user record the operator's text arrived on
385
+ */
386
+ function commandCodePromptRequestId(promptId) {
387
+ return `${exports.COMMAND_CODE_PROMPT_REQUEST_ID_PREFIX}${promptId}`;
388
+ }
@@ -19,7 +19,74 @@
19
19
  * Values only — no tmux process access — so this module is safe from any layer.
20
20
  */
21
21
  Object.defineProperty(exports, "__esModule", { value: true });
22
- exports.TERMINAL_KEY_VALUES = exports.OPENCODE_NAVIGATION_KEY_VALUES = exports.OPENCODE_DIRECT_KEY_VALUES = exports.OPENCODE_LEADER_CHORD_VALUES = exports.OPENCODE_LEADER_KEY = exports.NAVIGATION_KEY_VALUES = void 0;
22
+ exports.TERMINAL_KEY_VALUES = exports.OPENCODE_NAVIGATION_KEY_VALUES = exports.OPENCODE_DIRECT_KEY_VALUES = exports.OPENCODE_LEADER_CHORD_VALUES = exports.OPENCODE_LEADER_KEY = exports.SESSION_SCOPE_KEY_TOOL_IDS = exports.CLAUDE_NAVIGATION_KEY_VALUES = exports.NAVIGATION_KEY_VALUES = exports.SESSION_SCOPE_KEY = exports.ANSWER_KEY_VALUES = void 0;
23
+ /**
24
+ * The characters a dialog is answered WITH rather than navigated by (Issue #2254).
25
+ *
26
+ * `1`–`9` are the option numbers every numbered TUI dialog in this repository
27
+ * offers (codex's trust / `/model` pickers, claude's `PermissionRequest`
28
+ * screens, the hooks-review flow), and `y` / `n` are the two letters a bare
29
+ * `[y/n]` accepts. They are LITERAL characters on the wire, exactly like the
30
+ * codex pager's `q` has been since #1017 and opencode's chord letters since
31
+ * #2046 — `tmux send-keys -- 1` types a `1`.
32
+ *
33
+ * WHY THEY ARE IN THE BASE VOCABULARY, i.e. offered to every tool
34
+ * ---------------------------------------------------------------
35
+ * The state this exists for is "a wait is on screen and nothing could read it"
36
+ * (`ChatSurface`'s `promptUnreadable`). By construction nobody knows which tool
37
+ * drew that dialog *shape*, so there is no per-tool declaration to hang these
38
+ * off; what IS known is that the dialog is waiting for an answer, and that the
39
+ * chat surface had no way to send one before this Issue — the `/send` route
40
+ * refuses with `prompt_waiting`, and `/special-keys` published only arrows.
41
+ *
42
+ * The cost is the same one #2046 weighed for opencode's letters: a caller may
43
+ * POST `{cliToolId:"claude", keys:["y"]}` at an IDLE pane and type a `y` into
44
+ * the composer. That is a typo, not an escalation — the route has always been
45
+ * able to type `q` into any composer, sending a character is what the route is
46
+ * FOR, and the UI only draws these buttons while a wait is unreadable. What is
47
+ * deliberately still refused is a free string: `/send`'s `prompt_waiting` guard
48
+ * is untouched, `MAX_KEYS_LENGTH` is 10, and every other letter stays a 400.
49
+ *
50
+ * Note the overlap with {@link OPENCODE_LEADER_CHORD_VALUES}: `n` is in both,
51
+ * and `tests/unit/cli-tools/navigation-keys-declaration-2046.test.ts` pins the
52
+ * intersection to exactly `['n']` so a future widening of either list cannot
53
+ * quietly hand another tool an opencode chord letter.
54
+ */
55
+ exports.ANSWER_KEY_VALUES = [
56
+ '1', '2', '3', '4', '5', '6', '7', '8', '9',
57
+ 'y', 'n',
58
+ ];
59
+ /**
60
+ * claude's "use this session only" key (Issue #2297).
61
+ *
62
+ * MEASURED on claude 2.1.259 / 2.1.260 (`tests/fixtures/chat-dialog-card-2254/
63
+ * claude-model-2-1-259.txt`, and a live 200x1000 probe re-run for #2297): the
64
+ * `/model` overlay's footer reads
65
+ *
66
+ * Enter to set as default · s to use this session only · Esc to cancel
67
+ *
68
+ * so on that ONE screen `Enter` is not "confirm" — it rewrites `model` in
69
+ * `~/.claude/settings.json` (Issue #1495), and `s` is the only key that takes
70
+ * the highlighted model for the current session and leaves the file alone.
71
+ * Neither the shared pad nor the transport carried `s`, so the chat surface
72
+ * could offer the destructive half of that footer and not the safe half.
73
+ *
74
+ * A LITERAL character on the wire, exactly like the codex pager's `q` (#1017),
75
+ * opencode's chord letters (#2046) and the answer characters (#2254):
76
+ * `tmux send-keys -- s` types an `s`.
77
+ *
78
+ * WHY IT IS **NOT** IN {@link NAVIGATION_KEY_VALUES}
79
+ * -------------------------------------------------
80
+ * Unlike #2254's answer characters, this one has a named owner. `s` is a live
81
+ * binding on other tools' screens — copilot's session picker footer reads
82
+ * `s sort:relevance` (measured on 1.0.82), and opencode types a bare letter
83
+ * into its composer whenever a leader chord is not in flight. Publishing `s` to
84
+ * every tool would hand those screens a button that does something else. So it
85
+ * is declared by the claude-family tools alone, through
86
+ * {@link CLAUDE_NAVIGATION_KEY_VALUES}, and the route's per-tool check
87
+ * (Issue #2046) answers 400 for everyone else.
88
+ */
89
+ exports.SESSION_SCOPE_KEY = 's';
23
90
  /**
24
91
  * Navigation keys accepted by the special-keys API and the terminal UI.
25
92
  *
@@ -34,7 +101,46 @@ exports.NAVIGATION_KEY_VALUES = [
34
101
  // Issue #1017: Codex pager / edit-previous mode keys surfaced by NavigationButtons.
35
102
  // 'q' is the pager quit key (literal char). PageUp/PageDown/Home/End are tmux named keys.
36
103
  'PageUp', 'PageDown', 'Home', 'End', 'q',
104
+ // Issue #2254: the answer characters. Appended rather than interleaved so the
105
+ // pre-#2254 prefix of this list is still readable as one line in a diff.
106
+ ...exports.ANSWER_KEY_VALUES,
37
107
  ];
108
+ /**
109
+ * What a claude-family pane may be sent: the base pad plus
110
+ * {@link SESSION_SCOPE_KEY} (Issue #2297).
111
+ *
112
+ * Returned by `ClaudeTool.navigationKeys()` and `CommandCodeTool.navigationKeys()`
113
+ * — the two tools whose TUI is claude's inline overlay renderer. Command Code
114
+ * takes it for kinship rather than for a measured `/model` footer of its own:
115
+ * its own picker (v1.40.1, measured for this Issue) is a name list with a search
116
+ * box and an `enter to select · esc to cancel` footer and offers no session
117
+ * scope at all, so nothing DRAWS the `s` button there — see
118
+ * `readSelectionListShape()`, which gates the button on the footer being on
119
+ * screen rather than on the tool id. Declaring the key for both keeps the two
120
+ * halves of the claude family from drifting apart the day Command Code grows the
121
+ * footer, and costs nothing while it has not: an undrawn button sends nothing.
122
+ *
123
+ * `tests/unit/lib/cli-tools/session-scope-key-2297.test.ts` pins the membership
124
+ * in both directions, and the #2046 suite still pins every OTHER tool to the
125
+ * base pad exactly.
126
+ */
127
+ exports.CLAUDE_NAVIGATION_KEY_VALUES = [
128
+ ...exports.NAVIGATION_KEY_VALUES,
129
+ exports.SESSION_SCOPE_KEY,
130
+ ];
131
+ /**
132
+ * The tool ids whose `navigationKeys()` carry {@link SESSION_SCOPE_KEY}.
133
+ *
134
+ * Read by the chat surface, which cannot call `navigationKeys()` — that lives
135
+ * behind the CLITool gateway on the server — but must not draw a button whose
136
+ * key the route would answer 400 for. Pinned against the real registry by
137
+ * `tests/unit/lib/cli-tools/session-scope-key-2297.test.ts`, so this list and
138
+ * the declarations cannot disagree.
139
+ *
140
+ * Typed as a plain string tuple rather than `CLIToolType[]` so this module keeps
141
+ * the "values only, safe from any layer" property its header depends on.
142
+ */
143
+ exports.SESSION_SCOPE_KEY_TOOL_IDS = ['claude', 'command-code'];
38
144
  // ---------------------------------------------------------------------------
39
145
  // Per-tool vocabularies (Issue #2046)
40
146
  // ---------------------------------------------------------------------------
@@ -74,6 +180,25 @@ exports.OPENCODE_LEADER_CHORD_VALUES = [
74
180
  * `Tab` / `BTab` cycle the agent and are already in {@link NAVIGATION_KEY_VALUES}.
75
181
  */
76
182
  exports.OPENCODE_DIRECT_KEY_VALUES = ['C-p', 'C-t'];
183
+ /**
184
+ * {@link OPENCODE_LEADER_CHORD_VALUES} minus what the base pad already carries.
185
+ *
186
+ * Issue #2254 moved `n` into {@link ANSWER_KEY_VALUES}, and therefore into
187
+ * {@link NAVIGATION_KEY_VALUES}, which every tool's declaration starts from —
188
+ * so spreading the full chord list into the two unions below would list `n`
189
+ * twice. A duplicate is harmless to `Array.prototype.includes`, which is all the
190
+ * route does with these, and that is exactly why it needs its own guard: the
191
+ * only thing that would notice is the "no duplicate entries" assertion in
192
+ * `tests/unit/cli-tools/navigation-keys-declaration-2046.test.ts`.
193
+ *
194
+ * Written out rather than filtered at runtime because both unions are `as const`
195
+ * tuples whose LITERAL member types are the `TerminalKey` union — a
196
+ * `.filter()` would collapse them to `string[]` and take the compile-time check
197
+ * with it. The same suite pins this list to
198
+ * `OPENCODE_LEADER_CHORD_VALUES \ NAVIGATION_KEY_VALUES` so it cannot drift out
199
+ * of step with either side.
200
+ */
201
+ const OPENCODE_CHORD_ONLY_VALUES = ['a', 'l', 't', 'm', 'g', 'u', 'r', 'c'];
77
202
  /**
78
203
  * Everything an opencode pane may be sent — the base navigation pad plus this
79
204
  * tool's own chords. Returned by `OpenCodeTool.navigationKeys()`.
@@ -82,7 +207,7 @@ exports.OPENCODE_NAVIGATION_KEY_VALUES = [
82
207
  ...exports.NAVIGATION_KEY_VALUES,
83
208
  exports.OPENCODE_LEADER_KEY,
84
209
  ...exports.OPENCODE_DIRECT_KEY_VALUES,
85
- ...exports.OPENCODE_LEADER_CHORD_VALUES,
210
+ ...OPENCODE_CHORD_ONLY_VALUES,
86
211
  ];
87
212
  /**
88
213
  * The union of every tool's vocabulary — what the tmux transport must be able to
@@ -99,7 +224,10 @@ exports.OPENCODE_NAVIGATION_KEY_VALUES = [
99
224
  */
100
225
  exports.TERMINAL_KEY_VALUES = [
101
226
  ...exports.NAVIGATION_KEY_VALUES,
227
+ // Issue #2297: claude / Command Code declare it; nothing else does.
228
+ exports.SESSION_SCOPE_KEY,
102
229
  exports.OPENCODE_LEADER_KEY,
103
230
  ...exports.OPENCODE_DIRECT_KEY_VALUES,
104
- ...exports.OPENCODE_LEADER_CHORD_VALUES,
231
+ // Issue #2254: `n` is in the base pad now — see OPENCODE_CHORD_ONLY_VALUES.
232
+ ...OPENCODE_CHORD_ONLY_VALUES,
105
233
  ];