commandmate 0.10.2 → 0.10.4

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 (383) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-build-manifest.json +149 -149
  3. package/.next/app-path-routes-manifest.json +30 -30
  4. package/.next/build-manifest.json +2 -2
  5. package/.next/prerender-manifest.json +15 -15
  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/app/update/route.js +3 -3
  9. package/.next/server/app/api/app/update/route_client-reference-manifest.js +1 -1
  10. package/.next/server/app/api/app/update-check/route.js +1 -1
  11. package/.next/server/app/api/app/update-check/route_client-reference-manifest.js +1 -1
  12. package/.next/server/app/api/assistant/conversation/route.js +1 -1
  13. package/.next/server/app/api/assistant/conversation/route.js.nft.json +1 -1
  14. package/.next/server/app/api/assistant/conversation/route_client-reference-manifest.js +1 -1
  15. package/.next/server/app/api/assistant/current-output/route.js +1 -1
  16. package/.next/server/app/api/assistant/current-output/route.js.nft.json +1 -1
  17. package/.next/server/app/api/assistant/current-output/route_client-reference-manifest.js +1 -1
  18. package/.next/server/app/api/assistant/messages/route.js +1 -1
  19. package/.next/server/app/api/assistant/messages/route.js.nft.json +1 -1
  20. package/.next/server/app/api/assistant/messages/route_client-reference-manifest.js +1 -1
  21. package/.next/server/app/api/assistant/session/route.js +1 -1
  22. package/.next/server/app/api/assistant/session/route.js.nft.json +1 -1
  23. package/.next/server/app/api/assistant/session/route_client-reference-manifest.js +1 -1
  24. package/.next/server/app/api/assistant/start/route.js +1 -1
  25. package/.next/server/app/api/assistant/start/route.js.nft.json +1 -1
  26. package/.next/server/app/api/assistant/start/route_client-reference-manifest.js +1 -1
  27. package/.next/server/app/api/assistant/terminal/route.js +3 -2
  28. package/.next/server/app/api/assistant/terminal/route.js.nft.json +1 -1
  29. package/.next/server/app/api/assistant/terminal/route_client-reference-manifest.js +1 -1
  30. package/.next/server/app/api/assistant/tools/route.js +1 -1
  31. package/.next/server/app/api/assistant/tools/route.js.nft.json +1 -1
  32. package/.next/server/app/api/assistant/tools/route_client-reference-manifest.js +1 -1
  33. package/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
  34. package/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
  35. package/.next/server/app/api/auth/status/route_client-reference-manifest.js +1 -1
  36. package/.next/server/app/api/daily-summary/route.js +1 -1
  37. package/.next/server/app/api/daily-summary/route.js.nft.json +1 -1
  38. package/.next/server/app/api/daily-summary/route_client-reference-manifest.js +1 -1
  39. package/.next/server/app/api/daily-summary/status/route.js +1 -1
  40. package/.next/server/app/api/daily-summary/status/route.js.nft.json +1 -1
  41. package/.next/server/app/api/daily-summary/status/route_client-reference-manifest.js +1 -1
  42. package/.next/server/app/api/external-apps/[id]/health/route_client-reference-manifest.js +1 -1
  43. package/.next/server/app/api/external-apps/[id]/route_client-reference-manifest.js +1 -1
  44. package/.next/server/app/api/external-apps/route_client-reference-manifest.js +1 -1
  45. package/.next/server/app/api/hooks/claude-done/route.js +1 -1
  46. package/.next/server/app/api/hooks/claude-done/route.js.nft.json +1 -1
  47. package/.next/server/app/api/hooks/claude-done/route_client-reference-manifest.js +1 -1
  48. package/.next/server/app/api/ollama/models/route_client-reference-manifest.js +1 -1
  49. package/.next/server/app/api/push/subscriptions/route.js +1 -1
  50. package/.next/server/app/api/push/subscriptions/route.js.nft.json +1 -1
  51. package/.next/server/app/api/push/subscriptions/route_client-reference-manifest.js +1 -1
  52. package/.next/server/app/api/push/vapid/route_client-reference-manifest.js +1 -1
  53. package/.next/server/app/api/repositories/[id]/route.js +1 -47
  54. package/.next/server/app/api/repositories/[id]/route.js.nft.json +1 -1
  55. package/.next/server/app/api/repositories/[id]/route_client-reference-manifest.js +1 -1
  56. package/.next/server/app/api/repositories/[id]/todos/[todoId]/route.js +1 -1
  57. package/.next/server/app/api/repositories/[id]/todos/[todoId]/route.js.nft.json +1 -1
  58. package/.next/server/app/api/repositories/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
  59. package/.next/server/app/api/repositories/[id]/todos/route.js +1 -1
  60. package/.next/server/app/api/repositories/[id]/todos/route.js.nft.json +1 -1
  61. package/.next/server/app/api/repositories/[id]/todos/route_client-reference-manifest.js +1 -1
  62. package/.next/server/app/api/repositories/clone/[jobId]/route.js +1 -1
  63. package/.next/server/app/api/repositories/clone/[jobId]/route.js.nft.json +1 -1
  64. package/.next/server/app/api/repositories/clone/[jobId]/route_client-reference-manifest.js +1 -1
  65. package/.next/server/app/api/repositories/clone/route.js +1 -1
  66. package/.next/server/app/api/repositories/clone/route.js.nft.json +1 -1
  67. package/.next/server/app/api/repositories/clone/route_client-reference-manifest.js +1 -1
  68. package/.next/server/app/api/repositories/excluded/route.js +1 -47
  69. package/.next/server/app/api/repositories/excluded/route.js.nft.json +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/sidebar/group-order/route_client-reference-manifest.js +1 -1
  84. package/.next/server/app/api/slash-commands/route_client-reference-manifest.js +1 -1
  85. package/.next/server/app/api/templates/[id]/route_client-reference-manifest.js +1 -1
  86. package/.next/server/app/api/templates/route_client-reference-manifest.js +1 -1
  87. package/.next/server/app/api/todos/route.js +1 -1
  88. package/.next/server/app/api/todos/route.js.nft.json +1 -1
  89. package/.next/server/app/api/todos/route_client-reference-manifest.js +1 -1
  90. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js +1 -1
  91. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js.nft.json +1 -1
  92. package/.next/server/app/api/worktrees/[id]/auto-yes/route_client-reference-manifest.js +1 -1
  93. package/.next/server/app/api/worktrees/[id]/capture/route.js +1 -1
  94. package/.next/server/app/api/worktrees/[id]/capture/route.js.nft.json +1 -1
  95. package/.next/server/app/api/worktrees/[id]/capture/route_client-reference-manifest.js +1 -1
  96. package/.next/server/app/api/worktrees/[id]/cli-tool/route.js +1 -1
  97. package/.next/server/app/api/worktrees/[id]/cli-tool/route.js.nft.json +1 -1
  98. package/.next/server/app/api/worktrees/[id]/cli-tool/route_client-reference-manifest.js +1 -1
  99. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route.js +1 -1
  100. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route.js.nft.json +1 -1
  101. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route_client-reference-manifest.js +1 -1
  102. package/.next/server/app/api/worktrees/[id]/current-output/route.js +1 -1
  103. package/.next/server/app/api/worktrees/[id]/current-output/route.js.nft.json +1 -1
  104. package/.next/server/app/api/worktrees/[id]/current-output/route_client-reference-manifest.js +1 -1
  105. package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route.js +1 -1
  106. package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route.js.nft.json +1 -1
  107. package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route_client-reference-manifest.js +1 -1
  108. package/.next/server/app/api/worktrees/[id]/execution-logs/route.js +2 -2
  109. package/.next/server/app/api/worktrees/[id]/execution-logs/route.js.nft.json +1 -1
  110. package/.next/server/app/api/worktrees/[id]/execution-logs/route_client-reference-manifest.js +1 -1
  111. package/.next/server/app/api/worktrees/[id]/files/[...path]/route.js +1 -1
  112. package/.next/server/app/api/worktrees/[id]/files/[...path]/route.js.nft.json +1 -1
  113. package/.next/server/app/api/worktrees/[id]/files/[...path]/route_client-reference-manifest.js +1 -1
  114. package/.next/server/app/api/worktrees/[id]/git/branch/create/route.js +1 -1
  115. package/.next/server/app/api/worktrees/[id]/git/branch/create/route.js.nft.json +1 -1
  116. package/.next/server/app/api/worktrees/[id]/git/branch/create/route_client-reference-manifest.js +1 -1
  117. package/.next/server/app/api/worktrees/[id]/git/branch/delete/route.js +1 -1
  118. package/.next/server/app/api/worktrees/[id]/git/branch/delete/route.js.nft.json +1 -1
  119. package/.next/server/app/api/worktrees/[id]/git/branch/delete/route_client-reference-manifest.js +1 -1
  120. package/.next/server/app/api/worktrees/[id]/git/branches/route.js +1 -1
  121. package/.next/server/app/api/worktrees/[id]/git/branches/route.js.nft.json +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.js.nft.json +1 -1
  125. package/.next/server/app/api/worktrees/[id]/git/checkout/route_client-reference-manifest.js +1 -1
  126. package/.next/server/app/api/worktrees/[id]/git/commit/route.js +1 -1
  127. package/.next/server/app/api/worktrees/[id]/git/commit/route.js.nft.json +1 -1
  128. package/.next/server/app/api/worktrees/[id]/git/commit/route_client-reference-manifest.js +1 -1
  129. package/.next/server/app/api/worktrees/[id]/git/diff/route.js +1 -1
  130. package/.next/server/app/api/worktrees/[id]/git/diff/route.js.nft.json +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.js +1 -1
  133. package/.next/server/app/api/worktrees/[id]/git/fetch/route.js.nft.json +1 -1
  134. package/.next/server/app/api/worktrees/[id]/git/fetch/route_client-reference-manifest.js +1 -1
  135. package/.next/server/app/api/worktrees/[id]/git/log/route.js +1 -1
  136. package/.next/server/app/api/worktrees/[id]/git/log/route.js.nft.json +1 -1
  137. package/.next/server/app/api/worktrees/[id]/git/log/route_client-reference-manifest.js +1 -1
  138. package/.next/server/app/api/worktrees/[id]/git/pull/route.js +1 -1
  139. package/.next/server/app/api/worktrees/[id]/git/pull/route.js.nft.json +1 -1
  140. package/.next/server/app/api/worktrees/[id]/git/pull/route_client-reference-manifest.js +1 -1
  141. package/.next/server/app/api/worktrees/[id]/git/push/route.js +1 -1
  142. package/.next/server/app/api/worktrees/[id]/git/push/route.js.nft.json +1 -1
  143. package/.next/server/app/api/worktrees/[id]/git/push/route_client-reference-manifest.js +1 -1
  144. package/.next/server/app/api/worktrees/[id]/git/reset/route.js +1 -1
  145. package/.next/server/app/api/worktrees/[id]/git/reset/route.js.nft.json +1 -1
  146. package/.next/server/app/api/worktrees/[id]/git/reset/route_client-reference-manifest.js +1 -1
  147. package/.next/server/app/api/worktrees/[id]/git/revert/route.js +1 -1
  148. package/.next/server/app/api/worktrees/[id]/git/revert/route.js.nft.json +1 -1
  149. package/.next/server/app/api/worktrees/[id]/git/revert/route_client-reference-manifest.js +1 -1
  150. package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route.js +1 -1
  151. package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route.js.nft.json +1 -1
  152. package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route_client-reference-manifest.js +1 -1
  153. package/.next/server/app/api/worktrees/[id]/git/stage/route.js +1 -1
  154. package/.next/server/app/api/worktrees/[id]/git/stage/route.js.nft.json +1 -1
  155. package/.next/server/app/api/worktrees/[id]/git/stage/route_client-reference-manifest.js +1 -1
  156. package/.next/server/app/api/worktrees/[id]/git/staged/route.js +1 -1
  157. package/.next/server/app/api/worktrees/[id]/git/staged/route.js.nft.json +1 -1
  158. package/.next/server/app/api/worktrees/[id]/git/staged/route_client-reference-manifest.js +1 -1
  159. package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route.js +1 -1
  160. package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route.js.nft.json +1 -1
  161. package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route_client-reference-manifest.js +1 -1
  162. package/.next/server/app/api/worktrees/[id]/git/stash/apply/route.js +1 -1
  163. package/.next/server/app/api/worktrees/[id]/git/stash/apply/route.js.nft.json +1 -1
  164. package/.next/server/app/api/worktrees/[id]/git/stash/apply/route_client-reference-manifest.js +1 -1
  165. package/.next/server/app/api/worktrees/[id]/git/stash/pop/route.js +1 -1
  166. package/.next/server/app/api/worktrees/[id]/git/stash/pop/route.js.nft.json +1 -1
  167. package/.next/server/app/api/worktrees/[id]/git/stash/pop/route_client-reference-manifest.js +1 -1
  168. package/.next/server/app/api/worktrees/[id]/git/stash/push/route.js +1 -1
  169. package/.next/server/app/api/worktrees/[id]/git/stash/push/route.js.nft.json +1 -1
  170. package/.next/server/app/api/worktrees/[id]/git/stash/push/route_client-reference-manifest.js +1 -1
  171. package/.next/server/app/api/worktrees/[id]/git/stash/route.js +1 -1
  172. package/.next/server/app/api/worktrees/[id]/git/stash/route.js.nft.json +1 -1
  173. package/.next/server/app/api/worktrees/[id]/git/stash/route_client-reference-manifest.js +1 -1
  174. package/.next/server/app/api/worktrees/[id]/git/status/route.js +1 -1
  175. package/.next/server/app/api/worktrees/[id]/git/status/route.js.nft.json +1 -1
  176. package/.next/server/app/api/worktrees/[id]/git/status/route_client-reference-manifest.js +1 -1
  177. package/.next/server/app/api/worktrees/[id]/git/unstage/route.js +1 -1
  178. package/.next/server/app/api/worktrees/[id]/git/unstage/route.js.nft.json +1 -1
  179. package/.next/server/app/api/worktrees/[id]/git/unstage/route_client-reference-manifest.js +1 -1
  180. package/.next/server/app/api/worktrees/[id]/git/working-diff/route.js +1 -1
  181. package/.next/server/app/api/worktrees/[id]/git/working-diff/route.js.nft.json +1 -1
  182. package/.next/server/app/api/worktrees/[id]/git/working-diff/route_client-reference-manifest.js +1 -1
  183. package/.next/server/app/api/worktrees/[id]/interrupt/route.js +1 -1
  184. package/.next/server/app/api/worktrees/[id]/interrupt/route.js.nft.json +1 -1
  185. package/.next/server/app/api/worktrees/[id]/interrupt/route_client-reference-manifest.js +1 -1
  186. package/.next/server/app/api/worktrees/[id]/kill-session/route.js +1 -1
  187. package/.next/server/app/api/worktrees/[id]/kill-session/route.js.nft.json +1 -1
  188. package/.next/server/app/api/worktrees/[id]/kill-session/route_client-reference-manifest.js +1 -1
  189. package/.next/server/app/api/worktrees/[id]/logs/[filename]/route.js +1 -1
  190. package/.next/server/app/api/worktrees/[id]/logs/[filename]/route.js.nft.json +1 -1
  191. package/.next/server/app/api/worktrees/[id]/logs/[filename]/route_client-reference-manifest.js +1 -1
  192. package/.next/server/app/api/worktrees/[id]/logs/route.js +1 -1
  193. package/.next/server/app/api/worktrees/[id]/logs/route.js.nft.json +1 -1
  194. package/.next/server/app/api/worktrees/[id]/logs/route_client-reference-manifest.js +1 -1
  195. package/.next/server/app/api/worktrees/[id]/marp-render/route.js +2 -2
  196. package/.next/server/app/api/worktrees/[id]/marp-render/route.js.nft.json +1 -1
  197. package/.next/server/app/api/worktrees/[id]/marp-render/route_client-reference-manifest.js +1 -1
  198. package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route.js +1 -1
  199. package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route.js.nft.json +1 -1
  200. package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route_client-reference-manifest.js +1 -1
  201. package/.next/server/app/api/worktrees/[id]/memos/route.js +1 -1
  202. package/.next/server/app/api/worktrees/[id]/memos/route.js.nft.json +1 -1
  203. package/.next/server/app/api/worktrees/[id]/memos/route_client-reference-manifest.js +1 -1
  204. package/.next/server/app/api/worktrees/[id]/messages/route.js +1 -1
  205. package/.next/server/app/api/worktrees/[id]/messages/route.js.nft.json +1 -1
  206. package/.next/server/app/api/worktrees/[id]/messages/route_client-reference-manifest.js +1 -1
  207. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js +1 -1
  208. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js.nft.json +1 -1
  209. package/.next/server/app/api/worktrees/[id]/prompt-response/route_client-reference-manifest.js +1 -1
  210. package/.next/server/app/api/worktrees/[id]/respond/route.js +1 -1
  211. package/.next/server/app/api/worktrees/[id]/respond/route.js.nft.json +1 -1
  212. package/.next/server/app/api/worktrees/[id]/respond/route_client-reference-manifest.js +1 -1
  213. package/.next/server/app/api/worktrees/[id]/route.js +1 -1
  214. package/.next/server/app/api/worktrees/[id]/route.js.nft.json +1 -1
  215. package/.next/server/app/api/worktrees/[id]/route_client-reference-manifest.js +1 -1
  216. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route.js +1 -1
  217. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route.js.nft.json +1 -1
  218. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route_client-reference-manifest.js +1 -1
  219. package/.next/server/app/api/worktrees/[id]/schedules/active/route.js +1 -1
  220. package/.next/server/app/api/worktrees/[id]/schedules/active/route.js.nft.json +1 -1
  221. package/.next/server/app/api/worktrees/[id]/schedules/active/route_client-reference-manifest.js +1 -1
  222. package/.next/server/app/api/worktrees/[id]/schedules/route.js +2 -2
  223. package/.next/server/app/api/worktrees/[id]/schedules/route.js.nft.json +1 -1
  224. package/.next/server/app/api/worktrees/[id]/schedules/route_client-reference-manifest.js +1 -1
  225. package/.next/server/app/api/worktrees/[id]/search/route.js +1 -1
  226. package/.next/server/app/api/worktrees/[id]/search/route.js.nft.json +1 -1
  227. package/.next/server/app/api/worktrees/[id]/search/route_client-reference-manifest.js +1 -1
  228. package/.next/server/app/api/worktrees/[id]/send/route.js +1 -1
  229. package/.next/server/app/api/worktrees/[id]/send/route.js.nft.json +1 -1
  230. package/.next/server/app/api/worktrees/[id]/send/route_client-reference-manifest.js +1 -1
  231. package/.next/server/app/api/worktrees/[id]/slash-commands/route.js +1 -1
  232. package/.next/server/app/api/worktrees/[id]/slash-commands/route.js.nft.json +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]/start-polling/route.js +1 -1
  238. package/.next/server/app/api/worktrees/[id]/start-polling/route.js.nft.json +1 -1
  239. package/.next/server/app/api/worktrees/[id]/start-polling/route_client-reference-manifest.js +1 -1
  240. package/.next/server/app/api/worktrees/[id]/terminal/route.js +1 -1
  241. package/.next/server/app/api/worktrees/[id]/terminal/route.js.nft.json +1 -1
  242. package/.next/server/app/api/worktrees/[id]/terminal/route_client-reference-manifest.js +1 -1
  243. package/.next/server/app/api/worktrees/[id]/timers/history/route.js +1 -1
  244. package/.next/server/app/api/worktrees/[id]/timers/history/route.js.nft.json +1 -1
  245. package/.next/server/app/api/worktrees/[id]/timers/history/route_client-reference-manifest.js +1 -1
  246. package/.next/server/app/api/worktrees/[id]/timers/route.js +1 -1
  247. package/.next/server/app/api/worktrees/[id]/timers/route.js.nft.json +1 -1
  248. package/.next/server/app/api/worktrees/[id]/timers/route_client-reference-manifest.js +1 -1
  249. package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route.js +1 -1
  250. package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route.js.nft.json +1 -1
  251. package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
  252. package/.next/server/app/api/worktrees/[id]/todos/route.js +1 -1
  253. package/.next/server/app/api/worktrees/[id]/todos/route.js.nft.json +1 -1
  254. package/.next/server/app/api/worktrees/[id]/todos/route_client-reference-manifest.js +1 -1
  255. package/.next/server/app/api/worktrees/[id]/tree/[...path]/route.js +1 -1
  256. package/.next/server/app/api/worktrees/[id]/tree/[...path]/route.js.nft.json +1 -1
  257. package/.next/server/app/api/worktrees/[id]/tree/[...path]/route_client-reference-manifest.js +1 -1
  258. package/.next/server/app/api/worktrees/[id]/tree/route.js +1 -1
  259. package/.next/server/app/api/worktrees/[id]/tree/route.js.nft.json +1 -1
  260. package/.next/server/app/api/worktrees/[id]/tree/route_client-reference-manifest.js +1 -1
  261. package/.next/server/app/api/worktrees/[id]/upload/[...path]/route.js +1 -1
  262. package/.next/server/app/api/worktrees/[id]/upload/[...path]/route.js.nft.json +1 -1
  263. package/.next/server/app/api/worktrees/[id]/upload/[...path]/route_client-reference-manifest.js +1 -1
  264. package/.next/server/app/api/worktrees/[id]/viewed/route.js +1 -1
  265. package/.next/server/app/api/worktrees/[id]/viewed/route.js.nft.json +1 -1
  266. package/.next/server/app/api/worktrees/[id]/viewed/route_client-reference-manifest.js +1 -1
  267. package/.next/server/app/api/worktrees/route.js +1 -1
  268. package/.next/server/app/api/worktrees/route.js.nft.json +1 -1
  269. package/.next/server/app/api/worktrees/route_client-reference-manifest.js +1 -1
  270. package/.next/server/app/chat/page.js +1 -1
  271. package/.next/server/app/chat/page.js.nft.json +1 -1
  272. package/.next/server/app/chat/page_client-reference-manifest.js +1 -1
  273. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  274. package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
  275. package/.next/server/app/more/page.js +2 -2
  276. package/.next/server/app/more/page.js.nft.json +1 -1
  277. package/.next/server/app/more/page_client-reference-manifest.js +1 -1
  278. package/.next/server/app/offline/page_client-reference-manifest.js +1 -1
  279. package/.next/server/app/page.js +1 -1
  280. package/.next/server/app/page.js.nft.json +1 -1
  281. package/.next/server/app/page_client-reference-manifest.js +1 -1
  282. package/.next/server/app/proxy/[...path]/route_client-reference-manifest.js +1 -1
  283. package/.next/server/app/repositories/page.js +1 -1
  284. package/.next/server/app/repositories/page.js.nft.json +1 -1
  285. package/.next/server/app/repositories/page_client-reference-manifest.js +1 -1
  286. package/.next/server/app/review/page.js +1 -1
  287. package/.next/server/app/review/page.js.nft.json +1 -1
  288. package/.next/server/app/review/page_client-reference-manifest.js +1 -1
  289. package/.next/server/app/sessions/page.js +1 -1
  290. package/.next/server/app/sessions/page.js.nft.json +1 -1
  291. package/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  292. package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -1
  293. package/.next/server/app/worktrees/[id]/page.js +8 -8
  294. package/.next/server/app/worktrees/[id]/page.js.nft.json +1 -1
  295. package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -1
  296. package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
  297. package/.next/server/app-paths-manifest.json +30 -30
  298. package/.next/server/chunks/1068.js +1 -1
  299. package/.next/server/chunks/1117.js +1 -0
  300. package/.next/server/chunks/233.js +1 -1
  301. package/.next/server/chunks/2404.js +1 -1
  302. package/.next/server/chunks/3270.js +1 -1
  303. package/.next/server/chunks/3480.js +2 -2
  304. package/.next/server/chunks/3543.js +1 -1
  305. package/.next/server/chunks/3945.js +1 -1
  306. package/.next/server/chunks/406.js +47 -0
  307. package/.next/server/chunks/4444.js +1 -1
  308. package/.next/server/chunks/5381.js +1 -47
  309. package/.next/server/chunks/5959.js +2 -2
  310. package/.next/server/chunks/646.js +33 -0
  311. package/.next/server/chunks/8681.js +1 -0
  312. package/.next/server/chunks/8807.js +305 -300
  313. package/.next/server/chunks/9355.js +1 -1
  314. package/.next/server/chunks/9687.js +1 -1
  315. package/.next/server/middleware-manifest.json +5 -5
  316. package/.next/server/pages/500.html +1 -1
  317. package/.next/server/pages-manifest.json +1 -1
  318. package/.next/server/server-reference-manifest.json +1 -1
  319. package/.next/static/chunks/4560-2bf9cb6504cc4425.js +1 -0
  320. package/.next/static/chunks/7347-a013a163a75030ec.js +1 -0
  321. package/.next/static/chunks/app/chat/page-5d20240f98c07cee.js +1 -0
  322. package/.next/static/chunks/app/layout-fe5857360dfba2b9.js +1 -0
  323. package/.next/static/chunks/app/more/page-af1d2af13ea901d2.js +1 -0
  324. package/.next/static/chunks/app/page-3bbe737ec910d1fb.js +1 -0
  325. package/.next/static/chunks/app/repositories/page-ace9134ac165a6de.js +1 -0
  326. package/.next/static/chunks/app/review/page-331b80f4f58582bc.js +1 -0
  327. package/.next/static/chunks/app/sessions/page-d694149a7e8649b6.js +1 -0
  328. package/.next/static/chunks/app/worktrees/[id]/page-932a52f8d11971f7.js +1 -0
  329. package/.next/static/css/d7e2e8d1b8d69d36.css +1 -0
  330. package/.next/trace +10 -10
  331. package/dist/cli/commands/quickstart.d.ts.map +1 -1
  332. package/dist/cli/commands/quickstart.js +27 -0
  333. package/dist/cli/commands/status.d.ts.map +1 -1
  334. package/dist/cli/commands/status.js +19 -0
  335. package/dist/cli/types/index.d.ts +6 -0
  336. package/dist/cli/types/index.d.ts.map +1 -1
  337. package/dist/cli/utils/agent-instances.d.ts +1 -1
  338. package/dist/cli/utils/agent-instances.d.ts.map +1 -1
  339. package/dist/cli/utils/agent-instances.js +8 -1
  340. package/dist/cli/utils/api-client.d.ts +36 -0
  341. package/dist/cli/utils/api-client.d.ts.map +1 -1
  342. package/dist/cli/utils/api-client.js +82 -0
  343. package/dist/cli/utils/daemon.d.ts.map +1 -1
  344. package/dist/cli/utils/daemon.js +44 -9
  345. package/dist/cli/utils/package-info.d.ts +17 -0
  346. package/dist/cli/utils/package-info.d.ts.map +1 -0
  347. package/dist/cli/utils/package-info.js +31 -0
  348. package/dist/cli/utils/pid-manager.d.ts +65 -9
  349. package/dist/cli/utils/pid-manager.d.ts.map +1 -1
  350. package/dist/cli/utils/pid-manager.js +81 -21
  351. package/dist/cli/utils/process-inspector.d.ts +27 -0
  352. package/dist/cli/utils/process-inspector.d.ts.map +1 -0
  353. package/dist/cli/utils/process-inspector.js +37 -0
  354. package/dist/server/src/config/github-links.js +22 -0
  355. package/dist/server/src/lib/db/db-instance.js +22 -3
  356. package/dist/server/src/lib/db/db-repository.js +107 -19
  357. package/dist/server/src/lib/db/db.js +3 -2
  358. package/dist/server/src/lib/db/memo-db.js +32 -1
  359. package/dist/server/src/lib/db/migrations/index.js +2 -0
  360. package/dist/server/src/lib/db/migrations/runner.js +11 -1
  361. package/dist/server/src/lib/db/migrations/v43-remove-cm-root-dir-ghost-repository.js +126 -0
  362. package/dist/server/src/lib/git/worktrees.js +90 -0
  363. package/dist/server/src/lib/job-executor.js +8 -2
  364. package/dist/server/src/lib/realtime/types.js +76 -0
  365. package/dist/server/src/lib/schedule-manager.js +9 -1
  366. package/dist/server/src/lib/version-checker.js +297 -0
  367. package/dist/server/src/lib/ws-server.js +37 -0
  368. package/package.json +1 -1
  369. package/.next/server/chunks/2464.js +0 -33
  370. package/.next/server/chunks/6791.js +0 -47
  371. package/.next/static/chunks/7347-4a031aecf4664a6d.js +0 -1
  372. package/.next/static/chunks/8954-ce15ee4d0423f1b1.js +0 -1
  373. package/.next/static/chunks/app/chat/page-dee86bdf87516e40.js +0 -1
  374. package/.next/static/chunks/app/layout-d02f4691a4eff86b.js +0 -1
  375. package/.next/static/chunks/app/more/page-39ec8b5f27cf52e7.js +0 -1
  376. package/.next/static/chunks/app/page-ebf1db9826b4065d.js +0 -1
  377. package/.next/static/chunks/app/repositories/page-2be54cae5fcc1f7a.js +0 -1
  378. package/.next/static/chunks/app/review/page-ac4efe6857a0f3bf.js +0 -1
  379. package/.next/static/chunks/app/sessions/page-dc545a3d45374187.js +0 -1
  380. package/.next/static/chunks/app/worktrees/[id]/page-562c763045f66200.js +0 -1
  381. package/.next/static/css/eabd34bf2ab147a4.css +0 -1
  382. /package/.next/static/{SZPCFMNuIVbWNY8xv93Lf → uBCIYS1Hth7V4unroKqGu}/_buildManifest.js +0 -0
  383. /package/.next/static/{SZPCFMNuIVbWNY8xv93Lf → uBCIYS1Hth7V4unroKqGu}/_ssgManifest.js +0 -0
@@ -1,8 +1,10 @@
1
1
  "use strict";
2
2
  /**
3
- * PID File Manager
3
+ * PID / Daemon State File Manager
4
4
  * Issue #96: npm install CLI support
5
5
  * Issue #136: Phase 2 - Task 2.4 - Added factory functions for Issue number support
6
+ * Issue #1354/#1355/#1358: the file now records the daemon's version, effective settings, and
7
+ * a process-identity signature, not just the PID. See DaemonState.
6
8
  * SF-1: SRP - Separated from daemon.ts for single responsibility
7
9
  * MF-SEC-2: TOCTOU protection with O_EXCL atomic writes
8
10
  */
@@ -12,53 +14,80 @@ exports.createPidManager = createPidManager;
12
14
  exports.createIssuePidManager = createIssuePidManager;
13
15
  const fs_1 = require("fs");
14
16
  const resource_resolvers_1 = require("./resource-resolvers");
17
+ const process_inspector_1 = require("./process-inspector");
15
18
  /**
16
19
  * PID file manager for daemon process tracking
17
20
  */
18
21
  class PidManager {
19
22
  pidFilePath;
20
- constructor(pidFilePath) {
23
+ readStartTime;
24
+ /**
25
+ * @param pidFilePath - Path to the state file for this server
26
+ * @param readStartTime - Injectable process-identity reader (Issue #1358); defaults to `ps`.
27
+ * Overridden in tests to avoid spawning a real process.
28
+ */
29
+ constructor(pidFilePath, readStartTime = process_inspector_1.getProcessStartTime) {
21
30
  this.pidFilePath = pidFilePath;
31
+ this.readStartTime = readStartTime;
22
32
  }
23
33
  /**
24
- * Check if PID file exists
34
+ * Check if the state file exists
25
35
  */
26
36
  exists() {
27
37
  return (0, fs_1.existsSync)(this.pidFilePath);
28
38
  }
29
39
  /**
30
- * Read PID from file
31
- * @returns PID number or null if file doesn't exist or is invalid
40
+ * Read the daemon state from file.
41
+ *
42
+ * Tolerates the legacy format (a bare integer PID) by returning `{ pid }`, so a state file
43
+ * written by an older running daemon is still understood after a CLI upgrade (Issue #1354).
44
+ *
45
+ * @returns The daemon state, or null when the file is missing or invalid
32
46
  */
33
- readPid() {
47
+ readState() {
34
48
  if (!this.exists()) {
35
49
  return null;
36
50
  }
37
51
  try {
38
52
  const content = (0, fs_1.readFileSync)(this.pidFilePath, 'utf-8').trim();
39
- const pid = parseInt(content, 10);
40
- if (isNaN(pid) || pid <= 0) {
53
+ if (content.length === 0) {
41
54
  return null;
42
55
  }
43
- return pid;
56
+ // Legacy format: the file held only the PID as a bare integer.
57
+ if (/^\d+$/.test(content)) {
58
+ const pid = parseInt(content, 10);
59
+ return pid > 0 ? { pid } : null;
60
+ }
61
+ const parsed = JSON.parse(content);
62
+ if (typeof parsed.pid !== 'number' || !Number.isInteger(parsed.pid) || parsed.pid <= 0) {
63
+ return null;
64
+ }
65
+ return parsed;
44
66
  }
45
67
  catch {
46
68
  return null;
47
69
  }
48
70
  }
49
71
  /**
50
- * Write PID to file atomically
72
+ * Read PID from the state file
73
+ * @returns PID number or null if file doesn't exist or is invalid
74
+ */
75
+ readPid() {
76
+ return this.readState()?.pid ?? null;
77
+ }
78
+ /**
79
+ * Write the daemon state to file atomically
51
80
  * MF-SEC-2: Uses O_EXCL to prevent TOCTOU race conditions
52
81
  *
53
82
  * @returns true if successful, false if file already exists
54
83
  * @throws Error for other filesystem errors
55
84
  */
56
- writePid(pid) {
85
+ writeState(state) {
57
86
  try {
58
87
  // O_EXCL: Fail if file already exists (atomic check-and-create)
59
88
  const fd = (0, fs_1.openSync)(this.pidFilePath, fs_1.constants.O_WRONLY | fs_1.constants.O_CREAT | fs_1.constants.O_EXCL, 0o600);
60
89
  try {
61
- (0, fs_1.writeSync)(fd, String(pid));
90
+ (0, fs_1.writeSync)(fd, JSON.stringify(state));
62
91
  return true;
63
92
  }
64
93
  finally {
@@ -74,7 +103,17 @@ class PidManager {
74
103
  }
75
104
  }
76
105
  /**
77
- * Remove PID file
106
+ * Read a live process's start-time signature via the injected reader.
107
+ * Used by start() to record the daemon's identity at launch (Issue #1358).
108
+ *
109
+ * @param pid - Process ID to inspect
110
+ * @returns The start-time signature, or null when it cannot be read
111
+ */
112
+ getStartTime(pid) {
113
+ return this.readStartTime(pid);
114
+ }
115
+ /**
116
+ * Remove the state file
78
117
  */
79
118
  removePid() {
80
119
  if (this.exists()) {
@@ -87,29 +126,50 @@ class PidManager {
87
126
  }
88
127
  }
89
128
  /**
90
- * Check if the process recorded in PID file is running
129
+ * Check if the process recorded in the state file is the daemon we started.
91
130
  * NTH-1: ISP - Lightweight process check API
92
131
  *
93
- * @returns true if process is running, false otherwise
132
+ * Issue #1358: `process.kill(pid, 0)` alone only proves the PID is in use. When the state
133
+ * records a start-time signature, the live process's is compared to catch PID reuse; a
134
+ * mismatch is treated as not-running so stop() never kills, and start() never defers to, an
135
+ * unrelated process. EPERM (the PID was reused by a process we don't own) is likewise treated
136
+ * as stale rather than thrown, so a reused PID no longer crashes the command.
137
+ *
138
+ * @returns true if the daemon is running, false otherwise
94
139
  */
95
140
  isProcessRunning() {
96
- const pid = this.readPid();
97
- if (pid === null) {
141
+ const state = this.readState();
142
+ if (state === null) {
98
143
  return false;
99
144
  }
100
145
  try {
101
146
  // Sending signal 0 checks if process exists without killing it
102
- process.kill(pid, 0);
103
- return true;
147
+ process.kill(state.pid, 0);
104
148
  }
105
149
  catch (err) {
106
- if (err.code === 'ESRCH') {
150
+ const code = err.code;
151
+ if (code === 'ESRCH') {
107
152
  // Process not found
108
153
  return false;
109
154
  }
110
- // Other errors (e.g., EPERM) mean process exists but we can't signal it
155
+ if (code === 'EPERM') {
156
+ // Issue #1358: the PID now belongs to a process we don't own — i.e. it was reused by
157
+ // an unrelated (possibly other-user) process. Treat as stale, not an error.
158
+ return false;
159
+ }
160
+ // Other, genuinely unexpected errors still surface
111
161
  throw err;
112
162
  }
163
+ // Issue #1358: the PID exists, but on a long-running machine the OS may have reused it for
164
+ // an unrelated process after our daemon died. If we recorded the start time, verify the live
165
+ // process still has it. A null reading (no `ps`, etc.) leaves the best-effort answer intact.
166
+ if (state.startTime) {
167
+ const current = this.readStartTime(state.pid);
168
+ if (current !== null && current !== state.startTime) {
169
+ return false;
170
+ }
171
+ }
172
+ return true;
113
173
  }
114
174
  }
115
175
  exports.PidManager = PidManager;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Process Inspector
3
+ * Issue #1358: verify a PID still belongs to the daemon we started
4
+ *
5
+ * `process.kill(pid, 0)` only proves *some* process owns the PID. On a long-running machine
6
+ * the OS reuses PIDs, so after the daemon crashes the same PID can belong to an unrelated
7
+ * process. Recording the OS-reported start time at launch and comparing it later lets us tell
8
+ * "our daemon is still running" from "the PID was reused".
9
+ */
10
+ /**
11
+ * A function that returns a stable identity signature for a PID, or null when it cannot be
12
+ * determined. Injected into PidManager so tests can supply a deterministic reader.
13
+ */
14
+ export type ProcessStartTimeReader = (pid: number) => string | null;
15
+ /**
16
+ * Read a process's start time via `ps`, as an absolute wall-clock string.
17
+ *
18
+ * `-o lstart=` prints e.g. "Sat Jul 18 01:03:24 2026" and is stable across invocations (unlike
19
+ * `etime`, which advances), so two reads of the same live process return the same value while a
20
+ * reused PID returns a different one. Works on macOS and Linux; any failure (no `ps`, unknown
21
+ * PID, permission) returns null so callers fall back to best-effort behaviour instead of erroring.
22
+ *
23
+ * @param pid - Process ID to inspect
24
+ * @returns The start-time signature, or null when it cannot be read
25
+ */
26
+ export declare function getProcessStartTime(pid: number): string | null;
27
+ //# sourceMappingURL=process-inspector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-inspector.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/process-inspector.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH;;;GAGG;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;AAEpE;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAW9D"}
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ /**
3
+ * Process Inspector
4
+ * Issue #1358: verify a PID still belongs to the daemon we started
5
+ *
6
+ * `process.kill(pid, 0)` only proves *some* process owns the PID. On a long-running machine
7
+ * the OS reuses PIDs, so after the daemon crashes the same PID can belong to an unrelated
8
+ * process. Recording the OS-reported start time at launch and comparing it later lets us tell
9
+ * "our daemon is still running" from "the PID was reused".
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.getProcessStartTime = getProcessStartTime;
13
+ const child_process_1 = require("child_process");
14
+ /**
15
+ * Read a process's start time via `ps`, as an absolute wall-clock string.
16
+ *
17
+ * `-o lstart=` prints e.g. "Sat Jul 18 01:03:24 2026" and is stable across invocations (unlike
18
+ * `etime`, which advances), so two reads of the same live process return the same value while a
19
+ * reused PID returns a different one. Works on macOS and Linux; any failure (no `ps`, unknown
20
+ * PID, permission) returns null so callers fall back to best-effort behaviour instead of erroring.
21
+ *
22
+ * @param pid - Process ID to inspect
23
+ * @returns The start-time signature, or null when it cannot be read
24
+ */
25
+ function getProcessStartTime(pid) {
26
+ try {
27
+ const out = (0, child_process_1.execFileSync)('ps', ['-o', 'lstart=', '-p', String(pid)], {
28
+ encoding: 'utf-8',
29
+ stdio: ['ignore', 'pipe', 'ignore'],
30
+ timeout: 2000,
31
+ }).trim();
32
+ return out.length > 0 ? out : null;
33
+ }
34
+ catch {
35
+ return null;
36
+ }
37
+ }
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ /**
3
+ * GitHub URL Constants (Centralized)
4
+ * Issue #264: DRY - All GitHub URLs derived from GITHUB_REPO_BASE_URL
5
+ *
6
+ * [SEC-001] SSRF Prevention: GITHUB_API_URL is NOT included here.
7
+ * It remains hardcoded in version-checker.ts for security reasons.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.GITHUB_SECURITY_GUIDE_URL = exports.GITHUB_RELEASE_URL_PREFIX = exports.GITHUB_QUESTION_URL = exports.GITHUB_FEATURE_REQUEST_URL = exports.GITHUB_BUG_REPORT_URL = exports.GITHUB_NEW_ISSUE_URL = exports.GITHUB_ISSUES_URL = exports.GITHUB_REPO_BASE_URL = void 0;
11
+ exports.GITHUB_REPO_BASE_URL = 'https://github.com/Kewton/CommandMate';
12
+ // Issue URLs
13
+ exports.GITHUB_ISSUES_URL = `${exports.GITHUB_REPO_BASE_URL}/issues`;
14
+ exports.GITHUB_NEW_ISSUE_URL = `${exports.GITHUB_REPO_BASE_URL}/issues/new`;
15
+ // Template URLs (UI: uses filename in query parameter)
16
+ exports.GITHUB_BUG_REPORT_URL = `${exports.GITHUB_NEW_ISSUE_URL}?template=bug_report.md`;
17
+ exports.GITHUB_FEATURE_REQUEST_URL = `${exports.GITHUB_NEW_ISSUE_URL}?template=feature_request.md`;
18
+ exports.GITHUB_QUESTION_URL = `${exports.GITHUB_NEW_ISSUE_URL}?template=question.md`;
19
+ // Release URL (moved from version-checker.ts, re-exported there for backward compatibility)
20
+ exports.GITHUB_RELEASE_URL_PREFIX = `${exports.GITHUB_REPO_BASE_URL}/releases/`;
21
+ // Security Guide URL (moved from security-messages.ts)
22
+ exports.GITHUB_SECURITY_GUIDE_URL = `${exports.GITHUB_REPO_BASE_URL}/blob/main/docs/security-guide.md`;
@@ -45,11 +45,30 @@ function getDbInstance() {
45
45
  fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
46
46
  }
47
47
  // Issue #1263: recover from a better-sqlite3 ABI mismatch (Node.js version switch)
48
- dbInstance = (0, abi_recovery_1.openDatabaseWithAbiRecovery)(dbPath);
48
+ const db = (0, abi_recovery_1.openDatabaseWithAbiRecovery)(dbPath);
49
49
  // Issue #294: Enable foreign key enforcement BEFORE migrations
50
50
  // This ensures ON DELETE CASCADE works correctly for all tables
51
- dbInstance.pragma('foreign_keys = ON');
52
- (0, db_migrations_1.runMigrations)(dbInstance);
51
+ db.pragma('foreign_keys = ON');
52
+ // Issue #1360: harden against SQLITE_BUSY when the same DB file is opened by
53
+ // more than one process (e.g. a misconfigured worktree server sharing
54
+ // CM_DB_PATH). WAL lets readers and a single writer coexist instead of
55
+ // taking an exclusive lock, and busy_timeout makes a contended write wait
56
+ // for the lock (up to 5s) rather than failing immediately with the default
57
+ // busy_timeout of 0. Set before migrations so migration writes benefit too.
58
+ db.pragma('journal_mode = WAL');
59
+ db.pragma('busy_timeout = 5000');
60
+ // Issue #1353: only publish the connection once its schema is verified.
61
+ // Assigning before runMigrations() cached a database whose migrations had
62
+ // thrown, so every later caller was handed it back without the failure —
63
+ // the guard would fire once and be bypassed for the rest of the process.
64
+ try {
65
+ (0, db_migrations_1.runMigrations)(db);
66
+ }
67
+ catch (error) {
68
+ db.close();
69
+ throw error;
70
+ }
71
+ dbInstance = db;
53
72
  }
54
73
  return dbInstance;
55
74
  }
@@ -8,11 +8,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
8
8
  return (mod && mod.__esModule) ? mod : { "default": mod };
9
9
  };
10
10
  Object.defineProperty(exports, "__esModule", { value: true });
11
- exports.MAX_DISABLED_REPOSITORIES = void 0;
11
+ exports.MAX_DISABLED_REPOSITORIES = exports.RepositoryDbError = void 0;
12
12
  exports.createRepository = createRepository;
13
13
  exports.getRepositoryByNormalizedUrl = getRepositoryByNormalizedUrl;
14
14
  exports.getRepositoryById = getRepositoryById;
15
15
  exports.getRepositoryByPath = getRepositoryByPath;
16
+ exports.deleteRepository = deleteRepository;
17
+ exports.countWorktreesByRepositoryPath = countWorktreesByRepositoryPath;
16
18
  exports.updateRepository = updateRepository;
17
19
  exports.getAllRepositories = getAllRepositories;
18
20
  exports.getAllRepositoriesWithWorktreeCount = getAllRepositoriesWithWorktreeCount;
@@ -22,6 +24,7 @@ exports.ensureEnvRepositoriesRegistered = ensureEnvRepositoriesRegistered;
22
24
  exports.filterExcludedPaths = filterExcludedPaths;
23
25
  exports.registerAndFilterRepositories = registerAndFilterRepositories;
24
26
  exports.disableRepository = disableRepository;
27
+ exports.disableExistingRepository = disableExistingRepository;
25
28
  exports.getExcludedRepositoryPaths = getExcludedRepositoryPaths;
26
29
  exports.getExcludedRepositories = getExcludedRepositories;
27
30
  exports.restoreRepository = restoreRepository;
@@ -33,6 +36,28 @@ exports.getCloneJobsByStatus = getCloneJobsByStatus;
33
36
  const crypto_1 = require("crypto");
34
37
  const path_1 = __importDefault(require("path"));
35
38
  const system_directories_1 = require("../../config/system-directories");
39
+ /**
40
+ * Typed error for repositories-table operations.
41
+ *
42
+ * Issue #1352: `createRepository()` used to let a raw better-sqlite3
43
+ * `SqliteError: UNIQUE constraint failed` propagate. A concurrent clone of the
44
+ * same URL has a TOCTOU window where both jobs pass the duplicate checks and
45
+ * the losing `createRepository()` throws that raw error, which the background
46
+ * clone path only logs (#1340). Convert UNIQUE violations to an explicit
47
+ * `DUPLICATE` code here so callers can distinguish the collision from other DB
48
+ * failures. Mirrors `ExternalAppDbError` in `external-apps/db.ts`.
49
+ */
50
+ class RepositoryDbError extends Error {
51
+ code;
52
+ cause;
53
+ constructor(message, code, cause) {
54
+ super(message);
55
+ this.code = code;
56
+ this.cause = cause;
57
+ this.name = 'RepositoryDbError';
58
+ }
59
+ }
60
+ exports.RepositoryDbError = RepositoryDbError;
36
61
  /**
37
62
  * Map repository row to Repository model
38
63
  */
@@ -94,7 +119,22 @@ function createRepository(db, data) {
94
119
  )
95
120
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
96
121
  `);
97
- stmt.run(id, data.name, data.path, data.enabled !== false ? 1 : 0, data.visible !== false ? 1 : 0, data.cloneUrl || null, data.normalizedCloneUrl || null, data.cloneSource, data.isEnvManaged ? 1 : 0, now, now);
122
+ // Issue #1352: `repositories.path` is UNIQUE and `normalized_clone_url` has a
123
+ // partial UNIQUE index. A concurrent clone of the same URL can race past the
124
+ // duplicate checks and reach here twice; the loser must fail with an explicit
125
+ // DUPLICATE rather than a raw SqliteError. These DB constraints are what
126
+ // serialize the final registration — the guard turns the collision into a
127
+ // typed error instead of preventing it.
128
+ try {
129
+ stmt.run(id, data.name, data.path, data.enabled !== false ? 1 : 0, data.visible !== false ? 1 : 0, data.cloneUrl || null, data.normalizedCloneUrl || null, data.cloneSource, data.isEnvManaged ? 1 : 0, now, now);
130
+ }
131
+ catch (error) {
132
+ if (error instanceof Error && error.message.includes('UNIQUE constraint')) {
133
+ throw new RepositoryDbError(`A repository is already registered at path "${data.path}"` +
134
+ (data.normalizedCloneUrl ? ` or for URL "${data.normalizedCloneUrl}"` : ''), 'DUPLICATE', error);
135
+ }
136
+ throw new RepositoryDbError(`Failed to create repository: ${error instanceof Error ? error.message : 'Unknown error'}`, 'DB_ERROR', error instanceof Error ? error : undefined);
137
+ }
98
138
  return {
99
139
  id,
100
140
  name: data.name,
@@ -142,6 +182,39 @@ function getRepositoryByPath(db, path) {
142
182
  const row = stmt.get(path);
143
183
  return row ? mapRepositoryRow(row) : null;
144
184
  }
185
+ /**
186
+ * Physically delete a repositories row by id.
187
+ *
188
+ * Issue #1350: before this, the only way to "remove" a repository was
189
+ * `disableRepository()` (enabled=0) — the row itself was never deleted. A row
190
+ * whose on-disk directory has been removed and that has no worktrees left
191
+ * ("ghost") therefore lingered forever and blocked re-cloning the same URL,
192
+ * with no removal path in the UI or API. This gives callers a real delete so a
193
+ * ghost can be cleared. Linkage of worktrees/child rows is by
194
+ * `worktrees.repository_path` (TEXT), not a FK to `repositories`, so deleting
195
+ * the row does not cascade — callers must confirm the row is a ghost first.
196
+ *
197
+ * @returns true if a row was deleted, false if no row matched the id.
198
+ */
199
+ function deleteRepository(db, id) {
200
+ const result = db.prepare('DELETE FROM repositories WHERE id = ?').run(id);
201
+ return result.changes > 0;
202
+ }
203
+ /**
204
+ * Count the worktrees associated with a repository path.
205
+ *
206
+ * Repository ↔ worktree linkage is by matching `repositories.path` against
207
+ * `worktrees.repository_path` (TEXT) — see `getAllRepositoriesWithWorktreeCount`.
208
+ * Issue #1350 uses this to tell a recoverable "ghost" (directory gone AND zero
209
+ * worktrees) apart from a repository that still has worktrees registered, which
210
+ * must never be silently deleted.
211
+ */
212
+ function countWorktreesByRepositoryPath(db, repositoryPath) {
213
+ const row = db
214
+ .prepare('SELECT COUNT(*) AS count FROM worktrees WHERE repository_path = ?')
215
+ .get(repositoryPath);
216
+ return Number(row.count) || 0;
217
+ }
145
218
  /**
146
219
  * Update repository
147
220
  *
@@ -371,25 +444,40 @@ function registerAndFilterRepositories(db, repositoryPaths) {
371
444
  * SF-002: SRP - disable logic encapsulated
372
445
  */
373
446
  function disableRepository(db, repositoryPath) {
374
- const resolvedPath = resolveRepositoryPath(repositoryPath);
375
- const repo = getRepositoryByPath(db, resolvedPath);
376
- if (repo) {
377
- updateRepository(db, repo.id, { enabled: false });
447
+ if (disableExistingRepository(db, repositoryPath)) {
448
+ return;
378
449
  }
379
- else {
380
- // SEC-SF-004: Check disabled repository count limit before creating new record
381
- const disabledCount = db.prepare('SELECT COUNT(*) as count FROM repositories WHERE enabled = 0').get();
382
- if (disabledCount.count >= exports.MAX_DISABLED_REPOSITORIES) {
383
- throw new Error('Disabled repository limit exceeded');
384
- }
385
- createRepository(db, {
386
- name: path_1.default.basename(resolvedPath),
387
- path: resolvedPath,
388
- cloneSource: 'local',
389
- isEnvManaged: false,
390
- enabled: false, // Explicit: do not rely on undefined -> 1 default
391
- });
450
+ const resolvedPath = resolveRepositoryPath(repositoryPath);
451
+ // SEC-SF-004: Check disabled repository count limit before creating new record
452
+ const disabledCount = db.prepare('SELECT COUNT(*) as count FROM repositories WHERE enabled = 0').get();
453
+ if (disabledCount.count >= exports.MAX_DISABLED_REPOSITORIES) {
454
+ throw new Error('Disabled repository limit exceeded');
392
455
  }
456
+ createRepository(db, {
457
+ name: path_1.default.basename(resolvedPath),
458
+ path: resolvedPath,
459
+ cloneSource: 'local',
460
+ isEnvManaged: false,
461
+ enabled: false, // Explicit: do not rely on undefined -> 1 default
462
+ });
463
+ }
464
+ /**
465
+ * Disable a repository only when it is already registered (enabled=0).
466
+ *
467
+ * Unlike disableRepository(), this never creates a record, so callers that may be
468
+ * handed a path that was never registered do not leave a ghost `enabled=0` row behind.
469
+ *
470
+ * Issue #1346
471
+ *
472
+ * @returns true if a registered repository was disabled, false if none was registered
473
+ */
474
+ function disableExistingRepository(db, repositoryPath) {
475
+ const resolvedPath = resolveRepositoryPath(repositoryPath);
476
+ const repo = getRepositoryByPath(db, resolvedPath);
477
+ if (!repo)
478
+ return false;
479
+ updateRepository(db, repo.id, { enabled: false });
480
+ return true;
393
481
  }
394
482
  /**
395
483
  * Get paths of excluded (enabled=0) repositories
@@ -11,8 +11,8 @@
11
11
  */
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
13
  exports.removeAgentInstance = exports.addAgentInstance = exports.setAgentInstances = exports.countAgentInstances = exports.getAgentInstance = exports.getAgentInstances = exports.deleteSessionState = exports.clearInProgressMessageId = exports.setInProgressMessageId = exports.updateSessionState = exports.getSessionState = exports.getMessagesByDateRange = exports.ACTIVE_FILTER = exports.markPendingPromptsAsAnswered = exports.updatePromptData = exports.getMessageById = exports.recomputeLastUserMessage = exports.clearLastUserMessage = exports.updateLastUserMessage = exports.deleteMessagesByInstance = exports.deleteMessagesByCliTool = exports.deleteMessageById = exports.deleteAllMessages = exports.getLastMessage = exports.getLastUserMessage = exports.getMessages = exports.updateMessageContent = exports.createMessage = exports.getLastAssistantMessageAt = exports.deleteWorktreesByIds = exports.deleteRepositoryWorktrees = exports.migrateWorktreeIdPreservingChildren = exports.getWorktreesByRepository = exports.getWorktreeIdsByRepository = exports.getInitialBranch = exports.saveInitialBranch = exports.updateVibeLocalContextWindow = exports.updateVibeLocalModel = exports.updateSelectedAgents = exports.updateCliToolId = exports.updateStatus = exports.updateFavorite = exports.updateLastViewedAt = exports.updateWorktreeLink = exports.updateWorktreeDescription = exports.upsertWorktree = exports.getWorktreeById = exports.getRepositories = exports.getWorktrees = exports.initDatabase = void 0;
14
- exports.getLatestAssistantExecutionByConversation = exports.getAssistantExecutionById = exports.updateAssistantExecution = exports.createAssistantExecution = exports.archiveAssistantMessagesFrom = exports.archiveAllAssistantMessages = exports.getAssistantMessageById = exports.getAssistantMessages = exports.updateAssistantMessageStatus = exports.createAssistantMessage = exports.updateAssistantConversation = exports.createAssistantConversation = exports.getAssistantConversationByRepositoryAndCliTool = exports.getAssistantConversationById = exports.updateDailyReportContent = exports.saveDailyReport = exports.getDailyReport = exports.recoverStuckSendingTimers = exports.clearTimerHistory = exports.cleanupOldTimers = exports.getPendingTimerCountByWorktree = exports.cancelTimersByWorktree = exports.cancelTimer = exports.updateTimerStatus = exports.getPendingTimers = exports.getTimerById = exports.getTimersByWorktree = exports.createTimer = exports.WORKTREE_TODO_STATUSES = exports.isWorktreeTodoStatus = exports.reorderWorktreeTodos = exports.deleteWorktreeTodo = exports.updateWorktreeTodo = exports.createWorktreeTodo = exports.getWorktreeTodoById = exports.getTodosByWorktreeId = exports.deleteTodo = exports.updateTodo = exports.createTodo = exports.getTodoById = exports.getAllTodos = exports.getTodosByRepositoryId = exports.reorderMemos = exports.deleteMemo = exports.updateMemo = exports.createMemo = exports.getMemoById = exports.getMemosByWorktreeId = exports.InvalidAgentInstanceError = exports.AgentInstanceLimitError = void 0;
15
- exports.deletePushSubscriptionByEndpoint = exports.updatePushSubscriptionPreferences = exports.getPushSubscriptionsForKind = exports.getAllPushSubscriptions = exports.getPushSubscriptionByEndpoint = exports.upsertPushSubscription = exports.deleteAssistantSessionState = exports.updateAssistantSessionState = exports.getAssistantSessionState = exports.listRunningAssistantExecutions = exports.getRunningAssistantExecutionByConversation = void 0;
14
+ exports.getAssistantExecutionById = exports.updateAssistantExecution = exports.createAssistantExecution = exports.archiveAssistantMessagesFrom = exports.archiveAllAssistantMessages = exports.getAssistantMessageById = exports.getAssistantMessages = exports.updateAssistantMessageStatus = exports.createAssistantMessage = exports.updateAssistantConversation = exports.createAssistantConversation = exports.getAssistantConversationByRepositoryAndCliTool = exports.getAssistantConversationById = exports.updateDailyReportContent = exports.saveDailyReport = exports.getDailyReport = exports.recoverStuckSendingTimers = exports.clearTimerHistory = exports.cleanupOldTimers = exports.getPendingTimerCountByWorktree = exports.cancelTimersByWorktree = exports.cancelTimer = exports.updateTimerStatus = exports.getPendingTimers = exports.getTimerById = exports.getTimersByWorktree = exports.createTimer = exports.WORKTREE_TODO_STATUSES = exports.isWorktreeTodoStatus = exports.reorderWorktreeTodos = exports.deleteWorktreeTodo = exports.updateWorktreeTodo = exports.createWorktreeTodo = exports.getWorktreeTodoById = exports.getTodosByWorktreeId = exports.deleteTodo = exports.updateTodo = exports.createTodo = exports.getTodoById = exports.getAllTodos = exports.getTodosByRepositoryId = exports.MemoDbError = exports.reorderMemos = exports.deleteMemo = exports.updateMemo = exports.createMemo = exports.getMemoById = exports.getMemosByWorktreeId = exports.InvalidAgentInstanceError = exports.AgentInstanceLimitError = void 0;
15
+ exports.deletePushSubscriptionByEndpoint = exports.updatePushSubscriptionPreferences = exports.getPushSubscriptionsForKind = exports.getAllPushSubscriptions = exports.getPushSubscriptionByEndpoint = exports.upsertPushSubscription = exports.deleteAssistantSessionState = exports.updateAssistantSessionState = exports.getAssistantSessionState = exports.listRunningAssistantExecutions = exports.getRunningAssistantExecutionByConversation = exports.getLatestAssistantExecutionByConversation = void 0;
16
16
  // init-db
17
17
  var init_db_1 = require("./init-db");
18
18
  Object.defineProperty(exports, "initDatabase", { enumerable: true, get: function () { return init_db_1.initDatabase; } });
@@ -83,6 +83,7 @@ Object.defineProperty(exports, "createMemo", { enumerable: true, get: function (
83
83
  Object.defineProperty(exports, "updateMemo", { enumerable: true, get: function () { return memo_db_1.updateMemo; } });
84
84
  Object.defineProperty(exports, "deleteMemo", { enumerable: true, get: function () { return memo_db_1.deleteMemo; } });
85
85
  Object.defineProperty(exports, "reorderMemos", { enumerable: true, get: function () { return memo_db_1.reorderMemos; } });
86
+ Object.defineProperty(exports, "MemoDbError", { enumerable: true, get: function () { return memo_db_1.MemoDbError; } });
86
87
  // todo-db (repository-scoped Home ToDo widget)
87
88
  var todo_db_1 = require("./todo-db");
88
89
  Object.defineProperty(exports, "getTodosByRepositoryId", { enumerable: true, get: function () { return todo_db_1.getTodosByRepositoryId; } });
@@ -6,6 +6,7 @@
6
6
  * Issue #479: Extracted from db.ts for single-responsibility separation
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.MemoDbError = void 0;
9
10
  exports.getMemosByWorktreeId = getMemosByWorktreeId;
10
11
  exports.getMemoById = getMemoById;
11
12
  exports.createMemo = createMemo;
@@ -13,6 +14,26 @@ exports.updateMemo = updateMemo;
13
14
  exports.deleteMemo = deleteMemo;
14
15
  exports.reorderMemos = reorderMemos;
15
16
  const crypto_1 = require("crypto");
17
+ /**
18
+ * Database error for memo operations.
19
+ *
20
+ * Issue #1351: `createMemo` writes to a table with a
21
+ * `UNIQUE(worktree_id, position)` constraint. Converting the driver's opaque
22
+ * "UNIQUE constraint failed" message into a typed, coded error lets API callers
23
+ * map the collision to an explicit 409 instead of a generic 500. Mirrors
24
+ * `ExternalAppDbError` in `src/lib/external-apps/db.ts`.
25
+ */
26
+ class MemoDbError extends Error {
27
+ code;
28
+ cause;
29
+ constructor(message, code, cause) {
30
+ super(message);
31
+ this.code = code;
32
+ this.cause = cause;
33
+ this.name = 'MemoDbError';
34
+ }
35
+ }
36
+ exports.MemoDbError = MemoDbError;
16
37
  /**
17
38
  * Map database row to WorktreeMemo model
18
39
  */
@@ -73,7 +94,17 @@ function createMemo(db, worktreeId, options) {
73
94
  INSERT INTO worktree_memos (id, worktree_id, title, content, position, created_at, updated_at)
74
95
  VALUES (?, ?, ?, ?, ?, ?, ?)
75
96
  `);
76
- stmt.run(id, worktreeId, title, content, options.position, now, now);
97
+ try {
98
+ stmt.run(id, worktreeId, title, content, options.position, now, now);
99
+ }
100
+ catch (error) {
101
+ // UNIQUE(worktree_id, position) violation -> typed DUPLICATE error (Issue #1351).
102
+ // Other failures (e.g. FOREIGN KEY) are re-thrown unchanged.
103
+ if (error instanceof Error && error.message.includes('UNIQUE constraint')) {
104
+ throw new MemoDbError(`Memo position ${options.position} is already in use for worktree "${worktreeId}"`, 'DUPLICATE_POSITION', error);
105
+ }
106
+ throw error;
107
+ }
77
108
  return {
78
109
  id,
79
110
  worktreeId,
@@ -26,6 +26,7 @@ const v39_worktree_todo_detail_1 = require("./v39-worktree-todo-detail");
26
26
  const v40_timer_error_1 = require("./v40-timer-error");
27
27
  const v41_push_subscriptions_1 = require("./v41-push-subscriptions");
28
28
  const v42_push_subscription_locale_1 = require("./v42-push-subscription-locale");
29
+ const v43_remove_cm_root_dir_ghost_repository_1 = require("./v43-remove-cm-root-dir-ghost-repository");
29
30
  /**
30
31
  * Complete ordered list of all migrations.
31
32
  * Used internally by the barrel file (db-migrations.ts); NOT exported from the barrel (DR2-004).
@@ -55,4 +56,5 @@ exports.migrations = [
55
56
  ...v40_timer_error_1.v40_migrations,
56
57
  ...v41_push_subscriptions_1.v41_migrations,
57
58
  ...v42_push_subscription_locale_1.v42_migrations,
59
+ ...v43_remove_cm_root_dir_ghost_repository_1.v43_migrations,
58
60
  ];
@@ -17,7 +17,7 @@ const path_1 = __importDefault(require("path"));
17
17
  * Current schema version
18
18
  * Increment this when adding new migrations
19
19
  */
20
- exports.CURRENT_SCHEMA_VERSION = 42;
20
+ exports.CURRENT_SCHEMA_VERSION = 43;
21
21
  /**
22
22
  * Get current schema version from database
23
23
  */
@@ -56,6 +56,16 @@ function runMigrations(db, migrations) {
56
56
  // Get current version
57
57
  const currentVersion = getCurrentVersion(db);
58
58
  console.log(`Current schema version: ${currentVersion}`);
59
+ // Issue #1353: refuse a database written by a newer build.
60
+ // Migrations only move forward, so this build has no definition for the
61
+ // schema it is looking at: queries still written against renamed/dropped
62
+ // columns would fail at runtime, long after startup reported success.
63
+ // The check sits after the version read but before any migration writes.
64
+ if (currentVersion > exports.CURRENT_SCHEMA_VERSION) {
65
+ throw new Error(`This database (schema v${currentVersion}) was created by a newer version of CommandMate ` +
66
+ `(this build supports up to v${exports.CURRENT_SCHEMA_VERSION}). ` +
67
+ `Please update: commandmate update`);
68
+ }
59
69
  // Find pending migrations
60
70
  const pendingMigrations = migrations.filter(migration => migration.version > currentVersion);
61
71
  if (pendingMigrations.length === 0) {