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
@@ -90,7 +90,7 @@ var __importStar = (this && this.__importStar) || (function () {
90
90
  };
91
91
  })();
92
92
  Object.defineProperty(exports, "__esModule", { value: true });
93
- exports.CLAUDE_TRANSCRIPT_TAIL_BYTES = void 0;
93
+ exports.CLAUDE_TURN_RECHECK_LIMIT = exports.CLAUDE_TRANSCRIPT_TAIL_BYTES = void 0;
94
94
  exports.resetClaudeTranscriptSessions = resetClaudeTranscriptSessions;
95
95
  exports.resolveClaudeSessionId = resolveClaudeSessionId;
96
96
  exports.claudeProjectsRoot = claudeProjectsRoot;
@@ -324,6 +324,12 @@ async function captureClaudeTranscriptTurn(target, capture) {
324
324
  });
325
325
  }
326
326
  const pending = await selectUnwrittenClaudeTurns(target, built.turns);
327
+ // Before anything is written: the rows that are already there (#2264). This
328
+ // is deliberately ahead of the early return below, because "the newest turn
329
+ // is already a row" is the state the nine short rows the Issue measured were
330
+ // stuck in — the reader answered true and did nothing while the transcript
331
+ // beside it held the missing paragraph.
332
+ await refreshClaudeTurnRows(target, built.turns.slice(0, built.turns.length - pending.turns.length).slice(-exports.CLAUDE_TURN_RECHECK_LIMIT), path);
327
333
  if (pending.turns.length === 0) {
328
334
  // The anchor is the newest turn in the window, so there is nothing to
329
335
  // write and the newest turn is a row. True, for the reason
@@ -352,12 +358,23 @@ async function captureClaudeTranscriptTurn(target, capture) {
352
358
  // by timestamp, and each turn's `/send` row is adopted against the previous
353
359
  // turn's start, so a later turn must not get to claim a row an earlier one
354
360
  // is about to ask for.
361
+ //
362
+ // Every prompt row is recorded before any reply is written (Issue #2273).
363
+ // That is what lets a reply be dated at its turn's END without overtaking
364
+ // the NEXT turn's prompt: a queued `/send` row is written while this turn is
365
+ // still running, so its instant is only knowable once that row has been
366
+ // recorded. With one turn pending — the ordinary case — this is the single
367
+ // call it always was.
368
+ const userRows = [];
369
+ for (let index = 0; index < pending.turns.length; index += 1) {
370
+ const previousStartedAt = index === 0 ? pending.previousStartedAt : pending.turns[index - 1].startedAt;
371
+ userRows.push(await recordClaudeUserTurn(target, pending.turns[index], previousStartedAt));
372
+ }
373
+ const lastRecordAt = lastClaudeAssistantRecordAt(parsed.records);
355
374
  let captured = false;
356
375
  for (let index = 0; index < pending.turns.length; index += 1) {
357
376
  const turn = pending.turns[index];
358
- const previousStartedAt = index === 0 ? pending.previousStartedAt : pending.turns[index - 1].startedAt;
359
- const userRow = await recordClaudeUserTurn(target, turn, previousStartedAt);
360
- captured = await writeClaudeTurn(target, (0, transcript_1.renderClaudeTurn)(turn), resolveAssistantTimestampMs(turn, userRow), path);
377
+ captured = await writeClaudeTurn(target, turn, (0, transcript_1.renderClaudeTurn)(turn), resolveAssistantTimestampMs(turn, userRows[index], lastRecordAt.get(turn.promptUuid) ?? 0, nextTurnOpensAt(pending.turns, userRows, index)), path);
361
378
  }
362
379
  return captured;
363
380
  }
@@ -493,6 +510,11 @@ function collectHeadlessClaudeTurn(records, sessionId) {
493
510
  promptIsOperatorInput: false,
494
511
  blocks,
495
512
  assistantRecords,
513
+ // Never handed to a writer, so neither flag can be read off it; false is the
514
+ // value that would refuse the write if one were ever attempted.
515
+ closed: false,
516
+ superseded: false,
517
+ stopReasonObserved: false,
496
518
  overflowed,
497
519
  };
498
520
  }
@@ -632,22 +654,87 @@ async function recordClaudeUserTurn(target, turn, previousStartedAt = 0) {
632
654
  /**
633
655
  * When the assistant row for this turn is dated.
634
656
  *
635
- * #2121 dated it by the prompt record's clock so that a row written a poll late
636
- * still sorts where the conversation put it, and that is still what happens for
637
- * every turn that produced no user row.
638
- *
639
- * When there *is* a user row, it sits on that same instant — both come from the
640
- * one prompt record and `groupMessagesIntoPairs` orders by timestamp and
641
- * nothing else. A tie there is decided by whichever row the database happened to
642
- * return first, and the losing arrangement (assistant, then user) is exactly the
643
- * `orphan` pair this Issue exists to remove. So the reply is moved to the first
644
- * millisecond after the prompt: the smallest change that makes the order a
645
- * property of the data rather than of the query plan.
657
+ * **The turn's LAST assistant record, not its prompt (Issue #2273).** #2121
658
+ * dated the reply by the prompt record's clock so that a row written a poll late
659
+ * still sorted where the conversation put it, and #2196 moved it one millisecond
660
+ * on so that `groupMessagesIntoPairs` — which orders by timestamp and nothing
661
+ * else could never return the answer above the question. Both properties
662
+ * survive: `earliest` is a floor this never goes under.
663
+ *
664
+ * What neither accounted for is the row that lands BETWEEN the prompt and the
665
+ * reply. A tool approval is written when the dialog appears, seconds into the
666
+ * turn, and the chat surface orders its rows by timestamp so a reply dated at
667
+ * the turn's start draws ABOVE an approval that really happened before it. The
668
+ * measured case is in the Issue: prompt `04:49:50.989Z`, reply `04:49:54.000Z`,
669
+ * approval `04:49:57.513Z`, rendered as question → answer → approval.
670
+ *
671
+ * The turn's last assistant record is the moment the reply was finished, so
672
+ * everything the turn produced on the way sorts before it. `lastRecordAt` is 0
673
+ * when the window held no timestamped assistant record for the turn, and the row
674
+ * is then dated exactly where #2196 put it.
675
+ *
676
+ * `nextTurnOpensAt` is the ceiling. The next turn's prompt row may be a `/send`
677
+ * row written while THIS turn was still running — a queued prompt — and a reply
678
+ * that overtook it would be paired with the wrong question.
679
+ *
680
+ * @param lastRecordAt - Epoch ms of the turn's last assistant record, or 0
681
+ * @param nextTurnOpensAt - Epoch ms of the next turn's user row, or null when
682
+ * this is the newest turn in the window
646
683
  */
647
- function resolveAssistantTimestampMs(turn, userRow) {
648
- if (userRow.timestampMs === null)
649
- return turn.startedAt;
650
- return Math.max(turn.startedAt, userRow.timestampMs + 1);
684
+ function resolveAssistantTimestampMs(turn, userRow, lastRecordAt = 0, nextTurnOpensAt = null) {
685
+ const earliest = userRow.timestampMs === null
686
+ ? turn.startedAt
687
+ : Math.max(turn.startedAt, userRow.timestampMs + 1);
688
+ const latest = nextTurnOpensAt === null ? Number.POSITIVE_INFINITY : nextTurnOpensAt - 1;
689
+ return Math.max(earliest, Math.min(lastRecordAt, latest));
690
+ }
691
+ /**
692
+ * When each turn's last assistant record was written (Issue #2273).
693
+ *
694
+ * Keyed by `promptUuid`, which is the turn key {@link buildClaudeTurns} uses, and
695
+ * walked over the same records with the same two rules — sidechains skipped, a
696
+ * prompt record opening a turn — so the two passes cannot disagree about which
697
+ * turn a record belongs to. It is a second pass rather than a field on the
698
+ * accumulator because `./transcript` is not this Issue's to change.
699
+ *
700
+ * Only `assistant` records count. A turn's `user` records are its tool RESULTS,
701
+ * and the last of those is a step the agent took before it had finished
702
+ * answering; the reply is dated by the agent's last word.
703
+ *
704
+ * @returns `promptUuid` → epoch ms; absent for a turn with no timestamped
705
+ * assistant record
706
+ */
707
+ function lastClaudeAssistantRecordAt(records) {
708
+ const at = new Map();
709
+ let key = null;
710
+ for (const record of records) {
711
+ if (record.isSidechain)
712
+ continue;
713
+ if ((0, transcript_1.isClaudePromptRecord)(record)) {
714
+ key = record.uuid;
715
+ continue;
716
+ }
717
+ if (record.type !== 'assistant' || key === null || record.timestampMs === null)
718
+ continue;
719
+ if (record.timestampMs > (at.get(key) ?? 0))
720
+ at.set(key, record.timestampMs);
721
+ }
722
+ return at;
723
+ }
724
+ /**
725
+ * The instant the next pending turn's prompt row carries, or null (Issue #2273).
726
+ *
727
+ * The user row's own timestamp when there is one, because that is what History
728
+ * sorts on and it can be EARLIER than the turn's start — an adopted `/send` row
729
+ * was written when CommandMate handed the text to the pane, which for a queued
730
+ * prompt is while the previous turn was still running. The turn's start is the
731
+ * fallback for a turn that produced no row at all.
732
+ */
733
+ function nextTurnOpensAt(turns, userRows, index) {
734
+ const next = turns[index + 1];
735
+ if (!next)
736
+ return null;
737
+ return userRows[index + 1]?.timestampMs ?? next.startedAt;
651
738
  }
652
739
  /**
653
740
  * The transcript file for this instance, or null.
@@ -717,6 +804,113 @@ async function readClaudeTranscriptTail(path) {
717
804
  await handle?.close().catch(() => { });
718
805
  }
719
806
  }
807
+ /**
808
+ * How many already-written turns are re-rendered and compared (Issue #2264).
809
+ *
810
+ * The repair half of #2264 has to look at rows the reader has **already**
811
+ * written, which is the one thing the anchor rule deliberately does not do — so
812
+ * it is bounded here rather than by the window. Three, because the poller runs
813
+ * every two seconds and re-rendering the whole 4 MiB window on every tick would
814
+ * turn a repair into the most expensive thing the poll does, while a row that is
815
+ * going to grow grows within a second of being written.
816
+ *
817
+ * The cost of the bound is only paid by rows the old code left short: those are
818
+ * repaired on the next read that still has the turn among its newest three, and
819
+ * a session that has moved four turns past one of them keeps it. The Issue's own
820
+ * nine rows were all the newest turn at the time, so all nine are inside it.
821
+ */
822
+ exports.CLAUDE_TURN_RECHECK_LIMIT = 3;
823
+ /**
824
+ * Replace a saved row whose body has since grown (Issue #2264).
825
+ *
826
+ * The second half of the fix, and the half that repairs what the first half
827
+ * only stops happening again. A row keyed `claude-turn:<uuid>` is written once
828
+ * and every later read answers "already saved" — so the nine short rows the
829
+ * Issue measured were frozen, and the scrape that could have replaced them was
830
+ * suppressed two seconds later by that same idempotency answer.
831
+ *
832
+ * **Strictly longer, never merely different.** Equality is the ordinary case and
833
+ * must cost nothing, and a body that got *shorter* between two reads is not a
834
+ * turn that grew — it is a window that slid, or a truncation marker, and
835
+ * overwriting a full reply with a shorter one is the one outcome worse than the
836
+ * bug. Longer implies different, so one comparison covers both halves of the
837
+ * Issue's "differs and is longer".
838
+ *
839
+ * `message_updated`, never `message`: the row already existed and was already
840
+ * delivered when it was created (#2195), so a client that appended instead of
841
+ * replacing would show the reply twice.
842
+ *
843
+ * @param existing - The row `findMessageByRequestId` answered with
844
+ * @returns Whether the row was replaced
845
+ */
846
+ async function growClaudeTurnRow(target, existing, rendered, path) {
847
+ const instanceId = target.instanceId ?? target.cliToolId;
848
+ const previousLength = existing.content.length;
849
+ if (rendered.body.length <= previousLength)
850
+ return false;
851
+ const [{ getDbInstance }, { updateMessageContent }, { broadcastMessage }] = await Promise.all([
852
+ Promise.resolve().then(() => __importStar(require('../../../../lib/db/db-instance'))),
853
+ Promise.resolve().then(() => __importStar(require('../../../../lib/db'))),
854
+ Promise.resolve().then(() => __importStar(require('../../../../lib/ws-server'))),
855
+ ]);
856
+ updateMessageContent(getDbInstance(), existing.id, rendered.body);
857
+ broadcastMessage('message_updated', {
858
+ worktreeId: target.worktreeId,
859
+ message: { ...existing, content: rendered.body },
860
+ });
861
+ logger.info('claude-transcript-turn-updated', {
862
+ worktreeId: target.worktreeId,
863
+ instanceId,
864
+ sessionId: rendered.sessionId,
865
+ requestId: existing.requestId,
866
+ path,
867
+ previousLength,
868
+ bodyLength: rendered.body.length,
869
+ textBlocks: rendered.textBlocks,
870
+ toolBlocks: rendered.toolBlocks,
871
+ });
872
+ return true;
873
+ }
874
+ /**
875
+ * Re-read the newest already-written turns and grow the short ones (#2264).
876
+ *
877
+ * Runs before the pending turns are written and independently of whether there
878
+ * are any — the case it exists for is precisely the one
879
+ * {@link captureClaudeTranscriptTurn} used to return `true` from without doing
880
+ * anything: the newest turn already has a row, and that row is missing its last
881
+ * paragraph.
882
+ *
883
+ * Turns that are still open are skipped rather than compared. Their body is by
884
+ * definition not the final one, and a repair that raced the agent would rewrite
885
+ * the row on every poll of a long turn.
886
+ *
887
+ * The database is asked before the turn is rendered, so a candidate with no row
888
+ * — every candidate, in a session this reader has never written to — costs one
889
+ * indexed lookup and no Markdown.
890
+ *
891
+ * @param candidates - Already-written turns, oldest first, at most {@link CLAUDE_TURN_RECHECK_LIMIT}
892
+ * @returns How many rows were replaced
893
+ */
894
+ async function refreshClaudeTurnRows(target, candidates, path) {
895
+ if (candidates.length === 0)
896
+ return 0;
897
+ const [{ getDbInstance }, { findMessageByRequestId }] = await Promise.all([
898
+ Promise.resolve().then(() => __importStar(require('../../../../lib/db/db-instance'))),
899
+ Promise.resolve().then(() => __importStar(require('../../../../lib/db'))),
900
+ ]);
901
+ const db = getDbInstance();
902
+ let updated = 0;
903
+ for (const turn of candidates) {
904
+ if (!(0, transcript_1.isClaudeTurnWritable)(turn))
905
+ continue;
906
+ const existing = findMessageByRequestId(db, target.worktreeId, (0, agent_transcript_1.claudeTurnRequestId)(turn.promptUuid));
907
+ if (!existing)
908
+ continue;
909
+ if (await growClaudeTurnRow(target, existing, (0, transcript_1.renderClaudeTurn)(turn), path))
910
+ updated += 1;
911
+ }
912
+ return updated;
913
+ }
720
914
  /**
721
915
  * Write one rendered turn, unless it is already there.
722
916
  *
@@ -731,8 +925,33 @@ async function readClaudeTranscriptTail(path) {
731
925
  *
732
926
  * @returns Whether History holds this turn as the agent's own Markdown
733
927
  */
734
- async function writeClaudeTurn(target, rendered, timestampMs, path) {
928
+ async function writeClaudeTurn(target, turn, rendered, timestampMs, path) {
735
929
  const instanceId = target.instanceId ?? target.cliToolId;
930
+ if (!(0, transcript_1.isClaudeTurnWritable)(turn)) {
931
+ // The agent has not said `end_turn` for this prompt and no later prompt has
932
+ // taken over, so what is in the file is a turn in progress. Writing it would
933
+ // put a reply with its last paragraph missing into History **permanently** —
934
+ // the row is keyed on the prompt's `uuid`, so every later read finds it and
935
+ // answers "already saved". That is Issue #2264 exactly: 9 of `claude-2`'s 20
936
+ // turns on 2026-09-03 were saved as a bare `> **Tool calls (1)**` with not
937
+ // one character of prose, because the Stop hook beat the last append and the
938
+ // emptiness guard below cannot see the difference — a turn cut off after its
939
+ // tool calls renders a *non-empty* body.
940
+ //
941
+ // Handing it back to the scraper costs the Markdown rendering for this turn
942
+ // and nothing else: the Stop receiver asks again after a short delay, and
943
+ // the poller asks again when the pane returns to the composer.
944
+ logger.info('claude-transcript-turn-open', {
945
+ worktreeId: target.worktreeId,
946
+ instanceId,
947
+ sessionId: rendered.sessionId,
948
+ promptUuid: rendered.promptUuid,
949
+ assistantRecords: turn.assistantRecords,
950
+ textBlocks: rendered.textBlocks,
951
+ toolBlocks: rendered.toolBlocks,
952
+ });
953
+ return false;
954
+ }
736
955
  if (rendered.body.length === 0) {
737
956
  // The turn is open but the agent has not written anything to the file yet —
738
957
  // the prompt record is there and the assistant records are not. Answering
@@ -762,12 +981,17 @@ async function writeClaudeTurn(target, rendered, timestampMs, path) {
762
981
  Promise.resolve().then(() => __importStar(require('../../../../lib/ws-server'))),
763
982
  ]);
764
983
  const db = getDbInstance();
765
- if (findMessageByRequestId(db, target.worktreeId, requestId)) {
984
+ const existing = findMessageByRequestId(db, target.worktreeId, requestId);
985
+ if (existing) {
766
986
  logger.debug('claude-transcript-turn-already-saved', {
767
987
  worktreeId: target.worktreeId,
768
988
  instanceId,
769
989
  requestId,
770
990
  });
991
+ // The row may still be one of the short ones #2264 was reported for, and
992
+ // this is the one place that knows both the row and the turn. See
993
+ // {@link growClaudeTurnRow}.
994
+ await growClaudeTurnRow(target, existing, rendered, path);
771
995
  return true;
772
996
  }
773
997
  const message = createMessage(db, {
@@ -36,9 +36,12 @@
36
36
  * is therefore keyed on the *prompt* record, never on a `requestId`.
37
37
  * 3. **`type: "user"` is mostly not the user.** Of 19 user records in the
38
38
  * sampled session, 18 were `tool_result` payloads. Tool results, `isMeta`
39
- * placeholders (`[Image: original 1440x2170…]`), and the slash-command
39
+ * placeholders (`[Image: original 1440x2170…]`), and the built-in command
40
40
  * bookkeeping records (`<command-name>`, `<local-command-stdout>`) all have
41
- * `type: "user"` and none of them is a prompt. See {@link isClaudePromptRecord}.
41
+ * `type: "user"` and none of them is a prompt. The one `<command-…>` shape
42
+ * that *is* a prompt — a project command, recorded `<command-message>` first
43
+ * — is Issue #2265; see {@link CLAUDE_SLASH_COMMAND_PREFIX} and
44
+ * {@link isClaudePromptRecord}.
42
45
  * 4. **`thinking` blocks can be empty.** The block arrives with a `signature`
43
46
  * and `thinking: ""` when the text is not retained, so an empty one is
44
47
  * skipped rather than rendered as a blank quote.
@@ -53,13 +56,16 @@
53
56
  * @module lib/hooks/sources/claude/transcript
54
57
  */
55
58
  Object.defineProperty(exports, "__esModule", { value: true });
56
- exports.CLAUDE_HUMAN_PROMPT_SOURCES = exports.CLAUDE_HUMAN_ORIGIN_KIND = exports.CLAUDE_THINKING_LABEL = exports.MAX_CLAUDE_TOOL_DETAIL_LENGTH = exports.MAX_CLAUDE_TURN_BLOCKS = exports.CLAUDE_TURN_TRUNCATION_MARKER = exports.MAX_CLAUDE_TURN_BODY_LENGTH = exports.CLAUDE_PROJECTS_DIR_SEGMENTS = void 0;
59
+ exports.CLAUDE_END_TURN_STOP_REASON = exports.CLAUDE_HUMAN_PROMPT_SOURCES = exports.CLAUDE_HUMAN_ORIGIN_KIND = exports.CLAUDE_SLASH_COMMAND_PREFIX = exports.CLAUDE_THINKING_LABEL = exports.MAX_CLAUDE_TOOL_DETAIL_LENGTH = exports.MAX_CLAUDE_TURN_BLOCKS = exports.CLAUDE_TURN_TRUNCATION_MARKER = exports.MAX_CLAUDE_TURN_BODY_LENGTH = exports.CLAUDE_PROJECTS_DIR_SEGMENTS = void 0;
57
60
  exports.claudeProjectSlug = claudeProjectSlug;
61
+ exports.claudeSlashCommandPrompt = claudeSlashCommandPrompt;
58
62
  exports.readClaudeContentBlock = readClaudeContentBlock;
59
63
  exports.readClaudeTranscriptRecord = readClaudeTranscriptRecord;
60
64
  exports.parseClaudeTranscript = parseClaudeTranscript;
61
65
  exports.isClaudePromptRecord = isClaudePromptRecord;
62
66
  exports.isClaudeOperatorPromptRecord = isClaudeOperatorPromptRecord;
67
+ exports.isClaudeTurnClosingRecord = isClaudeTurnClosingRecord;
68
+ exports.isClaudeTurnWritable = isClaudeTurnWritable;
63
69
  exports.createClaudeTurn = createClaudeTurn;
64
70
  exports.buildClaudeTurns = buildClaudeTurns;
65
71
  exports.renderClaudeTurn = renderClaudeTurn;
@@ -111,18 +117,97 @@ exports.CLAUDE_THINKING_LABEL = 'Thinking';
111
117
  /**
112
118
  * Prefixes that mark a `type: "user"` record as bookkeeping rather than a prompt.
113
119
  *
114
- * All four were observed on real transcripts. `<local-command-caveat>` and the
115
- * `<command-…>` trio are how a slash command is recorded; `<local-command-stdout>`
116
- * is its output. Treating any of them as a prompt would open a turn that the
117
- * operator never typed, and the reply to the *next* real prompt would be filed
118
- * under it.
120
+ * Three since Issue #2265, which took `<command-message>` off the list — see
121
+ * {@link CLAUDE_SLASH_COMMAND_PREFIX} for the census that separated the two
122
+ * shapes the `<command-…>` trio is written in. What is left is the bookkeeping
123
+ * of a **built-in** command: `<command-name>` first is how Claude records
124
+ * `/model`, `/compact`, `/clear`, `/login` and `/plan`, `<local-command-stdout>`
125
+ * is that command's output, and `<local-command-caveat>` is the preamble in
126
+ * front of it. Treating any of them as a prompt would open a turn that the agent
127
+ * never answers, and the reply to the *next* real prompt would be filed under it.
119
128
  */
120
129
  const CLAUDE_SYNTHETIC_PROMPT_PREFIXES = [
121
130
  '<local-command-caveat>',
122
131
  '<local-command-stdout>',
123
132
  '<command-name>',
124
- '<command-message>',
125
133
  ];
134
+ /**
135
+ * The tag a slash command the operator typed opens with (Issue #2265).
136
+ *
137
+ * ## The two shapes, and why the leading tag is the discriminator
138
+ *
139
+ * Claude writes the same three tags for two quite different events, and it
140
+ * writes them in a different **order** for each. Measured over every
141
+ * `type: "user"` record under `~/.claude/projects` on 2026-09-03 whose text
142
+ * opens with one of the `<command-…>` tags — 222 records:
143
+ *
144
+ * | leading tag | count | `<command-name>` values |
145
+ * |---|---|---|
146
+ * | `<command-message>` | 118 | `/orchestrate`, `/release`, `/uat`, `/worktree-cleanup`, `/worktree-new`, `/multi-stage-design-review`, `/cmate-*` |
147
+ * | `<command-name>` | 104 | `/model`, `/compact`, `/clear`, `/login`, `/plan` |
148
+ *
149
+ * The split is exact and it is the split that matters here. The 118 are
150
+ * *project and user commands* — a `.claude/commands/*.md` or a skill, expanded
151
+ * into instructions the agent then works through, which is a turn with a reply
152
+ * in it. The 104 are commands Claude Code executes itself; their whole output is
153
+ * the `<local-command-stdout>` record that follows and the agent never answers
154
+ * them.
155
+ *
156
+ * Before #2265 both were excluded, on the reading that a slash command is not
157
+ * "the operator's text". That cost the 118 their entire turn: the reply was
158
+ * folded into whichever turn came before — already saved, so
159
+ * `selectUnwrittenClaudeTurns` answered "nothing to write", and the answer *this*
160
+ * reader gives is also what suppresses the scraper's copy. The measured loss was
161
+ * a `/release v0.30.1` turn of 7 text blocks and an `/orchestrate` turn of 8,
162
+ * neither of which reached History by any path at all.
163
+ *
164
+ * ## `origin`, and the versions that carry it
165
+ *
166
+ * The 118 also answer {@link isClaudeOperatorPromptRecord}, but only on recent
167
+ * Claude Code: of them, every record from 2.1.238 onwards (46) carries
168
+ * `origin: {"kind": "human"}` and every record before it (72, versions 2.1.220
169
+ * … 2.1.235) carries neither marker — those predate the field. On an old
170
+ * version the turn is still opened and its reply still written; only the `user`
171
+ * row is skipped, which is #2196's stated degradation and not a new one.
172
+ */
173
+ exports.CLAUDE_SLASH_COMMAND_PREFIX = '<command-message>';
174
+ /** `<command-name>/release</command-name>` — the command itself. */
175
+ const CLAUDE_COMMAND_NAME_PATTERN = /<command-name>([\s\S]*?)<\/command-name>/;
176
+ /** `<command-args>v0.30.1</command-args>` — absent on a bare invocation. */
177
+ const CLAUDE_COMMAND_ARGS_PATTERN = /<command-args>([\s\S]*?)<\/command-args>/;
178
+ /**
179
+ * The line the operator typed, rebuilt from a slash-command record (Issue #2265).
180
+ *
181
+ * `<command-name>` and `<command-args>` back into `/release v0.30.1`, which is
182
+ * the string that was in the composer and — for a command CommandMate sent — the
183
+ * string `sendUserMessage` already wrote to `chat_messages`. That equality is
184
+ * what makes the `/send` row *adoptable* instead of duplicated: `recordUserTurn`
185
+ * compares on normalised content, and the raw record text
186
+ * (`<command-message>release</command-message>\n<command-name>…`) matches nothing
187
+ * a person ever sent.
188
+ *
189
+ * Returns null for anything that is not this shape, including a
190
+ * `<command-message>` record with no `<command-name>` in it. Null is what keeps
191
+ * {@link isClaudePromptRecord} from opening a turn it could not name: a record
192
+ * whose command cannot be read would otherwise reach History as its own XML,
193
+ * which is exactly the class of mistake #2196's positive-evidence rule exists to
194
+ * avoid. No such record was observed — all 118 carried both tags.
195
+ *
196
+ * @param text - The record's text, as {@link ClaudeTranscriptRecord.text} holds it
197
+ * @returns `/name args`, `/name` when there are no arguments, or null
198
+ */
199
+ function claudeSlashCommandPrompt(text) {
200
+ const trimmed = text.trim();
201
+ if (!trimmed.startsWith(exports.CLAUDE_SLASH_COMMAND_PREFIX))
202
+ return null;
203
+ const name = CLAUDE_COMMAND_NAME_PATTERN.exec(trimmed)?.[1].trim() ?? '';
204
+ if (name.length === 0)
205
+ return null;
206
+ // Absent on a bare invocation, and empty on a command invoked with no
207
+ // arguments; both mean the prompt is the command name on its own.
208
+ const args = CLAUDE_COMMAND_ARGS_PATTERN.exec(trimmed)?.[1].trim() ?? '';
209
+ return args.length === 0 ? name : `${name} ${args}`;
210
+ }
126
211
  /**
127
212
  * Read one `message.content` element.
128
213
  *
@@ -235,6 +320,7 @@ function readClaudeTranscriptRecord(value) {
235
320
  isCompactSummary: value.isCompactSummary === true,
236
321
  isInterruption: (0, event_mapper_1.readStringField)(value, 'interruptedMessageId') !== null,
237
322
  timestampMs: Number.isFinite(parsed) ? parsed : null,
323
+ stopReason: message ? (0, event_mapper_1.readStringField)(message, 'stop_reason') : null,
238
324
  blocks,
239
325
  text,
240
326
  };
@@ -279,11 +365,19 @@ function parseClaudeTranscript(text) {
279
365
  *
280
366
  * - it carries a `tool_result` block — 18 of the 19 user records in the sampled
281
367
  * session were these;
282
- * - `isMeta` is true — the image placeholders and the local-command caveat;
283
- * - its text opens with one of {@link CLAUDE_SYNTHETIC_PROMPT_PREFIXES} the
284
- * slash-command bookkeeping;
368
+ * - `isMeta` is true — the image placeholders, the local-command caveat, and
369
+ * the body of the `.claude/commands/*.md` or skill a slash command expands
370
+ * to, which arrives on its own record right behind the one below;
371
+ * - its text opens with one of {@link CLAUDE_SYNTHETIC_PROMPT_PREFIXES} — a
372
+ * built-in command and its output;
285
373
  * - it has no text at all, or no `uuid` to name the turn with.
286
374
  *
375
+ * A record opening with {@link CLAUDE_SLASH_COMMAND_PREFIX} is the fifth case
376
+ * and the one Issue #2265 changed: it **is** a prompt, because the operator
377
+ * typed `/release v0.30.1` and the agent answers it at length. It qualifies only
378
+ * when {@link claudeSlashCommandPrompt} can actually read the command out of it,
379
+ * so a shape this reader could not name never opens a turn.
380
+ *
287
381
  * Everything else is treated as a prompt, including `[Request interrupted by
288
382
  * user]`. That is deliberate: an interruption really does end the turn, and the
289
383
  * records after it really do belong to whatever came next.
@@ -300,6 +394,8 @@ function isClaudePromptRecord(record) {
300
394
  const text = record.text.trim();
301
395
  if (text.length === 0)
302
396
  return false;
397
+ if (text.startsWith(exports.CLAUDE_SLASH_COMMAND_PREFIX))
398
+ return claudeSlashCommandPrompt(text) !== null;
303
399
  return !CLAUDE_SYNTHETIC_PROMPT_PREFIXES.some((prefix) => text.startsWith(prefix));
304
400
  }
305
401
  /**
@@ -345,6 +441,14 @@ exports.CLAUDE_HUMAN_PROMPT_SOURCES = ['typed', 'queued'];
345
441
  * is the pre-#2196 behaviour — an orphaned assistant pair, which is untidy, and
346
442
  * not a fabricated user message, which is wrong.
347
443
  *
444
+ * Issue #2265 widened what reaches here by one shape — the project-command
445
+ * record `isClaudePromptRecord` now accepts — and the rule holds on it without
446
+ * change: of the 118 such records under `~/.claude/projects` on 2026-09-03, the
447
+ * 46 written by Claude Code 2.1.238 and later carry `origin: {"kind": "human"}`
448
+ * and answer true, and the 72 written before the field existed carry no marker
449
+ * and answer false. The second group loses its `user` row and keeps its reply,
450
+ * which is this function's designed degradation rather than a new gap.
451
+ *
348
452
  * `isCompactSummary` and `isInterruption` are then checked explicitly even
349
453
  * though nothing observed carries a human marker *and* either flag. They are not
350
454
  * redundant by construction: compaction and interruption are both things the
@@ -362,16 +466,62 @@ function isClaudeOperatorPromptRecord(record) {
362
466
  return record.originKind === exports.CLAUDE_HUMAN_ORIGIN_KIND;
363
467
  return record.promptSource !== null && exports.CLAUDE_HUMAN_PROMPT_SOURCES.includes(record.promptSource);
364
468
  }
469
+ /**
470
+ * `message.stop_reason` on the record that ends a reply (Issue #2264).
471
+ *
472
+ * The other value this reader cares about is `tool_use`, which is not named as
473
+ * a constant because nothing branches on it: everything that is not `end_turn`
474
+ * leaves the turn open.
475
+ */
476
+ exports.CLAUDE_END_TURN_STOP_REASON = 'end_turn';
477
+ /**
478
+ * Whether this assistant record is the one that ended the reply (Issue #2264).
479
+ *
480
+ * `end_turn` **and** prose on the same record. See
481
+ * {@link ClaudeTurnAccumulator.closed} for why neither half alone is the rule,
482
+ * and note that the emptiness test here is the one `renderClaudeTurn` applies to
483
+ * a text block — a block whose `text` trims to nothing is not rendered, so it
484
+ * cannot be what makes a turn look finished either.
485
+ */
486
+ function isClaudeTurnClosingRecord(record) {
487
+ if (record.type !== 'assistant')
488
+ return false;
489
+ if (record.stopReason !== exports.CLAUDE_END_TURN_STOP_REASON)
490
+ return false;
491
+ return record.blocks.some((block) => block.type === 'text' && (block.text ?? '').trim().length > 0);
492
+ }
493
+ /**
494
+ * Whether a writer may record this turn (Issue #2264).
495
+ *
496
+ * Either proof that nothing more is coming: the agent said so
497
+ * ({@link ClaudeTurnAccumulator.closed}), or it has moved on to another prompt
498
+ * ({@link ClaudeTurnAccumulator.superseded}).
499
+ */
500
+ function isClaudeTurnWritable(turn) {
501
+ if (turn.closed || turn.superseded)
502
+ return true;
503
+ // No record of this turn said why it stopped, so there is no evidence to
504
+ // refuse it on. See {@link ClaudeTurnAccumulator.stopReasonObserved}: this is
505
+ // unreachable against every Claude version measured, and it is what keeps a
506
+ // version that stops writing the field from silently disabling the reader.
507
+ return !turn.stopReasonObserved;
508
+ }
365
509
  /** A brand-new accumulator for one turn. */
366
510
  function createClaudeTurn(record, sessionId) {
367
511
  return {
368
512
  sessionId: record.sessionId ?? sessionId,
369
513
  promptUuid: record.uuid,
370
514
  startedAt: record.timestampMs ?? 0,
371
- promptText: record.text,
515
+ // A slash command's record is XML and the operator typed a line; #2265 puts
516
+ // the line on the turn so that the `user` row reads `/release v0.30.1` and
517
+ // the `/send` row holding those same bytes is adopted rather than doubled.
518
+ promptText: claudeSlashCommandPrompt(record.text) ?? record.text,
372
519
  promptIsOperatorInput: isClaudeOperatorPromptRecord(record),
373
520
  blocks: [],
374
521
  assistantRecords: 0,
522
+ closed: false,
523
+ superseded: false,
524
+ stopReasonObserved: false,
375
525
  overflowed: false,
376
526
  };
377
527
  }
@@ -416,6 +566,13 @@ function buildClaudeTurns(records, sessionId) {
416
566
  continue;
417
567
  }
418
568
  current.assistantRecords += 1;
569
+ // Assigned rather than or-ed, so the value left standing is the *last*
570
+ // assistant record's answer. A turn that ends on a `tool_use` record after
571
+ // an earlier `end_turn` — which is what a turn Claude resumed looks like —
572
+ // is open again, and that is the reading the Issue's census supports.
573
+ current.closed = isClaudeTurnClosingRecord(record);
574
+ if (record.stopReason !== null)
575
+ current.stopReasonObserved = true;
419
576
  for (const block of record.blocks) {
420
577
  if (current.blocks.length >= exports.MAX_CLAUDE_TURN_BLOCKS) {
421
578
  current.overflowed = true;
@@ -424,6 +581,11 @@ function buildClaudeTurns(records, sessionId) {
424
581
  current.blocks.push(block);
425
582
  }
426
583
  }
584
+ // Every turn but the last one has a later prompt behind it, and a prompt is
585
+ // proof the agent moved on. See {@link ClaudeTurnAccumulator.superseded}.
586
+ for (let index = 0; index < turns.length - 1; index += 1) {
587
+ turns[index].superseded = true;
588
+ }
427
589
  return { turns, orphanedAssistantRecords, sidechainRecords };
428
590
  }
429
591
  /**