borgmcp 4.4.0 → 4.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/agent-integration-health.d.ts +2 -0
  2. package/dist/agent-integration-health.d.ts.map +1 -1
  3. package/dist/agent-integration-health.js +18 -1
  4. package/dist/agent-integration-health.js.map +1 -1
  5. package/dist/assimilate-cmd.d.ts +3 -0
  6. package/dist/assimilate-cmd.d.ts.map +1 -1
  7. package/dist/assimilate-cmd.js +12 -0
  8. package/dist/assimilate-cmd.js.map +1 -1
  9. package/dist/assimilate-deps.d.ts.map +1 -1
  10. package/dist/assimilate-deps.js +4 -2
  11. package/dist/assimilate-deps.js.map +1 -1
  12. package/dist/backends/launch-all-terminals.d.ts.map +1 -1
  13. package/dist/backends/launch-all-terminals.js +6 -3
  14. package/dist/backends/launch-all-terminals.js.map +1 -1
  15. package/dist/cli-help.js +2 -2
  16. package/dist/cli-help.js.map +1 -1
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +9 -2
  19. package/dist/index.js.map +1 -1
  20. package/dist/opencode-drone.d.ts +2 -0
  21. package/dist/opencode-drone.d.ts.map +1 -1
  22. package/dist/opencode-drone.js +86 -19
  23. package/dist/opencode-drone.js.map +1 -1
  24. package/dist/private-root.d.ts +2 -0
  25. package/dist/private-root.d.ts.map +1 -1
  26. package/dist/private-root.js +35 -1
  27. package/dist/private-root.js.map +1 -1
  28. package/dist/seats.d.ts +5 -0
  29. package/dist/seats.d.ts.map +1 -1
  30. package/dist/seats.js +10 -0
  31. package/dist/seats.js.map +1 -1
  32. package/dist/server-handshake.d.ts.map +1 -1
  33. package/dist/server-handshake.js +1 -0
  34. package/dist/server-handshake.js.map +1 -1
  35. package/dist/terminal-title.d.ts.map +1 -1
  36. package/dist/terminal-title.js +3 -2
  37. package/dist/terminal-title.js.map +1 -1
  38. package/docs/LOCAL_SERVER.md +7 -5
  39. package/package.json +1 -1
  40. package/src/agent-integration-health.ts +20 -1
  41. package/src/assimilate-cmd.ts +17 -0
  42. package/src/assimilate-deps.ts +4 -1
  43. package/src/backends/launch-all-terminals.ts +6 -3
  44. package/src/cli-help.ts +2 -2
  45. package/src/index.ts +8 -1
  46. package/src/opencode-drone.ts +116 -19
  47. package/src/private-root.ts +38 -1
  48. package/src/seats.ts +15 -0
  49. package/src/server-handshake.ts +1 -0
  50. package/src/terminal-title.ts +4 -2
package/src/seats.ts CHANGED
@@ -50,6 +50,7 @@ export interface SeatRecord {
50
50
  sessionId?: string;
51
51
  // binding + display (set atomically at FINALIZE; absent while pending)
52
52
  worktree?: string;
53
+ commonDir?: string;
53
54
  name?: string;
54
55
  droneLabel?: string;
55
56
  roleName?: string;
@@ -149,6 +150,7 @@ function isValidSeatRecord(ref: string, value: unknown): value is SeatRecord {
149
150
  if (r.roleClass !== undefined && (typeof r.roleClass !== 'string' || !ROLE_CLASSES.has(r.roleClass))) return false;
150
151
  if (r.isHumanSeat !== undefined && typeof r.isHumanSeat !== 'boolean') return false;
151
152
  if (r.worktree !== undefined && typeof r.worktree !== 'string') return false;
153
+ if (r.commonDir !== undefined && !isNonEmptyString(r.commonDir)) return false;
152
154
  if (r.droneId !== undefined && (typeof r.droneId !== 'string' || !UUID_RE.test(r.droneId))) return false;
153
155
  if (r.sessionId !== undefined && (typeof r.sessionId !== 'string' || !UUID_RE.test(r.sessionId))) return false;
154
156
  // State-consistency invariants (no inconsistent active|pending).
@@ -447,6 +449,7 @@ export type ActivateSeatOutcome = 'activated' | 'missing' | 'replaced';
447
449
  * worktree is decided). Merged atomically with activation by activateAndBindSeat. */
448
450
  export interface SeatBinding {
449
451
  worktree: string;
452
+ commonDir?: string;
450
453
  name: string;
451
454
  droneLabel: string;
452
455
  roleName?: string;
@@ -475,6 +478,7 @@ export async function activateAndBindSeat(input: {
475
478
  sessionId: string;
476
479
  expectedPendingDigest: string;
477
480
  worktree: string;
481
+ commonDir?: string;
478
482
  name: string;
479
483
  droneLabel: string;
480
484
  roleName?: string;
@@ -496,6 +500,7 @@ export async function activateAndBindSeat(input: {
496
500
  droneId: input.droneId,
497
501
  sessionId: input.sessionId,
498
502
  worktree: input.worktree,
503
+ ...(input.commonDir !== undefined ? { commonDir: input.commonDir } : {}),
499
504
  name: input.name,
500
505
  droneLabel: input.droneLabel,
501
506
  ...(input.roleName !== undefined ? { roleName: input.roleName } : {}),
@@ -675,6 +680,16 @@ export async function readAllActiveSeats(): Promise<Array<{ worktree: string; re
675
680
  return out;
676
681
  }
677
682
 
683
+ /** Whether this cube has an active seat from another canonical Git clone family. */
684
+ export async function hasActiveSeatInDifferentCloneFamily(cubeId: string, commonDir: string): Promise<boolean> {
685
+ const seats = await readAllActiveSeats();
686
+ return seats.some(({ record }) =>
687
+ record.cubeId === cubeId &&
688
+ record.commonDir !== undefined &&
689
+ record.commonDir !== commonDir
690
+ );
691
+ }
692
+
678
693
  /** All valid worktree-bound registry entries, including a PENDING seat whose
679
694
  * interrupted finalize preserved its worktree for a later resume. Read-only:
680
695
  * pending records remain non-hydratable and getActiveSeatForWorktree stays
@@ -410,6 +410,7 @@ export async function sendBorgServerAttach(
410
410
  sessionId: decoded.session.id,
411
411
  expectedPendingDigest: pendingBearerDigest,
412
412
  worktree: binding.worktree,
413
+ ...(binding.commonDir !== undefined ? { commonDir: binding.commonDir } : {}),
413
414
  name: binding.name,
414
415
  droneLabel: binding.droneLabel,
415
416
  ...(binding.roleName !== undefined ? { roleName: binding.roleName } : {}),
@@ -32,6 +32,8 @@
32
32
  * populated," so the assimilated path is the common case.
33
33
  */
34
34
 
35
+ import { escapeSyncDisplay } from './sync-roles-render.js';
36
+
35
37
  /**
36
38
  * Pure: compose the title string for a session. Exported so tests can
37
39
  * exercise every branch without TTY / process / fs dependencies.
@@ -46,9 +48,9 @@ export function composeTerminalTitle(
46
48
  repoBasename: string
47
49
  ): string {
48
50
  if (activeDrone) {
49
- return `borg · ${activeDrone.label} · ${activeDrone.cubeName}`;
51
+ return `borg · ${escapeSyncDisplay(activeDrone.label)} · ${escapeSyncDisplay(activeDrone.cubeName)}`;
50
52
  }
51
- return `borg · ${repoBasename}`;
53
+ return `borg · ${escapeSyncDisplay(repoBasename)}`;
52
54
  }
53
55
 
54
56
  /**