@synkro-sh/cli 1.6.36 → 1.6.38

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
@@ -602,54 +602,14 @@ var init_mcpConfig = __esm({
602
602
  });
603
603
 
604
604
  // cli/installer/skillParser.ts
605
- import { readFileSync as readFileSync4, existsSync as existsSync4 } from "fs";
606
- import { resolve as resolve2, basename } from "path";
607
- function parseSection(heading, body) {
608
- const lines = body.split("\n");
609
- const meta = {};
610
- const textLines = [];
611
- for (const line of lines) {
612
- const m = line.match(/^(mode|severity|category)\s*:\s*(.+)/i);
613
- if (m && META_KEYS.has(m[1].toLowerCase())) {
614
- meta[m[1].toLowerCase()] = m[2].trim();
615
- } else if (line.trim()) {
616
- textLines.push(line.trim());
617
- }
618
- }
619
- const description = textLines.join(" ").trim();
620
- const text = description ? `${heading}: ${description}` : heading;
621
- return {
622
- text,
623
- mode: meta.mode || "ask",
624
- severity: meta.severity || "medium",
625
- category: meta.category || "custom"
626
- };
627
- }
628
- function parseSkillFile(filePath) {
629
- if (!existsSync4(filePath)) return null;
630
- const content = readFileSync4(filePath, "utf-8");
631
- const source = `skill:${basename(filePath)}`;
632
- const sections = content.split(/^## /m).slice(1);
633
- if (sections.length === 0) return null;
634
- const rules = [];
635
- for (const section of sections) {
636
- const newlineIdx = section.indexOf("\n");
637
- if (newlineIdx === -1) continue;
638
- const heading = section.slice(0, newlineIdx).trim();
639
- const body = section.slice(newlineIdx + 1);
640
- if (!heading) continue;
641
- rules.push(parseSection(heading, body));
642
- }
643
- return rules.length > 0 ? { source, rules } : null;
644
- }
605
+ import { existsSync as existsSync4 } from "fs";
606
+ import { resolve as resolve2 } from "path";
645
607
  function resolveSkillPaths(skills, repoRoot) {
646
608
  return skills.filter((s) => s.endsWith(".md")).map((s) => resolve2(repoRoot, s)).filter((p) => existsSync4(p));
647
609
  }
648
- var META_KEYS;
649
610
  var init_skillParser = __esm({
650
611
  "cli/installer/skillParser.ts"() {
651
612
  "use strict";
652
- META_KEYS = /* @__PURE__ */ new Set(["mode", "severity", "category"]);
653
613
  }
654
614
  });
655
615
 
@@ -6056,7 +6016,7 @@ __export(stub_exports, {
6056
6016
  saveCredentials: () => saveCredentials
6057
6017
  });
6058
6018
  import { createServer } from "http";
6059
- import { writeFileSync as writeFileSync4, readFileSync as readFileSync5, existsSync as existsSync5, mkdirSync as mkdirSync4, unlinkSync as unlinkSync2 } from "fs";
6019
+ import { writeFileSync as writeFileSync4, readFileSync as readFileSync4, existsSync as existsSync5, mkdirSync as mkdirSync4, unlinkSync as unlinkSync2 } from "fs";
6060
6020
  import { homedir as homedir4, platform } from "os";
6061
6021
  import { join as join3, dirname as dirname4 } from "path";
6062
6022
  import { execFile } from "child_process";
@@ -6097,7 +6057,7 @@ function loadCredentials() {
6097
6057
  return null;
6098
6058
  }
6099
6059
  try {
6100
- const content = readFileSync5(AUTH_FILE, "utf8");
6060
+ const content = readFileSync4(AUTH_FILE, "utf8");
6101
6061
  return JSON.parse(content);
6102
6062
  } catch (error) {
6103
6063
  return null;
@@ -6955,7 +6915,7 @@ __export(macKeychain_exports, {
6955
6915
  writeCursorApiKey: () => writeCursorApiKey,
6956
6916
  writeRefreshAgent: () => writeRefreshAgent
6957
6917
  });
6958
- import { existsSync as existsSync7, mkdirSync as mkdirSync6, writeFileSync as writeFileSync6, chmodSync, readFileSync as readFileSync6, statSync } from "fs";
6918
+ import { existsSync as existsSync7, mkdirSync as mkdirSync6, writeFileSync as writeFileSync6, chmodSync, readFileSync as readFileSync5, statSync } from "fs";
6959
6919
  import { homedir as homedir5, platform as platform2 } from "os";
6960
6920
  import { join as join5 } from "path";
6961
6921
  import { spawnSync } from "child_process";
@@ -6983,7 +6943,7 @@ function exportKeychainCreds() {
6983
6943
  }
6984
6944
  function cursorApiKeyConfigured() {
6985
6945
  try {
6986
- return existsSync7(CURSOR_API_KEY_FILE) && readFileSync6(CURSOR_API_KEY_FILE, "utf-8").trim().length > 0;
6946
+ return existsSync7(CURSOR_API_KEY_FILE) && readFileSync5(CURSOR_API_KEY_FILE, "utf-8").trim().length > 0;
6987
6947
  } catch {
6988
6948
  return false;
6989
6949
  }
@@ -6999,7 +6959,7 @@ function writeCursorApiKey(key) {
6999
6959
  async function validateCursorApiKey() {
7000
6960
  let key;
7001
6961
  try {
7002
- key = readFileSync6(CURSOR_API_KEY_FILE, "utf-8").trim();
6962
+ key = readFileSync5(CURSOR_API_KEY_FILE, "utf-8").trim();
7003
6963
  } catch {
7004
6964
  return null;
7005
6965
  }
@@ -7093,7 +7053,7 @@ function refreshCreds() {
7093
7053
  }
7094
7054
  function readExportedCreds() {
7095
7055
  try {
7096
- return readFileSync6(CLAUDE_CREDS_FILE, "utf-8");
7056
+ return readFileSync5(CLAUDE_CREDS_FILE, "utf-8");
7097
7057
  } catch {
7098
7058
  return null;
7099
7059
  }
@@ -7140,9 +7100,10 @@ __export(dockerInstall_exports, {
7140
7100
  readContainerConfig: () => readContainerConfig,
7141
7101
  resolveWorkerConfig: () => resolveWorkerConfig,
7142
7102
  splitWorkers: () => splitWorkers,
7143
- waitForContainerReady: () => waitForContainerReady
7103
+ waitForContainerReady: () => waitForContainerReady,
7104
+ waitForWorkersReady: () => waitForWorkersReady
7144
7105
  });
7145
- import { copyFileSync, existsSync as existsSync8, mkdirSync as mkdirSync7, readFileSync as readFileSync7, readdirSync as readdirSync2 } from "fs";
7106
+ import { copyFileSync, existsSync as existsSync8, mkdirSync as mkdirSync7, readFileSync as readFileSync6, readdirSync as readdirSync2 } from "fs";
7146
7107
  import { homedir as homedir6 } from "os";
7147
7108
  import { join as join6 } from "path";
7148
7109
  import { execSync as execSync4, spawnSync as spawnSync2 } from "child_process";
@@ -7212,7 +7173,7 @@ function readSynkroFileConfig() {
7212
7173
  if (!root) return { pool: "auto" };
7213
7174
  const fp = join6(root, ".synkro");
7214
7175
  if (!existsSync8(fp)) return { pool: "auto" };
7215
- const raw = readFileSync7(fp, "utf-8");
7176
+ const raw = readFileSync6(fp, "utf-8");
7216
7177
  const parsed = raw.trimStart().startsWith("{") ? JSON.parse(raw) : parseSynkroYaml(raw);
7217
7178
  const pool = ["auto", "claude", "cursor"].includes(parsed?.grader?.pool) ? parsed.grader.pool : "auto";
7218
7179
  const cw = typeof parsed?.workers?.claude === "number" ? Math.max(0, Math.floor(parsed.workers.claude)) : void 0;
@@ -7467,6 +7428,22 @@ async function waitForContainerReady(timeoutMs = 6e4) {
7467
7428
  }
7468
7429
  return false;
7469
7430
  }
7431
+ async function waitForWorkersReady(timeoutMs = 6e4) {
7432
+ const start = Date.now();
7433
+ const url = `http://127.0.0.1:${HOST_GRADER_PORT}/healthz`;
7434
+ while (Date.now() - start < timeoutMs) {
7435
+ try {
7436
+ const r = await fetch(url, { signal: AbortSignal.timeout(2e3) });
7437
+ if (r.ok) {
7438
+ const data = await r.json();
7439
+ if ((data.healthy || 0) > 0) return true;
7440
+ }
7441
+ } catch {
7442
+ }
7443
+ await new Promise((r) => setTimeout(r, 1e3));
7444
+ }
7445
+ return false;
7446
+ }
7470
7447
  function dockerRemove() {
7471
7448
  spawnSync2("docker", ["rm", CONTAINER_NAME], { encoding: "utf-8", timeout: 3e4 });
7472
7449
  }
@@ -7674,14 +7651,14 @@ __export(setupGithub_exports, {
7674
7651
  import { createInterface as createInterface2 } from "readline/promises";
7675
7652
  import { stdin as input, stdout as output } from "process";
7676
7653
  import { execSync as execSync5, spawn as nodeSpawn } from "child_process";
7677
- import { existsSync as existsSync9, readFileSync as readFileSync8, unlinkSync as unlinkSync3 } from "fs";
7654
+ import { existsSync as existsSync9, readFileSync as readFileSync7, unlinkSync as unlinkSync3 } from "fs";
7678
7655
  import { homedir as homedir7, platform as platform3 } from "os";
7679
7656
  import { join as join7 } from "path";
7680
7657
  import { execFile as execFile2 } from "child_process";
7681
7658
  function readConfig() {
7682
7659
  if (!existsSync9(CONFIG_PATH)) return {};
7683
7660
  const out = {};
7684
- for (const line of readFileSync8(CONFIG_PATH, "utf-8").split("\n")) {
7661
+ for (const line of readFileSync7(CONFIG_PATH, "utf-8").split("\n")) {
7685
7662
  const t = line.trim();
7686
7663
  if (!t || t.startsWith("#")) continue;
7687
7664
  const eq = t.indexOf("=");
@@ -7751,7 +7728,7 @@ function captureClaudeSetupToken() {
7751
7728
  proc.on("close", (code) => {
7752
7729
  let raw = "";
7753
7730
  try {
7754
- raw = readFileSync8(tmpFile, "utf-8");
7731
+ raw = readFileSync7(tmpFile, "utf-8");
7755
7732
  } catch (e) {
7756
7733
  reject(new Error(`Could not read script output file: ${e.message}`));
7757
7734
  return;
@@ -8038,7 +8015,7 @@ __export(install_exports, {
8038
8015
  syncSkillFiles: () => syncSkillFiles,
8039
8016
  writeHookScripts: () => writeHookScripts
8040
8017
  });
8041
- import { existsSync as existsSync10, mkdirSync as mkdirSync8, writeFileSync as writeFileSync7, chmodSync as chmodSync2, readFileSync as readFileSync9, readdirSync as readdirSync3 } from "fs";
8018
+ import { existsSync as existsSync10, mkdirSync as mkdirSync8, writeFileSync as writeFileSync7, chmodSync as chmodSync2, readFileSync as readFileSync8, readdirSync as readdirSync3 } from "fs";
8042
8019
  import { homedir as homedir8 } from "os";
8043
8020
  import { join as join8 } from "path";
8044
8021
  import { execSync as execSync6, spawnSync as spawnSync3 } from "child_process";
@@ -8284,7 +8261,7 @@ function writeConfigEnv(opts) {
8284
8261
  `SYNKRO_CREDENTIALS_PATH=${shellQuoteSingle(credsPath)}`,
8285
8262
  `SYNKRO_TIER=${shellQuoteSingle(safeTier)}`,
8286
8263
  `SYNKRO_INFERENCE=${shellQuoteSingle(safeInference)}`,
8287
- `SYNKRO_VERSION=${shellQuoteSingle("1.6.36")}`
8264
+ `SYNKRO_VERSION=${shellQuoteSingle("1.6.38")}`
8288
8265
  ];
8289
8266
  if (safeSynkroBin) lines.push(`SYNKRO_CLI_BIN=${shellQuoteSingle(safeSynkroBin)}`);
8290
8267
  if (safeUserId) lines.push(`SYNKRO_USER_ID=${shellQuoteSingle(safeUserId)}`);
@@ -8307,7 +8284,7 @@ function resolveDeploymentMode() {
8307
8284
  if (envOverride === "bare-host" || envOverride === "docker") return envOverride;
8308
8285
  try {
8309
8286
  if (existsSync10(CONFIG_PATH2)) {
8310
- const m = readFileSync9(CONFIG_PATH2, "utf-8").match(/^SYNKRO_DEPLOYMENT_MODE='([^']*)'/m);
8287
+ const m = readFileSync8(CONFIG_PATH2, "utf-8").match(/^SYNKRO_DEPLOYMENT_MODE='([^']*)'/m);
8311
8288
  const val = m?.[1]?.toLowerCase();
8312
8289
  if (val === "bare-host" || val === "docker") return val;
8313
8290
  }
@@ -8336,14 +8313,14 @@ function collectLocalMetadata(includeClaudeCode = true) {
8336
8313
  }
8337
8314
  const claudeDir = join8(homedir8(), ".claude");
8338
8315
  try {
8339
- const settings = JSON.parse(readFileSync9(join8(claudeDir, "settings.json"), "utf-8"));
8316
+ const settings = JSON.parse(readFileSync8(join8(claudeDir, "settings.json"), "utf-8"));
8340
8317
  const plugins = Object.keys(settings.enabledPlugins ?? {}).filter((k) => settings.enabledPlugins[k]);
8341
8318
  if (plugins.length) meta.enabled_plugins = plugins;
8342
8319
  if (settings.permissions?.defaultMode) meta.permissions_mode = settings.permissions.defaultMode;
8343
8320
  } catch {
8344
8321
  }
8345
8322
  try {
8346
- const mcpCache = JSON.parse(readFileSync9(join8(claudeDir, "mcp-needs-auth-cache.json"), "utf-8"));
8323
+ const mcpCache = JSON.parse(readFileSync8(join8(claudeDir, "mcp-needs-auth-cache.json"), "utf-8"));
8347
8324
  const mcpNames = Object.keys(mcpCache);
8348
8325
  if (mcpNames.length) meta.mcp_servers = mcpNames;
8349
8326
  } catch {
@@ -8358,7 +8335,7 @@ function collectLocalMetadata(includeClaudeCode = true) {
8358
8335
  const sessionsDir = join8(claudeDir, "sessions");
8359
8336
  const files = readdirSync3(sessionsDir).filter((f) => f.endsWith(".json")).slice(-5);
8360
8337
  for (const f of files) {
8361
- const s = JSON.parse(readFileSync9(join8(sessionsDir, f), "utf-8"));
8338
+ const s = JSON.parse(readFileSync8(join8(sessionsDir, f), "utf-8"));
8362
8339
  if (s.version) {
8363
8340
  meta.cc_version = meta.cc_version || s.version;
8364
8341
  break;
@@ -8490,7 +8467,7 @@ async function installCommand(opts = {}) {
8490
8467
  for (const mode of ["edit", "bash"]) {
8491
8468
  const pidFile = join8(SYNKRO_DIR4, "daemon", mode, "daemon.pid");
8492
8469
  try {
8493
- const pid = parseInt(readFileSync9(pidFile, "utf-8").trim(), 10);
8470
+ const pid = parseInt(readFileSync8(pidFile, "utf-8").trim(), 10);
8494
8471
  if (pid > 0) {
8495
8472
  process.kill(pid, "SIGTERM");
8496
8473
  console.log(`Stopped stale ${mode} grader daemon (pid ${pid})`);
@@ -8727,7 +8704,7 @@ async function installCommand(opts = {}) {
8727
8704
  const ready = await waitForContainerReady(6e4);
8728
8705
  if (ready) {
8729
8706
  console.log(" \u2713 container ready");
8730
- const mcpJwt = readFileSync9(join8(SYNKRO_DIR4, ".mcp-jwt"), "utf-8").trim();
8707
+ const mcpJwt = readFileSync8(join8(SYNKRO_DIR4, ".mcp-jwt"), "utf-8").trim();
8731
8708
  try {
8732
8709
  const ingestResp = await fetch(`http://127.0.0.1:${hostMcpPort}/api/ingest`, {
8733
8710
  method: "POST",
@@ -8744,7 +8721,13 @@ async function installCommand(opts = {}) {
8744
8721
  } catch {
8745
8722
  console.warn(" \u26A0 ingest endpoint unreachable \u2014 telemetry spool may not drain.");
8746
8723
  }
8747
- await syncSkillFiles();
8724
+ const workersUp = await waitForWorkersReady(3e4);
8725
+ if (workersUp) {
8726
+ console.log(" \u2713 workers ready");
8727
+ await syncSkillFiles();
8728
+ } else {
8729
+ console.warn(" \u26A0 workers did not register within 30s \u2014 skill sync skipped");
8730
+ }
8748
8731
  } else {
8749
8732
  console.error(" \u2717 container did not become healthy within 60s");
8750
8733
  console.error(" Run `docker logs synkro-server` to debug.");
@@ -8759,7 +8742,7 @@ async function installCommand(opts = {}) {
8759
8742
  try {
8760
8743
  let mcpToken = "";
8761
8744
  try {
8762
- mcpToken = readFileSync9(join8(SYNKRO_DIR4, ".mcp-jwt"), "utf-8").trim();
8745
+ mcpToken = readFileSync8(join8(SYNKRO_DIR4, ".mcp-jwt"), "utf-8").trim();
8763
8746
  } catch {
8764
8747
  }
8765
8748
  if (mcpToken) {
@@ -8919,7 +8902,7 @@ function readSynkroFilePool() {
8919
8902
  if (!root) return "auto";
8920
8903
  const fp = join8(root, ".synkro");
8921
8904
  if (!existsSync10(fp)) return "auto";
8922
- const parsed = parseSynkroFileRaw(readFileSync9(fp, "utf-8"));
8905
+ const parsed = parseSynkroFileRaw(readFileSync8(fp, "utf-8"));
8923
8906
  const pool = parsed?.grader?.pool;
8924
8907
  if (pool === "cursor" || pool === "claude") return pool;
8925
8908
  } catch {
@@ -8932,7 +8915,7 @@ function readFullSynkroFile() {
8932
8915
  if (!root) return null;
8933
8916
  const fp = join8(root, ".synkro");
8934
8917
  if (!existsSync10(fp)) return null;
8935
- const parsed = parseSynkroFileRaw(readFileSync9(fp, "utf-8"));
8918
+ const parsed = parseSynkroFileRaw(readFileSync8(fp, "utf-8"));
8936
8919
  const valid = ["claude-code", "cursor"];
8937
8920
  const harness = Array.isArray(parsed.harness) ? parsed.harness.filter((h) => valid.includes(h)) : ["claude-code", "cursor"];
8938
8921
  return {
@@ -8983,7 +8966,7 @@ function reconcileHarness() {
8983
8966
  });
8984
8967
  console.log(" \u2713 Claude Code hooks registered");
8985
8968
  try {
8986
- const mcpJwt = readFileSync9(join8(SYNKRO_DIR4, ".mcp-jwt"), "utf-8").trim();
8969
+ const mcpJwt = readFileSync8(join8(SYNKRO_DIR4, ".mcp-jwt"), "utf-8").trim();
8987
8970
  if (mcpJwt) {
8988
8971
  installMcpConfig({ gatewayUrl: "", bearerToken: mcpJwt, local: true });
8989
8972
  console.log(" \u2713 Claude Code MCP registered");
@@ -9047,23 +9030,28 @@ async function syncSkillFiles() {
9047
9030
  if (resolved.length === 0) return;
9048
9031
  const mcpPort = process.env.SYNKRO_MCP_PORT || "18931";
9049
9032
  for (const fp of resolved) {
9050
- const skill = parseSkillFile(fp);
9051
- if (!skill || skill.rules.length === 0) continue;
9033
+ const content = readFileSync8(fp, "utf-8");
9034
+ if (!content.trim()) continue;
9035
+ const source = `skill:${fp.split("/").pop()}`;
9052
9036
  try {
9053
9037
  const resp = await fetch(`http://127.0.0.1:${mcpPort}/api/local/skills/sync`, {
9054
9038
  method: "POST",
9055
9039
  headers: { "Content-Type": "application/json" },
9056
- body: JSON.stringify(skill),
9057
- signal: AbortSignal.timeout(1e4)
9040
+ body: JSON.stringify({ source, content }),
9041
+ signal: AbortSignal.timeout(65e3)
9058
9042
  });
9059
9043
  if (resp.ok) {
9060
9044
  const result = await resp.json();
9061
- console.log(` \u2713 skill ${skill.source}: ${result.created} rules synced (${result.removed} removed)`);
9045
+ if (result.created > 0) {
9046
+ console.log(` \u2713 skill ${source}: ${result.created} new rules added`);
9047
+ } else {
9048
+ console.log(` \u2713 skill ${source}: ${result.message || "up to date"}`);
9049
+ }
9062
9050
  } else {
9063
- console.warn(` \u26A0 skill ${skill.source}: sync failed (${resp.status})`);
9051
+ console.warn(` \u26A0 skill ${source}: sync failed (${resp.status})`);
9064
9052
  }
9065
9053
  } catch (e) {
9066
- console.warn(` \u26A0 skill ${skill.source}: ${e.message}`);
9054
+ console.warn(` \u26A0 skill ${source}: ${e.message}`);
9067
9055
  }
9068
9056
  }
9069
9057
  }
@@ -9095,7 +9083,7 @@ function extractSessionInsights(projectsDir) {
9095
9083
  const sessionId = file.replace(".jsonl", "");
9096
9084
  const filePath = join8(projectsDir, file);
9097
9085
  try {
9098
- const content = readFileSync9(filePath, "utf-8");
9086
+ const content = readFileSync8(filePath, "utf-8");
9099
9087
  const lines = content.split("\n").filter(Boolean);
9100
9088
  for (let i = 0; i < lines.length; i++) {
9101
9089
  try {
@@ -9171,7 +9159,7 @@ function extractTextContent(content) {
9171
9159
  return "";
9172
9160
  }
9173
9161
  function parseTranscriptFile(filePath) {
9174
- const content = readFileSync9(filePath, "utf-8");
9162
+ const content = readFileSync8(filePath, "utf-8");
9175
9163
  const lines = content.split("\n").filter(Boolean);
9176
9164
  const messages = [];
9177
9165
  for (let i = 0; i < lines.length; i++) {
@@ -9241,7 +9229,7 @@ async function syncTranscriptsLocal(mcpPort, mcpToken, repo) {
9241
9229
  process.stdout.write(`\r Progress: ${i + 1}/${files.length} sessions (${totalMessages} messages embedded) `);
9242
9230
  }
9243
9231
  try {
9244
- const content = readFileSync9(join8(projectsDir, file), "utf-8");
9232
+ const content = readFileSync8(join8(projectsDir, file), "utf-8");
9245
9233
  const lineCount = content.split("\n").filter(Boolean).length;
9246
9234
  writeFileSync7(join8(OFFSETS_DIR, sessionId), String(lineCount), "utf-8");
9247
9235
  } catch {
@@ -9295,7 +9283,7 @@ async function syncTranscriptsBulk(gatewayUrl, token, repo) {
9295
9283
  const sessionId = file.replace(".jsonl", "");
9296
9284
  const filePath = join8(projectsDir, file);
9297
9285
  try {
9298
- const content = readFileSync9(filePath, "utf-8");
9286
+ const content = readFileSync8(filePath, "utf-8");
9299
9287
  const lineCount = content.split("\n").filter(Boolean).length;
9300
9288
  writeFileSync7(join8(OFFSETS_DIR, sessionId), String(lineCount), "utf-8");
9301
9289
  } catch {
@@ -9375,7 +9363,7 @@ rl.on('line', async (line) => {
9375
9363
  });
9376
9364
 
9377
9365
  // cli/local-cc/install.ts
9378
- import { existsSync as existsSync11, mkdirSync as mkdirSync9, writeFileSync as writeFileSync8, readFileSync as readFileSync10, chmodSync as chmodSync3, copyFileSync as copyFileSync2, renameSync as renameSync4, unlinkSync as unlinkSync4, openSync, fsyncSync, closeSync } from "fs";
9366
+ import { existsSync as existsSync11, mkdirSync as mkdirSync9, writeFileSync as writeFileSync8, readFileSync as readFileSync9, chmodSync as chmodSync3, copyFileSync as copyFileSync2, renameSync as renameSync4, unlinkSync as unlinkSync4, openSync, fsyncSync, closeSync } from "fs";
9379
9367
  import { join as join9 } from "path";
9380
9368
  import { homedir as homedir9 } from "os";
9381
9369
  import { spawnSync as spawnSync4 } from "child_process";
@@ -9414,7 +9402,7 @@ function safelyMutateClaudeJson(mutator) {
9414
9402
  if (!existsSync11(CLAUDE_JSON_PATH)) {
9415
9403
  return;
9416
9404
  }
9417
- const originalText = readFileSync10(CLAUDE_JSON_PATH, "utf-8");
9405
+ const originalText = readFileSync9(CLAUDE_JSON_PATH, "utf-8");
9418
9406
  let parsed;
9419
9407
  try {
9420
9408
  parsed = JSON.parse(originalText);
@@ -9984,7 +9972,7 @@ var init_disconnect = __esm({
9984
9972
  });
9985
9973
 
9986
9974
  // cli/local-cc/turnLog.ts
9987
- import { appendFileSync, existsSync as existsSync13, mkdirSync as mkdirSync10, openSync as openSync2, readFileSync as readFileSync11, readSync, closeSync as closeSync2, statSync as statSync2, watchFile, unwatchFile } from "fs";
9975
+ import { appendFileSync, existsSync as existsSync13, mkdirSync as mkdirSync10, openSync as openSync2, readFileSync as readFileSync10, readSync, closeSync as closeSync2, statSync as statSync2, watchFile, unwatchFile } from "fs";
9988
9976
  import { dirname as dirname6, join as join11 } from "path";
9989
9977
  import { homedir as homedir11 } from "os";
9990
9978
  function truncate(s, max = PREVIEW_MAX) {
@@ -10026,7 +10014,7 @@ function readRecentTurns(n = 20) {
10026
10014
  try {
10027
10015
  const size = statSync2(TURN_LOG_PATH).size;
10028
10016
  if (size === 0) return [];
10029
- const text = readFileSync11(TURN_LOG_PATH, "utf-8");
10017
+ const text = readFileSync10(TURN_LOG_PATH, "utf-8");
10030
10018
  const lines = text.split("\n").filter(Boolean);
10031
10019
  const lastN = lines.slice(-n).reverse();
10032
10020
  return lastN.map((line) => {
@@ -10472,13 +10460,13 @@ var init_pueue = __esm({
10472
10460
  });
10473
10461
 
10474
10462
  // cli/local-cc/settings.ts
10475
- import { existsSync as existsSync14, readFileSync as readFileSync12 } from "fs";
10463
+ import { existsSync as existsSync14, readFileSync as readFileSync11 } from "fs";
10476
10464
  import { homedir as homedir13 } from "os";
10477
10465
  import { join as join13 } from "path";
10478
10466
  function isLocalCCEnabled() {
10479
10467
  if (!existsSync14(CONFIG_PATH3)) return false;
10480
10468
  try {
10481
- const content = readFileSync12(CONFIG_PATH3, "utf-8");
10469
+ const content = readFileSync11(CONFIG_PATH3, "utf-8");
10482
10470
  const match = content.match(/^SYNKRO_LOCAL_INFERENCE='([^']*)'/m);
10483
10471
  return match?.[1] === "yes";
10484
10472
  } catch {
@@ -10502,7 +10490,7 @@ import { spawnSync as spawnSync7 } from "child_process";
10502
10490
  import { homedir as homedir14 } from "os";
10503
10491
  import { join as join14 } from "path";
10504
10492
  import { readFileSync as fsReadFileSync, existsSync as fsExistsSync } from "fs";
10505
- import { existsSync as existsSync15, readFileSync as readFileSync13, writeFileSync as writeFileSync9 } from "fs";
10493
+ import { existsSync as existsSync15, readFileSync as readFileSync12, writeFileSync as writeFileSync9 } from "fs";
10506
10494
  function deploymentMode() {
10507
10495
  const env = (process.env.SYNKRO_DEPLOYMENT_MODE || "").toLowerCase();
10508
10496
  if (env === "docker") return "docker";
@@ -10609,14 +10597,14 @@ TROUBLESHOOTING
10609
10597
  }
10610
10598
  function readGatewayUrl() {
10611
10599
  if (existsSync15(CONFIG_PATH4)) {
10612
- const m = readFileSync13(CONFIG_PATH4, "utf-8").match(/^SYNKRO_GATEWAY_URL='([^']*)'/m);
10600
+ const m = readFileSync12(CONFIG_PATH4, "utf-8").match(/^SYNKRO_GATEWAY_URL='([^']*)'/m);
10613
10601
  if (m) return m[1];
10614
10602
  }
10615
10603
  return "https://api.synkro.sh";
10616
10604
  }
10617
10605
  function updateLocalInferenceFlag(enabled) {
10618
10606
  if (!existsSync15(CONFIG_PATH4)) return;
10619
- let content = readFileSync13(CONFIG_PATH4, "utf-8");
10607
+ let content = readFileSync12(CONFIG_PATH4, "utf-8");
10620
10608
  const flag = enabled ? "yes" : "no";
10621
10609
  if (content.includes("SYNKRO_LOCAL_INFERENCE=")) {
10622
10610
  content = content.replace(/^SYNKRO_LOCAL_INFERENCE='[^']*'/m, `SYNKRO_LOCAL_INFERENCE='${flag}'`);
@@ -10808,7 +10796,11 @@ async function cmdRestart(rest = []) {
10808
10796
  await dockerUpdate({ claudeWorkers, cursorWorkers });
10809
10797
  const ready = await waitForContainerReady(6e4);
10810
10798
  console.log(ready ? "\u2713 container ready" : "\u26A0 container did not pass /healthz within 60s");
10811
- if (ready) await syncSkillFiles();
10799
+ if (ready) {
10800
+ const workersUp = await waitForWorkersReady(3e4);
10801
+ console.log(workersUp ? "\u2713 workers ready" : "\u26A0 workers did not register within 30s");
10802
+ if (workersUp) await syncSkillFiles();
10803
+ }
10812
10804
  return;
10813
10805
  }
10814
10806
  stopTask(CHANNEL_PRIMARY);
@@ -11159,13 +11151,13 @@ var config_exports = {};
11159
11151
  __export(config_exports, {
11160
11152
  configCommand: () => configCommand
11161
11153
  });
11162
- import { readFileSync as readFileSync14, writeFileSync as writeFileSync10, existsSync as existsSync16 } from "fs";
11154
+ import { readFileSync as readFileSync13, writeFileSync as writeFileSync10, existsSync as existsSync16 } from "fs";
11163
11155
  import { join as join15 } from "path";
11164
11156
  import { homedir as homedir15 } from "os";
11165
11157
  function readConfigEnv() {
11166
11158
  if (!existsSync16(CONFIG_PATH5)) return {};
11167
11159
  const out = {};
11168
- for (const line of readFileSync14(CONFIG_PATH5, "utf-8").split("\n")) {
11160
+ for (const line of readFileSync13(CONFIG_PATH5, "utf-8").split("\n")) {
11169
11161
  const t = line.trim();
11170
11162
  if (!t || t.startsWith("#")) continue;
11171
11163
  const eq = t.indexOf("=");
@@ -11178,7 +11170,7 @@ function updateConfigValue(key, value) {
11178
11170
  console.error("No config found. Run `synkro install` first.");
11179
11171
  process.exit(1);
11180
11172
  }
11181
- const lines = readFileSync14(CONFIG_PATH5, "utf-8").split("\n");
11173
+ const lines = readFileSync13(CONFIG_PATH5, "utf-8").split("\n");
11182
11174
  const pattern = new RegExp(`^${key}=`);
11183
11175
  let found = false;
11184
11176
  const updated = lines.map((line) => {
@@ -11305,14 +11297,14 @@ var init_config = __esm({
11305
11297
  });
11306
11298
 
11307
11299
  // cli/bootstrap.js
11308
- import { readFileSync as readFileSync15, existsSync as existsSync17 } from "fs";
11300
+ import { readFileSync as readFileSync14, existsSync as existsSync17 } from "fs";
11309
11301
  import { resolve as resolve3 } from "path";
11310
11302
  var envCandidates = [
11311
11303
  resolve3(process.env.HOME ?? "", ".synkro", "config.env")
11312
11304
  ];
11313
11305
  for (const envPath of envCandidates) {
11314
11306
  if (!existsSync17(envPath)) continue;
11315
- const envContent = readFileSync15(envPath, "utf-8");
11307
+ const envContent = readFileSync14(envPath, "utf-8");
11316
11308
  for (const line of envContent.split("\n")) {
11317
11309
  const trimmed = line.trim();
11318
11310
  if (!trimmed || trimmed.startsWith("#")) continue;
@@ -11327,7 +11319,7 @@ var args = process.argv.slice(2);
11327
11319
  var cmd = args[0] || "";
11328
11320
  var subArgs = args.slice(1);
11329
11321
  function printVersion() {
11330
- console.log("1.6.36");
11322
+ console.log("1.6.38");
11331
11323
  }
11332
11324
  function printHelp2() {
11333
11325
  console.log(`Synkro CLI \u2014 runtime safety for AI coding agents