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.
- package/CONTRIBUTING.md +15 -0
- package/LICENSE +201 -33
- package/NOTICE +2 -0
- package/README.md +85 -36
- package/SECURITY.md +7 -0
- package/dist/agent-runtime.d.ts.map +1 -0
- package/dist/agent-runtime.js +63 -1
- package/dist/agent-runtime.js.map +1 -0
- package/dist/assimilate-cmd.d.ts +96 -17
- package/dist/assimilate-cmd.d.ts.map +1 -0
- package/dist/assimilate-cmd.js +1396 -48
- package/dist/assimilate-cmd.js.map +1 -0
- package/dist/assimilate-deps.d.ts.map +1 -0
- package/dist/assimilate-deps.js +384 -3
- package/dist/assimilate-deps.js.map +1 -0
- package/dist/assimilate-guard.d.ts +5 -7
- package/dist/assimilate-guard.d.ts.map +1 -0
- package/dist/assimilate-guard.js +60 -2
- package/dist/assimilate-guard.js.map +1 -0
- package/dist/assimilate-welcome.d.ts +1 -1
- package/dist/assimilate-welcome.d.ts.map +1 -0
- package/dist/assimilate-welcome.js +32 -2
- package/dist/assimilate-welcome.js.map +1 -0
- package/dist/auth-env.d.ts +7 -50
- package/dist/auth-env.d.ts.map +1 -0
- package/dist/auth-env.js +22 -1
- package/dist/auth-env.js.map +1 -0
- package/dist/backends/launch-all-pastelist.d.ts.map +1 -0
- package/dist/backends/launch-all-pastelist.js +11 -4
- package/dist/backends/launch-all-pastelist.js.map +1 -0
- package/dist/backends/launch-all-tmux.d.ts.map +1 -0
- package/dist/backends/launch-all-tmux.js +49 -1
- package/dist/backends/launch-all-tmux.js.map +1 -0
- package/dist/backends/launch-all-windows.d.ts.map +1 -0
- package/dist/backends/launch-all-windows.js +86 -12
- package/dist/backends/launch-all-windows.js.map +1 -0
- package/dist/bare-launch-menu.d.ts.map +1 -0
- package/dist/bare-launch-menu.js +83 -6
- package/dist/bare-launch-menu.js.map +1 -0
- package/dist/claude-launch-args.d.ts.map +1 -0
- package/dist/claude-launch-args.js +34 -1
- package/dist/claude-launch-args.js.map +1 -0
- package/dist/claude.d.ts.map +1 -0
- package/dist/claude.js +486 -14
- package/dist/claude.js.map +1 -0
- package/dist/cleanup-cmd.d.ts +5 -5
- package/dist/cleanup-cmd.d.ts.map +1 -0
- package/dist/cleanup-cmd.js +453 -14
- package/dist/cleanup-cmd.js.map +1 -0
- package/dist/clear-rewake-core.d.ts.map +1 -0
- package/dist/clear-rewake-core.js +23 -2
- package/dist/clear-rewake-core.js.map +1 -0
- package/dist/clear-rewake.d.ts.map +1 -0
- package/dist/clear-rewake.js +19 -1
- package/dist/clear-rewake.js.map +1 -0
- package/dist/cli-help.d.ts +5 -0
- package/dist/cli-help.d.ts.map +1 -0
- package/dist/cli-help.js +104 -56
- package/dist/cli-help.js.map +1 -0
- package/dist/cli-platform.d.ts.map +1 -0
- package/dist/cli-platform.js +106 -4
- package/dist/cli-platform.js.map +1 -0
- package/dist/cli-tool-approval.d.ts +84 -0
- package/dist/cli-tool-approval.d.ts.map +1 -0
- package/dist/cli-tool-approval.js +583 -0
- package/dist/cli-tool-approval.js.map +1 -0
- package/dist/codex-app-server.d.ts.map +1 -0
- package/dist/codex-app-server.js +228 -4
- package/dist/codex-app-server.js.map +1 -0
- package/dist/codex-app-wake.d.ts.map +1 -0
- package/dist/codex-app-wake.js +432 -2
- package/dist/codex-app-wake.js.map +1 -0
- package/dist/codex-launch.d.ts.map +1 -0
- package/dist/codex-launch.js +102 -2
- package/dist/codex-launch.js.map +1 -0
- package/dist/codex-remote.d.ts +6 -1
- package/dist/codex-remote.d.ts.map +1 -0
- package/dist/codex-remote.js +394 -1
- package/dist/codex-remote.js.map +1 -0
- package/dist/codex-wake-resolve.d.ts.map +1 -0
- package/dist/codex-wake-resolve.js +127 -1
- package/dist/codex-wake-resolve.js.map +1 -0
- package/dist/config-utils.d.ts +2 -2
- package/dist/config-utils.d.ts.map +1 -0
- package/dist/config-utils.js +766 -3
- package/dist/config-utils.js.map +1 -0
- package/dist/config.d.ts +98 -61
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +426 -1
- package/dist/config.js.map +1 -0
- package/dist/console-prefix.d.ts.map +1 -0
- package/dist/console-prefix.js +96 -1
- package/dist/console-prefix.js.map +1 -0
- package/dist/cube-name.d.ts.map +1 -0
- package/dist/cube-name.js +67 -1
- package/dist/cube-name.js.map +1 -0
- package/dist/cubes.d.ts +126 -18
- package/dist/cubes.d.ts.map +1 -0
- package/dist/cubes.js +412 -4
- package/dist/cubes.js.map +1 -0
- package/dist/debug.d.ts.map +1 -0
- package/dist/debug.js +71 -1
- package/dist/debug.js.map +1 -0
- package/dist/direct-log.d.ts.map +1 -0
- package/dist/direct-log.js +11 -1
- package/dist/direct-log.js.map +1 -0
- package/dist/docs-sections.d.ts +11 -10
- package/dist/docs-sections.d.ts.map +1 -0
- package/dist/docs-sections.js +113 -3
- package/dist/docs-sections.js.map +1 -0
- package/dist/drone-lifecycle.d.ts +5 -21
- package/dist/drone-lifecycle.d.ts.map +1 -0
- package/dist/drone-lifecycle.js +57 -8
- package/dist/drone-lifecycle.js.map +1 -0
- package/dist/drone-management.d.ts +29 -0
- package/dist/drone-management.d.ts.map +1 -0
- package/dist/drone-management.js +109 -0
- package/dist/drone-management.js.map +1 -0
- package/dist/ensure-mcp-config.d.ts.map +1 -0
- package/dist/ensure-mcp-config.js +36 -1
- package/dist/ensure-mcp-config.js.map +1 -0
- package/dist/evict-drone.d.ts +10 -2
- package/dist/evict-drone.d.ts.map +1 -0
- package/dist/evict-drone.js +60 -1
- package/dist/evict-drone.js.map +1 -0
- package/dist/gc-orphan-inboxes.d.ts.map +1 -0
- package/dist/gc-orphan-inboxes.js +177 -1
- package/dist/gc-orphan-inboxes.js.map +1 -0
- package/dist/inbox-monitor.d.ts +1 -1
- package/dist/inbox-monitor.d.ts.map +1 -0
- package/dist/inbox-monitor.js +856 -3
- package/dist/inbox-monitor.js.map +1 -0
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1034 -37
- package/dist/index.js.map +1 -0
- package/dist/launch-all-cmd.d.ts.map +1 -0
- package/dist/launch-all-cmd.js +377 -37
- package/dist/launch-all-cmd.js.map +1 -0
- package/dist/launch-all-command.d.ts.map +1 -0
- package/dist/launch-all-command.js +24 -1
- package/dist/launch-all-command.js.map +1 -0
- package/dist/launch-all-deps.d.ts +3 -8
- package/dist/launch-all-deps.d.ts.map +1 -0
- package/dist/launch-all-deps.js +99 -1
- package/dist/launch-all-deps.js.map +1 -0
- package/dist/launch-all-discovery.d.ts +1 -0
- package/dist/launch-all-discovery.d.ts.map +1 -0
- package/dist/launch-all-discovery.js +90 -4
- package/dist/launch-all-discovery.js.map +1 -0
- package/dist/launch-all-locks.d.ts.map +1 -0
- package/dist/launch-all-locks.js +54 -1
- package/dist/launch-all-locks.js.map +1 -0
- package/dist/launch-gate.d.ts +2 -2
- package/dist/launch-gate.d.ts.map +1 -0
- package/dist/launch-gate.js +73 -1
- package/dist/launch-gate.js.map +1 -0
- package/dist/lifecycle-log-guard.d.ts.map +1 -0
- package/dist/lifecycle-log-guard.js +93 -2
- package/dist/lifecycle-log-guard.js.map +1 -0
- package/dist/list-roles-render.d.ts.map +1 -0
- package/dist/list-roles-render.js +40 -6
- package/dist/list-roles-render.js.map +1 -0
- package/dist/local-log-routing.d.ts +19 -0
- package/dist/local-log-routing.d.ts.map +1 -0
- package/dist/local-log-routing.js +67 -0
- package/dist/local-log-routing.js.map +1 -0
- package/dist/local-manage-tool-result.d.ts +8 -0
- package/dist/local-manage-tool-result.d.ts.map +1 -0
- package/dist/local-manage-tool-result.js +10 -0
- package/dist/local-manage-tool-result.js.map +1 -0
- package/dist/local-server-cursor.d.ts +34 -0
- package/dist/local-server-cursor.d.ts.map +1 -0
- package/dist/local-server-cursor.js +151 -0
- package/dist/local-server-cursor.js.map +1 -0
- package/dist/log-audit.d.ts.map +1 -0
- package/dist/log-audit.js +194 -3
- package/dist/log-audit.js.map +1 -0
- package/dist/log-stream.d.ts +31 -18
- package/dist/log-stream.d.ts.map +1 -0
- package/dist/log-stream.js +1214 -12
- package/dist/log-stream.js.map +1 -0
- package/dist/model-presets.d.ts.map +1 -0
- package/dist/model-presets.js +19 -1
- package/dist/model-presets.js.map +1 -0
- package/dist/name-validator.d.ts.map +1 -0
- package/dist/name-validator.js +22 -1
- package/dist/name-validator.js.map +1 -0
- package/dist/opencode-drone.d.ts.map +1 -0
- package/dist/opencode-drone.js +438 -4
- package/dist/opencode-drone.js.map +1 -0
- package/dist/opencode-plugin.d.ts +1 -1
- package/dist/opencode-plugin.d.ts.map +1 -0
- package/dist/opencode-plugin.js +29 -4
- package/dist/opencode-plugin.js.map +1 -0
- package/dist/parse-assimilate-args.d.ts +1 -1
- package/dist/parse-assimilate-args.d.ts.map +1 -0
- package/dist/parse-assimilate-args.js +125 -1
- package/dist/parse-assimilate-args.js.map +1 -0
- package/dist/parse-launch-all-args.d.ts.map +1 -0
- package/dist/parse-launch-all-args.js +70 -1
- package/dist/parse-launch-all-args.js.map +1 -0
- package/dist/postinstall-banner.d.ts.map +1 -0
- package/dist/postinstall-banner.js +27 -2
- package/dist/postinstall-banner.js.map +1 -0
- package/dist/postinstall.d.ts.map +1 -0
- package/dist/postinstall.js +32 -5
- package/dist/postinstall.js.map +1 -0
- package/dist/readiness-probe.d.ts.map +1 -0
- package/dist/readiness-probe.js +9 -1
- package/dist/readiness-probe.js.map +1 -0
- package/dist/regen-format.d.ts.map +1 -0
- package/dist/regen-format.js +545 -13
- package/dist/regen-format.js.map +1 -0
- package/dist/regen.d.ts.map +1 -0
- package/dist/regen.js +141 -5
- package/dist/regen.js.map +1 -0
- package/dist/remote-client.d.ts +65 -175
- package/dist/remote-client.d.ts.map +1 -0
- package/dist/remote-client.js +942 -1
- package/dist/remote-client.js.map +1 -0
- package/dist/reset-local-seat-cmd.d.ts +50 -0
- package/dist/reset-local-seat-cmd.d.ts.map +1 -0
- package/dist/reset-local-seat-cmd.js +169 -0
- package/dist/reset-local-seat-cmd.js.map +1 -0
- package/dist/role-match.d.ts.map +1 -0
- package/dist/role-match.js +23 -1
- package/dist/role-match.js.map +1 -0
- package/dist/role-resolver.d.ts.map +1 -0
- package/dist/role-resolver.js +60 -1
- package/dist/role-resolver.js.map +1 -0
- package/dist/roster-render.d.ts.map +1 -0
- package/dist/roster-render.js +121 -3
- package/dist/roster-render.js.map +1 -0
- package/dist/seat-probe.d.ts +32 -13
- package/dist/seat-probe.d.ts.map +1 -0
- package/dist/seat-probe.js +78 -1
- package/dist/seat-probe.js.map +1 -0
- package/dist/seat-store.d.ts +76 -0
- package/dist/seat-store.d.ts.map +1 -0
- package/dist/seat-store.js +309 -0
- package/dist/seat-store.js.map +1 -0
- package/dist/seats.d.ts +303 -0
- package/dist/seats.d.ts.map +1 -0
- package/dist/seats.js +551 -0
- package/dist/seats.js.map +1 -0
- package/dist/self-path.d.ts +27 -0
- package/dist/self-path.d.ts.map +1 -0
- package/dist/self-path.js +43 -0
- package/dist/self-path.js.map +1 -0
- package/dist/server-endpoint.d.ts +9 -0
- package/dist/server-endpoint.d.ts.map +1 -0
- package/dist/server-endpoint.js +38 -0
- package/dist/server-endpoint.js.map +1 -0
- package/dist/server-errors.d.ts +50 -0
- package/dist/server-errors.d.ts.map +1 -0
- package/dist/server-errors.js +79 -0
- package/dist/server-errors.js.map +1 -0
- package/dist/server-handshake.d.ts +197 -0
- package/dist/server-handshake.d.ts.map +1 -0
- package/dist/server-handshake.js +505 -0
- package/dist/server-handshake.js.map +1 -0
- package/dist/server-response.d.ts +3 -0
- package/dist/server-response.d.ts.map +1 -0
- package/dist/server-response.js +67 -0
- package/dist/server-response.js.map +1 -0
- package/dist/server-trust.d.ts +14 -0
- package/dist/server-trust.d.ts.map +1 -0
- package/dist/server-trust.js +225 -0
- package/dist/server-trust.js.map +1 -0
- package/dist/setup-confirm.d.ts +3 -3
- package/dist/setup-confirm.d.ts.map +1 -0
- package/dist/setup-confirm.js +126 -2
- package/dist/setup-confirm.js.map +1 -0
- package/dist/setup.d.ts +5 -3
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +169 -46
- package/dist/setup.js.map +1 -0
- package/dist/shell-escape.d.ts.map +1 -0
- package/dist/shell-escape.js +22 -1
- package/dist/shell-escape.js.map +1 -0
- package/dist/spawn.d.ts +2 -2
- package/dist/spawn.d.ts.map +1 -0
- package/dist/spawn.js +29 -10
- package/dist/spawn.js.map +1 -0
- package/dist/startup-services.d.ts +0 -1
- package/dist/startup-services.d.ts.map +1 -0
- package/dist/startup-services.js +26 -1
- package/dist/startup-services.js.map +1 -0
- package/dist/stream-owner.d.ts +6 -2
- package/dist/stream-owner.d.ts.map +1 -0
- package/dist/stream-owner.js +547 -2
- package/dist/stream-owner.js.map +1 -0
- package/dist/stream-status.d.ts +1 -1
- package/dist/stream-status.d.ts.map +1 -0
- package/dist/stream-status.js +268 -3
- package/dist/stream-status.js.map +1 -0
- package/dist/sync-roles-render.d.ts.map +1 -0
- package/dist/sync-roles-render.js +118 -3
- package/dist/sync-roles-render.js.map +1 -0
- package/dist/sync.d.ts +1 -1
- package/dist/sync.d.ts.map +1 -0
- package/dist/sync.js +286 -22
- package/dist/sync.js.map +1 -0
- package/dist/terminal-title.d.ts.map +1 -0
- package/dist/terminal-title.js +68 -1
- package/dist/terminal-title.js.map +1 -0
- package/dist/token-store.d.ts +17 -111
- package/dist/token-store.d.ts.map +1 -0
- package/dist/token-store.js +81 -1
- package/dist/token-store.js.map +1 -0
- package/dist/tool-manifest.d.ts +4 -8
- package/dist/tool-manifest.d.ts.map +1 -0
- package/dist/tool-manifest.js +554 -1
- package/dist/tool-manifest.js.map +1 -0
- package/dist/tool-scope.d.ts +8 -12
- package/dist/tool-scope.d.ts.map +1 -0
- package/dist/tool-scope.js +97 -1
- package/dist/tool-scope.js.map +1 -0
- package/dist/types.d.ts +1 -5
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/unknown-subcommand.d.ts +1 -1
- package/dist/unknown-subcommand.d.ts.map +1 -0
- package/dist/unknown-subcommand.js +37 -1
- package/dist/unknown-subcommand.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +78 -2
- package/dist/version.js.map +1 -0
- package/dist/working-repo.d.ts.map +1 -0
- package/dist/working-repo.js +81 -1
- package/dist/working-repo.js.map +1 -0
- package/dist/worktree-lifecycle.d.ts.map +1 -0
- package/dist/worktree-lifecycle.js +205 -2
- package/dist/worktree-lifecycle.js.map +1 -0
- package/docs/EXTRACTION_PROVENANCE.md +40 -0
- package/docs/LOCAL_SERVER.md +103 -0
- package/docs/RELEASING.md +120 -0
- package/package.json +52 -34
- package/src/agent-runtime.ts +69 -0
- package/src/assimilate-cmd.ts +1864 -0
- package/src/assimilate-deps.ts +444 -0
- package/src/assimilate-guard.ts +84 -0
- package/src/assimilate-welcome.ts +39 -0
- package/src/auth-env.ts +21 -0
- package/src/backends/launch-all-pastelist.ts +18 -0
- package/src/backends/launch-all-tmux.ts +75 -0
- package/src/backends/launch-all-windows.ts +110 -0
- package/src/bare-launch-menu.ts +148 -0
- package/src/claude-launch-args.ts +35 -0
- package/src/claude.ts +561 -0
- package/src/cleanup-cmd.ts +581 -0
- package/src/clear-rewake-core.ts +34 -0
- package/src/clear-rewake.ts +18 -0
- package/src/cli-help.ts +116 -0
- package/src/cli-platform.ts +127 -0
- package/src/cli-tool-approval.ts +716 -0
- package/src/codex-app-server.ts +238 -0
- package/src/codex-app-wake.ts +512 -0
- package/src/codex-launch.ts +140 -0
- package/src/codex-remote.ts +500 -0
- package/src/codex-wake-resolve.ts +155 -0
- package/src/config-utils.ts +811 -0
- package/src/config.ts +595 -0
- package/src/console-prefix.ts +99 -0
- package/src/cube-name.ts +69 -0
- package/src/cubes.ts +583 -0
- package/src/debug.ts +73 -0
- package/src/direct-log.ts +9 -0
- package/src/docs-sections.ts +129 -0
- package/src/drone-lifecycle.ts +62 -0
- package/src/drone-management.ts +162 -0
- package/src/ensure-mcp-config.ts +54 -0
- package/src/evict-drone.ts +82 -0
- package/src/gc-orphan-inboxes.ts +229 -0
- package/src/inbox-monitor.ts +1005 -0
- package/src/index.ts +1201 -0
- package/src/launch-all-cmd.ts +450 -0
- package/src/launch-all-command.ts +30 -0
- package/src/launch-all-deps.ts +188 -0
- package/src/launch-all-discovery.ts +118 -0
- package/src/launch-all-locks.ts +74 -0
- package/src/launch-gate.ts +80 -0
- package/src/lifecycle-log-guard.ts +144 -0
- package/src/list-roles-render.ts +52 -0
- package/src/local-log-routing.ts +106 -0
- package/src/local-manage-tool-result.ts +10 -0
- package/src/local-server-cursor.ts +188 -0
- package/src/log-audit.ts +207 -0
- package/src/log-stream.ts +1505 -0
- package/src/model-presets.ts +22 -0
- package/src/name-validator.ts +23 -0
- package/src/opencode-drone.ts +528 -0
- package/src/opencode-plugin.ts +38 -0
- package/src/parse-assimilate-args.ts +125 -0
- package/src/parse-launch-all-args.ts +100 -0
- package/src/postinstall-banner.ts +37 -0
- package/src/postinstall.ts +36 -0
- package/src/readiness-probe.ts +12 -0
- package/src/regen-format.ts +651 -0
- package/src/regen.ts +150 -0
- package/src/remote-client.ts +1379 -0
- package/src/reset-local-seat-cmd.ts +227 -0
- package/src/role-match.ts +29 -0
- package/src/role-resolver.ts +93 -0
- package/src/roster-render.ts +196 -0
- package/src/seat-probe.ts +115 -0
- package/src/seat-store.ts +333 -0
- package/src/seats.ts +741 -0
- package/src/self-path.ts +51 -0
- package/src/server-endpoint.ts +38 -0
- package/src/server-errors.ts +93 -0
- package/src/server-handshake.ts +783 -0
- package/src/server-response.ts +76 -0
- package/src/server-trust.ts +245 -0
- package/src/setup-confirm.ts +171 -0
- package/src/setup.ts +186 -0
- package/src/shell-escape.ts +22 -0
- package/src/spawn.ts +31 -0
- package/src/startup-services.ts +36 -0
- package/src/stream-owner.ts +686 -0
- package/src/stream-status.ts +337 -0
- package/src/sync-roles-render.ts +163 -0
- package/src/sync.ts +363 -0
- package/src/terminal-title.ts +76 -0
- package/src/token-store.ts +102 -0
- package/src/tool-manifest.ts +610 -0
- package/src/tool-scope.ts +110 -0
- package/src/types.ts +5 -0
- package/src/unknown-subcommand.ts +35 -0
- package/src/version.ts +82 -0
- package/src/working-repo.ts +99 -0
- package/src/worktree-lifecycle.ts +254 -0
- package/dist/auth-recovery.d.ts +0 -33
- package/dist/auth-recovery.js +0 -1
- package/dist/auth.d.ts +0 -103
- package/dist/auth.js +0 -39
- package/dist/device-auth.d.ts +0 -75
- package/dist/device-auth.js +0 -1
- package/dist/drone-address.d.ts +0 -26
- package/dist/drone-address.js +0 -1
- package/dist/get-started.d.ts +0 -20
- package/dist/get-started.js +0 -2
- package/dist/health-beat.d.ts +0 -134
- package/dist/health-beat.js +0 -1
- package/dist/role-section.d.ts +0 -110
- package/dist/role-section.js +0 -8
- package/dist/setup-action.d.ts +0 -20
- package/dist/setup-action.js +0 -1
- package/dist/stale-version-check.d.ts +0 -40
- package/dist/stale-version-check.js +0 -1
- package/dist/subscription-retry.d.ts +0 -40
- package/dist/subscription-retry.js +0 -1
- package/dist/templates.d.ts +0 -107
- package/dist/templates.js +0 -359
- package/dist/token-crypto.d.ts +0 -50
- package/dist/token-crypto.js +0 -1
package/dist/sync.js
CHANGED
|
@@ -1,22 +1,286 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
`
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
`
|
|
16
|
-
|
|
17
|
-
`)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
package/dist/sync.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EACL,aAAa,EACb,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,qBAAqB,GAEtB,MAAM,yBAAyB,CAAC;AA4BjC,MAAM,WAAW,GAAuB;IACtC,OAAO,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;QAC1B,MAAM,CAAC,GAAG,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;QAC3D,OAAO;YACL,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,EAAE;YACtB,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,EAAE;SACvB,CAAC;IACJ,CAAC;IACD,GAAG,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE;IACxB,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;IAC5C,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;CAC7C,CAAC;AAEF,MAAM,cAAc,GAAG,aAAa,CAAC;AAErC,qEAAqE;AACrE,wBAAwB;AACxB,qEAAqE;AAErE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,eAAe,CAC7B,OAAgB,EAChB,GAAW,EACX,aAAqB;IAErB,IAAI,aAAa,CAAC,UAAU,CAAC,KAAK,CAAC;QAAE,OAAO,aAAa,CAAC;IAC1D,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,iBAAiB,CAAC,EAAE,GAAG,CAAC,CAAC;IAClE,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;IAC3D,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,GAAG,CAAC,CAAC;IACxE,IAAI,OAAO,GAAG,OAAO,CAAC;IACtB,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM;aACpC,KAAK,CAAC,IAAI,CAAC;aACX,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC;QAC1C,IAAI,iBAAiB;YAAE,OAAO,GAAG,iBAAiB,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;IACtF,CAAC;IACD,OAAO,qBAAqB,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;AACrE,CAAC;AAcD;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,IAAwB;IAClD,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAC9B,MAAM,QAAQ,GAAG,GAAG,EAAE,CAAC;IAEvB,gBAAgB;IAChB,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,iBAAiB,CAAC,EAAE,QAAQ,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5E,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,iCAAiC,QAAQ,GAAG,EAAE,CAAC;IACjF,CAAC;IAED,sDAAsD;IACtD,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,EAAE,QAAQ,CAAC,CAAC;IACnE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,sBAAsB,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC;IACjF,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACzF,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IAE7D,sBAAsB;IACtB,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE,QAAQ,CAAC,CAAC;IACpF,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,kCAAkC,WAAW,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC;IAClG,CAAC;IACD,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IACzC,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,kEAAkE,EAAE,CAAC;IACvG,CAAC;IAED,uEAAuE;IACvE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,QAAQ,CAAC,CAAC;IACvE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,4BAA4B,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC;IACtF,CAAC;IAED,MAAM,QAAQ,GAAG,eAAe,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IAE5D,sCAAsC;IACtC,IAAI,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IACrD,CAAC;IAED,8DAA8D;IAC9D,IAAI,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC7C,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IAC/C,CAAC;IAED,6CAA6C;IAC7C,uEAAuE;IACvE,oEAAoE;IACpE,kEAAkE;IAClE,oEAAoE;IACpE,gEAAgE;IAChE,oEAAoE;IACpE,qEAAqE;IACrE,qDAAqD;IACrD,IAAI,QAAQ,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,CAAC;QACxD,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IACtD,CAAC;IACD,uEAAuE;IACvE,uDAAuD;IACvD,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,QAAQ,CAAC,CAAC;IACnF,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACnE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,IAAI,KAAK,cAAc,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC9F,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;IACvD,OAAO,EAAE,IAAI,EAAE,oBAAoB,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;AACnE,CAAC;AAED,qEAAqE;AACrE,eAAe;AACf,qEAAqE;AAErE,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,OAAiB,EAAE,EAAE,OAAoB,EAAE,KAAK,EAAE,KAAK,EAAE;IACrF,MAAM,MAAM,GAAG,EAAE,GAAG,WAAW,EAAE,GAAG,IAAI,EAAE,CAAC;IAC3C,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IACrD,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IAElC,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC3B,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,gBAAgB,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC;QACpD,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC3B,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,2CAA2C,CAAC,CAAC,CAAC;QAClE,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;YAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC;QAC9E,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;QAC7F,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,kFAAkF,CAAC,CAAC,CAAC;QACzG,OAAO,CAAC,CAAC;IACX,CAAC;IAED,uEAAuE;IACvE,+DAA+D;IAC/D,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;QACrE,IAAI,GAAG,CAAC,MAAM,KAAK,gBAAgB,EAAE,CAAC;YACpC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,KAAK,CAAC,QAAQ,yBAAyB,cAAc,KAAK,CAAC,CAAC,CAAC;YACzF,OAAO,CAAC,CAAC;QACX,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,KAAK,iBAAiB,EAAE,CAAC;YACrC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,KAAK,CAAC,QAAQ,uBAAuB,cAAc,KAAK,CAAC,CAAC,CAAC;YACvF,OAAO,CAAC,CAAC;QACX,CAAC;QACD,yEAAyE;QACzE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,OAAO,IAAI,cAAc,KAAK,CAAC,CAAC,CAAC;QAC9D,OAAO,CAAC,CAAC;IACX,CAAC;IAED,oEAAoE;IACpE,8DAA8D;IAC9D,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,cAAc,CAAC,KAAK,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAClE,CAAC;IAED,qEAAqE;IACrE,mEAAmE;IACnE,IAAI,KAAK,CAAC,IAAI,KAAK,oBAAoB,EAAE,CAAC;QACxC,IAAI,KAAK,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;YACxB,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,KAAK,CAAC,MAAM,wCAAwC,cAAc,KAAK,CAAC,CAAC,CAAC;YACtG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,+DAA+D,CAAC,CAAC,CAAC;YACpF,OAAO,CAAC,CAAC;QACX,CAAC;QACD,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,cAAc,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;QACxE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,0BAA0B,cAAc,iDAAiD,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;YACpI,OAAO,CAAC,CAAC;QACX,CAAC;QACD,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,KAAK,CAAC,MAAM,cAAc,KAAK,CAAC,OAAO,UAAU,KAAK,CAAC,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,SAAS,cAAc,iBAAiB,CAAC,CAAC,CAAC;QACtJ,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC,CAAC;QAC9D,OAAO,CAAC,CAAC;IACX,CAAC;IAED,sEAAsE;IACtE,sEAAsE;IACtE,IAAI,KAAK,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC;QAC7B,MAAM,IAAI,GAAG,cAAc,CAAC,KAAK,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE;YACpE,aAAa,EAAE,OAAO,OAAO,qBAAqB,cAAc,GAAG;SACpE,CAAC,CAAC;QACH,IAAI,IAAI,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC,CAAC,yDAAyD;QACtF,qEAAqE;QACrE,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,OAAO,EAAE,cAAc,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QAC1F,IAAI,OAAO,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAChC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,4BAA4B,OAAO,OAAO,CAAC,CAAC,CAAC;QACjE,CAAC;aAAM,IAAI,OAAO,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YAC1C,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,OAAO,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC;QAC/C,CAAC;QACD,OAAO,CAAC,CAAC;IACX,CAAC;IAED,kBAAkB;IAClB,MAAM,WAAW,GAAU,KAAK,CAAC;IACjC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC,CAAC;IACpD,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;;;GAIG;AACH,SAAS,cAAc,CACrB,QAAgB,EAChB,GAAY,EACZ,GAAiB,EACjB,MAA2B,EAC3B,MAA2B,EAC3B,OAAmC,EAAE;IAErC,MAAM,GAAG,GAAG,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC;IAChE,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC7B,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,aAAa,kBAAkB,QAAQ,SAAS,cAAc,KAAK,CAAC,CAAC,CAAC;QAClG,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,QAAQ,SAAS,cAAc,KAAK,CAAC,CAAC,CAAC;QACrE,CAAC;QACD,OAAO,CAAC,CAAC;IACX,CAAC;IACD,yEAAyE;IACzE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,gBAAgB,GAAG,CAAC,OAAO,IAAI,aAAa,0BAA0B,CAAC,CAAC,CAAC;IAC7F,OAAO,CAAC,CAAC;AACX,CAAC;AAQD;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,OAAiB;IAC7C,IAAI,KAAK,GAAG,KAAK,CAAC;IAClB,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACtB,KAAK,GAAG,IAAI,CAAC;QACf,CAAC;aAAM,CAAC;YACN,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,KAAK,EAAE,wBAAwB,GAAG,8BAA8B;aACjE,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC;AAC1C,CAAC"}
|
|
@@ -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"}
|
package/dist/terminal-title.js
CHANGED
|
@@ -1 +1,68 @@
|
|
|
1
|
-
|
|
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"}
|
package/dist/token-store.d.ts
CHANGED
|
@@ -1,27 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Local-server credential backend.
|
|
3
3
|
*
|
|
4
|
-
* config.ts
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
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 = '
|
|
9
|
+
export type TokenBackendName = 'file';
|
|
22
10
|
/**
|
|
23
|
-
* Account-agnostic key/value store over
|
|
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
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
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
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
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
|
|
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"}
|