claude-code-swarm 0.3.26 → 0.4.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.
package/src/config.mjs CHANGED
@@ -105,6 +105,13 @@ export function readConfig(configPath = CONFIG_PATH, globalConfigPath = GLOBAL_C
105
105
  trust: project.inbox?.federation?.trust ?? global.inbox?.federation?.trust ?? undefined,
106
106
  },
107
107
  },
108
+ // Cascade integration. Only meaningful when `map` is enabled — the
109
+ // sidecar emits x-cascade/* notifications over the MAP connection.
110
+ // When map is disabled there is no connection to emit on, so cascade
111
+ // becomes an inert no-op (no hard failure — mirrors opentasks/minimem).
112
+ cascade: {
113
+ enabled: envBool("SWARM_CASCADE_ENABLED") ?? Boolean(project.cascade?.enabled ?? global.cascade?.enabled),
114
+ },
108
115
  minimem: {
109
116
  enabled: envBool("SWARM_MINIMEM_ENABLED") ?? Boolean(project.minimem?.enabled ?? global.minimem?.enabled),
110
117
  provider: envStr("SWARM_MINIMEM_PROVIDER") ?? project.minimem?.provider ?? global.minimem?.provider ?? "auto",
@@ -24,7 +24,7 @@ const log = createLogger("map");
24
24
  * authRequired challenge with the server's preferred method + this credential.
25
25
  * When absent, uses the standard SDK connect() for open mode servers.
26
26
  */
27
- export async function connectToMAP({ server, scope, systemId, onMessage, credential, projectContext, inboxEnabled }) {
27
+ export async function connectToMAP({ server, scope, systemId, onMessage, credential, projectContext, inboxEnabled, cascadeEnabled }) {
28
28
  try {
29
29
  const mapSdk = await resolvePackage("@multi-agent-protocol/sdk");
30
30
  if (!mapSdk) throw new Error("@multi-agent-protocol/sdk not available");
@@ -49,6 +49,23 @@ export async function connectToMAP({ server, scope, systemId, onMessage, credent
49
49
  ...(projectContext?.task_graph ? {
50
50
  opentasks: { canQuery: true, canLink: true, canAnnotate: true, canTask: true },
51
51
  } : {}),
52
+ // Cascade capability (CascadeCapability, git-cascade >= 0.0.8) — gated
53
+ // on cascade.enabled. cc-swarm runs cascade in "observed git" mode: it
54
+ // watches git state and serves diffs. It now also probes in-progress
55
+ // *merge* conflict state on every poll tick and emits
56
+ // `x-cascade/stream.conflicted` / `stream.conflict_resolved` on the
57
+ // transitions — so `emitsConflicts: true` ships honestly. Action-layer
58
+ // remains observe-only (`canAct: false`); the watcher does not drive
59
+ // merges / rebases / pauses.
60
+ // canServeDiff: true — the diff server (src/cascade-diff-server.mjs) is wired
61
+ // canAct: false — no cascade action handler
62
+ // emitsConflicts: true — the watcher observes merge-conflict transitions
63
+ // TODO: rebase-conflict observation (`.git/rebase-merge/`,
64
+ // `.git/rebase-apply/`) is a known follow-up. v1 covers `git merge`
65
+ // conflicts only.
66
+ ...(cascadeEnabled ? {
67
+ cascade: { canServeDiff: true, canAct: false, emitsConflicts: true },
68
+ } : {}),
52
69
  },
53
70
  metadata: {
54
71
  systemId,
package/src/paths.mjs CHANGED
@@ -102,6 +102,10 @@ export const LOGS_DIR = path.join(GLOBAL_CONFIG_DIR, "tmp", "logs");
102
102
  export const OPENTASKS_DIR = path.join(_tmpDir, "opentasks");
103
103
  export const OPENTASKS_SYNC_STATE_PATH = path.join(_tmpDir, "opentasks", "sync-state.json");
104
104
 
105
+ // cascade runtime state — git-cascade tracker DB (local-mode state store)
106
+ export const CASCADE_DIR = path.join(_tmpDir, "cascade");
107
+ export const CASCADE_DB_PATH = path.join(_tmpDir, "cascade", "tracker.db");
108
+
105
109
  /**
106
110
  * Whether paths resolved to global (~/.claude-swarm/tmp/) vs project-level.
107
111
  */
@@ -149,6 +153,14 @@ export function ensureOpentasksDir() {
149
153
  fs.mkdirSync(OPENTASKS_DIR, { recursive: true });
150
154
  }
151
155
 
156
+ /**
157
+ * Ensure the cascade runtime directory exists.
158
+ * Holds the git-cascade tracker DB (local-mode state store).
159
+ */
160
+ export function ensureCascadeDir() {
161
+ fs.mkdirSync(CASCADE_DIR, { recursive: true });
162
+ }
163
+
152
164
  /**
153
165
  * Resolve the plugin root directory.
154
166
  * Works from any file in src/ or scripts/.
@@ -104,6 +104,12 @@ export function createCommandHandler(connection, scope, registeredAgents, opts =
104
104
  // Keyed by dispatch_id → { conversation_id, received_at }.
105
105
  const _pendingNudges = new Map();
106
106
 
107
+ // Cascade attribution hint — the single most-recent { agentId, taskRef, ts }
108
+ // sent by the PostToolUse(Bash) hook via the cascade-attribution command.
109
+ // The cascade-watcher reads this (via getCascadeAttribution) to stamp
110
+ // agent_id / task_ref on observed-git events when the hint is fresh.
111
+ let _cascadeAttribution = null;
112
+
107
113
  // Connection-ready gate: commands that need `conn` await this promise.
108
114
  // If connection is already available, resolves immediately.
109
115
  // When connection arrives later (via setConnection), resolves the pending promise.
@@ -510,6 +516,21 @@ export function createCommandHandler(connection, scope, registeredAgents, opts =
510
516
  break;
511
517
  }
512
518
 
519
+ // --- Cascade attribution hint ---
520
+ // Sent by the PostToolUse(Bash) hook. Stores the single most-recent
521
+ // attribution hint; the cascade-watcher reads it to attribute
522
+ // observed-git events. Attribution-only — no git detection here.
523
+
524
+ case "cascade-attribution": {
525
+ _cascadeAttribution = {
526
+ agentId: command.agentId || "",
527
+ taskRef: command.taskRef || null,
528
+ ts: typeof command.ts === "number" ? command.ts : Date.now(),
529
+ };
530
+ respond(client, { ok: true });
531
+ break;
532
+ }
533
+
513
534
  default:
514
535
  respond(client, { ok: false, error: `Unknown action: ${action}` });
515
536
  }
@@ -519,6 +540,11 @@ export function createCommandHandler(connection, scope, registeredAgents, opts =
519
540
  }
520
541
  };
521
542
 
543
+ // Expose the latest cascade attribution hint so the sidecar can pass a
544
+ // getter to startCascadeWatcher as `getAttribution`. Returns the single
545
+ // most-recent { agentId, taskRef, ts } hint, or null when none received.
546
+ handler.getCascadeAttribution = () => _cascadeAttribution;
547
+
522
548
  // Allow updating the connection reference (also resolves any pending waitForConn)
523
549
  handler.setConnection = (newConn) => {
524
550
  conn = newConn;