borgmcp 1.1.14 → 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 +86 -37
- 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/launch-all-deps.js
CHANGED
|
@@ -1 +1,99 @@
|
|
|
1
|
-
|
|
1
|
+
// gh#556 Part 2 — `borg launch-all [cube]` dependency seam.
|
|
2
|
+
//
|
|
3
|
+
// LaunchAllDeps is the full injectable seam list (per spec §10) so every
|
|
4
|
+
// pure module (discovery / parser / orchestrator / backends) is unit-testable
|
|
5
|
+
// with vi.fn() stubs. buildDefaultLaunchAllDeps() (added in launch-all-cmd
|
|
6
|
+
// wiring / Phase 4) wires the real-IO production modules.
|
|
7
|
+
import { spawnSync } from 'node:child_process';
|
|
8
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync, statSync, readdirSync, } from 'node:fs';
|
|
9
|
+
import { homedir as osHomedir } from 'node:os';
|
|
10
|
+
import { createInterface } from 'node:readline/promises';
|
|
11
|
+
import { readAllProjectIdentities as cubesReadAllProjectIdentities, getProjectCliPreferenceForPath, findProjectRoot, getActiveCube, } from './cubes.js';
|
|
12
|
+
import { getRoster, getCube } from './remote-client.js';
|
|
13
|
+
import { defaultProbeSeat } from './seat-probe.js';
|
|
14
|
+
/** Real-IO factory wiring production modules (spec §10). Test code stubs LaunchAllDeps directly. */
|
|
15
|
+
export function buildDefaultLaunchAllDeps() {
|
|
16
|
+
return {
|
|
17
|
+
runSync: (cmd, args, opts) => {
|
|
18
|
+
const r = spawnSync(cmd, args, { encoding: 'utf-8', cwd: opts?.cwd });
|
|
19
|
+
if (r.error)
|
|
20
|
+
throw r.error;
|
|
21
|
+
if (r.status !== 0) {
|
|
22
|
+
throw new Error(`${cmd} exited ${r.status}: ${(r.stderr ?? '').toString().trim()}`);
|
|
23
|
+
}
|
|
24
|
+
return (r.stdout ?? '').toString();
|
|
25
|
+
},
|
|
26
|
+
runSyncExitCode: (cmd, args) => spawnSync(cmd, args, { encoding: 'utf-8' }).status ?? 1,
|
|
27
|
+
attachInteractive: (cmd, args) => {
|
|
28
|
+
spawnSync(cmd, args, { stdio: 'inherit' });
|
|
29
|
+
},
|
|
30
|
+
cwd: () => process.cwd(),
|
|
31
|
+
pathExists: (p) => existsSync(p),
|
|
32
|
+
homedir: () => osHomedir(),
|
|
33
|
+
mkdirp: (dir) => {
|
|
34
|
+
mkdirSync(dir, { recursive: true });
|
|
35
|
+
},
|
|
36
|
+
readFileOpt: (p) => {
|
|
37
|
+
try {
|
|
38
|
+
return readFileSync(p, 'utf-8');
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
writeFile: (p, content, mode) => {
|
|
45
|
+
writeFileSync(p, content, { mode: mode ?? 0o600 });
|
|
46
|
+
},
|
|
47
|
+
unlinkOpt: (p) => {
|
|
48
|
+
try {
|
|
49
|
+
unlinkSync(p);
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
/* ENOENT ignored */
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
statMtime: (p) => {
|
|
56
|
+
try {
|
|
57
|
+
return statSync(p).mtimeMs;
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
listDir: (p) => {
|
|
64
|
+
try {
|
|
65
|
+
return readdirSync(p);
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return [];
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
getRoster: (token, apiUrl, since, serverTrustIdentity) => getRoster(token, apiUrl, since, serverTrustIdentity),
|
|
72
|
+
// getCube uses the drone session token via authedFetch (cubeId-only); apiUrl/token unused.
|
|
73
|
+
getCube: (_apiUrl, _token, cubeId) => getCube(cubeId),
|
|
74
|
+
probeSeat: (sessionToken, apiUrl, serverTrustIdentity) => defaultProbeSeat(sessionToken, apiUrl, serverTrustIdentity),
|
|
75
|
+
getCliPreferenceForPath: (projectPath) => getProjectCliPreferenceForPath(projectPath),
|
|
76
|
+
readAllProjectIdentities: () => cubesReadAllProjectIdentities(),
|
|
77
|
+
findProjectRoot: (dir) => findProjectRoot(dir),
|
|
78
|
+
getActiveCube: () => getActiveCube(),
|
|
79
|
+
prompt: async (message) => {
|
|
80
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
81
|
+
try {
|
|
82
|
+
return (await rl.question(message)).trim();
|
|
83
|
+
}
|
|
84
|
+
finally {
|
|
85
|
+
rl.close();
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
isTTY: () => process.stdin.isTTY === true,
|
|
89
|
+
getEnv: (name) => process.env[name],
|
|
90
|
+
platform: () => process.platform,
|
|
91
|
+
stderr: (line) => {
|
|
92
|
+
process.stderr.write(line);
|
|
93
|
+
},
|
|
94
|
+
stdout: (line) => {
|
|
95
|
+
process.stdout.write(line);
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=launch-all-deps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launch-all-deps.js","sourceRoot":"","sources":["../src/launch-all-deps.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launch-all-discovery.d.ts","sourceRoot":"","sources":["../src/launch-all-discovery.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAErE,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAOD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAI1E;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,SAAS,GAAG,MAAM,EAAE,CAmBrE;AAED,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,YAAY,EAClB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,cAAc,EAAE,CAAC,CA0C3B"}
|
|
@@ -1,4 +1,90 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
// gh#556 Part 2 — drone-worktree discovery for `borg launch-all`.
|
|
2
|
+
//
|
|
3
|
+
// Scheme-agnostic: enumerates `git worktree list --porcelain` (the authoritative
|
|
4
|
+
// source covering BOTH old sibling paths and new ~/.borg/worktrees/<repo>/<name>
|
|
5
|
+
// paths from Part 1) and cross-references ~/.config/borgmcp/cubes.json, keeping
|
|
6
|
+
// only worktrees whose saved identity has cubeId === target.
|
|
7
|
+
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
8
|
+
function isUuid(s) {
|
|
9
|
+
return UUID_RE.test(s);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* --only TIER-1 (local, no server call): exact case-insensitive droneLabel match,
|
|
13
|
+
* OR droneLabel prefix match (`--only drone` matches `drone-1`, `drone-2`, ...).
|
|
14
|
+
* Tier-2 (role-name) matching is best-effort in the orchestrator (spec §8.4).
|
|
15
|
+
*/
|
|
16
|
+
export function matchesOnlyLabel(droneLabel, only) {
|
|
17
|
+
const l = droneLabel.toLowerCase();
|
|
18
|
+
const o = only.toLowerCase();
|
|
19
|
+
return l === o || l.startsWith(o);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Enumerate the LINKED worktree paths from `git worktree list --porcelain`,
|
|
23
|
+
* dropping the main worktree (always block[0]). Throws a user-readable error if
|
|
24
|
+
* the command fails (not inside a git repo).
|
|
25
|
+
*/
|
|
26
|
+
export function enumerateLinkedWorktrees(runSync) {
|
|
27
|
+
let raw;
|
|
28
|
+
try {
|
|
29
|
+
raw = runSync('git', ['worktree', 'list', '--porcelain']);
|
|
30
|
+
}
|
|
31
|
+
catch (e) {
|
|
32
|
+
throw new Error(`launch-all: git worktree list failed — must be run from inside a git repository\n` +
|
|
33
|
+
` (inner: ${e instanceof Error ? e.message : String(e)})`);
|
|
34
|
+
}
|
|
35
|
+
const blocks = raw.trim().split(/\n\n+/);
|
|
36
|
+
// blocks[0] is the main worktree — always drop it.
|
|
37
|
+
return blocks
|
|
38
|
+
.slice(1)
|
|
39
|
+
.map((block) => {
|
|
40
|
+
const m = block.match(/^worktree (.+)$/m);
|
|
41
|
+
return m ? m[1].trim() : null;
|
|
42
|
+
})
|
|
43
|
+
.filter((p) => p !== null);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Full discovery pipeline (spec §3.5): enumerate → cubes.json lookup → filter
|
|
47
|
+
* (dir-present / has-entry / cubeId-match / UUID-valid / --only) → candidates in
|
|
48
|
+
* stable porcelain order.
|
|
49
|
+
*/
|
|
50
|
+
export async function discoverDroneCandidates(opts, deps) {
|
|
51
|
+
const worktreePaths = enumerateLinkedWorktrees((cmd, args) => deps.runSync(cmd, args));
|
|
52
|
+
const identities = await deps.readAllProjectIdentities();
|
|
53
|
+
const byPath = new Map(identities.map((e) => [e.projectPath, e.cube]));
|
|
54
|
+
const candidates = [];
|
|
55
|
+
for (const worktreeDir of worktreePaths) {
|
|
56
|
+
// 1. directory not present on disk (orphaned worktree)
|
|
57
|
+
if (!deps.pathExists(worktreeDir)) {
|
|
58
|
+
deps.stderr(`skipping ${worktreeDir}: directory not found (orphaned worktree — run \`git worktree prune\`)\n`);
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
// 2. no cubes.json entry → not a drone worktree; skip silently
|
|
62
|
+
const cube = byPath.get(worktreeDir);
|
|
63
|
+
if (!cube)
|
|
64
|
+
continue;
|
|
65
|
+
// 3. cubeId mismatch → different cube; skip silently
|
|
66
|
+
if (cube.cubeId !== opts.targetCubeId)
|
|
67
|
+
continue;
|
|
68
|
+
// 4. malformed entry (cubeId/droneId not UUID) → warn + skip
|
|
69
|
+
if (!isUuid(cube.cubeId) || !isUuid(cube.droneId)) {
|
|
70
|
+
deps.stderr(`skipping ${worktreeDir}: its saved seat has a malformed cubeId/droneId — re-assimilate to fix\n`);
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
// 5. --only filter (tier-1 label) → skip silently (counted in the filter report)
|
|
74
|
+
if (opts.only !== undefined && !matchesOnlyLabel(cube.droneLabel, opts.only))
|
|
75
|
+
continue;
|
|
76
|
+
candidates.push({
|
|
77
|
+
worktreeDir,
|
|
78
|
+
cubeId: cube.cubeId,
|
|
79
|
+
droneId: cube.droneId,
|
|
80
|
+
droneLabel: cube.droneLabel,
|
|
81
|
+
sessionToken: cube.sessionToken,
|
|
82
|
+
apiUrl: cube.apiUrl,
|
|
83
|
+
...(cube.serverTrustIdentity === undefined
|
|
84
|
+
? {}
|
|
85
|
+
: { serverTrustIdentity: cube.serverTrustIdentity }),
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
return candidates;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=launch-all-discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launch-all-discovery.js","sourceRoot":"","sources":["../src/launch-all-discovery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launch-all-locks.d.ts","sourceRoot":"","sources":["../src/launch-all-locks.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D,eAAO,MAAM,aAAa,QAAgB,CAAC;AAE3C,iFAAiF;AACjF,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEjF;AAED,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,iFAAiF;AACjF,wBAAgB,eAAe,CAC7B,IAAI,EAAE,aAAa,EACnB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,MAAM,GACpB,IAAI,CAIN;AAED,oFAAoF;AACpF,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAQxF;AAED,sFAAsF;AACtF,wBAAgB,UAAU,CACxB,IAAI,EAAE,aAAa,EACnB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,GACZ;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,CAWxC"}
|
package/dist/launch-all-locks.js
CHANGED
|
@@ -1 +1,54 @@
|
|
|
1
|
-
|
|
1
|
+
// gh#556 Part 2 — per-worktree launch lock markers (spec §6).
|
|
2
|
+
//
|
|
3
|
+
// Timestamp-based markers (the agent PID is not synchronously available when
|
|
4
|
+
// `borg assimilate --here` is dispatched via tmux send-keys). A marker <5min old
|
|
5
|
+
// means the seat appears live → skip unless --force. Markers are never deleted by
|
|
6
|
+
// launch-all itself; the next invocation sweeps mtime-stale (>5min) markers.
|
|
7
|
+
import { createHash } from 'node:crypto';
|
|
8
|
+
import { join } from 'node:path';
|
|
9
|
+
export const LOCK_STALE_MS = 5 * 60 * 1000;
|
|
10
|
+
/** SHA-1 hex of the worktree abs path → fixed-length collision-safe filename. */
|
|
11
|
+
export function worktreeLockName(absPath) {
|
|
12
|
+
return createHash('sha1').update(absPath, 'utf8').digest('hex');
|
|
13
|
+
}
|
|
14
|
+
export function locksDir(homeDir, cubeId) {
|
|
15
|
+
return join(homeDir, '.config', 'borgmcp', 'locks', cubeId);
|
|
16
|
+
}
|
|
17
|
+
export function lockPath(homeDir, cubeId, absPath) {
|
|
18
|
+
return join(locksDir(homeDir, cubeId), worktreeLockName(absPath) + '.pid');
|
|
19
|
+
}
|
|
20
|
+
/** Write the launch marker (mkdir -p the cube's locks dir first). Mode 0o600. */
|
|
21
|
+
export function writeLockMarker(deps, cubeId, droneLabel, worktreeDir, launchedAtISO) {
|
|
22
|
+
deps.mkdirp(locksDir(deps.homedir(), cubeId));
|
|
23
|
+
const marker = { launchedAt: launchedAtISO, droneLabel, worktreeDir };
|
|
24
|
+
deps.writeFile(lockPath(deps.homedir(), cubeId, worktreeDir), JSON.stringify(marker), 0o600);
|
|
25
|
+
}
|
|
26
|
+
/** Delete mtime-stale (>5min) `.pid` markers in locks/<cubeId>/ (crash cleanup). */
|
|
27
|
+
export function sweepStaleLocks(deps, cubeId, nowMs) {
|
|
28
|
+
const dir = locksDir(deps.homedir(), cubeId);
|
|
29
|
+
for (const name of deps.listDir(dir)) {
|
|
30
|
+
if (!name.endsWith('.pid'))
|
|
31
|
+
continue;
|
|
32
|
+
const p = join(dir, name);
|
|
33
|
+
const mtime = deps.statMtime(p);
|
|
34
|
+
if (mtime !== null && nowMs - mtime > LOCK_STALE_MS)
|
|
35
|
+
deps.unlinkOpt(p);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/** True iff a fresh (<=5min by its launchedAt content) marker exists for the seat. */
|
|
39
|
+
export function isLockLive(deps, cubeId, worktreeDir, nowMs) {
|
|
40
|
+
const raw = deps.readFileOpt(lockPath(deps.homedir(), cubeId, worktreeDir));
|
|
41
|
+
if (raw === null)
|
|
42
|
+
return { live: false };
|
|
43
|
+
try {
|
|
44
|
+
const marker = JSON.parse(raw);
|
|
45
|
+
const t = Date.parse(marker.launchedAt);
|
|
46
|
+
if (!Number.isFinite(t))
|
|
47
|
+
return { live: false };
|
|
48
|
+
return { live: nowMs - t <= LOCK_STALE_MS, launchedAt: marker.launchedAt };
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return { live: false };
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=launch-all-locks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launch-all-locks.js","sourceRoot":"","sources":["../src/launch-all-locks.ts"],"names":[],"mappings":"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"}
|
package/dist/launch-gate.d.ts
CHANGED
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
* SR-BINDING (1482e7f9): BORG_SESSION is ACTIVATION-ONLY. It is
|
|
29
29
|
* user-settable by design (manual BORG_SESSION=1 is a supported override
|
|
30
30
|
* for power users/tests) and MUST NEVER be consulted for an access or
|
|
31
|
-
* security decision — server-side
|
|
32
|
-
* security boundary and
|
|
31
|
+
* security decision — server-side drone-session auth is the
|
|
32
|
+
* security boundary and is unchanged by this gate.
|
|
33
33
|
*/
|
|
34
34
|
export declare const BORG_SESSION_ENV = "BORG_SESSION";
|
|
35
35
|
/** True when this process runs inside a borg-launched session. */
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launch-gate.d.ts","sourceRoot":"","sources":["../src/launch-gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAKH,eAAO,MAAM,gBAAgB,iBAAiB,CAAC;AAE/C,kEAAkE;AAClE,wBAAgB,aAAa,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAE3E;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAO9D;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,IAAI,MAAM,EAAE,CAErD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAMnG"}
|
package/dist/launch-gate.js
CHANGED
|
@@ -1 +1,73 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* gh#673 P1 — the borg-launch ACTIVATION gate (WI-4 + WI-5-claude).
|
|
3
|
+
*
|
|
4
|
+
* The `borg` wrapper sets BORG_SESSION=1 in the agent's launch env
|
|
5
|
+
* (claude.ts / assimilate-cmd.ts launchEnv — same pattern as
|
|
6
|
+
* BORG_CODEX_REMOTE_WAKE). Claude Code spawns the borg-mcp MCP child and
|
|
7
|
+
* runs hook commands with that env inherited, so four activation bins
|
|
8
|
+
* gate on it:
|
|
9
|
+
* 1. the MCP tool surface (index.ts CallTool top) — a vanilla session
|
|
10
|
+
* gets a non-silent re-launch notice per tool, never a half-success;
|
|
11
|
+
* 2. the borg-regen SessionStart hook bin — exit-0 no-op;
|
|
12
|
+
* 3. the borg-clear-rewake clear-only hook bin — exit-0 no-op;
|
|
13
|
+
* 4. the borg-log-audit UserPromptSubmit hook bin — exit-0 no-op.
|
|
14
|
+
* Result: `claude` launched directly is vanilla Claude Code; `borg`
|
|
15
|
+
* launches get the full surface.
|
|
16
|
+
*
|
|
17
|
+
* Codex (V2/V2b probes): codex does NOT forward parent env to MCP
|
|
18
|
+
* children — only the pinned [mcp_servers.borg.env] list — so simple
|
|
19
|
+
* launchEnv inheritance can't deliver the marker there. But a
|
|
20
|
+
* PER-INVOCATION `-c 'mcp_servers.borg.env.BORG_SESSION="1"'` config
|
|
21
|
+
* override DOES reach the child (V2b-proven). The borg wrapper appends
|
|
22
|
+
* `codexBorgSessionConfigArgs()` to every codex launch, so codex rides
|
|
23
|
+
* the exact same isBorgSession() gate: vanilla codex children lack the
|
|
24
|
+
* var and gate dormant; borg-launched children carry it. The codex
|
|
25
|
+
* SessionStart hook bin gates via the codex PROCESS env, which the
|
|
26
|
+
* wrapper's launchEnv marks directly.
|
|
27
|
+
*
|
|
28
|
+
* SR-BINDING (1482e7f9): BORG_SESSION is ACTIVATION-ONLY. It is
|
|
29
|
+
* user-settable by design (manual BORG_SESSION=1 is a supported override
|
|
30
|
+
* for power users/tests) and MUST NEVER be consulted for an access or
|
|
31
|
+
* security decision — server-side drone-session auth is the
|
|
32
|
+
* security boundary and is unchanged by this gate.
|
|
33
|
+
*/
|
|
34
|
+
import { envToggleOn } from './auth-env.js';
|
|
35
|
+
import { debugLog } from './debug.js';
|
|
36
|
+
export const BORG_SESSION_ENV = 'BORG_SESSION';
|
|
37
|
+
/** True when this process runs inside a borg-launched session. */
|
|
38
|
+
export function isBorgSession(env = process.env) {
|
|
39
|
+
return envToggleOn(env[BORG_SESSION_ENV]);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The non-silent per-tool notice a vanilla (non-borg-launched) session
|
|
43
|
+
* receives when invoking a borg_* tool. Explains the state — nothing is
|
|
44
|
+
* wrong with the cube — and points at the borg launch path.
|
|
45
|
+
*/
|
|
46
|
+
export function borgSessionToolNotice(toolName) {
|
|
47
|
+
return (`◼ ${toolName} is inactive: this session wasn't launched via \`borg\`, so the borg ` +
|
|
48
|
+
`coordination surface is dormant (vanilla Claude Code). To use cube coordination, ` +
|
|
49
|
+
`re-launch from a terminal with \`borg\` (or \`borg assimilate\` to set up a seat first). ` +
|
|
50
|
+
`Power users can opt in manually by launching with BORG_SESSION=1.`);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The per-invocation codex config override that injects BORG_SESSION into
|
|
54
|
+
* the codex-spawned borg-mcp child's pinned env (V2b-proven mechanism —
|
|
55
|
+
* inherited env never reaches codex MCP children). Appended to the codex
|
|
56
|
+
* launch args by both launch sites (claude.ts + assimilate-cmd.ts).
|
|
57
|
+
* TOML string value, hence the inner quotes.
|
|
58
|
+
*/
|
|
59
|
+
export function codexBorgSessionConfigArgs() {
|
|
60
|
+
return ['-c', `mcp_servers.borg.env.${BORG_SESSION_ENV}="1"`];
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Gate decision with BORG_DEBUG observability — one funnel so every bin
|
|
64
|
+
* logs refusals the same way.
|
|
65
|
+
*/
|
|
66
|
+
export function gateAllowsActivation(surface, env = process.env) {
|
|
67
|
+
const allowed = isBorgSession(env);
|
|
68
|
+
if (!allowed) {
|
|
69
|
+
debugLog(`launch-gate: ${surface} dormant — BORG_SESSION absent (not a borg-launched session; gh#673)`);
|
|
70
|
+
}
|
|
71
|
+
return allowed;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=launch-gate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launch-gate.js","sourceRoot":"","sources":["../src/launch-gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,MAAM,CAAC,MAAM,gBAAgB,GAAG,cAAc,CAAC;AAE/C,kEAAkE;AAClE,MAAM,UAAU,aAAa,CAAC,MAAyB,OAAO,CAAC,GAAG;IAChE,OAAO,WAAW,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC;AAC5C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAAgB;IACpD,OAAO,CACL,KAAK,QAAQ,uEAAuE;QACpF,mFAAmF;QACnF,2FAA2F;QAC3F,mEAAmE,CACpE,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,0BAA0B;IACxC,OAAO,CAAC,IAAI,EAAE,wBAAwB,gBAAgB,MAAM,CAAC,CAAC;AAChE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAe,EAAE,MAAyB,OAAO,CAAC,GAAG;IACxF,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IACnC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,QAAQ,CAAC,gBAAgB,OAAO,sEAAsE,CAAC,CAAC;IAC1G,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle-log-guard.d.ts","sourceRoot":"","sources":["../src/lifecycle-log-guard.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,OAAO,CAAC;AAElD,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,mBAAmB;IAC3B,WAAW,CAAC,EAAE;QACZ,OAAO,EAAE,MAAM,CAAC;QAChB,EAAE,EAAE,MAAM,CAAC;KACZ,CAAC;IACF,SAAS,CAAC,EAAE;QACV,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,OAAO,CAAC;QACd,EAAE,EAAE,MAAM,CAAC;KACZ,CAAC;CACH;AAMD,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAUjF;AA8BD,wBAAgB,mCAAmC,CACjD,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,mBAAmB,GAAG,SAAS,EACtC,KAAK,GAAE,MAAmB,GACzB;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,eAAe,GAAG,IAAI,CAAA;CAAE,CAqBvD;AAED,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,mBAAmB,EAC5B,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,eAAe,GAAG,IAAI,CAAA;CAAE,CAAC,CAMhE;AAED,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,mBAAmB,GAAG,SAAS,EACxC,MAAM,GAAE,MAAiC,GACxC,mBAAmB,CAqBrB;AAED,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,mBAAmB,EAC5B,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAKf"}
|
|
@@ -1,2 +1,93 @@
|
|
|
1
|
-
import{mkdir
|
|
2
|
-
|
|
1
|
+
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
const STATE_FILE = join(homedir(), '.config', 'borgmcp', 'lifecycle-log-state.json');
|
|
5
|
+
const ARRIVAL_DUPLICATE_WINDOW_MS = 10 * 60 * 1000;
|
|
6
|
+
export function lifecycleSignalForMessage(message) {
|
|
7
|
+
if (message.startsWith('ARRIVAL: '))
|
|
8
|
+
return 'arrival';
|
|
9
|
+
if (message.startsWith('READY: ') &&
|
|
10
|
+
message.includes('capacity clean') &&
|
|
11
|
+
message.includes('awaiting next dispatch')) {
|
|
12
|
+
return 'ready';
|
|
13
|
+
}
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
function stateKey(subject) {
|
|
17
|
+
return `${subject.cubeId}:${subject.droneId}`;
|
|
18
|
+
}
|
|
19
|
+
async function readState() {
|
|
20
|
+
try {
|
|
21
|
+
const raw = await readFile(STATE_FILE, 'utf8');
|
|
22
|
+
const parsed = JSON.parse(raw);
|
|
23
|
+
if (parsed &&
|
|
24
|
+
typeof parsed === 'object' &&
|
|
25
|
+
parsed.entries &&
|
|
26
|
+
typeof parsed.entries === 'object' &&
|
|
27
|
+
!Array.isArray(parsed.entries)) {
|
|
28
|
+
return parsed;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
if (err?.code !== 'ENOENT')
|
|
33
|
+
throw err;
|
|
34
|
+
}
|
|
35
|
+
return { entries: {} };
|
|
36
|
+
}
|
|
37
|
+
async function writeState(state) {
|
|
38
|
+
await mkdir(dirname(STATE_FILE), { recursive: true });
|
|
39
|
+
await writeFile(STATE_FILE, JSON.stringify(state, null, 2) + '\n', { mode: 0o600 });
|
|
40
|
+
}
|
|
41
|
+
export function shouldSuppressLifecycleLogFromState(message, state, nowMs = Date.now()) {
|
|
42
|
+
const signal = lifecycleSignalForMessage(message);
|
|
43
|
+
if (!signal)
|
|
44
|
+
return { suppress: false, signal: null };
|
|
45
|
+
if (signal === 'arrival') {
|
|
46
|
+
const lastArrivalAt = state?.lastArrival?.at
|
|
47
|
+
? new Date(state.lastArrival.at).getTime()
|
|
48
|
+
: NaN;
|
|
49
|
+
const isRecent = Number.isFinite(lastArrivalAt) &&
|
|
50
|
+
nowMs - lastArrivalAt < ARRIVAL_DUPLICATE_WINDOW_MS;
|
|
51
|
+
return {
|
|
52
|
+
suppress: state?.lastArrival?.message === message && isRecent,
|
|
53
|
+
signal,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
suppress: state?.idleReady?.open === true && state.idleReady.message === message,
|
|
58
|
+
signal,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
export async function shouldSuppressLifecycleLog(subject, message) {
|
|
62
|
+
const state = await readState();
|
|
63
|
+
return shouldSuppressLifecycleLogFromState(message, state.entries[stateKey(subject)]);
|
|
64
|
+
}
|
|
65
|
+
export function nextLifecycleStateAfterLog(message, current, nowIso = new Date().toISOString()) {
|
|
66
|
+
const signal = lifecycleSignalForMessage(message);
|
|
67
|
+
if (signal === 'arrival') {
|
|
68
|
+
return {
|
|
69
|
+
...current,
|
|
70
|
+
lastArrival: { message, at: nowIso },
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
if (signal === 'ready') {
|
|
74
|
+
return {
|
|
75
|
+
...current,
|
|
76
|
+
idleReady: { message, open: true, at: nowIso },
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
if (current?.idleReady?.open) {
|
|
80
|
+
return {
|
|
81
|
+
...current,
|
|
82
|
+
idleReady: { ...current.idleReady, open: false, at: nowIso },
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
return current ?? {};
|
|
86
|
+
}
|
|
87
|
+
export async function recordLifecycleLog(subject, message) {
|
|
88
|
+
const state = await readState();
|
|
89
|
+
const key = stateKey(subject);
|
|
90
|
+
state.entries[key] = nextLifecycleStateAfterLog(message, state.entries[key]);
|
|
91
|
+
await writeState(state);
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=lifecycle-log-guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle-log-guard.js","sourceRoot":"","sources":["../src/lifecycle-log-guard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-roles-render.d.ts","sourceRoot":"","sources":["../src/list-roles-render.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAkB7E"}
|
|
@@ -1,6 +1,40 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
`
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Sprint 6 / gh#153 — pure render function for `borg_list-roles` MCP tool.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from the inline `case 'borg_list-roles'` handler in
|
|
5
|
+
* `index.ts` per drone-3's QA-FAIL 2026-05-18T13:27:53Z so the render
|
|
6
|
+
* logic is unit-testable without exercising the full MCP tool dispatch
|
|
7
|
+
* stack. The handler simply calls `renderRoleList(roles, cubeId)` and
|
|
8
|
+
* returns its output.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Render the role registry for a cube as a markdown list with role IDs
|
|
12
|
+
* exposed for use with `borg_reassign-drone`. Returns the empty-roles
|
|
13
|
+
* placeholder when the input array is empty.
|
|
14
|
+
*
|
|
15
|
+
* Each role line shape:
|
|
16
|
+
* - **<name>**(<tags>) `<uuid>` — <description>
|
|
17
|
+
*
|
|
18
|
+
* Tags collected in order: Queen, human-seat, default, mandatory, can-broadcast,
|
|
19
|
+
* receives-all-direct. Joined with `, `; suffix omitted entirely when no tags apply.
|
|
20
|
+
*/
|
|
21
|
+
export function renderRoleList(roles, cubeId) {
|
|
22
|
+
if (!roles.length) {
|
|
23
|
+
return 'No roles in this cube yet.';
|
|
24
|
+
}
|
|
25
|
+
const lines = roles.map((r) => {
|
|
26
|
+
const tags = [
|
|
27
|
+
r.role_class === 'queen' ? 'Queen' : null,
|
|
28
|
+
r.is_human_seat ? 'human-seat' : null,
|
|
29
|
+
r.is_default ? 'default' : null,
|
|
30
|
+
r.is_mandatory ? 'mandatory' : null,
|
|
31
|
+
r.can_broadcast ? 'can-broadcast' : null,
|
|
32
|
+
r.receives_all_direct ? 'receives-all-direct' : null,
|
|
33
|
+
].filter(Boolean).join(', ');
|
|
34
|
+
const tagSuffix = tags ? ` (${tags})` : '';
|
|
35
|
+
const desc = r.short_description || '_(no description)_';
|
|
36
|
+
return `- **${r.name}**${tagSuffix} \`${r.id}\` — ${desc}`;
|
|
37
|
+
});
|
|
38
|
+
return `Roles in cube ${cubeId} (${roles.length}):\n\n${lines.join('\n')}\n\nUse the role IDs above with \`borg_reassign-drone\` to change a drone's role.`;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=list-roles-render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-roles-render.js","sourceRoot":"","sources":["../src/list-roles-render.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAcH;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc,CAAC,KAAsB,EAAE,MAAc;IACnE,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QAClB,OAAO,4BAA4B,CAAC;IACtC,CAAC;IACD,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QAC5B,MAAM,IAAI,GAAG;YACX,CAAC,CAAC,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI;YACzC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI;YACrC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI;YAC/B,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI;YACnC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI;YACxC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,IAAI;SACrD,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7B,MAAM,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,GAAG,CAAC,CAAC,iBAAiB,IAAI,oBAAoB,CAAC;QACzD,OAAO,OAAO,CAAC,CAAC,IAAI,KAAK,SAAS,MAAM,CAAC,CAAC,EAAE,QAAQ,IAAI,EAAE,CAAC;IAC7D,CAAC,CAAC,CAAC;IACH,OAAO,iBAAiB,MAAM,KAAK,KAAK,CAAC,MAAM,SAAS,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,mFAAmF,CAAC;AAC9J,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface LocalRoutingDrone {
|
|
2
|
+
id: string;
|
|
3
|
+
label?: string | null;
|
|
4
|
+
role_id?: string | null;
|
|
5
|
+
}
|
|
6
|
+
export interface LocalRoutingRole {
|
|
7
|
+
id: string;
|
|
8
|
+
name: string;
|
|
9
|
+
is_human_seat?: boolean;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Resolve the public `borg_log to:` addressing forms against the local
|
|
13
|
+
* server's authoritative cube roster. This intentionally mirrors the hosted
|
|
14
|
+
* route resolver: exact drone id/label first, then displayed short UUID, then
|
|
15
|
+
* role name/slug expansion. Every failure is closed before the log POST so a
|
|
16
|
+
* miss can never degrade into a broadcast.
|
|
17
|
+
*/
|
|
18
|
+
export declare function resolveLocalLogRecipients(recipients: readonly string[], drones: readonly LocalRoutingDrone[], roles: readonly LocalRoutingRole[]): string[];
|
|
19
|
+
//# sourceMappingURL=local-log-routing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-log-routing.d.ts","sourceRoot":"","sources":["../src/local-log-routing.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,SAAS,MAAM,EAAE,EAC7B,MAAM,EAAE,SAAS,iBAAiB,EAAE,EACpC,KAAK,EAAE,SAAS,gBAAgB,EAAE,GACjC,MAAM,EAAE,CAgFV"}
|