commandmate 0.49.1 → 0.49.2

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 (456) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-build-manifest.json +128 -132
  3. package/.next/app-path-routes-manifest.json +22 -22
  4. package/.next/build-manifest.json +2 -2
  5. package/.next/prerender-manifest.json +12 -12
  6. package/.next/required-server-files.json +1 -1
  7. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  8. package/.next/server/app/api/agents/update/route_client-reference-manifest.js +1 -1
  9. package/.next/server/app/api/agents/versions/route_client-reference-manifest.js +1 -1
  10. package/.next/server/app/api/app/release-notes/route_client-reference-manifest.js +1 -1
  11. package/.next/server/app/api/app/update/route_client-reference-manifest.js +1 -1
  12. package/.next/server/app/api/app/update-check/route_client-reference-manifest.js +1 -1
  13. package/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
  14. package/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
  15. package/.next/server/app/api/auth/status/route_client-reference-manifest.js +1 -1
  16. package/.next/server/app/api/capabilities/route.js +1 -1
  17. package/.next/server/app/api/capabilities/route_client-reference-manifest.js +1 -1
  18. package/.next/server/app/api/daily-summary/route_client-reference-manifest.js +1 -1
  19. package/.next/server/app/api/daily-summary/status/route_client-reference-manifest.js +1 -1
  20. package/.next/server/app/api/external-apps/[id]/health/route_client-reference-manifest.js +1 -1
  21. package/.next/server/app/api/external-apps/[id]/route_client-reference-manifest.js +1 -1
  22. package/.next/server/app/api/external-apps/route_client-reference-manifest.js +1 -1
  23. package/.next/server/app/api/fs/browse/route_client-reference-manifest.js +1 -1
  24. package/.next/server/app/api/fs/recent-paths/route_client-reference-manifest.js +1 -1
  25. package/.next/server/app/api/hooks/agent-event/route.js +2 -2
  26. package/.next/server/app/api/hooks/agent-event/route.js.nft.json +1 -1
  27. package/.next/server/app/api/hooks/agent-event/route_client-reference-manifest.js +1 -1
  28. package/.next/server/app/api/hooks/claude-done/route.js +2 -2
  29. package/.next/server/app/api/hooks/claude-done/route.js.nft.json +1 -1
  30. package/.next/server/app/api/hooks/claude-done/route_client-reference-manifest.js +1 -1
  31. package/.next/server/app/api/hooks/permission-request/route.js +1 -1
  32. package/.next/server/app/api/hooks/permission-request/route.js.nft.json +1 -1
  33. package/.next/server/app/api/hooks/permission-request/route_client-reference-manifest.js +1 -1
  34. package/.next/server/app/api/metrics/vibe/route_client-reference-manifest.js +1 -1
  35. package/.next/server/app/api/ollama/models/route_client-reference-manifest.js +1 -1
  36. package/.next/server/app/api/push/escalation/route_client-reference-manifest.js +1 -1
  37. package/.next/server/app/api/push/subscriptions/route.js +1 -1
  38. package/.next/server/app/api/push/subscriptions/route_client-reference-manifest.js +1 -1
  39. package/.next/server/app/api/push/vapid/route_client-reference-manifest.js +1 -1
  40. package/.next/server/app/api/relays/[relayId]/cancel/route.js +1 -1
  41. package/.next/server/app/api/relays/[relayId]/cancel/route.js.nft.json +1 -1
  42. package/.next/server/app/api/relays/[relayId]/cancel/route_client-reference-manifest.js +1 -1
  43. package/.next/server/app/api/relays/[relayId]/route_client-reference-manifest.js +1 -1
  44. package/.next/server/app/api/relays/route.js +1 -1
  45. package/.next/server/app/api/relays/route.js.nft.json +1 -1
  46. package/.next/server/app/api/relays/route_client-reference-manifest.js +1 -1
  47. package/.next/server/app/api/remote/pair/route_client-reference-manifest.js +1 -1
  48. package/.next/server/app/api/repositories/[id]/route_client-reference-manifest.js +1 -1
  49. package/.next/server/app/api/repositories/clone/[jobId]/route.js +1 -1
  50. package/.next/server/app/api/repositories/clone/[jobId]/route.js.nft.json +1 -1
  51. package/.next/server/app/api/repositories/clone/[jobId]/route_client-reference-manifest.js +1 -1
  52. package/.next/server/app/api/repositories/clone/route.js +1 -1
  53. package/.next/server/app/api/repositories/clone/route.js.nft.json +1 -1
  54. package/.next/server/app/api/repositories/clone/route_client-reference-manifest.js +1 -1
  55. package/.next/server/app/api/repositories/excluded/route_client-reference-manifest.js +1 -1
  56. package/.next/server/app/api/repositories/restore/route.js +1 -1
  57. package/.next/server/app/api/repositories/restore/route.js.nft.json +1 -1
  58. package/.next/server/app/api/repositories/restore/route_client-reference-manifest.js +1 -1
  59. package/.next/server/app/api/repositories/route.js +1 -1
  60. package/.next/server/app/api/repositories/route.js.nft.json +1 -1
  61. package/.next/server/app/api/repositories/route_client-reference-manifest.js +1 -1
  62. package/.next/server/app/api/repositories/scan/route.js +1 -1
  63. package/.next/server/app/api/repositories/scan/route.js.nft.json +1 -1
  64. package/.next/server/app/api/repositories/scan/route_client-reference-manifest.js +1 -1
  65. package/.next/server/app/api/repositories/sync/route.js +1 -1
  66. package/.next/server/app/api/repositories/sync/route.js.nft.json +1 -1
  67. package/.next/server/app/api/repositories/sync/route_client-reference-manifest.js +1 -1
  68. package/.next/server/app/api/repositories/validate-path/route_client-reference-manifest.js +1 -1
  69. package/.next/server/app/api/settings/default-agents/route.js +1 -1
  70. package/.next/server/app/api/settings/default-agents/route.js.nft.json +1 -1
  71. package/.next/server/app/api/settings/default-agents/route_client-reference-manifest.js +1 -1
  72. package/.next/server/app/api/settings/default-surface-mode/route_client-reference-manifest.js +1 -1
  73. package/.next/server/app/api/sidebar/group-order/route_client-reference-manifest.js +1 -1
  74. package/.next/server/app/api/skills/[id]/route_client-reference-manifest.js +1 -1
  75. package/.next/server/app/api/skills/installations/route_client-reference-manifest.js +1 -1
  76. package/.next/server/app/api/skills/operations/route_client-reference-manifest.js +1 -1
  77. package/.next/server/app/api/skills/reindex/route_client-reference-manifest.js +1 -1
  78. package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
  79. package/.next/server/app/api/slash-commands/route_client-reference-manifest.js +1 -1
  80. package/.next/server/app/api/tasks/[taskId]/cancel/route_client-reference-manifest.js +1 -1
  81. package/.next/server/app/api/tasks/[taskId]/route.js +1 -1
  82. package/.next/server/app/api/tasks/[taskId]/route_client-reference-manifest.js +1 -1
  83. package/.next/server/app/api/templates/[id]/route_client-reference-manifest.js +1 -1
  84. package/.next/server/app/api/templates/route_client-reference-manifest.js +1 -1
  85. package/.next/server/app/api/verification/runs/[runId]/route.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.js +1 -1
  88. package/.next/server/app/api/verification/runs/route_client-reference-manifest.js +1 -1
  89. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js +1 -1
  90. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js.nft.json +1 -1
  91. package/.next/server/app/api/worktrees/[id]/auto-yes/route_client-reference-manifest.js +1 -1
  92. package/.next/server/app/api/worktrees/[id]/capture/route.js +1 -1
  93. package/.next/server/app/api/worktrees/[id]/capture/route.js.nft.json +1 -1
  94. package/.next/server/app/api/worktrees/[id]/capture/route_client-reference-manifest.js +1 -1
  95. package/.next/server/app/api/worktrees/[id]/clear-composer/route.js +1 -1
  96. package/.next/server/app/api/worktrees/[id]/clear-composer/route.js.nft.json +1 -1
  97. package/.next/server/app/api/worktrees/[id]/clear-composer/route_client-reference-manifest.js +1 -1
  98. package/.next/server/app/api/worktrees/[id]/cli-reference/route.js +1 -1
  99. package/.next/server/app/api/worktrees/[id]/cli-reference/route_client-reference-manifest.js +1 -1
  100. package/.next/server/app/api/worktrees/[id]/cli-tool/route.js +1 -1
  101. package/.next/server/app/api/worktrees/[id]/cli-tool/route_client-reference-manifest.js +1 -1
  102. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route.js +1 -1
  103. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route_client-reference-manifest.js +1 -1
  104. package/.next/server/app/api/worktrees/[id]/current-output/route.js +1 -1
  105. package/.next/server/app/api/worktrees/[id]/current-output/route.js.nft.json +1 -1
  106. package/.next/server/app/api/worktrees/[id]/current-output/route_client-reference-manifest.js +1 -1
  107. package/.next/server/app/api/worktrees/[id]/direct-input/route.js +1 -1
  108. package/.next/server/app/api/worktrees/[id]/direct-input/route.js.nft.json +1 -1
  109. package/.next/server/app/api/worktrees/[id]/direct-input/route_client-reference-manifest.js +1 -1
  110. package/.next/server/app/api/worktrees/[id]/env/route.js +1 -1
  111. package/.next/server/app/api/worktrees/[id]/env/route_client-reference-manifest.js +1 -1
  112. package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route.js +1 -1
  113. package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route_client-reference-manifest.js +1 -1
  114. package/.next/server/app/api/worktrees/[id]/execution-logs/route.js +1 -1
  115. package/.next/server/app/api/worktrees/[id]/execution-logs/route_client-reference-manifest.js +1 -1
  116. package/.next/server/app/api/worktrees/[id]/files/[...path]/route_client-reference-manifest.js +1 -1
  117. package/.next/server/app/api/worktrees/[id]/git/branch/create/route.js +1 -1
  118. package/.next/server/app/api/worktrees/[id]/git/branch/create/route_client-reference-manifest.js +1 -1
  119. package/.next/server/app/api/worktrees/[id]/git/branch/delete/route.js +1 -1
  120. package/.next/server/app/api/worktrees/[id]/git/branch/delete/route_client-reference-manifest.js +1 -1
  121. package/.next/server/app/api/worktrees/[id]/git/branches/route.js +1 -1
  122. package/.next/server/app/api/worktrees/[id]/git/branches/route_client-reference-manifest.js +1 -1
  123. package/.next/server/app/api/worktrees/[id]/git/checkout/route.js +1 -1
  124. package/.next/server/app/api/worktrees/[id]/git/checkout/route_client-reference-manifest.js +1 -1
  125. package/.next/server/app/api/worktrees/[id]/git/commit/route.js +1 -1
  126. package/.next/server/app/api/worktrees/[id]/git/commit/route_client-reference-manifest.js +1 -1
  127. package/.next/server/app/api/worktrees/[id]/git/diff/route.js +1 -1
  128. package/.next/server/app/api/worktrees/[id]/git/diff/route_client-reference-manifest.js +1 -1
  129. package/.next/server/app/api/worktrees/[id]/git/fetch/route.js +1 -1
  130. package/.next/server/app/api/worktrees/[id]/git/fetch/route_client-reference-manifest.js +1 -1
  131. package/.next/server/app/api/worktrees/[id]/git/log/route.js +1 -1
  132. package/.next/server/app/api/worktrees/[id]/git/log/route_client-reference-manifest.js +1 -1
  133. package/.next/server/app/api/worktrees/[id]/git/pull/route.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.js +1 -1
  136. package/.next/server/app/api/worktrees/[id]/git/push/route_client-reference-manifest.js +1 -1
  137. package/.next/server/app/api/worktrees/[id]/git/reset/route.js +1 -1
  138. package/.next/server/app/api/worktrees/[id]/git/reset/route_client-reference-manifest.js +1 -1
  139. package/.next/server/app/api/worktrees/[id]/git/revert/route.js +1 -1
  140. package/.next/server/app/api/worktrees/[id]/git/revert/route_client-reference-manifest.js +1 -1
  141. package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route.js +1 -1
  142. package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route_client-reference-manifest.js +1 -1
  143. package/.next/server/app/api/worktrees/[id]/git/stage/route.js +1 -1
  144. package/.next/server/app/api/worktrees/[id]/git/stage/route_client-reference-manifest.js +1 -1
  145. package/.next/server/app/api/worktrees/[id]/git/staged/route.js +1 -1
  146. package/.next/server/app/api/worktrees/[id]/git/staged/route_client-reference-manifest.js +1 -1
  147. package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route.js +1 -1
  148. package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route_client-reference-manifest.js +1 -1
  149. package/.next/server/app/api/worktrees/[id]/git/stash/apply/route.js +1 -1
  150. package/.next/server/app/api/worktrees/[id]/git/stash/apply/route_client-reference-manifest.js +1 -1
  151. package/.next/server/app/api/worktrees/[id]/git/stash/pop/route.js +1 -1
  152. package/.next/server/app/api/worktrees/[id]/git/stash/pop/route_client-reference-manifest.js +1 -1
  153. package/.next/server/app/api/worktrees/[id]/git/stash/push/route.js +1 -1
  154. package/.next/server/app/api/worktrees/[id]/git/stash/push/route_client-reference-manifest.js +1 -1
  155. package/.next/server/app/api/worktrees/[id]/git/stash/route.js +1 -1
  156. package/.next/server/app/api/worktrees/[id]/git/stash/route_client-reference-manifest.js +1 -1
  157. package/.next/server/app/api/worktrees/[id]/git/status/route.js +1 -1
  158. package/.next/server/app/api/worktrees/[id]/git/status/route_client-reference-manifest.js +1 -1
  159. package/.next/server/app/api/worktrees/[id]/git/unstage/route.js +1 -1
  160. package/.next/server/app/api/worktrees/[id]/git/unstage/route_client-reference-manifest.js +1 -1
  161. package/.next/server/app/api/worktrees/[id]/git/working-diff/route.js +1 -1
  162. package/.next/server/app/api/worktrees/[id]/git/working-diff/route_client-reference-manifest.js +1 -1
  163. package/.next/server/app/api/worktrees/[id]/instances/notes/route.js +1 -1
  164. package/.next/server/app/api/worktrees/[id]/instances/notes/route_client-reference-manifest.js +1 -1
  165. package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js +1 -1
  166. package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js.nft.json +1 -1
  167. package/.next/server/app/api/worktrees/[id]/instances/opencode/route_client-reference-manifest.js +1 -1
  168. package/.next/server/app/api/worktrees/[id]/interrupt/route.js +1 -1
  169. package/.next/server/app/api/worktrees/[id]/interrupt/route.js.nft.json +1 -1
  170. package/.next/server/app/api/worktrees/[id]/interrupt/route_client-reference-manifest.js +1 -1
  171. package/.next/server/app/api/worktrees/[id]/kill-session/route.js +2 -1
  172. package/.next/server/app/api/worktrees/[id]/kill-session/route.js.nft.json +1 -1
  173. package/.next/server/app/api/worktrees/[id]/kill-session/route_client-reference-manifest.js +1 -1
  174. package/.next/server/app/api/worktrees/[id]/logs/[filename]/route.js +1 -1
  175. package/.next/server/app/api/worktrees/[id]/logs/[filename]/route.js.nft.json +1 -1
  176. package/.next/server/app/api/worktrees/[id]/logs/[filename]/route_client-reference-manifest.js +1 -1
  177. package/.next/server/app/api/worktrees/[id]/logs/route.js +2 -2
  178. package/.next/server/app/api/worktrees/[id]/logs/route.js.nft.json +1 -1
  179. package/.next/server/app/api/worktrees/[id]/logs/route_client-reference-manifest.js +1 -1
  180. package/.next/server/app/api/worktrees/[id]/marp-render/route.js +1 -1
  181. package/.next/server/app/api/worktrees/[id]/marp-render/route_client-reference-manifest.js +1 -1
  182. package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route.js +1 -1
  183. package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route_client-reference-manifest.js +1 -1
  184. package/.next/server/app/api/worktrees/[id]/memos/route.js +1 -1
  185. package/.next/server/app/api/worktrees/[id]/memos/route_client-reference-manifest.js +1 -1
  186. package/.next/server/app/api/worktrees/[id]/messages/route.js +1 -1
  187. package/.next/server/app/api/worktrees/[id]/messages/route_client-reference-manifest.js +1 -1
  188. package/.next/server/app/api/worktrees/[id]/opencode/diff/route.js +1 -1
  189. package/.next/server/app/api/worktrees/[id]/opencode/diff/route.js.nft.json +1 -1
  190. package/.next/server/app/api/worktrees/[id]/opencode/diff/route_client-reference-manifest.js +1 -1
  191. package/.next/server/app/api/worktrees/[id]/opencode/session/route.js +1 -1
  192. package/.next/server/app/api/worktrees/[id]/opencode/session/route.js.nft.json +1 -1
  193. package/.next/server/app/api/worktrees/[id]/opencode/session/route_client-reference-manifest.js +1 -1
  194. package/.next/server/app/api/worktrees/[id]/opencode/share/route.js +1 -1
  195. package/.next/server/app/api/worktrees/[id]/opencode/share/route.js.nft.json +1 -1
  196. package/.next/server/app/api/worktrees/[id]/opencode/share/route_client-reference-manifest.js +1 -1
  197. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js +1 -1
  198. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js.nft.json +1 -1
  199. package/.next/server/app/api/worktrees/[id]/prompt-response/route_client-reference-manifest.js +1 -1
  200. package/.next/server/app/api/worktrees/[id]/prompt-response/strict/route.js +1 -1
  201. package/.next/server/app/api/worktrees/[id]/prompt-response/strict/route.js.nft.json +1 -1
  202. package/.next/server/app/api/worktrees/[id]/prompt-response/strict/route_client-reference-manifest.js +1 -1
  203. package/.next/server/app/api/worktrees/[id]/resolve-target/route.js +1 -1
  204. package/.next/server/app/api/worktrees/[id]/resolve-target/route_client-reference-manifest.js +1 -1
  205. package/.next/server/app/api/worktrees/[id]/respond/route.js +1 -1
  206. package/.next/server/app/api/worktrees/[id]/respond/route.js.nft.json +1 -1
  207. package/.next/server/app/api/worktrees/[id]/respond/route_client-reference-manifest.js +1 -1
  208. package/.next/server/app/api/worktrees/[id]/route.js +1 -1
  209. package/.next/server/app/api/worktrees/[id]/route.js.nft.json +1 -1
  210. package/.next/server/app/api/worktrees/[id]/route_client-reference-manifest.js +1 -1
  211. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route.js +1 -1
  212. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route_client-reference-manifest.js +1 -1
  213. package/.next/server/app/api/worktrees/[id]/schedules/active/route.js +1 -1
  214. package/.next/server/app/api/worktrees/[id]/schedules/active/route_client-reference-manifest.js +1 -1
  215. package/.next/server/app/api/worktrees/[id]/schedules/route.js +1 -1
  216. package/.next/server/app/api/worktrees/[id]/schedules/route_client-reference-manifest.js +1 -1
  217. package/.next/server/app/api/worktrees/[id]/search/route_client-reference-manifest.js +1 -1
  218. package/.next/server/app/api/worktrees/[id]/send/route.js +2 -2
  219. package/.next/server/app/api/worktrees/[id]/send/route.js.nft.json +1 -1
  220. package/.next/server/app/api/worktrees/[id]/send/route_client-reference-manifest.js +1 -1
  221. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js +3 -3
  222. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js.nft.json +1 -1
  223. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route_client-reference-manifest.js +1 -1
  224. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route_client-reference-manifest.js +1 -1
  225. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route_client-reference-manifest.js +1 -1
  226. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route_client-reference-manifest.js +1 -1
  227. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route_client-reference-manifest.js +1 -1
  228. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update/route_client-reference-manifest.js +1 -1
  229. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route_client-reference-manifest.js +1 -1
  230. package/.next/server/app/api/worktrees/[id]/skills/route.js +1 -1
  231. package/.next/server/app/api/worktrees/[id]/skills/route_client-reference-manifest.js +1 -1
  232. package/.next/server/app/api/worktrees/[id]/slash-commands/route.js +1 -1
  233. package/.next/server/app/api/worktrees/[id]/slash-commands/route_client-reference-manifest.js +1 -1
  234. package/.next/server/app/api/worktrees/[id]/special-keys/route.js +1 -1
  235. package/.next/server/app/api/worktrees/[id]/special-keys/route.js.nft.json +1 -1
  236. package/.next/server/app/api/worktrees/[id]/special-keys/route_client-reference-manifest.js +1 -1
  237. package/.next/server/app/api/worktrees/[id]/tasks/route.js +1 -1
  238. package/.next/server/app/api/worktrees/[id]/tasks/route_client-reference-manifest.js +1 -1
  239. package/.next/server/app/api/worktrees/[id]/terminal/route.js +2 -2
  240. package/.next/server/app/api/worktrees/[id]/terminal/route.js.nft.json +1 -1
  241. package/.next/server/app/api/worktrees/[id]/terminal/route_client-reference-manifest.js +1 -1
  242. package/.next/server/app/api/worktrees/[id]/timers/history/route.js +1 -1
  243. package/.next/server/app/api/worktrees/[id]/timers/history/route_client-reference-manifest.js +1 -1
  244. package/.next/server/app/api/worktrees/[id]/timers/route.js +1 -1
  245. package/.next/server/app/api/worktrees/[id]/timers/route.js.nft.json +1 -1
  246. package/.next/server/app/api/worktrees/[id]/timers/route_client-reference-manifest.js +1 -1
  247. package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route.js +1 -1
  248. package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route.js.nft.json +1 -1
  249. package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
  250. package/.next/server/app/api/worktrees/[id]/todos/route.js +1 -1
  251. package/.next/server/app/api/worktrees/[id]/todos/route.js.nft.json +1 -1
  252. package/.next/server/app/api/worktrees/[id]/todos/route_client-reference-manifest.js +1 -1
  253. package/.next/server/app/api/worktrees/[id]/tree/[...path]/route_client-reference-manifest.js +1 -1
  254. package/.next/server/app/api/worktrees/[id]/tree/route_client-reference-manifest.js +1 -1
  255. package/.next/server/app/api/worktrees/[id]/upload/[...path]/route_client-reference-manifest.js +1 -1
  256. package/.next/server/app/api/worktrees/[id]/verify/config/route.js +1 -1
  257. package/.next/server/app/api/worktrees/[id]/verify/config/route_client-reference-manifest.js +1 -1
  258. package/.next/server/app/api/worktrees/[id]/verify/route.js +1 -1
  259. package/.next/server/app/api/worktrees/[id]/verify/route.js.nft.json +1 -1
  260. package/.next/server/app/api/worktrees/[id]/verify/route_client-reference-manifest.js +1 -1
  261. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route.js +1 -1
  262. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route.js.nft.json +1 -1
  263. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route_client-reference-manifest.js +1 -1
  264. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route.js +1 -1
  265. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route_client-reference-manifest.js +1 -1
  266. package/.next/server/app/api/worktrees/[id]/verify/runs/route.js +1 -1
  267. package/.next/server/app/api/worktrees/[id]/verify/runs/route_client-reference-manifest.js +1 -1
  268. package/.next/server/app/api/worktrees/[id]/viewed/route.js +1 -1
  269. package/.next/server/app/api/worktrees/[id]/viewed/route_client-reference-manifest.js +1 -1
  270. package/.next/server/app/api/worktrees/apply-default-agents/route_client-reference-manifest.js +1 -1
  271. package/.next/server/app/api/worktrees/route.js +1 -1
  272. package/.next/server/app/api/worktrees/route.js.nft.json +1 -1
  273. package/.next/server/app/api/worktrees/route_client-reference-manifest.js +1 -1
  274. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  275. package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
  276. package/.next/server/app/more/page_client-reference-manifest.js +1 -1
  277. package/.next/server/app/offline/page_client-reference-manifest.js +1 -1
  278. package/.next/server/app/page_client-reference-manifest.js +1 -1
  279. package/.next/server/app/proxy/[...path]/route_client-reference-manifest.js +1 -1
  280. package/.next/server/app/repositories/page_client-reference-manifest.js +1 -1
  281. package/.next/server/app/review/page.js +1 -1
  282. package/.next/server/app/review/page_client-reference-manifest.js +1 -1
  283. package/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  284. package/.next/server/app/skills/[skillId]/page_client-reference-manifest.js +1 -1
  285. package/.next/server/app/skills/installed/page_client-reference-manifest.js +1 -1
  286. package/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  287. package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -1
  288. package/.next/server/app/worktrees/[id]/page.js +2 -2
  289. package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -1
  290. package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
  291. package/.next/server/app-paths-manifest.json +22 -22
  292. package/.next/server/chunks/1062.js +1 -0
  293. package/.next/server/chunks/110.js +1 -0
  294. package/.next/server/chunks/1501.js +5 -4
  295. package/.next/server/chunks/1656.js +2 -2
  296. package/.next/server/chunks/1957.js +2 -0
  297. package/.next/server/chunks/2119.js +1 -1
  298. package/.next/server/chunks/2445.js +1 -1
  299. package/.next/server/chunks/2897.js +1 -0
  300. package/.next/server/chunks/3417.js +1 -0
  301. package/.next/server/chunks/3505.js +1 -1
  302. package/.next/server/chunks/3756.js +1 -0
  303. package/.next/server/chunks/3801.js +3 -3
  304. package/.next/server/chunks/4911.js +1 -0
  305. package/.next/server/chunks/4936.js +1 -0
  306. package/.next/server/chunks/5209.js +2 -1
  307. package/.next/server/chunks/5354.js +1 -1
  308. package/.next/server/chunks/6130.js +1 -1
  309. package/.next/server/chunks/6401.js +1 -1
  310. package/.next/server/chunks/7023.js +2 -2
  311. package/.next/server/chunks/7905.js +1 -1
  312. package/.next/server/chunks/8581.js +15 -15
  313. package/.next/server/chunks/8728.js +2 -2
  314. package/.next/server/chunks/8782.js +1 -1
  315. package/.next/server/chunks/9390.js +1 -1
  316. package/.next/server/chunks/9584.js +1 -1
  317. package/.next/server/chunks/9731.js +2 -2
  318. package/.next/server/middleware-manifest.json +5 -5
  319. package/.next/server/pages/500.html +1 -1
  320. package/.next/server/server-reference-manifest.json +1 -1
  321. package/.next/static/chunks/{2407-675ba6b21844dc3b.js → 2407-07a237575e1ceb9e.js} +1 -1
  322. package/.next/static/chunks/3931-61ad1a4fc0208d0e.js +1 -0
  323. package/.next/static/chunks/5794-7975b8e51e731b19.js +1 -0
  324. package/.next/static/chunks/6966-d8dc6032410ffaba.js +1 -0
  325. package/.next/static/chunks/7197-ed3b3d99ac3bd450.js +1 -0
  326. package/.next/static/chunks/7636-a48cf0f7110250c5.js +1 -0
  327. package/.next/static/chunks/app/layout-4f64316957b0a8e5.js +1 -0
  328. package/.next/static/chunks/app/more/page-ff5af5ca48774c89.js +1 -0
  329. package/.next/static/chunks/app/page-b4863bfe0452e09d.js +1 -0
  330. package/.next/static/chunks/app/review/page-ff3efb96fdf9bb4b.js +1 -0
  331. package/.next/static/chunks/app/sessions/{page-890fd50ec9739973.js → page-c6eb7c02db2f4c80.js} +1 -1
  332. package/.next/static/chunks/app/worktrees/[id]/{page-f6d3ab8185d93aae.js → page-33afc6aa96289fb0.js} +1 -1
  333. package/.next/trace +13 -13
  334. package/dist/cli/commands/ask.d.ts.map +1 -1
  335. package/dist/cli/commands/ask.js +56 -5
  336. package/dist/cli/commands/attach.d.ts +4 -1
  337. package/dist/cli/commands/attach.d.ts.map +1 -1
  338. package/dist/cli/commands/attach.js +19 -7
  339. package/dist/cli/commands/command-target.d.ts +7 -0
  340. package/dist/cli/commands/command-target.d.ts.map +1 -1
  341. package/dist/cli/commands/command-target.js +10 -0
  342. package/dist/cli/commands/instances.d.ts.map +1 -1
  343. package/dist/cli/commands/instances.js +38 -2
  344. package/dist/cli/commands/message-dispatch.d.ts +17 -3
  345. package/dist/cli/commands/message-dispatch.d.ts.map +1 -1
  346. package/dist/cli/commands/message-dispatch.js +14 -8
  347. package/dist/cli/commands/relays.d.ts +2 -1
  348. package/dist/cli/commands/relays.d.ts.map +1 -1
  349. package/dist/cli/commands/relays.js +4 -3
  350. package/dist/cli/commands/respond-strict.d.ts.map +1 -1
  351. package/dist/cli/commands/respond-strict.js +22 -5
  352. package/dist/cli/commands/respond.d.ts +2 -2
  353. package/dist/cli/commands/respond.d.ts.map +1 -1
  354. package/dist/cli/commands/respond.js +40 -37
  355. package/dist/cli/commands/send.d.ts.map +1 -1
  356. package/dist/cli/commands/send.js +8 -4
  357. package/dist/cli/commands/wait-instance.d.ts +9 -1
  358. package/dist/cli/commands/wait-instance.d.ts.map +1 -1
  359. package/dist/cli/commands/wait-instance.js +15 -0
  360. package/dist/cli/commands/wait-poll-state.d.ts +18 -0
  361. package/dist/cli/commands/wait-poll-state.d.ts.map +1 -1
  362. package/dist/cli/commands/wait-verify.d.ts +2 -1
  363. package/dist/cli/commands/wait-verify.d.ts.map +1 -1
  364. package/dist/cli/commands/wait-verify.js +5 -1
  365. package/dist/cli/commands/wait.d.ts.map +1 -1
  366. package/dist/cli/commands/wait.js +37 -13
  367. package/dist/cli/commands/whoami.d.ts.map +1 -1
  368. package/dist/cli/commands/whoami.js +3 -1
  369. package/dist/cli/docs/agent-operations.d.ts +1 -1
  370. package/dist/cli/docs/agent-operations.d.ts.map +1 -1
  371. package/dist/cli/docs/agent-operations.js +1 -0
  372. package/dist/cli/types/api-responses.d.ts +3 -1
  373. package/dist/cli/types/api-responses.d.ts.map +1 -1
  374. package/dist/cli/utils/api-client.d.ts +55 -1
  375. package/dist/cli/utils/api-client.d.ts.map +1 -1
  376. package/dist/cli/utils/api-client.js +220 -18
  377. package/dist/cli/utils/follow-up-command.d.ts +38 -0
  378. package/dist/cli/utils/follow-up-command.d.ts.map +1 -0
  379. package/dist/cli/utils/follow-up-command.js +57 -0
  380. package/dist/cli/utils/reply-ledger.d.ts +1 -1
  381. package/dist/cli/utils/reply-ledger.d.ts.map +1 -1
  382. package/dist/cli/utils/reply-ledger.js +7 -2
  383. package/dist/cli/utils/server-capabilities.d.ts +18 -0
  384. package/dist/cli/utils/server-capabilities.d.ts.map +1 -1
  385. package/dist/cli/utils/server-capabilities.js +36 -3
  386. package/dist/cli/utils/session-target.d.ts +1 -1
  387. package/dist/cli/utils/session-target.d.ts.map +1 -1
  388. package/dist/cli/utils/session-target.js +3 -0
  389. package/dist/cli/utils/verify-runner.d.ts +7 -0
  390. package/dist/cli/utils/verify-runner.d.ts.map +1 -1
  391. package/dist/cli/utils/verify-runner.js +51 -15
  392. package/dist/lib/cli-tools/session-name.d.ts.map +1 -1
  393. package/dist/lib/cli-tools/session-name.js +11 -3
  394. package/dist/lib/session/send-attempt-types.d.ts +25 -0
  395. package/dist/lib/session/send-attempt-types.d.ts.map +1 -1
  396. package/dist/lib/session/send-attempt-types.js +10 -1
  397. package/dist/lib/verification/session-kill-ledger.d.ts +110 -0
  398. package/dist/lib/verification/session-kill-ledger.d.ts.map +1 -0
  399. package/dist/lib/verification/session-kill-ledger.js +174 -0
  400. package/dist/server/locales/en/worktree.json +2 -0
  401. package/dist/server/locales/ja/worktree.json +2 -0
  402. package/dist/server/src/config/cli-tool-timing-config.js +1 -7
  403. package/dist/server/src/lib/auto-yes-poller.js +5 -1
  404. package/dist/server/src/lib/cli-tools/antigravity.js +5 -2
  405. package/dist/server/src/lib/cli-tools/base.js +39 -0
  406. package/dist/server/src/lib/cli-tools/codex.js +7 -4
  407. package/dist/server/src/lib/cli-tools/command-code.js +7 -3
  408. package/dist/server/src/lib/cli-tools/copilot.js +5 -3
  409. package/dist/server/src/lib/cli-tools/gemini.js +10 -2
  410. package/dist/server/src/lib/cli-tools/launch-keys.js +39 -0
  411. package/dist/server/src/lib/cli-tools/opencode-v2.js +6 -2
  412. package/dist/server/src/lib/cli-tools/opencode.js +5 -2
  413. package/dist/server/src/lib/cli-tools/session-name.js +11 -3
  414. package/dist/server/src/lib/cli-tools/submit-composer-read.js +16 -6
  415. package/dist/server/src/lib/cli-tools/submit-verified-sender.js +164 -7
  416. package/dist/server/src/lib/cli-tools/vibe-local.js +4 -2
  417. package/dist/server/src/lib/db/db-migration-path.js +63 -2
  418. package/dist/server/src/lib/detection/prompt-detect-multiple-choice.js +5 -4
  419. package/dist/server/src/lib/hooks/sources/copilot/hook-settings.js +2 -3
  420. package/dist/server/src/lib/prompt-answer-errors.js +76 -2
  421. package/dist/server/src/lib/session/agent-event-state.js +4 -0
  422. package/dist/server/src/lib/session/agent-session-lifecycle.js +6 -1
  423. package/dist/server/src/lib/session/claude-session.js +22 -6
  424. package/dist/server/src/lib/session/current-output-builder.js +5 -3
  425. package/dist/server/src/lib/session/current-output-history-writers.js +1 -1
  426. package/dist/server/src/lib/session/prompt-submit-receipt.js +155 -0
  427. package/dist/server/src/lib/session/prompt-waiting-guard.js +10 -3
  428. package/dist/server/src/lib/session/send-attempt-state.js +48 -0
  429. package/dist/server/src/lib/session/send-attempt-types.js +10 -1
  430. package/dist/server/src/lib/session/send-user-message.js +5 -4
  431. package/dist/server/src/lib/session/session-launch-flight.js +243 -0
  432. package/dist/server/src/lib/session/session-starting-state.js +40 -4
  433. package/dist/server/src/lib/session/structured-prompt.js +12 -9
  434. package/dist/server/src/lib/session/waiting-episode-binding.js +4 -2
  435. package/dist/server/src/lib/session-cleanup.js +32 -0
  436. package/dist/server/src/lib/session-key-sender.js +0 -27
  437. package/dist/server/src/lib/verification/env-clean-gate.js +129 -0
  438. package/dist/server/src/lib/verification/env-snapshot.js +11 -2
  439. package/dist/server/src/lib/verification/session-kill-ledger.js +174 -0
  440. package/package.json +5 -1
  441. package/release-notes/0.49.2.json +49 -0
  442. package/.next/server/chunks/3773.js +0 -1
  443. package/.next/server/chunks/5775.js +0 -1
  444. package/.next/server/chunks/7604.js +0 -2
  445. package/.next/static/chunks/3931-1a1abab16248f14d.js +0 -1
  446. package/.next/static/chunks/4768-ad6f82f034f21eae.js +0 -1
  447. package/.next/static/chunks/5794-80ac3f06f098ea29.js +0 -1
  448. package/.next/static/chunks/6654-f3534f35f16644bc.js +0 -1
  449. package/.next/static/chunks/7665-e9ef6e0a85b9fa49.js +0 -1
  450. package/.next/static/chunks/8606-ce17ffa77f39608e.js +0 -1
  451. package/.next/static/chunks/app/layout-8bfac4724277b47f.js +0 -1
  452. package/.next/static/chunks/app/more/page-87c84987b2765213.js +0 -1
  453. package/.next/static/chunks/app/page-1b820c421db48c2c.js +0 -1
  454. package/.next/static/chunks/app/review/page-e2fd4a590646a2d8.js +0 -1
  455. /package/.next/static/{fqfSDqQMweROeHUzOt_m1 → yGatWDsS532awSs51kXyd}/_buildManifest.js +0 -0
  456. /package/.next/static/{fqfSDqQMweROeHUzOt_m1 → yGatWDsS532awSs51kXyd}/_ssgManifest.js +0 -0
@@ -92,7 +92,8 @@ class VibeLocalTool extends base_1.BaseCLITool {
92
92
  }
93
93
  // Start vibe-local in interactive mode with auto-approve (-y)
94
94
  // -y flag skips the permission confirmation prompt
95
- await (0, tmux_1.sendKeys)(sessionName, (0, launch_screen_1.withLaunchScreenCleared)(vibeLocalCommand), true);
95
+ // Issue #3981: in one writer's turn of the input lock.
96
+ await this.typeLaunchLines(sessionName, [(0, launch_screen_1.withLaunchScreenCleared)(vibeLocalCommand)]);
96
97
  // Wait for vibe-local to initialize (banner + model loading)
97
98
  await new Promise((resolve) => setTimeout(resolve, VIBE_LOCAL_INIT_WAIT_MS));
98
99
  logger.info('started-vibe-local-session');
@@ -137,7 +138,8 @@ class VibeLocalTool extends base_1.BaseCLITool {
137
138
  }
138
139
  catch (error) {
139
140
  const errorMessage = (0, errors_1.getErrorMessage)(error);
140
- throw new Error(`Failed to send message to Vibe Local: ${errorMessage}`);
141
+ // Issue #4031: the cause keeps a failed `load-buffer`'s code (`classifySendFailure`).
142
+ throw new Error(`Failed to send message to Vibe Local: ${errorMessage}`, { cause: error });
141
143
  }
142
144
  }
143
145
  /**
@@ -15,6 +15,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.resolveAndValidatePath = resolveAndValidatePath;
16
16
  exports.getLegacyDbPaths = getLegacyDbPaths;
17
17
  exports.migrateDbIfNeeded = migrateDbIfNeeded;
18
+ const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
19
+ const crypto_1 = __importDefault(require("crypto"));
18
20
  const fs_1 = __importDefault(require("fs"));
19
21
  const path_1 = __importDefault(require("path"));
20
22
  const os_1 = require("os");
@@ -83,6 +85,61 @@ function getLegacyDbPaths() {
83
85
  }
84
86
  return paths;
85
87
  }
88
+ /**
89
+ * Whether committed updates of `dbPath` may still live only in its `-wal` file.
90
+ *
91
+ * An empty or absent `-wal` means the main file is the whole database.
92
+ */
93
+ function hasPendingWal(dbPath) {
94
+ try {
95
+ return fs_1.default.statSync(`${dbPath}-wal`).size > 0;
96
+ }
97
+ catch {
98
+ return false;
99
+ }
100
+ }
101
+ /**
102
+ * Write a self-contained copy of the database at `sourcePath` to `destPath`
103
+ * (Issue #3993).
104
+ *
105
+ * Same tool as the pre-migration backup (`migrations/pre-migration-backup.ts`,
106
+ * Issue #3985): `VACUUM INTO` reads inside one read transaction, so updates
107
+ * still in `-wal` are included, and the result is a rollback-journal file that
108
+ * needs no sidecar. Copying the main file alone dropped them. The source is
109
+ * opened read-only; the copy is written to a temporary name and renamed into
110
+ * place, because `VACUUM INTO` refuses a non-empty destination.
111
+ */
112
+ function snapshotDatabase(sourcePath, destPath) {
113
+ const tempPath = `${destPath}.${crypto_1.default.randomBytes(4).toString('hex')}.partial`;
114
+ try {
115
+ // VACUUM INTO accepts an empty existing file; creating it first fixes the mode.
116
+ fs_1.default.closeSync(fs_1.default.openSync(tempPath, 'wx', 0o600));
117
+ const source = new better_sqlite3_1.default(sourcePath, { readonly: true, fileMustExist: true });
118
+ try {
119
+ source.prepare('VACUUM INTO ?').run(tempPath);
120
+ }
121
+ finally {
122
+ source.close();
123
+ }
124
+ fs_1.default.renameSync(tempPath, destPath);
125
+ }
126
+ catch (error) {
127
+ fs_1.default.rmSync(tempPath, { force: true });
128
+ throw error;
129
+ }
130
+ }
131
+ /**
132
+ * Copy a legacy database: a consistent snapshot when it has a non-empty `-wal`,
133
+ * the file itself otherwise (unchanged from before Issue #3993).
134
+ */
135
+ function copyLegacyDatabase(sourcePath, destPath) {
136
+ if (hasPendingWal(sourcePath)) {
137
+ snapshotDatabase(sourcePath, destPath);
138
+ }
139
+ else {
140
+ fs_1.default.copyFileSync(sourcePath, destPath);
141
+ }
142
+ }
86
143
  /**
87
144
  * Migrate database to new path if legacy DB exists
88
145
  *
@@ -92,6 +149,10 @@ function getLegacyDbPaths() {
92
149
  * 3. Creates a backup of the legacy database
93
150
  * 4. Copies the database to the new location
94
151
  *
152
+ * A legacy database with a non-empty `-wal` is copied as a `VACUUM INTO`
153
+ * snapshot (both the backup and the new location), so updates not yet written
154
+ * back to the main file are kept (Issue #3993).
155
+ *
95
156
  * Security features:
96
157
  * - SEC-002: Symlink resolution via realpathSync
97
158
  * - SEC-003: Directory creation with mode 0o700
@@ -125,7 +186,7 @@ function migrateDbIfNeeded(targetPath) {
125
186
  }
126
187
  // Create backup (SEC-006)
127
188
  const backupPath = `${resolvedLegacyPath}.bak`;
128
- fs_1.default.copyFileSync(resolvedLegacyPath, backupPath);
189
+ copyLegacyDatabase(resolvedLegacyPath, backupPath);
129
190
  fs_1.default.chmodSync(backupPath, 0o600);
130
191
  // Create target directory if needed (SEC-003)
131
192
  const targetDir = path_1.default.dirname(resolvedTargetPath);
@@ -133,7 +194,7 @@ function migrateDbIfNeeded(targetPath) {
133
194
  fs_1.default.mkdirSync(targetDir, { recursive: true, mode: 0o700 });
134
195
  }
135
196
  // Copy database to new location
136
- fs_1.default.copyFileSync(resolvedLegacyPath, resolvedTargetPath);
197
+ copyLegacyDatabase(resolvedLegacyPath, resolvedTargetPath);
137
198
  logger.info(`[Migration] Database migrated from ${resolvedLegacyPath} to ${resolvedTargetPath}`);
138
199
  logger.info(`[Migration] Backup created at ${backupPath}`);
139
200
  return {
@@ -753,7 +753,7 @@ function detectMultipleChoicePrompt(output, options, truncateRawContentFn) {
753
753
  // Issue #1699: the same block, cut at the previous turn's boundary. Display
754
754
  // keeps the wide window; deny patterns are judged against this one.
755
755
  const approvalBlock = extractApprovalTarget(lines, questionEndIndex, effectiveEnd, pickerTop);
756
- // Issue #616: Determine submitMode from confirmation footer (detected in single-pass above)
756
+ // Issue #616: Determine submitMode from confirmation footer (detected in single-pass by findConfirmationFooter())
757
757
  const submitMode = hasConfirmationFooter
758
758
  ? (hasNumberFooter ? 'answer_only' : 'answer_then_enter')
759
759
  : undefined;
@@ -808,7 +808,7 @@ function hasModelOverlayFooter(scanWindow) {
808
808
  // [Issue #1495] Claude `/model` local-settings overlay guard.
809
809
  // The `/model` overlay renders a ❯-marked numbered model list ("1. Default …
810
810
  // 5. Haiku") under a "Select model" header, which the option-collection logic
811
- // below would otherwise return as a genuine multiple_choice prompt. Auto-Yes
811
+ // (collectOptions()) would otherwise return as a genuine multiple_choice prompt. Auto-Yes
812
812
  // (detectAndRespondToPrompt) calls detectPrompt() directly and would resolve +
813
813
  // Enter-confirm the default option — silently changing the user's default model.
814
814
  // The overlay-unique "Enter to set as default …" footer never appears in real
@@ -948,10 +948,11 @@ function isMetadataRow(state, rawLine, line, paneCut) {
948
948
  // would then poison isValidPrecedingOption() and cause every real option
949
949
  // above (1./2./3.) to be rejected — resulting in collectedOptions.length<2
950
950
  // and a spurious no_prompt verdict. Treat the summary line as metadata
951
- // (same continuation handling as COLLAPSED_OUTPUT_PATTERN above) so the
951
+ // (same continuation handling as the COLLAPSED_OUTPUT_PATTERN check earlier
952
+ // in isMetadataRow()) so the
952
953
  // reverse scan continues into the actual option block.
953
954
  //
954
- // Defense-in-depth: works alongside the S2 effectiveEnd trim above. Either
955
+ // Defense-in-depth: works alongside the S2 effectiveEnd trim in findScanWindow(). Either
955
956
  // S1 or S2 alone is sufficient to fix Issue #704; keeping both protects
956
957
  // against future Claude renderings where the footer line text changes
957
958
  // (S1 still catches) or the summary line wording changes (S2 still
@@ -868,9 +868,8 @@ function writeCopilotHookSettings(options = {}) {
868
868
  *
869
869
  * Applied to the launched process rather than through `tmux set-environment`:
870
870
  * the pane is created before the agent starts and the assignment then travels
871
- * with the one process that matters, out of reach of
872
- * `sanitizeSessionEnvironment` and of anything else that edits the session's
873
- * environment later.
871
+ * with the one process that matters, out of reach of anything that edits
872
+ * the session's environment later (claude's `unset CLAUDECODE` among them).
874
873
  *
875
874
  * Returned as a map since Issue #1846. It used to be a pre-quoted
876
875
  * `NAME=value NAME=value` string that the caller concatenated in front of the
@@ -2,12 +2,17 @@
2
2
  /**
3
3
  * The refusals and failures `prompt-answer-sender` throws, with the reason
4
4
  * codes they carry (Issue #3965: moved out of `prompt-answer-sender`, which
5
- * re-exports every name here, so callers keep importing from it).
5
+ * re-exports every error and reason code here, so callers keep importing from it).
6
+ *
7
+ * Issue #3982: also how each of them is answered over HTTP
8
+ * ({@link promptAnswerErrorResponse}), in one table both answering routes read.
9
+ * That mapping is imported from this module directly.
6
10
  *
7
11
  * Type-only imports: this module must not import the sender back.
8
12
  */
9
13
  Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.PromptAnswerAbortedError = exports.PromptAnswerInputLostError = exports.ANSWER_INPUT_LOST_REASON = exports.PromptAnswerNotDeliveredError = exports.ANSWER_NOT_DELIVERED_REASON = exports.MultiSelectAnswerRejectedError = exports.MULTI_SELECT_NOT_COMMITTED_REASON = exports.FreeTextAtChoiceOnlyPromptError = exports.FreeTextAnswerRejectedError = exports.FREE_TEXT_AT_MENU_ROW_REASON = exports.PromptAnswerRejectedError = exports.ANSWER_MODE_KEYS_REASON = void 0;
14
+ exports.PROMPT_ANSWER_ERROR_RESPONSES = exports.PromptAnswerAbortedError = exports.ANSWER_ABORTED_REASON = exports.PromptAnswerInputLostError = exports.ANSWER_INPUT_LOST_REASON = exports.PromptAnswerNotDeliveredError = exports.ANSWER_NOT_DELIVERED_REASON = exports.MultiSelectAnswerRejectedError = exports.MULTI_SELECT_NOT_COMMITTED_REASON = exports.FreeTextAtChoiceOnlyPromptError = exports.FreeTextAnswerRejectedError = exports.FREE_TEXT_AT_MENU_ROW_REASON = exports.PromptAnswerRejectedError = exports.ANSWER_MODE_KEYS_REASON = void 0;
15
+ exports.promptAnswerErrorResponse = promptAnswerErrorResponse;
11
16
  /**
12
17
  * The reason code a caller gets back when a digit meets a `keys`-mode dialog
13
18
  * (Issue #2033).
@@ -269,6 +274,12 @@ class PromptAnswerInputLostError extends Error {
269
274
  }
270
275
  }
271
276
  exports.PromptAnswerInputLostError = PromptAnswerInputLostError;
277
+ /**
278
+ * The reason code of {@link PromptAnswerAbortedError} on the wire (Issue #3982).
279
+ * Neither answering route passes a `stillCurrent`, so neither is expected to
280
+ * see one; it has a code so that the mapping below has no hole.
281
+ */
282
+ exports.ANSWER_ABORTED_REASON = 'answer_aborted';
272
283
  /**
273
284
  * The caller's `stillCurrent` said no after one of the send's waits
274
285
  * (Issue #3706): the keys not yet sent were not sent. Keys already typed cannot
@@ -286,3 +297,66 @@ class PromptAnswerAbortedError extends Error {
286
297
  }
287
298
  }
288
299
  exports.PromptAnswerAbortedError = PromptAnswerAbortedError;
300
+ function row(errorClass, facts, status) {
301
+ return [errorClass, { facts: facts, status }];
302
+ }
303
+ /**
304
+ * Every error class this module exports, and how each route answers it
305
+ * (Issue #3982).
306
+ *
307
+ * Before this table each route had its own `instanceof` chain, and an error
308
+ * added to one was missing from the other: `/prompt-response` answered
309
+ * {@link PromptAnswerInputLostError} as a bare 500 with neither `reason` nor
310
+ * `keysSent`, so a caller could only find the reason by reading the message —
311
+ * which is also where a quoted answer lands. A unit test enumerates this
312
+ * module's exported classes and fails when one has no row here.
313
+ *
314
+ * `keysSent` is stated here for the refusals that never touch the pane rather
315
+ * than put on those errors: Auto-Yes reads `keysSent` off a thrown error to
316
+ * count its attempt, and that count is not this table's to change.
317
+ */
318
+ exports.PROMPT_ANSWER_ERROR_RESPONSES = new Map([
319
+ row(PromptAnswerRejectedError, (e) => ({ reason: e.reason, keysSent: false }), { 'prompt-response': 200, respond: 500 }),
320
+ row(FreeTextAnswerRejectedError, (e) => ({ reason: e.reason, keysSent: false }), { 'prompt-response': 200, respond: 500 }),
321
+ row(FreeTextAtChoiceOnlyPromptError, (e) => ({ reason: e.reason, keysSent: false }), { 'prompt-response': 200, respond: 500 }),
322
+ row(MultiSelectAnswerRejectedError, (e) => ({ reason: e.reason, keysSent: e.keysSent }), { 'prompt-response': 200, respond: 500 }),
323
+ row(PromptAnswerNotDeliveredError, (e) => ({ reason: e.reason, keysSent: e.keysSent }), { 'prompt-response': 200, respond: 409 }),
324
+ // Keys reached the pane: a failure, not a refusal, on both routes (#3952 review P2).
325
+ row(PromptAnswerInputLostError, (e) => ({ reason: e.reason, keysSent: e.keysSent }), { 'prompt-response': 500, respond: 500 }),
326
+ row(PromptAnswerAbortedError, (e) => ({ reason: exports.ANSWER_ABORTED_REASON, keysSent: e.keysSent }), { 'prompt-response': 500, respond: 500 }),
327
+ ]);
328
+ /** The mapping row for an error, or null when it is not one of this module's. */
329
+ function mappingOf(error) {
330
+ if (!(error instanceof Error))
331
+ return null;
332
+ for (const [errorClass, mapping] of exports.PROMPT_ANSWER_ERROR_RESPONSES) {
333
+ if (error instanceof errorClass)
334
+ return mapping;
335
+ }
336
+ return null;
337
+ }
338
+ /**
339
+ * How `route` answers an error `sendPromptAnswer` threw (Issue #3982), or null
340
+ * for an error this module does not define (the route keeps its own 500).
341
+ *
342
+ * The body always carries `reason` and `keysSent`. Its other keys are the ones
343
+ * each status already had: `success: false` + `message` for a 200 refusal (the
344
+ * route adds `answer`), `error` for a 409, and `error` prefixed
345
+ * `Failed to send answer to tmux:` for a 500. That 500's `error` still quotes
346
+ * the message, so a CLI older than this table reads it as before.
347
+ */
348
+ function promptAnswerErrorResponse(error, route) {
349
+ const mapping = mappingOf(error);
350
+ if (mapping === null)
351
+ return null;
352
+ const err = error;
353
+ const { reason, keysSent } = mapping.facts(err);
354
+ const status = mapping.status[route];
355
+ if (status === 200) {
356
+ return { status, body: { success: false, reason, message: err.message, keysSent } };
357
+ }
358
+ if (status >= 500) {
359
+ return { status, body: { error: `Failed to send answer to tmux: ${err.message}`, reason, keysSent } };
360
+ }
361
+ return { status, body: { error: err.message, reason, keysSent } };
362
+ }
@@ -69,6 +69,7 @@ const agent_event_structured_state_1 = require("../../lib/session/agent-event-st
69
69
  const agent_event_awaiting_instruction_1 = require("../../lib/session/agent-event-awaiting-instruction");
70
70
  const agent_event_ask_user_question_1 = require("../../lib/session/agent-event-ask-user-question");
71
71
  const global_state_1 = require("../global-state");
72
+ const prompt_submit_receipt_1 = require("../../lib/session/prompt-submit-receipt");
72
73
  var agent_event_dedup_2 = require("../../lib/session/agent-event-dedup");
73
74
  Object.defineProperty(exports, "AGENT_EVENT_DEDUP_WINDOW_MS", { enumerable: true, get: function () { return agent_event_dedup_2.AGENT_EVENT_DEDUP_WINDOW_MS; } });
74
75
  Object.defineProperty(exports, "agentEventKeyClaimedAt", { enumerable: true, get: function () { return agent_event_dedup_2.agentEventKeyClaimedAt; } });
@@ -224,6 +225,9 @@ function recordAgentEvent(worktreeId, cliToolId, instanceId, record, options = {
224
225
  return { recorded: false, skipped: 'late-session-start' };
225
226
  }
226
227
  lastAgentEvent.set(key, record);
228
+ // Issue #4035: what the sender asks before trusting an empty-looking composer
229
+ // on a session's first prompt.
230
+ (0, prompt_submit_receipt_1.notePromptSubmitHook)({ worktreeId, cliToolId, instanceId }, record.event, record.at);
227
231
  const outcomes = [];
228
232
  if (record.event === 'session_start') {
229
233
  // Issue #2357: a new agent process, whatever model it names first is its
@@ -46,6 +46,7 @@ const session_generation_archive_1 = require("../../lib/session/session-generati
46
46
  const session_starting_state_1 = require("../../lib/session/session-starting-state");
47
47
  const auto_yes_enter_fallback_state_1 = require("../../lib/polling/auto-yes-enter-fallback-state");
48
48
  const instance_input_lock_1 = require("../../lib/session/instance-input-lock");
49
+ const prompt_submit_receipt_1 = require("../../lib/session/prompt-submit-receipt");
49
50
  const session_name_1 = require("../../lib/cli-tools/session-name");
50
51
  const logger_1 = require("../../lib/logger");
51
52
  const logger = (0, logger_1.createLogger)('lib/session/agent-session-lifecycle');
@@ -93,7 +94,11 @@ function beginAgentSession(target, at = Date.now()) {
93
94
  // `invalidateInstanceInput`). In memory only; a name that does not resolve
94
95
  // has no lock to expire.
95
96
  try {
96
- (0, instance_input_lock_1.invalidateInstanceInput)((0, session_name_1.resolveSessionName)(target.cliToolId, target.worktreeId, target.instanceId));
97
+ const sessionName = (0, session_name_1.resolveSessionName)(target.cliToolId, target.worktreeId, target.instanceId);
98
+ (0, instance_input_lock_1.invalidateInstanceInput)(sessionName);
99
+ // Issue #4035: the new process's first prompt is confirmed by its own
100
+ // `UserPromptSubmit`, which is looked up by this session name.
101
+ (0, prompt_submit_receipt_1.notePromptSubmitSession)(sessionName, target, at);
97
102
  }
98
103
  catch (error) {
99
104
  logger.warn('instance-input-invalidate-failed', {
@@ -35,6 +35,8 @@ const agent_event_state_1 = require("../../lib/session/agent-event-state");
35
35
  const session_start_error_1 = require("../../lib/session/session-start-error");
36
36
  const launch_screen_1 = require("../../lib/session/launch-screen");
37
37
  const instance_input_lock_1 = require("../../lib/session/instance-input-lock");
38
+ const session_launch_flight_1 = require("../../lib/session/session-launch-flight");
39
+ const launch_keys_1 = require("../../lib/cli-tools/launch-keys");
38
40
  const logger = (0, logger_1.createLogger)('claude-session');
39
41
  const execAsync = (0, util_1.promisify)(child_process_1.exec);
40
42
  // ----- Helper Functions -----
@@ -686,12 +688,22 @@ async function startClaudeSession(options) {
686
688
  sessionName,
687
689
  workingDirectory: worktreePath,
688
690
  });
689
- // SF-S2-003: Sanitize environment after createSession, before launching Claude CLI
690
- await (0, session_key_sender_1.sanitizeSessionEnvironment)(sessionName);
691
- // Start Claude CLI in interactive mode using dynamically resolved path.
692
- // Issue #3975: one writer's turn, as gemini's launch line; the init polls
693
- // below stay outside the lock.
694
- await (0, instance_input_lock_1.withInstanceInputLock)(sessionName, () => (0, tmux_1.sendKeys)(sessionName, (0, launch_screen_1.withLaunchScreenCleared)(launchCommand), true));
691
+ // SF-S2-003: Sanitize environment after createSession, before launching
692
+ // Claude CLI (what session-key-sender's `sanitizeSessionEnvironment` did
693
+ // until #4032 removed it): drop CLAUDECODE from
694
+ // tmux's global environment (MF-S3-002), then `unset` it in the pane's
695
+ // shell, then start Claude in interactive mode using the dynamically
696
+ // resolved path.
697
+ //
698
+ // Issue #3981: the two lines are typed in ONE writer's turn of the input
699
+ // lock (#3975 locked only the launch line; the `unset` went out before it
700
+ // with no lock), so neither lands inside a send's body. The sanitize's
701
+ // 100 ms pause between them is gone: both lines queue in the same shell's
702
+ // input in order, so the `unset` runs first without it, and a pause inside
703
+ // the turn would only hold sends off longer. The init polls below stay
704
+ // outside the lock.
705
+ await execAsync('tmux set-environment -g -u CLAUDECODE 2>/dev/null || true');
706
+ await (0, launch_keys_1.typeLaunchLines)(sessionName, ['unset CLAUDECODE', (0, launch_screen_1.withLaunchScreenCleared)(launchCommand)]);
695
707
  // Wait for Claude to initialize with dynamic detection (OCP-001)
696
708
  // Use constants instead of hardcoded values
697
709
  const maxWaitTime = exports.CLAUDE_INIT_TIMEOUT;
@@ -799,6 +811,10 @@ async function startClaudeSession(options) {
799
811
  */
800
812
  async function sendMessageToClaude(worktreeId, message, instanceId) {
801
813
  const sessionName = getSessionName(worktreeId, instanceId);
814
+ // Issue #3981: a session another request is still launching shows a shell
815
+ // (`❯ ` can pass for Claude's prompt) — wait for that launch, or, holding the
816
+ // input lock as the send service does, refuse with nothing typed (R1).
817
+ await (0, session_launch_flight_1.settleSessionLaunch)(sessionName, 'Claude Code');
802
818
  await (0, session_key_sender_1.sendMessageToSession)(sessionName, message, exports.CLAUDE_POST_PROMPT_DELAY, exports.CLAUDE_SEND_PROMPT_WAIT_TIMEOUT);
803
819
  }
804
820
  /**
@@ -237,7 +237,7 @@ function readAgentEvents(worktreeId, cliToolId, instanceId, resolvedInstanceId)
237
237
  * every value below is derived from the arguments, and nothing is assigned
238
238
  * outside this function.
239
239
  */
240
- function composePromptData({ worktreeId, cliToolId, output, captureWindowLines, statusResult, startingSince, promptWaiting, askUserQuestion, eventSource, }) {
240
+ function composePromptData({ worktreeId, cliToolId, instanceId, output, captureWindowLines, statusResult, startingSince, promptWaiting, askUserQuestion, eventSource, }) {
241
241
  const scraperPromptWaiting = statusResult.hasActivePrompt;
242
242
  // Issue #1726: the agent's own account of what it asked. It contributes only
243
243
  // where some other layer has already established that a dialog is on screen —
@@ -338,9 +338,9 @@ function composePromptData({ worktreeId, cliToolId, output, captureWindowLines,
338
338
  : scraperPromptWaiting
339
339
  ? correctedPromptData ??
340
340
  scraperPromptData ??
341
- (structuredFacts ? (0, structured_prompt_1.buildStructuredPromptData)(worktreeId, structuredFacts) : null)
341
+ (structuredFacts ? (0, structured_prompt_1.buildStructuredPromptData)(worktreeId, structuredFacts, instanceId) : null)
342
342
  : structuredFacts
343
- ? (0, structured_prompt_1.buildStructuredPromptData)(worktreeId, structuredFacts)
343
+ ? (0, structured_prompt_1.buildStructuredPromptData)(worktreeId, structuredFacts, instanceId)
344
344
  : null;
345
345
  // Issue #2870: whether `/prompt-response` would answer the prompt published
346
346
  // above, read by the SAME function it re-verifies with. In #2868 `promptData`
@@ -813,6 +813,7 @@ async function buildPayload(db, worktreeId, cliToolId, instanceId) {
813
813
  const { structuredFacts, promptData, promptAnswerable } = composePromptData({
814
814
  worktreeId,
815
815
  cliToolId,
816
+ instanceId,
816
817
  output,
817
818
  captureWindowLines,
818
819
  statusResult,
@@ -920,6 +921,7 @@ async function buildPayload(db, worktreeId, cliToolId, instanceId) {
920
921
  worktreeId,
921
922
  cliToolId,
922
923
  instanceId: resolvedInstanceId,
924
+ respondInstanceId: instanceId,
923
925
  state: promptWaiting,
924
926
  facts: structuredFacts,
925
927
  });
@@ -221,7 +221,7 @@ function recordUnclassifiedFrame(db, params) {
221
221
  * nothing else.
222
222
  */
223
223
  function recordStructuredPrompt(db, params) {
224
- const record = (0, structured_prompt_1.buildStructuredPromptHistoryRecord)(params.worktreeId, params.facts);
224
+ const record = (0, structured_prompt_1.buildStructuredPromptHistoryRecord)(params.worktreeId, params.facts, params.respondInstanceId);
225
225
  try {
226
226
  const message = (0, db_1.createMessage)(db, {
227
227
  worktreeId: params.worktreeId,
@@ -0,0 +1,155 @@
1
+ "use strict";
2
+ /**
3
+ * Whether the agent itself reported a sent prompt (Issue #4035).
4
+ *
5
+ * The submit-verified sender decides "the message left the composer" from the
6
+ * screen. Two of its rules say only that the body is NOT in the composer — B
7
+ * (no composer, or an empty one) and F (other text, such as claude's dim
8
+ * `Try "…"` placeholder) — and right after a claude session starts that is not
9
+ * the same thing: measured on Claude Code 2.1.314 (`tests/fixtures/claude-first-send-4035/`),
10
+ * keys typed in the first second after the prompt appeared were drawn into the
11
+ * composer ~1.7 s later, the Enter typed after them was lost, and the frame
12
+ * read after the Enter still showed the idle placeholder, so F answered
13
+ * `submitted` for a body that sat unsent until the next send threw it away.
14
+ *
15
+ * Claude reports every submitted prompt with its `UserPromptSubmit` hook. This
16
+ * module keeps, per tmux session this server started, when that hook last
17
+ * arrived, so the sender can ask for it before trusting B or F on the
18
+ * session's first prompt ({@link readPromptSubmitReceipt}). It also keeps a
19
+ * fingerprint (digests, never the text) of the last body the sender reported
20
+ * submitted, so a later send that has to clear that very body out of the
21
+ * composer can say so ({@link matchesSubmittedBody}).
22
+ *
23
+ * In memory on `globalThis`, like the other per-session state; a session this
24
+ * server did not start (one adopted after a restart) has no entry, and every
25
+ * question about it is answered "not required", i.e. exactly as before.
26
+ *
27
+ * @module lib/session/prompt-submit-receipt
28
+ */
29
+ Object.defineProperty(exports, "__esModule", { value: true });
30
+ exports.notePromptSubmitSession = notePromptSubmitSession;
31
+ exports.notePromptSubmitHook = notePromptSubmitHook;
32
+ exports.getPromptSubmitTarget = getPromptSubmitTarget;
33
+ exports.readPromptSubmitReceipt = readPromptSubmitReceipt;
34
+ exports.noteSubmittedBody = noteSubmittedBody;
35
+ exports.matchesSubmittedBody = matchesSubmittedBody;
36
+ exports.clearPromptSubmitReceipts = clearPromptSubmitReceipts;
37
+ const crypto_1 = require("crypto");
38
+ const auto_yes_state_1 = require("../../lib/auto-yes-state");
39
+ const global_state_1 = require("../../lib/global-state");
40
+ /** How many sessions are tracked at once; the least recently started is forgotten first. */
41
+ const MAX_TRACKED_SESSIONS = 1024;
42
+ /**
43
+ * Compacted characters a body's prefix fingerprint covers. A composer read is
44
+ * cut by the reader, so a long body is recognised by its beginning.
45
+ */
46
+ const BODY_PREFIX_CHARS = 64;
47
+ const sessions = (0, global_state_1.getOrInitGlobal)('__promptSubmitSessions', () => new Map());
48
+ const sessionByInstance = (0, global_state_1.getOrInitGlobal)('__promptSubmitSessionByInstance', () => new Map());
49
+ function instanceKey(target) {
50
+ return (0, auto_yes_state_1.buildCompositeKey)(target.worktreeId, target.cliToolId, target.instanceId);
51
+ }
52
+ /** The tools whose prompt hook is trusted as proof of a submit. */
53
+ function reportsPrompts(cliToolId) {
54
+ // Claude only. codex's hooks run in a machine-wide daemon that can file a
55
+ // turn under the wrong instance (#2874), and copilot's arrive out of order
56
+ // (#1903); neither is evidence about one pane's composer.
57
+ return cliToolId === 'claude';
58
+ }
59
+ /**
60
+ * A session's generation began here (`beginAgentSession`). Forgets what was
61
+ * known about the previous process in the same pane name.
62
+ */
63
+ function notePromptSubmitSession(sessionName, target, at = Date.now()) {
64
+ sessions.delete(sessionName);
65
+ sessions.set(sessionName, { target, startedAt: at, lastEventAt: null, lastPromptAt: null, submittedBody: null });
66
+ sessionByInstance.set(instanceKey(target), sessionName);
67
+ while (sessions.size > MAX_TRACKED_SESSIONS) {
68
+ const oldest = sessions.keys().next().value;
69
+ if (oldest === undefined)
70
+ break;
71
+ const entry = sessions.get(oldest);
72
+ sessions.delete(oldest);
73
+ if (entry !== undefined && sessionByInstance.get(instanceKey(entry.target)) === oldest) {
74
+ sessionByInstance.delete(instanceKey(entry.target));
75
+ }
76
+ }
77
+ }
78
+ /** A hook was applied for this instance (`recordAgentEvent`). */
79
+ function notePromptSubmitHook(target, event, at) {
80
+ let sessionName;
81
+ try {
82
+ sessionName = sessionByInstance.get(instanceKey(target));
83
+ }
84
+ catch {
85
+ return;
86
+ }
87
+ const entry = sessionName === undefined ? undefined : sessions.get(sessionName);
88
+ if (entry === undefined)
89
+ return;
90
+ entry.lastEventAt = at;
91
+ if (event === 'user_prompt_submit')
92
+ entry.lastPromptAt = at;
93
+ }
94
+ /** The instance a session this server started runs, or null. */
95
+ function getPromptSubmitTarget(sessionName) {
96
+ return sessions.get(sessionName)?.target ?? null;
97
+ }
98
+ /**
99
+ * Whether the screen's B/F verdict for a send whose first Enter went in at
100
+ * `enteredAt` needs the agent's own report (Issue #4035).
101
+ */
102
+ function readPromptSubmitReceipt(sessionName, cliToolId, enteredAt) {
103
+ if (!reportsPrompts(cliToolId))
104
+ return 'not-required';
105
+ const entry = sessions.get(sessionName);
106
+ if (entry === undefined || entry.target.cliToolId !== cliToolId)
107
+ return 'not-required';
108
+ if (entry.lastPromptAt !== null && entry.lastPromptAt >= enteredAt)
109
+ return 'received';
110
+ if (entry.lastEventAt === null || entry.lastEventAt < entry.startedAt)
111
+ return 'not-required';
112
+ if (entry.lastPromptAt !== null && entry.lastPromptAt >= entry.startedAt)
113
+ return 'not-required';
114
+ return 'awaited';
115
+ }
116
+ function compact(text) {
117
+ return text.replace(/\s+/g, '');
118
+ }
119
+ function digest(text) {
120
+ return (0, crypto_1.createHash)('sha256').update(text, 'utf8').digest('hex').slice(0, 16);
121
+ }
122
+ /**
123
+ * The sender reported this body submitted on this session from the screen
124
+ * alone — not for one the agent's hook reported, which did leave.
125
+ */
126
+ function noteSubmittedBody(sessionName, message) {
127
+ const entry = sessions.get(sessionName);
128
+ if (entry === undefined)
129
+ return;
130
+ const body = compact(message);
131
+ entry.submittedBody = {
132
+ full: digest(body),
133
+ prefix: body.length >= BODY_PREFIX_CHARS ? digest(body.slice(0, BODY_PREFIX_CHARS)) : null,
134
+ };
135
+ }
136
+ /**
137
+ * Whether a composer read is the body last reported submitted on this session:
138
+ * the whole of it, or — for a read long enough — its beginning.
139
+ */
140
+ function matchesSubmittedBody(sessionName, composerText) {
141
+ const body = sessions.get(sessionName)?.submittedBody;
142
+ if (body === null || body === undefined)
143
+ return false;
144
+ const read = compact(composerText);
145
+ if (read === '')
146
+ return false;
147
+ if (digest(read) === body.full)
148
+ return true;
149
+ return body.prefix !== null && read.length >= BODY_PREFIX_CHARS && digest(read.slice(0, BODY_PREFIX_CHARS)) === body.prefix;
150
+ }
151
+ /** Forget every session (tests). */
152
+ function clearPromptSubmitReceipts() {
153
+ sessions.clear();
154
+ sessionByInstance.clear();
155
+ }
@@ -128,13 +128,20 @@ async function isPromptWaiting(worktreeId, cliToolId, instanceId, options) {
128
128
  * That is precisely the state where a guard turns into an outage, so the message
129
129
  * has to name the way past it and how long it lasts if they do nothing.
130
130
  *
131
+ * Issue #4031: the commands it names carry ` --instance <id>` when the refused
132
+ * request named an instance, so the answer goes to the instance that is
133
+ * waiting. A request for the primary instance (no `instanceId`) gets the
134
+ * sentence as before.
135
+ *
131
136
  * @param blockedBy - Which layer refused; omitted callers get the plain message
137
+ * @param instanceId - The instance the refused request named, if any
132
138
  */
133
- function promptWaitingMessage(worktreeId, blockedBy) {
139
+ function promptWaitingMessage(worktreeId, blockedBy, instanceId) {
140
+ const target = instanceId ? ` --instance ${instanceId}` : '';
134
141
  const base = `${worktreeId} is waiting on a prompt. Sending now would type into the ` +
135
142
  `prompt's input line instead of reaching the agent, and would leave that ` +
136
143
  `text in place for the next answer. Answer the prompt first: ` +
137
- `\`commandmate respond ${worktreeId} <answer>\`.`;
144
+ `\`commandmate respond ${worktreeId} <answer>${target}\`.`;
138
145
  if (blockedBy !== 'structured')
139
146
  return base;
140
147
  const ttlMinutes = Math.round(prompt_waiting_composition_1.STRUCTURED_SEND_BLOCK_MAX_AGE_MS / 60_000);
@@ -142,6 +149,6 @@ function promptWaitingMessage(worktreeId, blockedBy) {
142
149
  `visible to the terminal scraper, so if the pane looks idle the record has ` +
143
150
  `outlived its dialog: it stops blocking sends ${ttlMinutes} minutes after ` +
144
151
  `it was reported, or immediately with ` +
145
- `\`commandmate send ${worktreeId} <message> --ignore-structured-prompt\` ` +
152
+ `\`commandmate send ${worktreeId} <message>${target} --ignore-structured-prompt\` ` +
146
153
  `(server-wide: ${prompt_waiting_composition_1.STRUCTURED_SEND_GUARD_ENV}=off).`);
147
154
  }