@synkro-sh/cli 1.7.87 → 1.7.88

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/dist/bootstrap.js CHANGED
@@ -147,7 +147,7 @@ function getIdentity() {
147
147
  if (cached2) return cached2;
148
148
  let cliVersion = "0.0.0";
149
149
  try {
150
- cliVersion = "1.7.87";
150
+ cliVersion = "1.7.88";
151
151
  } catch {
152
152
  }
153
153
  const creds = loadCredentialsIdentity();
@@ -5478,6 +5478,7 @@ __export(dockerInstall_exports, {
5478
5478
  normalizeProvider: () => normalizeProvider,
5479
5479
  poolLabel: () => poolLabel,
5480
5480
  readContainerConfig: () => readContainerConfig,
5481
+ resolveConductorProvider: () => resolveConductorProvider,
5481
5482
  resolveGraderPool: () => resolveGraderPool,
5482
5483
  resolveWorkerConfig: () => resolveWorkerConfig,
5483
5484
  splitWorkers: () => splitWorkers,
@@ -5488,6 +5489,15 @@ import { copyFileSync, existsSync as existsSync19, mkdirSync as mkdirSync12, rea
5488
5489
  import { homedir as homedir16 } from "os";
5489
5490
  import { join as join14 } from "path";
5490
5491
  import { execSync as execSync3, spawnSync as spawnSync3 } from "child_process";
5492
+ function resolveConductorProvider(pool, counts) {
5493
+ if (pool !== "auto") return pool;
5494
+ const ranked = [
5495
+ ["claude_code", counts.claudeWorkers],
5496
+ ["cursor", counts.cursorWorkers],
5497
+ ["codex", counts.codexWorkers]
5498
+ ];
5499
+ return ranked.reduce((best, candidate) => candidate[1] > best[1] ? candidate : best, ranked[0])[0];
5500
+ }
5491
5501
  function splitWorkers(total, providers) {
5492
5502
  const t = Math.max(0, Math.floor(total));
5493
5503
  const selected = ["claude_code", "cursor", "codex"].filter((provider) => providers.includes(provider));
@@ -5634,7 +5644,10 @@ function resolveWorkerConfig(rest) {
5634
5644
  const cw = sc.claudeWorkers || 0;
5635
5645
  const curw = sc.cursorWorkers || 0;
5636
5646
  const codw = sc.codexWorkers || 0;
5637
- if (cw + curw + codw > 0) return { claudeWorkers: cw, cursorWorkers: curw, codexWorkers: codw, explicit };
5647
+ if (cw + curw + codw > 0) {
5648
+ const counts2 = { claudeWorkers: cw, cursorWorkers: curw, codexWorkers: codw };
5649
+ return { ...counts2, conductorProvider: resolveConductorProvider(sc.pool, counts2), explicit };
5650
+ }
5638
5651
  }
5639
5652
  if (sc.pool === "cursor") {
5640
5653
  provs = ["cursor"];
@@ -5647,7 +5660,9 @@ function resolveWorkerConfig(rest) {
5647
5660
  if (provs.length === 0) provs = ["claude_code"];
5648
5661
  }
5649
5662
  }
5650
- return { ...splitWorkers(workers, provs), explicit };
5663
+ const counts = splitWorkers(workers, provs);
5664
+ const pool = provs.length === 1 ? provs[0] : "auto";
5665
+ return { ...counts, conductorProvider: resolveConductorProvider(pool, counts), explicit };
5651
5666
  }
5652
5667
  function imageTag() {
5653
5668
  const registry = process.env.SYNKRO_IMAGE_REGISTRY || "";
@@ -5721,8 +5736,13 @@ async function dockerInstall(opts = {}) {
5721
5736
  const cursorWorkers = opts.cursorWorkers ?? 0;
5722
5737
  const codexWorkers = opts.codexWorkers ?? 0;
5723
5738
  const totalWorkers = claudeWorkers + cursorWorkers + codexWorkers;
5739
+ const workerCounts = { claudeWorkers, cursorWorkers, codexWorkers };
5740
+ const conductorProvider = opts.conductorProvider ?? resolveConductorProvider("auto", workerCounts);
5741
+ const usesClaude = claudeWorkers > 0 || conductorProvider === "claude_code";
5742
+ const usesCursor = cursorWorkers > 0 || conductorProvider === "cursor";
5743
+ const usesCodex = codexWorkers > 0 || conductorProvider === "codex";
5724
5744
  const codexHomeDir = opts.codexHomeDir ?? join14(SYNKRO_DIR7, "codex-local-session");
5725
- if (codexWorkers > 0 && !existsSync19(join14(codexHomeDir, "auth.json"))) {
5745
+ if (usesCodex && !existsSync19(join14(codexHomeDir, "auth.json"))) {
5726
5746
  throw new DockerInstallError(
5727
5747
  "Codex grader credentials are missing. Re-run `synkro install` to authorize an isolated Codex session."
5728
5748
  );
@@ -5743,14 +5763,14 @@ async function dockerInstall(opts = {}) {
5743
5763
  if (needsKeychainBridge()) {
5744
5764
  const claudeCredsPath = exportKeychainCreds();
5745
5765
  if (!claudeCredsPath) {
5746
- if (claudeWorkers > 0) {
5766
+ if (usesClaude) {
5747
5767
  throw new DockerInstallError(
5748
5768
  "Claude Code keychain entry not found. Run `claude login` (or open Claude Code and sign in) before installing the container."
5749
5769
  );
5750
5770
  }
5751
5771
  console.warn(" \u26A0 Claude Code keychain entry not found \u2014 live usage telemetry stays off until you sign in to Claude Code (grading is unaffected).");
5752
5772
  }
5753
- if (cursorWorkers > 0 && !cursorApiKeyConfigured()) {
5773
+ if (usesCursor && !cursorApiKeyConfigured()) {
5754
5774
  console.warn(" \u26A0 No Cursor API key found \u2014 Cursor grader workers will be idle.");
5755
5775
  console.warn(" Generate a key at cursor.com \u2192 Settings \u2192 API Keys, then:");
5756
5776
  console.warn(` echo 'YOUR_KEY' > ~/.synkro/cursor-creds/api-key && chmod 600 ~/.synkro/cursor-creds/api-key`);
@@ -5821,8 +5841,8 @@ async function dockerInstall(opts = {}) {
5821
5841
  `${CLAUDE_HOST_STATE_DIR}:/data/claude-host-state:ro`,
5822
5842
  // Cursor creds — mounted RW so the in-container refresher can rotate the
5823
5843
  // access token in place. Only mounted when the install includes Cursor.
5824
- ...cursorWorkers > 0 ? ["-v", `${CURSOR_CREDS_DIR}:/home/synkro/.cursor-creds:rw`] : [],
5825
- ...codexWorkers > 0 ? ["-v", `${codexHomeDir}:/home/synkro/.codex:rw`] : [],
5844
+ ...usesCursor ? ["-v", `${CURSOR_CREDS_DIR}:/home/synkro/.cursor-creds:rw`] : [],
5845
+ ...usesCodex ? ["-v", `${codexHomeDir}:/home/synkro/.codex:rw`] : [],
5826
5846
  "-e",
5827
5847
  `WORKERS_PER_POOL=${totalWorkers}`,
5828
5848
  "-e",
@@ -5831,6 +5851,8 @@ async function dockerInstall(opts = {}) {
5831
5851
  `CURSOR_WORKERS=${cursorWorkers}`,
5832
5852
  "-e",
5833
5853
  `CODEX_WORKERS=${codexWorkers}`,
5854
+ "-e",
5855
+ `SYNKRO_CONDUCTOR_PROVIDER=${conductorProvider}`,
5834
5856
  // Pass through the batch-size lever if the operator set it. Defaults
5835
5857
  // inside the container to 5; clamped to [1, 20] by synkro-server.ts.
5836
5858
  ...process.env.SYNKRO_MAX_BATCH_SIZE ? ["-e", `SYNKRO_MAX_BATCH_SIZE=${process.env.SYNKRO_MAX_BATCH_SIZE}`] : [],
@@ -5949,6 +5971,7 @@ function readContainerConfig() {
5949
5971
  claudeWorkers: num(get("CLAUDE_WORKERS")),
5950
5972
  cursorWorkers: num(get("CURSOR_WORKERS")),
5951
5973
  codexWorkers: num(get("CODEX_WORKERS")),
5974
+ conductorProvider: normalizeProvider(get("SYNKRO_CONDUCTOR_PROVIDER") || "") || void 0,
5952
5975
  connectedRepo: get("SYNKRO_CONNECTED_REPO") || void 0
5953
5976
  };
5954
5977
  }
@@ -6645,6 +6668,19 @@ exit $RC
6645
6668
  }
6646
6669
  });
6647
6670
 
6671
+ // cli/installer/graderSmoke.ts
6672
+ function isPrimerAckVerdict(value) {
6673
+ return /<category>\s*primer_ack\s*<\/category>/i.test(value) || /<reason>\s*(?:batch )?primer received\s*<\/reason>/i.test(value);
6674
+ }
6675
+ function isValidRiskyEditSmokeVerdict(value) {
6676
+ return /<synkro-verdict(?:\s[^>]*)?>[\s\S]*<\/synkro-verdict>/i.test(value) && /<ok>\s*false\s*<\/ok>/i.test(value) && !isPrimerAckVerdict(value);
6677
+ }
6678
+ var init_graderSmoke = __esm({
6679
+ "cli/installer/graderSmoke.ts"() {
6680
+ "use strict";
6681
+ }
6682
+ });
6683
+
6648
6684
  // cli/commands/install.ts
6649
6685
  var install_exports = {};
6650
6686
  __export(install_exports, {
@@ -6908,7 +6944,7 @@ function writeConfigEnv(opts) {
6908
6944
  `SYNKRO_CREDENTIALS_PATH=${shellQuoteSingle2(credsPath)}`,
6909
6945
  `SYNKRO_TIER=${shellQuoteSingle2(safeTier)}`,
6910
6946
  `SYNKRO_INFERENCE=${shellQuoteSingle2(safeInference)}`,
6911
- `SYNKRO_VERSION=${shellQuoteSingle2("1.7.87")}`
6947
+ `SYNKRO_VERSION=${shellQuoteSingle2("1.7.88")}`
6912
6948
  ];
6913
6949
  if (safeSynkroBin) lines.push(`SYNKRO_CLI_BIN=${shellQuoteSingle2(safeSynkroBin)}`);
6914
6950
  if (safeUserId) lines.push(`SYNKRO_USER_ID=${shellQuoteSingle2(safeUserId)}`);
@@ -6997,9 +7033,13 @@ async function provisionCloudContainer(opts) {
6997
7033
  ({ claudeWorkers, cursorWorkers, codexWorkers } = splitWorkers(totalWorkers, providers));
6998
7034
  }
6999
7035
  if (claudeWorkers + cursorWorkers + codexWorkers === 0) codexWorkers = totalWorkers;
7000
- const selectedKind = codexWorkers > 0 && claudeWorkers === 0 && cursorWorkers === 0 ? "codex" : cursorWorkers > 0 && claudeWorkers === 0 ? "cursor" : "claude_code";
7036
+ const selectedKind = resolveConductorProvider(sf?.grader.pool || "auto", {
7037
+ claudeWorkers,
7038
+ cursorWorkers,
7039
+ codexWorkers
7040
+ });
7001
7041
  let setupToken = "";
7002
- if (claudeWorkers > 0) {
7042
+ if (claudeWorkers > 0 || selectedKind === "claude_code") {
7003
7043
  try {
7004
7044
  console.log(" Authorize your Claude account for the hosted Claude worker \u2014");
7005
7045
  console.log(" a browser window will open for approval...\n");
@@ -7050,7 +7090,7 @@ async function provisionCloudContainer(opts) {
7050
7090
  if (opts.hasCursor) harness.push("cursor");
7051
7091
  if (opts.hasCodex) harness.push("codex");
7052
7092
  let cursorApiKey = "";
7053
- if (cursorWorkers > 0) {
7093
+ if (cursorWorkers > 0 || selectedKind === "cursor") {
7054
7094
  try {
7055
7095
  cursorApiKey = readFileSync20(join18(SYNKRO_DIR11, "cursor-creds", "api-key"), "utf-8").trim();
7056
7096
  } catch {
@@ -7062,7 +7102,7 @@ async function provisionCloudContainer(opts) {
7062
7102
  } catch (e) {
7063
7103
  console.warn(` (cloud token unavailable, using session token: ${e.message})`);
7064
7104
  }
7065
- if (codexWorkers > 0) {
7105
+ if (codexWorkers > 0 || selectedKind === "codex") {
7066
7106
  const codex = await setupCodexCloud(opts.gatewayUrl, opts.jwt, (message) => console.log(` ${message}`));
7067
7107
  if (!codex.ok) {
7068
7108
  console.error(` \u2717 ${codex.error || "Codex cloud authorization failed"}`);
@@ -7081,6 +7121,7 @@ async function provisionCloudContainer(opts) {
7081
7121
  claude_workers: claudeWorkers,
7082
7122
  cursor_workers: cursorWorkers,
7083
7123
  codex_workers: codexWorkers,
7124
+ conductor_provider: selectedKind,
7084
7125
  cursor_api_key: cursorApiKey,
7085
7126
  // never logged; gateway stores it as the org secret
7086
7127
  connected_repo: repo,
@@ -7206,11 +7247,12 @@ async function verifyCloudGrader(jwt2, requestedKind) {
7206
7247
  body = JSON.parse(raw);
7207
7248
  } catch {
7208
7249
  }
7209
- if (r.ok && typeof body.result === "string" && body.result.includes("<synkro-verdict>")) {
7250
+ if (r.ok && typeof body.result === "string" && isValidRiskyEditSmokeVerdict(body.result)) {
7210
7251
  console.log(" \u2713 smoke grade passed \u2014 cloud grading is live\n");
7211
7252
  return true;
7212
7253
  }
7213
- const detail = (body.error || raw || "").trim().slice(0, 300) || "(empty response)";
7254
+ const invalidVerdict = r.ok && typeof body.result === "string" ? `invalid smoke verdict: ${body.result}` : "";
7255
+ const detail = (body.error || invalidVerdict || raw || "").trim().slice(0, 300) || "(empty response)";
7214
7256
  console.warn(` \u2717 smoke grade FAILED (HTTP ${r.status}): ${detail}`);
7215
7257
  if (body.error_code) {
7216
7258
  console.warn(` \u25B8 ${body.error_code}: ${body.hint || ""}`);
@@ -7644,7 +7686,7 @@ async function installCommand(opts = {}) {
7644
7686
  await setTelemetryState({ enabled: true, remoteFlushEnabled: telemetryConsent });
7645
7687
  emit("install", {
7646
7688
  phase: "started",
7647
- cli_version_to: "1.7.87",
7689
+ cli_version_to: "1.7.88",
7648
7690
  agents_detected: agents.map((a) => a.kind),
7649
7691
  with_github: false,
7650
7692
  with_local_cc: false,
@@ -7985,8 +8027,13 @@ async function installCommand(opts = {}) {
7985
8027
  ({ claudeWorkers, cursorWorkers, codexWorkers } = splitWorkers(totalWorkers, providers));
7986
8028
  if (synkroFilePool !== "auto") console.log(` synkro.toml: grader pool set to ${poolLabel(synkroFilePool)}`);
7987
8029
  }
8030
+ const conductorProvider = resolveConductorProvider(sf?.grader.pool || "auto", {
8031
+ claudeWorkers,
8032
+ cursorWorkers,
8033
+ codexWorkers
8034
+ });
7988
8035
  let codexHomeDir;
7989
- if (codexWorkers > 0) {
8036
+ if (codexWorkers > 0 || conductorProvider === "codex") {
7990
8037
  const codexSetup = await setupCodexLocal((message) => console.log(` ${message}`));
7991
8038
  if (!codexSetup.ok || !codexSetup.home) {
7992
8039
  console.error(` \u2717 ${codexSetup.error || "Codex grader authorization failed"}`);
@@ -7996,7 +8043,7 @@ async function installCommand(opts = {}) {
7996
8043
  }
7997
8044
  console.log(` worker pool: ${claudeWorkers} claude + ${cursorWorkers} cursor + ${codexWorkers} codex`);
7998
8045
  const connectedRepo = detectGitRepo2() || void 0;
7999
- const { image, hostMcpPort, hostGraderPort, hostCwePort, hostPglitePort } = await dockerInstall({ claudeWorkers, cursorWorkers, codexWorkers, codexHomeDir, connectedRepo });
8046
+ const { image, hostMcpPort, hostGraderPort, hostCwePort, hostPglitePort } = await dockerInstall({ claudeWorkers, cursorWorkers, codexWorkers, conductorProvider, codexHomeDir, connectedRepo });
8000
8047
  console.log(` \u2713 pulled ${image}`);
8001
8048
  console.log(` container started \u2014 MCP=${hostMcpPort} general=${hostGraderPort} CWE=${hostCwePort} pglite=${hostPglitePort}`);
8002
8049
  console.log(" waiting for container to be ready...");
@@ -8421,7 +8468,10 @@ function reconcileHarness() {
8421
8468
  const cw = Math.max(0, Math.floor(sf.workers.claude || 0));
8422
8469
  const curw = Math.max(0, Math.floor(sf.workers.cursor || 0));
8423
8470
  const codw = Math.max(0, Math.floor(sf.workers.codex || 0));
8424
- if (cw + curw + codw > 0) return { claudeWorkers: cw, cursorWorkers: curw, codexWorkers: codw };
8471
+ if (cw + curw + codw > 0) {
8472
+ const counts2 = { claudeWorkers: cw, cursorWorkers: curw, codexWorkers: codw };
8473
+ return { ...counts2, conductorProvider: resolveConductorProvider(sf.grader.pool, counts2) };
8474
+ }
8425
8475
  }
8426
8476
  const total = parseInt(process.env.SYNKRO_WORKERS_PER_POOL || "8", 10);
8427
8477
  const providers = [];
@@ -8437,7 +8487,8 @@ function reconcileHarness() {
8437
8487
  if (wantCodex) providers.push("codex");
8438
8488
  }
8439
8489
  if (providers.length === 0) providers.push("claude_code");
8440
- return splitWorkers(total, providers);
8490
+ const counts = splitWorkers(total, providers);
8491
+ return { ...counts, conductorProvider: resolveConductorProvider(sf.grader.pool, counts) };
8441
8492
  }
8442
8493
  async function ingestSkillTasks(tasks, mcpPort) {
8443
8494
  const summary = { ingested: 0, rules: 0, rejected: [] };
@@ -9169,6 +9220,7 @@ var init_install = __esm({
9169
9220
  init_setupToken();
9170
9221
  init_codexCloudSetup();
9171
9222
  init_ptyShim();
9223
+ init_graderSmoke();
9172
9224
  SYNKRO_DIR11 = join18(homedir20(), ".synkro");
9173
9225
  HOOKS_DIR = join18(SYNKRO_DIR11, "hooks");
9174
9226
  BIN_DIR = join18(SYNKRO_DIR11, "bin");
@@ -11719,9 +11771,9 @@ async function warmChannels(ready1, ready2) {
11719
11771
  async function cmdStart(rest = []) {
11720
11772
  if (inDockerMode()) {
11721
11773
  if (rest.length > 0) {
11722
- const { claudeWorkers, cursorWorkers, codexWorkers } = resolveWorkerConfig(rest);
11774
+ const { claudeWorkers, cursorWorkers, codexWorkers, conductorProvider } = resolveWorkerConfig(rest);
11723
11775
  console.log(`Starting synkro-server container (${claudeWorkers} claude + ${cursorWorkers} cursor + ${codexWorkers} codex)...`);
11724
- await dockerUpdate({ claudeWorkers, cursorWorkers, codexWorkers });
11776
+ await dockerUpdate({ claudeWorkers, cursorWorkers, codexWorkers, conductorProvider });
11725
11777
  const ready3 = await waitForContainerReady(6e4);
11726
11778
  console.log(ready3 ? "\u2713 container ready" : "\u26A0 container did not pass /healthz within 60s");
11727
11779
  return;
@@ -11768,18 +11820,19 @@ async function cmdRestart(rest = []) {
11768
11820
  let claudeWorkers;
11769
11821
  let cursorWorkers;
11770
11822
  let codexWorkers;
11823
+ let conductorProvider;
11771
11824
  if (explicit) {
11772
- ({ claudeWorkers, cursorWorkers, codexWorkers } = resolveWorkerConfig(rest));
11825
+ ({ claudeWorkers, cursorWorkers, codexWorkers, conductorProvider } = resolveWorkerConfig(rest));
11773
11826
  } else {
11774
11827
  const reconciled = reconcileHarness();
11775
11828
  if (reconciled) {
11776
- ({ claudeWorkers, cursorWorkers, codexWorkers } = reconciled);
11829
+ ({ claudeWorkers, cursorWorkers, codexWorkers, conductorProvider } = reconciled);
11777
11830
  } else {
11778
- ({ claudeWorkers, cursorWorkers, codexWorkers } = resolveWorkerConfig(rest));
11831
+ ({ claudeWorkers, cursorWorkers, codexWorkers, conductorProvider } = resolveWorkerConfig(rest));
11779
11832
  }
11780
11833
  }
11781
11834
  console.log(`Restarting synkro-server container (${claudeWorkers} claude + ${cursorWorkers} cursor + ${codexWorkers} codex, pulling latest image)...`);
11782
- await dockerUpdate({ claudeWorkers, cursorWorkers, codexWorkers });
11835
+ await dockerUpdate({ claudeWorkers, cursorWorkers, codexWorkers, conductorProvider });
11783
11836
  const ready = await waitForContainerReady(6e4);
11784
11837
  console.log(ready ? "\u2713 container ready" : "\u26A0 container did not pass /healthz within 60s");
11785
11838
  if (ready) {
@@ -13134,7 +13187,7 @@ async function startCommand(rest = []) {
13134
13187
  if (cfg.explicit) {
13135
13188
  console.log(`Synkro: starting server (${cfg.claudeWorkers} claude + ${cfg.cursorWorkers} cursor + ${cfg.codexWorkers} codex)
13136
13189
  `);
13137
- await dockerUpdate({ claudeWorkers: cfg.claudeWorkers, cursorWorkers: cfg.cursorWorkers, codexWorkers: cfg.codexWorkers, connectedRepo: resolveConnectedRepo() });
13190
+ await dockerUpdate({ claudeWorkers: cfg.claudeWorkers, cursorWorkers: cfg.cursorWorkers, codexWorkers: cfg.codexWorkers, conductorProvider: cfg.conductorProvider, connectedRepo: resolveConnectedRepo() });
13138
13191
  const ready = await waitForContainerReady(6e4);
13139
13192
  if (!ready) {
13140
13193
  console.error("\n\u26A0 container did not pass /healthz within 60s");
@@ -13162,10 +13215,11 @@ async function updateCommand() {
13162
13215
  const claudeWorkers = cfg.claudeWorkers ?? 8;
13163
13216
  const cursorWorkers = cfg.cursorWorkers ?? 0;
13164
13217
  const codexWorkers = cfg.codexWorkers ?? 0;
13218
+ const conductorProvider = cfg.conductorProvider;
13165
13219
  console.log("Synkro: updating to the latest container image");
13166
13220
  console.log(` preserving pool: ${claudeWorkers} claude + ${cursorWorkers} cursor + ${codexWorkers} codex worker(s)
13167
13221
  `);
13168
- await dockerUpdate({ claudeWorkers, cursorWorkers, codexWorkers, connectedRepo: resolveConnectedRepo() });
13222
+ await dockerUpdate({ claudeWorkers, cursorWorkers, codexWorkers, conductorProvider, connectedRepo: resolveConnectedRepo() });
13169
13223
  const ready = await waitForContainerReady(9e4);
13170
13224
  if (!ready) {
13171
13225
  console.error("\n\u26A0 container did not pass its health check within 90s \u2014 check: docker logs synkro-server");
@@ -13190,17 +13244,19 @@ async function restartCommand(rest = []) {
13190
13244
  let claudeWorkers = cfg.claudeWorkers;
13191
13245
  let cursorWorkers = cfg.cursorWorkers;
13192
13246
  let codexWorkers = cfg.codexWorkers;
13247
+ let conductorProvider = cfg.conductorProvider;
13193
13248
  if (!cfg.explicit) {
13194
13249
  const reconciled = reconcileHarness();
13195
13250
  if (reconciled) {
13196
13251
  claudeWorkers = reconciled.claudeWorkers;
13197
13252
  cursorWorkers = reconciled.cursorWorkers;
13198
13253
  codexWorkers = reconciled.codexWorkers;
13254
+ conductorProvider = reconciled.conductorProvider;
13199
13255
  }
13200
13256
  }
13201
13257
  console.log(`Synkro: restarting server (${claudeWorkers} claude + ${cursorWorkers} cursor + ${codexWorkers} codex)
13202
13258
  `);
13203
- await dockerUpdate({ claudeWorkers, cursorWorkers, codexWorkers, connectedRepo: resolveConnectedRepo() });
13259
+ await dockerUpdate({ claudeWorkers, cursorWorkers, codexWorkers, conductorProvider, connectedRepo: resolveConnectedRepo() });
13204
13260
  const ready = await waitForContainerReady(6e4);
13205
13261
  if (!ready) {
13206
13262
  console.error("\n\u26A0 container did not pass /healthz within 60s");
@@ -13630,7 +13686,7 @@ var subArgs = args.slice(1);
13630
13686
  var isDetachedChild = process.env.SYNKRO_TELEMETRY_DETACHED === "1";
13631
13687
  var FLUSH_SKIP = /* @__PURE__ */ new Set(["grade", "version", "--version", "-v", "help", "--help", "-h", ""]);
13632
13688
  function printVersion() {
13633
- console.log("1.7.87");
13689
+ console.log("1.7.88");
13634
13690
  }
13635
13691
  function printHelp2() {
13636
13692
  console.log(`Synkro CLI \u2014 runtime safety for AI coding agents