borgmcp 1.1.15 → 2.0.1

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 (459) hide show
  1. package/CONTRIBUTING.md +15 -0
  2. package/LICENSE +201 -33
  3. package/NOTICE +2 -0
  4. package/README.md +85 -36
  5. package/SECURITY.md +7 -0
  6. package/dist/agent-runtime.d.ts.map +1 -0
  7. package/dist/agent-runtime.js +63 -1
  8. package/dist/agent-runtime.js.map +1 -0
  9. package/dist/assimilate-cmd.d.ts +96 -17
  10. package/dist/assimilate-cmd.d.ts.map +1 -0
  11. package/dist/assimilate-cmd.js +1396 -48
  12. package/dist/assimilate-cmd.js.map +1 -0
  13. package/dist/assimilate-deps.d.ts.map +1 -0
  14. package/dist/assimilate-deps.js +384 -3
  15. package/dist/assimilate-deps.js.map +1 -0
  16. package/dist/assimilate-guard.d.ts +5 -7
  17. package/dist/assimilate-guard.d.ts.map +1 -0
  18. package/dist/assimilate-guard.js +60 -2
  19. package/dist/assimilate-guard.js.map +1 -0
  20. package/dist/assimilate-welcome.d.ts +1 -1
  21. package/dist/assimilate-welcome.d.ts.map +1 -0
  22. package/dist/assimilate-welcome.js +32 -2
  23. package/dist/assimilate-welcome.js.map +1 -0
  24. package/dist/auth-env.d.ts +7 -50
  25. package/dist/auth-env.d.ts.map +1 -0
  26. package/dist/auth-env.js +22 -1
  27. package/dist/auth-env.js.map +1 -0
  28. package/dist/backends/launch-all-pastelist.d.ts.map +1 -0
  29. package/dist/backends/launch-all-pastelist.js +11 -4
  30. package/dist/backends/launch-all-pastelist.js.map +1 -0
  31. package/dist/backends/launch-all-tmux.d.ts.map +1 -0
  32. package/dist/backends/launch-all-tmux.js +49 -1
  33. package/dist/backends/launch-all-tmux.js.map +1 -0
  34. package/dist/backends/launch-all-windows.d.ts.map +1 -0
  35. package/dist/backends/launch-all-windows.js +86 -12
  36. package/dist/backends/launch-all-windows.js.map +1 -0
  37. package/dist/bare-launch-menu.d.ts.map +1 -0
  38. package/dist/bare-launch-menu.js +83 -6
  39. package/dist/bare-launch-menu.js.map +1 -0
  40. package/dist/claude-launch-args.d.ts.map +1 -0
  41. package/dist/claude-launch-args.js +34 -1
  42. package/dist/claude-launch-args.js.map +1 -0
  43. package/dist/claude.d.ts.map +1 -0
  44. package/dist/claude.js +486 -14
  45. package/dist/claude.js.map +1 -0
  46. package/dist/cleanup-cmd.d.ts +5 -5
  47. package/dist/cleanup-cmd.d.ts.map +1 -0
  48. package/dist/cleanup-cmd.js +453 -14
  49. package/dist/cleanup-cmd.js.map +1 -0
  50. package/dist/clear-rewake-core.d.ts.map +1 -0
  51. package/dist/clear-rewake-core.js +23 -2
  52. package/dist/clear-rewake-core.js.map +1 -0
  53. package/dist/clear-rewake.d.ts.map +1 -0
  54. package/dist/clear-rewake.js +19 -1
  55. package/dist/clear-rewake.js.map +1 -0
  56. package/dist/cli-help.d.ts +5 -0
  57. package/dist/cli-help.d.ts.map +1 -0
  58. package/dist/cli-help.js +104 -56
  59. package/dist/cli-help.js.map +1 -0
  60. package/dist/cli-platform.d.ts.map +1 -0
  61. package/dist/cli-platform.js +106 -4
  62. package/dist/cli-platform.js.map +1 -0
  63. package/dist/cli-tool-approval.d.ts +84 -0
  64. package/dist/cli-tool-approval.d.ts.map +1 -0
  65. package/dist/cli-tool-approval.js +583 -0
  66. package/dist/cli-tool-approval.js.map +1 -0
  67. package/dist/codex-app-server.d.ts.map +1 -0
  68. package/dist/codex-app-server.js +228 -4
  69. package/dist/codex-app-server.js.map +1 -0
  70. package/dist/codex-app-wake.d.ts.map +1 -0
  71. package/dist/codex-app-wake.js +432 -2
  72. package/dist/codex-app-wake.js.map +1 -0
  73. package/dist/codex-launch.d.ts.map +1 -0
  74. package/dist/codex-launch.js +102 -2
  75. package/dist/codex-launch.js.map +1 -0
  76. package/dist/codex-remote.d.ts +6 -1
  77. package/dist/codex-remote.d.ts.map +1 -0
  78. package/dist/codex-remote.js +394 -1
  79. package/dist/codex-remote.js.map +1 -0
  80. package/dist/codex-wake-resolve.d.ts.map +1 -0
  81. package/dist/codex-wake-resolve.js +127 -1
  82. package/dist/codex-wake-resolve.js.map +1 -0
  83. package/dist/config-utils.d.ts +2 -2
  84. package/dist/config-utils.d.ts.map +1 -0
  85. package/dist/config-utils.js +766 -3
  86. package/dist/config-utils.js.map +1 -0
  87. package/dist/config.d.ts +98 -61
  88. package/dist/config.d.ts.map +1 -0
  89. package/dist/config.js +426 -1
  90. package/dist/config.js.map +1 -0
  91. package/dist/console-prefix.d.ts.map +1 -0
  92. package/dist/console-prefix.js +96 -1
  93. package/dist/console-prefix.js.map +1 -0
  94. package/dist/cube-name.d.ts.map +1 -0
  95. package/dist/cube-name.js +67 -1
  96. package/dist/cube-name.js.map +1 -0
  97. package/dist/cubes.d.ts +126 -18
  98. package/dist/cubes.d.ts.map +1 -0
  99. package/dist/cubes.js +412 -4
  100. package/dist/cubes.js.map +1 -0
  101. package/dist/debug.d.ts.map +1 -0
  102. package/dist/debug.js +71 -1
  103. package/dist/debug.js.map +1 -0
  104. package/dist/direct-log.d.ts.map +1 -0
  105. package/dist/direct-log.js +11 -1
  106. package/dist/direct-log.js.map +1 -0
  107. package/dist/docs-sections.d.ts +11 -10
  108. package/dist/docs-sections.d.ts.map +1 -0
  109. package/dist/docs-sections.js +113 -3
  110. package/dist/docs-sections.js.map +1 -0
  111. package/dist/drone-lifecycle.d.ts +5 -21
  112. package/dist/drone-lifecycle.d.ts.map +1 -0
  113. package/dist/drone-lifecycle.js +57 -8
  114. package/dist/drone-lifecycle.js.map +1 -0
  115. package/dist/drone-management.d.ts +29 -0
  116. package/dist/drone-management.d.ts.map +1 -0
  117. package/dist/drone-management.js +109 -0
  118. package/dist/drone-management.js.map +1 -0
  119. package/dist/ensure-mcp-config.d.ts.map +1 -0
  120. package/dist/ensure-mcp-config.js +36 -1
  121. package/dist/ensure-mcp-config.js.map +1 -0
  122. package/dist/evict-drone.d.ts +10 -2
  123. package/dist/evict-drone.d.ts.map +1 -0
  124. package/dist/evict-drone.js +60 -1
  125. package/dist/evict-drone.js.map +1 -0
  126. package/dist/gc-orphan-inboxes.d.ts.map +1 -0
  127. package/dist/gc-orphan-inboxes.js +177 -1
  128. package/dist/gc-orphan-inboxes.js.map +1 -0
  129. package/dist/inbox-monitor.d.ts +1 -1
  130. package/dist/inbox-monitor.d.ts.map +1 -0
  131. package/dist/inbox-monitor.js +856 -3
  132. package/dist/inbox-monitor.js.map +1 -0
  133. package/dist/index.d.ts +6 -4
  134. package/dist/index.d.ts.map +1 -0
  135. package/dist/index.js +1034 -37
  136. package/dist/index.js.map +1 -0
  137. package/dist/launch-all-cmd.d.ts.map +1 -0
  138. package/dist/launch-all-cmd.js +377 -37
  139. package/dist/launch-all-cmd.js.map +1 -0
  140. package/dist/launch-all-command.d.ts.map +1 -0
  141. package/dist/launch-all-command.js +24 -1
  142. package/dist/launch-all-command.js.map +1 -0
  143. package/dist/launch-all-deps.d.ts +3 -8
  144. package/dist/launch-all-deps.d.ts.map +1 -0
  145. package/dist/launch-all-deps.js +99 -1
  146. package/dist/launch-all-deps.js.map +1 -0
  147. package/dist/launch-all-discovery.d.ts +1 -0
  148. package/dist/launch-all-discovery.d.ts.map +1 -0
  149. package/dist/launch-all-discovery.js +90 -4
  150. package/dist/launch-all-discovery.js.map +1 -0
  151. package/dist/launch-all-locks.d.ts.map +1 -0
  152. package/dist/launch-all-locks.js +54 -1
  153. package/dist/launch-all-locks.js.map +1 -0
  154. package/dist/launch-gate.d.ts +2 -2
  155. package/dist/launch-gate.d.ts.map +1 -0
  156. package/dist/launch-gate.js +73 -1
  157. package/dist/launch-gate.js.map +1 -0
  158. package/dist/lifecycle-log-guard.d.ts.map +1 -0
  159. package/dist/lifecycle-log-guard.js +93 -2
  160. package/dist/lifecycle-log-guard.js.map +1 -0
  161. package/dist/list-roles-render.d.ts.map +1 -0
  162. package/dist/list-roles-render.js +40 -6
  163. package/dist/list-roles-render.js.map +1 -0
  164. package/dist/local-log-routing.d.ts +19 -0
  165. package/dist/local-log-routing.d.ts.map +1 -0
  166. package/dist/local-log-routing.js +67 -0
  167. package/dist/local-log-routing.js.map +1 -0
  168. package/dist/local-manage-tool-result.d.ts +8 -0
  169. package/dist/local-manage-tool-result.d.ts.map +1 -0
  170. package/dist/local-manage-tool-result.js +10 -0
  171. package/dist/local-manage-tool-result.js.map +1 -0
  172. package/dist/local-server-cursor.d.ts +34 -0
  173. package/dist/local-server-cursor.d.ts.map +1 -0
  174. package/dist/local-server-cursor.js +151 -0
  175. package/dist/local-server-cursor.js.map +1 -0
  176. package/dist/log-audit.d.ts.map +1 -0
  177. package/dist/log-audit.js +194 -3
  178. package/dist/log-audit.js.map +1 -0
  179. package/dist/log-stream.d.ts +31 -18
  180. package/dist/log-stream.d.ts.map +1 -0
  181. package/dist/log-stream.js +1214 -12
  182. package/dist/log-stream.js.map +1 -0
  183. package/dist/model-presets.d.ts.map +1 -0
  184. package/dist/model-presets.js +19 -1
  185. package/dist/model-presets.js.map +1 -0
  186. package/dist/name-validator.d.ts.map +1 -0
  187. package/dist/name-validator.js +22 -1
  188. package/dist/name-validator.js.map +1 -0
  189. package/dist/opencode-drone.d.ts.map +1 -0
  190. package/dist/opencode-drone.js +438 -4
  191. package/dist/opencode-drone.js.map +1 -0
  192. package/dist/opencode-plugin.d.ts +1 -1
  193. package/dist/opencode-plugin.d.ts.map +1 -0
  194. package/dist/opencode-plugin.js +29 -4
  195. package/dist/opencode-plugin.js.map +1 -0
  196. package/dist/parse-assimilate-args.d.ts +1 -1
  197. package/dist/parse-assimilate-args.d.ts.map +1 -0
  198. package/dist/parse-assimilate-args.js +125 -1
  199. package/dist/parse-assimilate-args.js.map +1 -0
  200. package/dist/parse-launch-all-args.d.ts.map +1 -0
  201. package/dist/parse-launch-all-args.js +70 -1
  202. package/dist/parse-launch-all-args.js.map +1 -0
  203. package/dist/postinstall-banner.d.ts.map +1 -0
  204. package/dist/postinstall-banner.js +27 -2
  205. package/dist/postinstall-banner.js.map +1 -0
  206. package/dist/postinstall.d.ts.map +1 -0
  207. package/dist/postinstall.js +32 -5
  208. package/dist/postinstall.js.map +1 -0
  209. package/dist/readiness-probe.d.ts.map +1 -0
  210. package/dist/readiness-probe.js +9 -1
  211. package/dist/readiness-probe.js.map +1 -0
  212. package/dist/regen-format.d.ts.map +1 -0
  213. package/dist/regen-format.js +545 -13
  214. package/dist/regen-format.js.map +1 -0
  215. package/dist/regen.d.ts.map +1 -0
  216. package/dist/regen.js +141 -5
  217. package/dist/regen.js.map +1 -0
  218. package/dist/remote-client.d.ts +65 -175
  219. package/dist/remote-client.d.ts.map +1 -0
  220. package/dist/remote-client.js +942 -1
  221. package/dist/remote-client.js.map +1 -0
  222. package/dist/reset-local-seat-cmd.d.ts +50 -0
  223. package/dist/reset-local-seat-cmd.d.ts.map +1 -0
  224. package/dist/reset-local-seat-cmd.js +169 -0
  225. package/dist/reset-local-seat-cmd.js.map +1 -0
  226. package/dist/role-match.d.ts.map +1 -0
  227. package/dist/role-match.js +23 -1
  228. package/dist/role-match.js.map +1 -0
  229. package/dist/role-resolver.d.ts.map +1 -0
  230. package/dist/role-resolver.js +60 -1
  231. package/dist/role-resolver.js.map +1 -0
  232. package/dist/roster-render.d.ts.map +1 -0
  233. package/dist/roster-render.js +121 -3
  234. package/dist/roster-render.js.map +1 -0
  235. package/dist/seat-probe.d.ts +32 -13
  236. package/dist/seat-probe.d.ts.map +1 -0
  237. package/dist/seat-probe.js +78 -1
  238. package/dist/seat-probe.js.map +1 -0
  239. package/dist/seat-store.d.ts +76 -0
  240. package/dist/seat-store.d.ts.map +1 -0
  241. package/dist/seat-store.js +309 -0
  242. package/dist/seat-store.js.map +1 -0
  243. package/dist/seats.d.ts +303 -0
  244. package/dist/seats.d.ts.map +1 -0
  245. package/dist/seats.js +551 -0
  246. package/dist/seats.js.map +1 -0
  247. package/dist/self-path.d.ts +27 -0
  248. package/dist/self-path.d.ts.map +1 -0
  249. package/dist/self-path.js +43 -0
  250. package/dist/self-path.js.map +1 -0
  251. package/dist/server-endpoint.d.ts +9 -0
  252. package/dist/server-endpoint.d.ts.map +1 -0
  253. package/dist/server-endpoint.js +38 -0
  254. package/dist/server-endpoint.js.map +1 -0
  255. package/dist/server-errors.d.ts +50 -0
  256. package/dist/server-errors.d.ts.map +1 -0
  257. package/dist/server-errors.js +79 -0
  258. package/dist/server-errors.js.map +1 -0
  259. package/dist/server-handshake.d.ts +197 -0
  260. package/dist/server-handshake.d.ts.map +1 -0
  261. package/dist/server-handshake.js +505 -0
  262. package/dist/server-handshake.js.map +1 -0
  263. package/dist/server-response.d.ts +3 -0
  264. package/dist/server-response.d.ts.map +1 -0
  265. package/dist/server-response.js +67 -0
  266. package/dist/server-response.js.map +1 -0
  267. package/dist/server-trust.d.ts +14 -0
  268. package/dist/server-trust.d.ts.map +1 -0
  269. package/dist/server-trust.js +225 -0
  270. package/dist/server-trust.js.map +1 -0
  271. package/dist/setup-confirm.d.ts +3 -3
  272. package/dist/setup-confirm.d.ts.map +1 -0
  273. package/dist/setup-confirm.js +126 -2
  274. package/dist/setup-confirm.js.map +1 -0
  275. package/dist/setup.d.ts +5 -3
  276. package/dist/setup.d.ts.map +1 -0
  277. package/dist/setup.js +169 -46
  278. package/dist/setup.js.map +1 -0
  279. package/dist/shell-escape.d.ts.map +1 -0
  280. package/dist/shell-escape.js +22 -1
  281. package/dist/shell-escape.js.map +1 -0
  282. package/dist/spawn.d.ts +2 -2
  283. package/dist/spawn.d.ts.map +1 -0
  284. package/dist/spawn.js +29 -10
  285. package/dist/spawn.js.map +1 -0
  286. package/dist/startup-services.d.ts +0 -1
  287. package/dist/startup-services.d.ts.map +1 -0
  288. package/dist/startup-services.js +26 -1
  289. package/dist/startup-services.js.map +1 -0
  290. package/dist/stream-owner.d.ts +6 -2
  291. package/dist/stream-owner.d.ts.map +1 -0
  292. package/dist/stream-owner.js +547 -2
  293. package/dist/stream-owner.js.map +1 -0
  294. package/dist/stream-status.d.ts +1 -1
  295. package/dist/stream-status.d.ts.map +1 -0
  296. package/dist/stream-status.js +268 -3
  297. package/dist/stream-status.js.map +1 -0
  298. package/dist/sync-roles-render.d.ts.map +1 -0
  299. package/dist/sync-roles-render.js +118 -3
  300. package/dist/sync-roles-render.js.map +1 -0
  301. package/dist/sync.d.ts +1 -1
  302. package/dist/sync.d.ts.map +1 -0
  303. package/dist/sync.js +286 -22
  304. package/dist/sync.js.map +1 -0
  305. package/dist/terminal-title.d.ts.map +1 -0
  306. package/dist/terminal-title.js +68 -1
  307. package/dist/terminal-title.js.map +1 -0
  308. package/dist/token-store.d.ts +17 -111
  309. package/dist/token-store.d.ts.map +1 -0
  310. package/dist/token-store.js +81 -1
  311. package/dist/token-store.js.map +1 -0
  312. package/dist/tool-manifest.d.ts +4 -8
  313. package/dist/tool-manifest.d.ts.map +1 -0
  314. package/dist/tool-manifest.js +554 -1
  315. package/dist/tool-manifest.js.map +1 -0
  316. package/dist/tool-scope.d.ts +8 -12
  317. package/dist/tool-scope.d.ts.map +1 -0
  318. package/dist/tool-scope.js +97 -1
  319. package/dist/tool-scope.js.map +1 -0
  320. package/dist/types.d.ts +1 -5
  321. package/dist/types.d.ts.map +1 -0
  322. package/dist/types.js +5 -0
  323. package/dist/types.js.map +1 -0
  324. package/dist/unknown-subcommand.d.ts +1 -1
  325. package/dist/unknown-subcommand.d.ts.map +1 -0
  326. package/dist/unknown-subcommand.js +37 -1
  327. package/dist/unknown-subcommand.js.map +1 -0
  328. package/dist/version.d.ts +1 -1
  329. package/dist/version.d.ts.map +1 -0
  330. package/dist/version.js +78 -2
  331. package/dist/version.js.map +1 -0
  332. package/dist/working-repo.d.ts.map +1 -0
  333. package/dist/working-repo.js +81 -1
  334. package/dist/working-repo.js.map +1 -0
  335. package/dist/worktree-lifecycle.d.ts.map +1 -0
  336. package/dist/worktree-lifecycle.js +205 -2
  337. package/dist/worktree-lifecycle.js.map +1 -0
  338. package/docs/EXTRACTION_PROVENANCE.md +40 -0
  339. package/docs/LOCAL_SERVER.md +103 -0
  340. package/docs/RELEASING.md +120 -0
  341. package/package.json +52 -34
  342. package/src/agent-runtime.ts +69 -0
  343. package/src/assimilate-cmd.ts +1864 -0
  344. package/src/assimilate-deps.ts +444 -0
  345. package/src/assimilate-guard.ts +84 -0
  346. package/src/assimilate-welcome.ts +39 -0
  347. package/src/auth-env.ts +21 -0
  348. package/src/backends/launch-all-pastelist.ts +18 -0
  349. package/src/backends/launch-all-tmux.ts +75 -0
  350. package/src/backends/launch-all-windows.ts +110 -0
  351. package/src/bare-launch-menu.ts +148 -0
  352. package/src/claude-launch-args.ts +35 -0
  353. package/src/claude.ts +561 -0
  354. package/src/cleanup-cmd.ts +581 -0
  355. package/src/clear-rewake-core.ts +34 -0
  356. package/src/clear-rewake.ts +18 -0
  357. package/src/cli-help.ts +116 -0
  358. package/src/cli-platform.ts +127 -0
  359. package/src/cli-tool-approval.ts +716 -0
  360. package/src/codex-app-server.ts +238 -0
  361. package/src/codex-app-wake.ts +512 -0
  362. package/src/codex-launch.ts +140 -0
  363. package/src/codex-remote.ts +500 -0
  364. package/src/codex-wake-resolve.ts +155 -0
  365. package/src/config-utils.ts +811 -0
  366. package/src/config.ts +595 -0
  367. package/src/console-prefix.ts +99 -0
  368. package/src/cube-name.ts +69 -0
  369. package/src/cubes.ts +583 -0
  370. package/src/debug.ts +73 -0
  371. package/src/direct-log.ts +9 -0
  372. package/src/docs-sections.ts +129 -0
  373. package/src/drone-lifecycle.ts +62 -0
  374. package/src/drone-management.ts +162 -0
  375. package/src/ensure-mcp-config.ts +54 -0
  376. package/src/evict-drone.ts +82 -0
  377. package/src/gc-orphan-inboxes.ts +229 -0
  378. package/src/inbox-monitor.ts +1005 -0
  379. package/src/index.ts +1201 -0
  380. package/src/launch-all-cmd.ts +450 -0
  381. package/src/launch-all-command.ts +30 -0
  382. package/src/launch-all-deps.ts +188 -0
  383. package/src/launch-all-discovery.ts +118 -0
  384. package/src/launch-all-locks.ts +74 -0
  385. package/src/launch-gate.ts +80 -0
  386. package/src/lifecycle-log-guard.ts +144 -0
  387. package/src/list-roles-render.ts +52 -0
  388. package/src/local-log-routing.ts +106 -0
  389. package/src/local-manage-tool-result.ts +10 -0
  390. package/src/local-server-cursor.ts +188 -0
  391. package/src/log-audit.ts +207 -0
  392. package/src/log-stream.ts +1505 -0
  393. package/src/model-presets.ts +22 -0
  394. package/src/name-validator.ts +23 -0
  395. package/src/opencode-drone.ts +528 -0
  396. package/src/opencode-plugin.ts +38 -0
  397. package/src/parse-assimilate-args.ts +125 -0
  398. package/src/parse-launch-all-args.ts +100 -0
  399. package/src/postinstall-banner.ts +37 -0
  400. package/src/postinstall.ts +36 -0
  401. package/src/readiness-probe.ts +12 -0
  402. package/src/regen-format.ts +651 -0
  403. package/src/regen.ts +150 -0
  404. package/src/remote-client.ts +1379 -0
  405. package/src/reset-local-seat-cmd.ts +227 -0
  406. package/src/role-match.ts +29 -0
  407. package/src/role-resolver.ts +93 -0
  408. package/src/roster-render.ts +196 -0
  409. package/src/seat-probe.ts +115 -0
  410. package/src/seat-store.ts +333 -0
  411. package/src/seats.ts +741 -0
  412. package/src/self-path.ts +51 -0
  413. package/src/server-endpoint.ts +38 -0
  414. package/src/server-errors.ts +93 -0
  415. package/src/server-handshake.ts +783 -0
  416. package/src/server-response.ts +76 -0
  417. package/src/server-trust.ts +245 -0
  418. package/src/setup-confirm.ts +171 -0
  419. package/src/setup.ts +186 -0
  420. package/src/shell-escape.ts +22 -0
  421. package/src/spawn.ts +31 -0
  422. package/src/startup-services.ts +36 -0
  423. package/src/stream-owner.ts +686 -0
  424. package/src/stream-status.ts +337 -0
  425. package/src/sync-roles-render.ts +163 -0
  426. package/src/sync.ts +363 -0
  427. package/src/terminal-title.ts +76 -0
  428. package/src/token-store.ts +102 -0
  429. package/src/tool-manifest.ts +610 -0
  430. package/src/tool-scope.ts +110 -0
  431. package/src/types.ts +5 -0
  432. package/src/unknown-subcommand.ts +35 -0
  433. package/src/version.ts +82 -0
  434. package/src/working-repo.ts +99 -0
  435. package/src/worktree-lifecycle.ts +254 -0
  436. package/dist/auth-recovery.d.ts +0 -33
  437. package/dist/auth-recovery.js +0 -1
  438. package/dist/auth.d.ts +0 -103
  439. package/dist/auth.js +0 -39
  440. package/dist/device-auth.d.ts +0 -75
  441. package/dist/device-auth.js +0 -1
  442. package/dist/drone-address.d.ts +0 -26
  443. package/dist/drone-address.js +0 -1
  444. package/dist/get-started.d.ts +0 -20
  445. package/dist/get-started.js +0 -2
  446. package/dist/health-beat.d.ts +0 -134
  447. package/dist/health-beat.js +0 -1
  448. package/dist/role-section.d.ts +0 -110
  449. package/dist/role-section.js +0 -8
  450. package/dist/setup-action.d.ts +0 -20
  451. package/dist/setup-action.js +0 -1
  452. package/dist/stale-version-check.d.ts +0 -40
  453. package/dist/stale-version-check.js +0 -1
  454. package/dist/subscription-retry.d.ts +0 -40
  455. package/dist/subscription-retry.js +0 -1
  456. package/dist/templates.d.ts +0 -107
  457. package/dist/templates.js +0 -359
  458. package/dist/token-crypto.d.ts +0 -50
  459. package/dist/token-crypto.js +0 -1
package/dist/sync.js CHANGED
@@ -1,22 +1,286 @@
1
- import{spawnSync as y}from"node:child_process";import{basename as p}from"node:path";import o from"chalk";import{adoptWorktree as b,syncWorktree as k,cleanupMerged as v,isMerged as A,perWorktreeBranchName as D}from"./worktree-lifecycle.js";const W={runSync:(i,e,u)=>{const r=y(i,e,{cwd:u,encoding:"utf-8"});return{status:r.status,stdout:r.stdout??"",stderr:r.stderr??""}},cwd:()=>process.cwd(),stderr:i=>process.stderr.write(i),stdout:i=>process.stdout.write(i)},c="origin/main";function x(i,e,u){if(u.startsWith("wt-"))return u;const r=i("git",["rev-parse","--show-toplevel"],e),d=r.status===0?r.stdout.trim():e,s=i("git",["worktree","list","--porcelain"],e);let n=d;if(s.status===0){const t=s.stdout.split(`
2
- `).find(f=>f.startsWith("worktree "));t&&(n=t.slice(9).trim())}return D(p(d),p(n))}function E(i){const{runSync:e,cwd:u}=i,r=u();if(e("git",["rev-parse","--show-toplevel"],r).status!==0)return{kind:"error",reason:`not in a git repository (cwd: ${r})`};const d=e("git",["status","--porcelain"],r);if(d.status!==0)return{kind:"error",reason:`git status failed: ${d.stderr.trim()}`};const s=d.stdout.split(`
3
- `).map(g=>g.trim()).filter(g=>g.length>0);if(s.length>0)return{kind:"dirty",files:s};const n=e("git",["rev-parse","--abbrev-ref","HEAD"],r);if(n.status!==0)return{kind:"error",reason:`cannot resolve current branch: ${n.stderr.trim()}`};const t=n.stdout.trim();if(t==="HEAD")return{kind:"error",reason:"detached HEAD; run `borg assimilate` to adopt a wt- branch first"};const f=e("git",["fetch","origin","--prune"],r);if(f.status!==0)return{kind:"error",reason:`git fetch origin failed: ${f.stderr.trim()}`};const a=x(e,r,t);if(t.startsWith("wt-"))return{kind:"on-wt",branch:t,wtBranch:t};if(t==="main"||t==="master")return{kind:"on-main",branch:t,wtBranch:a};if(A(e,r,"HEAD",c))return{kind:"feature-merged",branch:t,wtBranch:a};const l=e("git",["merge-base","HEAD",c],r),m=l.status===0?l.stdout.trim():"",w=e("git",["rev-list","--count",`${m}..${c}`],r),$=parseInt(w.stdout.trim(),10)||0;return{kind:"feature-mid-sprint",branch:t,wtBranch:a,commits:$}}async function O(i={},e={prune:!1}){const u={...W,...i},{runSync:r,cwd:d,stderr:s,stdout:n}=u,t=E(u);if(t.kind==="error")return s(o.red(`\u25FC borg sync: ${t.reason}
4
- `)),1;if(t.kind==="dirty"){s(o.yellow(`\u25FC Working tree has uncommitted changes.
5
- `));for(const a of t.files.slice(0,5))s(o.gray(` ${a}
6
- `));return t.files.length>5&&s(o.gray(` ... and ${t.files.length-5} more
7
- `)),s(o.yellow("\u25FC Commit, stash, or restore before running `borg sync`. Nothing was changed.\n")),1}if(t.kind==="on-wt"){const a=k(r,d(),t.wtBranch,c);return a.action==="fast-forwarded"?(n(o.blue(`\u25FC On \`${t.wtBranch}\`; fast-forwarded to ${c}.
8
- `)),0):a.action==="already-current"?(n(o.blue(`\u25FC On \`${t.wtBranch}\`; up to date with ${c}.
9
- `)),0):(s(o.yellow(`\u25FC ${a.message??"sync skipped"}.
10
- `)),1)}if(t.kind==="on-main")return h(t.wtBranch,r,d,n,s);if(t.kind==="feature-mid-sprint"){if(t.commits===0)return n(o.blue(`\u25FC On \`${t.branch}\` (feature branch); up to date with ${c}.
11
- `)),n(o.gray(`\u25FC Continue your sprint, or post REVIEW-READY when complete.
12
- `)),0;const a=r("git",["merge","--no-edit",c],d());return a.status!==0?(s(o.red(`\u25FC borg sync: git merge ${c} failed (likely conflict). Resolve manually:
13
- ${a.stderr.trim()}
14
- `)),1):(n(o.blue(`\u25FC On \`${t.branch}\`; merged ${t.commits} commit${t.commits===1?"":"s"} from ${c} (no rebase).
15
- `)),n(o.gray(`\u25FC Re-run tests; continue your sprint.
16
- `)),0)}if(t.kind==="feature-merged"){const a=t.branch,l=h(t.wtBranch,r,d,n,s,{adoptedPrefix:`\u25FC \`${a}\` is merged into ${c};`});if(l!==0)return l;const m=v(r,d(),a,c,{prune:e.prune});return m.action==="pruned"?n(o.blue(`\u25FC Pruned merged branch \`${a}\`.
17
- `)):m.action==="announced"&&n(o.gray(`\u25FC ${m.message}
18
- `)),0}const f=t;return s(o.red(`\u25FC borg sync: unhandled state
19
- `)),1}function h(i,e,u,r,d,s={}){const n=b(e,u(),i,c);return n.action==="adopted"?(s.adoptedPrefix?r(o.blue(`${s.adoptedPrefix} switched to \`${i}\` at ${c}.
20
- `)):r(o.blue(`\u25FC On \`${i}\` at ${c}.
21
- `)),0):(d(o.yellow(`\u25FC borg sync: ${n.message??"not adopted"}. Nothing was changed.
22
- `)),1)}function P(i){let e=!1;for(const u of i)if(u==="--prune")e=!0;else return{ok:!1,error:`unexpected argument: ${u}. Usage: borg sync [--prune]`};return{ok:!0,options:{prune:e}}}export{E as detectState,P as parseSyncArgs,x as resolveWtBranch,O as runSync};
1
+ /**
2
+ * `borg sync` worktree lifecycle management subcommand (gh#33).
3
+ *
4
+ * Reconciled to the per-worktree `wt-<suffix>` branch model (PR-B,
5
+ * ruling ea643b33). Replaces the previous main-centric semantics
6
+ * ("idle = on main"; "post-merge = checkout main") — under the approved
7
+ * gh#33 model `main` is NEVER a working branch in any worktree; it is
8
+ * purely the integration target. Every worktree works on a named
9
+ * `wt-<suffix>` branch and `borg sync` keeps it current with
10
+ * origin/main, returns to it after a feature branch merges, and absorbs
11
+ * upstream into an in-progress feature branch — never touching `main`
12
+ * as a checkout.
13
+ *
14
+ * All git mutation/decision logic is delegated to
15
+ * `src/worktree-lifecycle.ts` (the seam PR-A added:
16
+ * `adoptWorktree`, `syncWorktree`, `cleanupMerged`, `isMerged`,
17
+ * `localBranchExists`) so the never-discard guards (dirty / unmerged
18
+ * HEAD / unmerged target wt- branch) and the args-array subprocess
19
+ * shape are shared, not duplicated.
20
+ *
21
+ * Lifecycle states:
22
+ * 1. dirty — uncommitted changes; refuse (never discard).
23
+ * 2. on-wt — on the per-worktree `wt-<suffix>` branch;
24
+ * fast-forward it to origin/main (ff-only).
25
+ * 3. on-main — on `main`/`master` (or detached at a merged
26
+ * point); adopt the `wt-<suffix>` branch
27
+ * (Q4: main is never a working branch).
28
+ * 4. feature-mid-sprint — on a feature branch not yet merged; absorb
29
+ * origin/main into it via `git merge --no-edit`
30
+ * (no rebase — cube workflow rule (a)) when
31
+ * origin/main advanced; else no-op.
32
+ * 5. feature-merged — on a feature branch fully merged into
33
+ * origin/main; return to `wt-<suffix>` and
34
+ * ANNOUNCE the prunable feature branch (prune
35
+ * only with `--prune`, Q3).
36
+ *
37
+ * Anti-features (intentional, unchanged):
38
+ * - No auto-stash / auto-commit / auto-discard on dirty tree.
39
+ * - No force-push, no rebase, no --force-with-lease.
40
+ * - No remote-branch deletion (Coordinator owns merge actions).
41
+ * - Local feature-branch deletion only on explicit `--prune` (Q3).
42
+ */
43
+ import { spawnSync } from 'node:child_process';
44
+ import { basename } from 'node:path';
45
+ import chalk from 'chalk';
46
+ import { adoptWorktree, syncWorktree, cleanupMerged, isMerged, perWorktreeBranchName, } from './worktree-lifecycle.js';
47
+ const defaultDeps = {
48
+ runSync: (cmd, args, cwd) => {
49
+ const r = spawnSync(cmd, args, { cwd, encoding: 'utf-8' });
50
+ return {
51
+ status: r.status,
52
+ stdout: r.stdout ?? '',
53
+ stderr: r.stderr ?? '',
54
+ };
55
+ },
56
+ cwd: () => process.cwd(),
57
+ stderr: (line) => process.stderr.write(line),
58
+ stdout: (line) => process.stdout.write(line),
59
+ };
60
+ const DEFAULT_BRANCH = 'origin/main';
61
+ // ------------------------------------------------------------------
62
+ // wt- branch resolution
63
+ // ------------------------------------------------------------------
64
+ /**
65
+ * Resolve the per-worktree `wt-` branch for the current checkout,
66
+ * DETERMINISTICALLY per worktree.
67
+ *
68
+ * - current branch is already `wt-*` → that is the branch.
69
+ * - otherwise → derive `wt-<suffix>` from THIS worktree's directory
70
+ * basename minus the main worktree's (repo) basename prefix — the
71
+ * same `perWorktreeBranchName` derivation the spawn path uses, so
72
+ * the name matches what `borg assimilate --worktree` created.
73
+ *
74
+ * This must NOT list `git branch --list wt-*`: in linked worktrees the
75
+ * local branch namespace is SHARED across all siblings (gh#33 CR-v2
76
+ * blocker 32bc45da), so every drone's `wt-` branch is visible and a
77
+ * "single match" heuristic is never satisfied in a real multi-drone
78
+ * cube. The directory-derivation is unique per worktree and never
79
+ * ambiguous. The first `worktree <path>` line of
80
+ * `git worktree list --porcelain` is the main worktree (the repo dir);
81
+ * its basename is the prefix to strip. For an independent clone the
82
+ * main worktree IS this worktree, so the prefix == basename and the
83
+ * result is `wt-<basename>` (no strip) — consistent with PR-A's
84
+ * in-place adoption.
85
+ */
86
+ export function resolveWtBranch(runSync, cwd, currentBranch) {
87
+ if (currentBranch.startsWith('wt-'))
88
+ return currentBranch;
89
+ const top = runSync('git', ['rev-parse', '--show-toplevel'], cwd);
90
+ const thisDir = top.status === 0 ? top.stdout.trim() : cwd;
91
+ const wtList = runSync('git', ['worktree', 'list', '--porcelain'], cwd);
92
+ let mainDir = thisDir;
93
+ if (wtList.status === 0) {
94
+ const firstWorktreeLine = wtList.stdout
95
+ .split('\n')
96
+ .find((l) => l.startsWith('worktree '));
97
+ if (firstWorktreeLine)
98
+ mainDir = firstWorktreeLine.slice('worktree '.length).trim();
99
+ }
100
+ return perWorktreeBranchName(basename(thisDir), basename(mainDir));
101
+ }
102
+ /**
103
+ * Detect the worktree's lifecycle state. Read-only except for the
104
+ * `git fetch origin --prune` needed to measure against the latest tip.
105
+ */
106
+ export function detectState(deps) {
107
+ const { runSync, cwd } = deps;
108
+ const cwdValue = cwd();
109
+ // (1) git repo?
110
+ if (runSync('git', ['rev-parse', '--show-toplevel'], cwdValue).status !== 0) {
111
+ return { kind: 'error', reason: `not in a git repository (cwd: ${cwdValue})` };
112
+ }
113
+ // (2) dirty FIRST — never act on uncommitted changes.
114
+ const status = runSync('git', ['status', '--porcelain'], cwdValue);
115
+ if (status.status !== 0) {
116
+ return { kind: 'error', reason: `git status failed: ${status.stderr.trim()}` };
117
+ }
118
+ const dirty = status.stdout.split('\n').map((l) => l.trim()).filter((l) => l.length > 0);
119
+ if (dirty.length > 0)
120
+ return { kind: 'dirty', files: dirty };
121
+ // (3) current branch.
122
+ const branchProbe = runSync('git', ['rev-parse', '--abbrev-ref', 'HEAD'], cwdValue);
123
+ if (branchProbe.status !== 0) {
124
+ return { kind: 'error', reason: `cannot resolve current branch: ${branchProbe.stderr.trim()}` };
125
+ }
126
+ const branch = branchProbe.stdout.trim();
127
+ if (branch === 'HEAD') {
128
+ return { kind: 'error', reason: 'detached HEAD; run `borg assimilate` to adopt a wt- branch first' };
129
+ }
130
+ // (4) fetch — fatal on failure (can't reason about lifecycle offline).
131
+ const fetch = runSync('git', ['fetch', 'origin', '--prune'], cwdValue);
132
+ if (fetch.status !== 0) {
133
+ return { kind: 'error', reason: `git fetch origin failed: ${fetch.stderr.trim()}` };
134
+ }
135
+ const wtBranch = resolveWtBranch(runSync, cwdValue, branch);
136
+ // (5) on the per-worktree wt- branch.
137
+ if (branch.startsWith('wt-')) {
138
+ return { kind: 'on-wt', branch, wtBranch: branch };
139
+ }
140
+ // (6) on main/master — Q4: never a working branch; adopt wt-.
141
+ if (branch === 'main' || branch === 'master') {
142
+ return { kind: 'on-main', branch, wtBranch };
143
+ }
144
+ // (7) feature branch — merged vs mid-sprint.
145
+ // ASSUMPTION (gh#33 CR NIT 0e19637a): merged-detection keys off commit
146
+ // ancestry (`isMerged` = HEAD is an ancestor of origin/main), which
147
+ // holds for merge-commit / fast-forward integration. A squash- or
148
+ // rebase-merged PR leaves the feature tip a NON-ancestor → it would
149
+ // classify here as mid-sprint, not merged. That degrades safely
150
+ // (merge-back of origin/main, no discard), and this cube integrates
151
+ // via merge commits, so it is not triggered. If squash-merge is ever
152
+ // adopted, switch this to PR-merged-state detection.
153
+ if (isMerged(runSync, cwdValue, 'HEAD', DEFAULT_BRANCH)) {
154
+ return { kind: 'feature-merged', branch, wtBranch };
155
+ }
156
+ // not merged → mid-sprint. Count how far origin/main advanced past the
157
+ // merge-base so the message can report it (0 → no-op).
158
+ const mergeBase = runSync('git', ['merge-base', 'HEAD', DEFAULT_BRANCH], cwdValue);
159
+ const base = mergeBase.status === 0 ? mergeBase.stdout.trim() : '';
160
+ const count = runSync('git', ['rev-list', '--count', `${base}..${DEFAULT_BRANCH}`], cwdValue);
161
+ const commits = parseInt(count.stdout.trim(), 10) || 0;
162
+ return { kind: 'feature-mid-sprint', branch, wtBranch, commits };
163
+ }
164
+ // ------------------------------------------------------------------
165
+ // Orchestrator
166
+ // ------------------------------------------------------------------
167
+ export async function runSync(deps = {}, opts = { prune: false }) {
168
+ const merged = { ...defaultDeps, ...deps };
169
+ const { runSync: run, cwd, stderr, stdout } = merged;
170
+ const state = detectState(merged);
171
+ if (state.kind === 'error') {
172
+ stderr(chalk.red(`◼ borg sync: ${state.reason}\n`));
173
+ return 1;
174
+ }
175
+ if (state.kind === 'dirty') {
176
+ stderr(chalk.yellow(`◼ Working tree has uncommitted changes.\n`));
177
+ for (const line of state.files.slice(0, 5))
178
+ stderr(chalk.gray(` ${line}\n`));
179
+ if (state.files.length > 5)
180
+ stderr(chalk.gray(` ... and ${state.files.length - 5} more\n`));
181
+ stderr(chalk.yellow(`◼ Commit, stash, or restore before running \`borg sync\`. Nothing was changed.\n`));
182
+ return 1;
183
+ }
184
+ // on-wt: fast-forward the per-worktree branch to origin/main (ff-only,
185
+ // clean-gated, never merge/rebase). Delegates to syncWorktree.
186
+ if (state.kind === 'on-wt') {
187
+ const res = syncWorktree(run, cwd(), state.wtBranch, DEFAULT_BRANCH);
188
+ if (res.action === 'fast-forwarded') {
189
+ stdout(chalk.blue(`◼ On \`${state.wtBranch}\`; fast-forwarded to ${DEFAULT_BRANCH}.\n`));
190
+ return 0;
191
+ }
192
+ if (res.action === 'already-current') {
193
+ stdout(chalk.blue(`◼ On \`${state.wtBranch}\`; up to date with ${DEFAULT_BRANCH}.\n`));
194
+ return 0;
195
+ }
196
+ // skipped-diverged: the wt- branch has local commits not on origin/main.
197
+ stderr(chalk.yellow(`◼ ${res.message ?? 'sync skipped'}.\n`));
198
+ return 1;
199
+ }
200
+ // on-main: adopt the wt- branch (Q4 — move off main). adoptWorktree
201
+ // applies the dirty / unmerged-HEAD / unmerged-target guards.
202
+ if (state.kind === 'on-main') {
203
+ return adoptAndReport(state.wtBranch, run, cwd, stdout, stderr);
204
+ }
205
+ // feature-mid-sprint: absorb origin/main into the feature branch (no
206
+ // rebase). Leaves the drone on the feature branch to keep working.
207
+ if (state.kind === 'feature-mid-sprint') {
208
+ if (state.commits === 0) {
209
+ stdout(chalk.blue(`◼ On \`${state.branch}\` (feature branch); up to date with ${DEFAULT_BRANCH}.\n`));
210
+ stdout(chalk.gray(`◼ Continue your sprint, or post REVIEW-READY when complete.\n`));
211
+ return 0;
212
+ }
213
+ const merge = run('git', ['merge', '--no-edit', DEFAULT_BRANCH], cwd());
214
+ if (merge.status !== 0) {
215
+ stderr(chalk.red(`◼ borg sync: git merge ${DEFAULT_BRANCH} failed (likely conflict). Resolve manually:\n${merge.stderr.trim()}\n`));
216
+ return 1;
217
+ }
218
+ stdout(chalk.blue(`◼ On \`${state.branch}\`; merged ${state.commits} commit${state.commits === 1 ? '' : 's'} from ${DEFAULT_BRANCH} (no rebase).\n`));
219
+ stdout(chalk.gray(`◼ Re-run tests; continue your sprint.\n`));
220
+ return 0;
221
+ }
222
+ // feature-merged: the PR merged. Return to the wt- branch (adopt) and
223
+ // announce the prunable feature branch (prune only with --prune, Q3).
224
+ if (state.kind === 'feature-merged') {
225
+ const feature = state.branch;
226
+ const code = adoptAndReport(state.wtBranch, run, cwd, stdout, stderr, {
227
+ adoptedPrefix: `◼ \`${feature}\` is merged into ${DEFAULT_BRANCH};`,
228
+ });
229
+ if (code !== 0)
230
+ return code; // adoption blocked (dirty/unmerged target) — don't prune
231
+ // Now on the wt- branch — safe to prune/announce the merged feature.
232
+ const cleanup = cleanupMerged(run, cwd(), feature, DEFAULT_BRANCH, { prune: opts.prune });
233
+ if (cleanup.action === 'pruned') {
234
+ stdout(chalk.blue(`◼ Pruned merged branch \`${feature}\`.\n`));
235
+ }
236
+ else if (cleanup.action === 'announced') {
237
+ stdout(chalk.gray(`◼ ${cleanup.message}\n`));
238
+ }
239
+ return 0;
240
+ }
241
+ // Exhaustiveness.
242
+ const _exhaustive = state;
243
+ stderr(chalk.red(`◼ borg sync: unhandled state\n`));
244
+ return 1;
245
+ }
246
+ /**
247
+ * Shared adopt-the-wt-branch path for the on-main + feature-merged
248
+ * states. Surfaces the never-discard outcomes; returns the process exit
249
+ * code (0 adopted, 1 blocked/ambiguous).
250
+ */
251
+ function adoptAndReport(wtBranch, run, cwd, stdout, stderr, opts = {}) {
252
+ const res = adoptWorktree(run, cwd(), wtBranch, DEFAULT_BRANCH);
253
+ if (res.action === 'adopted') {
254
+ if (opts.adoptedPrefix) {
255
+ stdout(chalk.blue(`${opts.adoptedPrefix} switched to \`${wtBranch}\` at ${DEFAULT_BRANCH}.\n`));
256
+ }
257
+ else {
258
+ stdout(chalk.blue(`◼ On \`${wtBranch}\` at ${DEFAULT_BRANCH}.\n`));
259
+ }
260
+ return 0;
261
+ }
262
+ // skipped-dirty handled upstream (dirty state), but defensively surface.
263
+ stderr(chalk.yellow(`◼ borg sync: ${res.message ?? 'not adopted'}. Nothing was changed.\n`));
264
+ return 1;
265
+ }
266
+ /**
267
+ * Parse args after `borg sync`. Supports `--prune` (Q3: delete a merged
268
+ * feature branch after returning to the wt- branch). Rejects anything
269
+ * else to keep room for future flags.
270
+ */
271
+ export function parseSyncArgs(rawArgs) {
272
+ let prune = false;
273
+ for (const arg of rawArgs) {
274
+ if (arg === '--prune') {
275
+ prune = true;
276
+ }
277
+ else {
278
+ return {
279
+ ok: false,
280
+ error: `unexpected argument: ${arg}. Usage: borg sync [--prune]`,
281
+ };
282
+ }
283
+ }
284
+ return { ok: true, options: { prune } };
285
+ }
286
+ //# sourceMappingURL=sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal-title.d.ts","sourceRoot":"","sources":["../src/terminal-title.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,WAAW,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,EACvD,YAAY,EAAE,MAAM,GACnB,MAAM,CAKR;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,EACvD,YAAY,EAAE,MAAM,EACpB,MAAM,GAAE,MAAM,CAAC,WAA4B,GAC1C,MAAM,CASR"}
@@ -1 +1,68 @@
1
- function n(e,r){return e?`borg \xB7 ${e.label} \xB7 ${e.cubeName}`:`borg \xB7 ${r}`}function o(e,r,t=process.stdout){const i=n(e,r);return t.isTTY&&t.write(`\x1B]0;${i}\x07`),i}export{n as composeTerminalTitle,o as setTerminalTitle};
1
+ /**
2
+ * Terminal-title setter for borg drone sessions.
3
+ *
4
+ * Multiple Claude Code sessions across sibling worktrees are visually
5
+ * indistinguishable in Cmd-Tab / tab bars / Mission Control on macOS,
6
+ * and likewise on most Linux terminal emulators. Setting the terminal
7
+ * title via the OSC 0 / OSC 2 escape gives each window a free per-
8
+ * session identity.
9
+ *
10
+ * Format (Queen-specified):
11
+ * - Assimilated drone session: `borg · <label> · <cubeName>`
12
+ * - Unassimilated session: `borg · <repo-basename>`
13
+ *
14
+ * Why OSC 0 (`\x1b]0;…\x07`): sets both window title AND icon name on
15
+ * most terminals. OSC 2 sets only window title; OSC 1 sets only icon
16
+ * name. OSC 0 is the maximally-portable choice — works in iTerm2,
17
+ * macOS Terminal, kitty, alacritty, ghostty, GNOME Terminal, xterm.
18
+ *
19
+ * Lifetime: the escape is emitted once, before spawning Claude Code.
20
+ * Claude Code itself does not set its own window title (verified
21
+ * 2026-05-11), so the borg-set title persists for the whole session.
22
+ *
23
+ * Limitations (acceptable for v1; flagged for future):
24
+ * - Title doesn't update mid-session on `borg_assimilate`. The
25
+ * borgmcp client process can't write the escape post-spawn
26
+ * because stdio is owned by Claude Code at that point (and stdio
27
+ * to Claude is JSON-RPC — terminal escapes would be parsed as
28
+ * invalid messages).
29
+ * - Falls back to repo-basename for the unassimilated case; loses
30
+ * drone identity until the cube is joined. Typical pattern is
31
+ * "drone has been around long enough that cubes.json is already
32
+ * populated," so the assimilated path is the common case.
33
+ */
34
+ /**
35
+ * Pure: compose the title string for a session. Exported so tests can
36
+ * exercise every branch without TTY / process / fs dependencies.
37
+ *
38
+ * @param activeDrone — `{label, cubeName}` if this project is
39
+ * assimilated to a cube, null otherwise.
40
+ * @param repoBasename — fallback identity for the unassimilated case
41
+ * (typically `basename(process.cwd())`).
42
+ */
43
+ export function composeTerminalTitle(activeDrone, repoBasename) {
44
+ if (activeDrone) {
45
+ return `borg · ${activeDrone.label} · ${activeDrone.cubeName}`;
46
+ }
47
+ return `borg · ${repoBasename}`;
48
+ }
49
+ /**
50
+ * Side-effecting: emit the OSC 0 escape to stdout, but only if stdout
51
+ * is a TTY. When stdout is piped (CI, redirection, scripted
52
+ * invocation), emitting the raw escape would pollute the captured
53
+ * output without doing anything useful — so we no-op.
54
+ *
55
+ * Returns the title string that WOULD have been emitted, regardless of
56
+ * TTY state, so callers can log it independently for diagnostics.
57
+ */
58
+ export function setTerminalTitle(activeDrone, repoBasename, stdout = process.stdout) {
59
+ const title = composeTerminalTitle(activeDrone, repoBasename);
60
+ if (stdout.isTTY) {
61
+ // OSC 0: ESC ] 0 ; <title> BEL
62
+ // (BEL terminator is honored by all OSC-supporting terminals;
63
+ // ST = `ESC \` is an alternative but BEL has wider compat.)
64
+ stdout.write(`\x1b]0;${title}\x07`);
65
+ }
66
+ return title;
67
+ }
68
+ //# sourceMappingURL=terminal-title.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal-title.js","sourceRoot":"","sources":["../src/terminal-title.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAClC,WAAuD,EACvD,YAAoB;IAEpB,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,UAAU,WAAW,CAAC,KAAK,MAAM,WAAW,CAAC,QAAQ,EAAE,CAAC;IACjE,CAAC;IACD,OAAO,UAAU,YAAY,EAAE,CAAC;AAClC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,gBAAgB,CAC9B,WAAuD,EACvD,YAAoB,EACpB,SAA6B,OAAO,CAAC,MAAM;IAE3C,MAAM,KAAK,GAAG,oBAAoB,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IAC9D,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,+BAA+B;QAC/B,8DAA8D;QAC9D,4DAA4D;QAC5D,MAAM,CAAC,KAAK,CAAC,UAAU,KAAK,MAAM,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -1,27 +1,14 @@
1
1
  /**
2
- * gh#557 token storage backends + selection.
2
+ * Local-server credential backend.
3
3
  *
4
- * config.ts exposes the public token API (storeIdToken/getIdToken/...). This
5
- * module supplies the interchangeable storage engines it sits on top of:
6
- *
7
- * - KeychainBackend — OS keychain via @napi-rs/keyring (the default;
8
- * real platform at-rest encryption).
9
- * - EncryptedFileBackend — ~/.borg/credentials, all accounts in one
10
- * AES-256-GCM blob, file 0600 / dir 0700. Engages
11
- * only when no keychain is available. Obfuscation-
12
- * grade (see token-crypto.ts).
13
- * - caller-managed — BORG_TOKEN / BORG_TOKEN_FILE: an externally
14
- * supplied id_token, used read-only with no store
15
- * (the caller owns its lifecycle/freshness).
16
- *
17
- * Every engine takes its side-effecting dependencies (keyring entry factory,
18
- * fs, machine key) by injection so the logic is unit-tested without a real
19
- * keychain or disk.
4
+ * config.ts's local-server credential group sits on top of this. Storage is the
5
+ * 0600 file store (Queen rescope) the OS keychain (@napi-rs/keyring) is GONE.
6
+ * The raw secret rests only in the 0600 file, parity with the server's own TLS
7
+ * private keys; there is no keychain and no obfuscation-grade fallback.
20
8
  */
21
- export type TokenBackendName = 'keychain' | 'encrypted-file';
9
+ export type TokenBackendName = 'file';
22
10
  /**
23
- * Account-agnostic key/value store over a backing engine. `account` is one
24
- * of config.ts's three slots (id-token, refresh-token, expiry).
11
+ * Account-agnostic key/value store over the 0600 credential file.
25
12
  */
26
13
  export interface TokenBackend {
27
14
  readonly name: TokenBackendName;
@@ -30,97 +17,16 @@ export interface TokenBackend {
30
17
  delete(account: string): Promise<void>;
31
18
  }
32
19
  /**
33
- * The slice of @napi-rs/keyring's AsyncEntry this backend depends on. The
34
- * return types mirror AsyncEntry exactly (deletePassword resolves to an
35
- * implementation-defined value we ignore) so the real class is assignable.
36
- */
37
- export interface KeyringEntry {
38
- setPassword(value: string): Promise<void>;
39
- getPassword(): Promise<string | null | undefined>;
40
- deletePassword(): Promise<unknown>;
41
- }
42
- export type KeyringEntryFactory = (account: string) => KeyringEntry;
43
- /**
44
- * Build the OS-keychain backend. Preserves config.ts's prior semantics:
45
- * a missing entry reads as null, and delete is silent on a NoEntry error
46
- * (idempotent clear) while other errors propagate (fail-loud).
47
- */
48
- export declare function makeKeychainBackend(entryFactory?: KeyringEntryFactory): TokenBackend;
49
- /** The minimal fs surface the file backend needs (injected for tests). */
50
- export interface FileStoreFs {
51
- readFile(filePath: string): Promise<string>;
52
- writeFile(filePath: string, data: string, mode: number): Promise<void>;
53
- mkdir(dir: string, mode: number): Promise<void>;
54
- /** Atomically move `from`→`to` (overwrites). Used for crash-safe writes. */
55
- rename(from: string, to: string): Promise<void>;
56
- /**
57
- * Atomically create `lockPath` ONLY if it does not exist (O_EXCL). Resolves
58
- * `true` if it was created (lock acquired) or `false` if it already existed
59
- * (lock held by another process). This is the inter-process serialization
60
- * primitive — no native dependency.
61
- */
62
- createExclusive(lockPath: string, content: string): Promise<boolean>;
63
- /** Remove a file; silent if already gone (lock release + stale-lock steal). */
64
- removeFile(filePath: string): Promise<void>;
65
- /** Age in ms (now − mtime) of a file, or null if it does not exist. */
66
- fileAgeMs(filePath: string): Promise<number | null>;
67
- }
68
- export interface EncryptedFileBackendDeps {
69
- filePath: string;
70
- key: Buffer;
71
- fs: FileStoreFs;
72
- /** Backoff between lock-acquire retries; defaults to a real setTimeout sleep. */
73
- sleep?: (ms: number) => Promise<void>;
74
- /** Monotonic clock for the acquire deadline; defaults to Date.now. */
75
- now?: () => number;
76
- /** Unique suffix for the write temp file; defaults to a random hex token. */
77
- uniqueSuffix?: () => string;
78
- }
79
- /**
80
- * Build the encrypted-file backend. All accounts live in one JSON object
81
- * encrypted as a single AES-256-GCM envelope at `filePath`.
82
- *
83
- * A missing file reads as an empty map. A file that won't decrypt (wrong
84
- * machine key after a hostname change, truncation, tampering) is ALSO
85
- * treated as empty: the only consequence is the user re-runs `borg setup`,
86
- * which is the right fail-safe for credential material — a hard crash on a
87
- * corrupt dotfile would be worse UX than transparent re-auth.
20
+ * Build a TokenBackend over a single 0600 store file, all accounts held in one
21
+ * `{version, accounts}` map. get/set/delete read-modify-write the file via the
22
+ * seat-store's atomic 0600 writer the RAW secret rests only in the 0600 file
23
+ * (parity with the server's TLS keys), never a keychain.
88
24
  *
89
- * gh#570 concurrency + atomicity. Multiple `borg` processes (e.g. sibling
90
- * drone sessions on one host) can share `~/.borg/credentials`. Two fixes:
91
- * - Anti-lost-update (load-bearing): `set`/`delete` serialize their whole
92
- * read-modify-write cycle behind an O_EXCL lock file, so concurrent
93
- * writers no longer each read a stale map and clobber each other.
94
- * - Anti-corruption: every write goes to a unique temp file then `rename`s
95
- * into place, so a reader (which is intentionally lock-FREE) always sees a
96
- * complete old-or-new file, never a torn one.
97
- */
98
- export declare function makeEncryptedFileBackend(deps: EncryptedFileBackendDeps): TokenBackend;
99
- /** User-facing BORG_TOKEN_STORE values (friendlier than the backend names). */
100
- export type ForcedStore = 'keychain' | 'file';
101
- export interface SelectTokenBackendDeps {
102
- keyringAvailable: () => Promise<boolean>;
103
- makeKeychain: () => TokenBackend;
104
- makeFile: () => TokenBackend;
105
- /** BORG_TOKEN_STORE override: skip probing and force a backend. */
106
- forced?: ForcedStore;
107
- }
108
- /**
109
- * Select the persistent backend: a forced choice (BORG_TOKEN_STORE=keychain|file)
110
- * wins and skips the probe; otherwise probe the keychain and fall back to the
111
- * encrypted file when it's unavailable.
112
- */
113
- export declare function selectTokenBackend(deps: SelectTokenBackendDeps): Promise<TokenBackend>;
114
- export interface CallerManagedDeps {
115
- env: NodeJS.ProcessEnv;
116
- readFile: (filePath: string) => Promise<string>;
117
- }
118
- /**
119
- * Resolve an externally-supplied id_token (no storage). BORG_TOKEN takes
120
- * precedence; otherwise BORG_TOKEN_FILE is read from disk. Returns null when
121
- * neither is configured. The value is trimmed (env vars and files commonly
122
- * carry trailing newlines). The caller owns this token's freshness, so it
123
- * bypasses the keychain AND the expiry check in config.ts.
25
+ * These ops are NON-flocking by design: the config layer holds the single store
26
+ * lock (withStoreLock over CREDENTIALS_LOCK) continuously across each
27
+ * read-compare-write, so nesting a second lock here would deadlock the O_EXCL
28
+ * lockfile. Pure reads (get) are safe lock-free because atomicWrite0600's rename
29
+ * guarantees a reader only ever sees a complete file.
124
30
  */
125
- export declare function readCallerManagedIdToken(deps: CallerManagedDeps): Promise<string | null>;
31
+ export declare function makeFileBackend(filePath: string): TokenBackend;
126
32
  //# sourceMappingURL=token-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-store.d.ts","sourceRoot":"","sources":["../src/token-store.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAEtC;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC7C,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC;AAID;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,CA8D9D"}