@synkro-sh/cli 1.6.34 → 1.6.36
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 +223 -39
- package/dist/bootstrap.js.map +1 -1
- package/package.json +1 -1
package/dist/bootstrap.js
CHANGED
|
@@ -1198,6 +1198,7 @@ export interface SynkroFileConfig {
|
|
|
1198
1198
|
version: number;
|
|
1199
1199
|
harness: ('claude-code' | 'cursor')[];
|
|
1200
1200
|
grader: { pool: 'auto' | 'claude' | 'cursor'; mode?: string };
|
|
1201
|
+
workers: { claude?: number; cursor?: number };
|
|
1201
1202
|
ruleset: string;
|
|
1202
1203
|
skills: string[];
|
|
1203
1204
|
scanning: { cwe: boolean; cve: boolean };
|
|
@@ -1207,11 +1208,60 @@ const SYNKRO_FILE_DEFAULTS: SynkroFileConfig = {
|
|
|
1207
1208
|
version: 1,
|
|
1208
1209
|
harness: ['claude-code', 'cursor'],
|
|
1209
1210
|
grader: { pool: 'auto' },
|
|
1211
|
+
workers: {},
|
|
1210
1212
|
ruleset: 'default',
|
|
1211
1213
|
skills: [],
|
|
1212
1214
|
scanning: { cwe: true, cve: true },
|
|
1213
1215
|
};
|
|
1214
1216
|
|
|
1217
|
+
function parseSynkroYaml(raw: string): Record<string, any> {
|
|
1218
|
+
const result: Record<string, any> = {};
|
|
1219
|
+
const lines = raw.split('\\n');
|
|
1220
|
+
let currentKey = '';
|
|
1221
|
+
let currentObj: Record<string, any> | null = null;
|
|
1222
|
+
let currentArr: string[] | null = null;
|
|
1223
|
+
|
|
1224
|
+
for (const line of lines) {
|
|
1225
|
+
if (!line.trim() || line.trim().startsWith('#')) continue;
|
|
1226
|
+
|
|
1227
|
+
if (line.match(/^\\S/) && line.includes(':')) {
|
|
1228
|
+
if (currentObj && currentKey) result[currentKey] = currentObj;
|
|
1229
|
+
if (currentArr && currentKey) result[currentKey] = currentArr;
|
|
1230
|
+
currentObj = null;
|
|
1231
|
+
currentArr = null;
|
|
1232
|
+
|
|
1233
|
+
const colonIdx = line.indexOf(':');
|
|
1234
|
+
const key = line.slice(0, colonIdx).trim();
|
|
1235
|
+
const val = line.slice(colonIdx + 1).trim();
|
|
1236
|
+
currentKey = key;
|
|
1237
|
+
|
|
1238
|
+
if (val) {
|
|
1239
|
+
if (val === '[]') result[key] = [];
|
|
1240
|
+
else if (val === 'true') result[key] = true;
|
|
1241
|
+
else if (val === 'false') result[key] = false;
|
|
1242
|
+
else if (/^\\d+$/.test(val)) result[key] = parseInt(val, 10);
|
|
1243
|
+
else result[key] = val;
|
|
1244
|
+
currentKey = '';
|
|
1245
|
+
}
|
|
1246
|
+
} else if (line.match(/^ - /)) {
|
|
1247
|
+
if (!currentArr) currentArr = [];
|
|
1248
|
+
currentArr.push(line.replace(/^ - /, '').trim());
|
|
1249
|
+
} else if (line.match(/^ \\S/) && line.includes(':')) {
|
|
1250
|
+
if (!currentObj) currentObj = {};
|
|
1251
|
+
const colonIdx = line.indexOf(':');
|
|
1252
|
+
const k = line.slice(0, colonIdx).trim();
|
|
1253
|
+
const v = line.slice(colonIdx + 1).trim();
|
|
1254
|
+
if (v === 'true') currentObj[k] = true;
|
|
1255
|
+
else if (v === 'false') currentObj[k] = false;
|
|
1256
|
+
else if (/^\\d+$/.test(v)) currentObj[k] = parseInt(v, 10);
|
|
1257
|
+
else currentObj[k] = v;
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
if (currentObj && currentKey) result[currentKey] = currentObj;
|
|
1261
|
+
if (currentArr && currentKey) result[currentKey] = currentArr;
|
|
1262
|
+
return result;
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1215
1265
|
let _synkroFileCache: SynkroFileConfig | undefined;
|
|
1216
1266
|
|
|
1217
1267
|
export function loadSynkroFile(cwd?: string): SynkroFileConfig {
|
|
@@ -1221,7 +1271,8 @@ export function loadSynkroFile(cwd?: string): SynkroFileConfig {
|
|
|
1221
1271
|
const fp = root + '/.synkro';
|
|
1222
1272
|
try {
|
|
1223
1273
|
if (!existsSync(fp)) { _synkroFileCache = SYNKRO_FILE_DEFAULTS; return _synkroFileCache; }
|
|
1224
|
-
const
|
|
1274
|
+
const raw = readFileSync(fp, 'utf-8');
|
|
1275
|
+
const parsed = raw.trimStart().startsWith('{') ? JSON.parse(raw) : parseSynkroYaml(raw);
|
|
1225
1276
|
const validHarness = ['claude-code', 'cursor'] as const;
|
|
1226
1277
|
const harness = Array.isArray(parsed.harness)
|
|
1227
1278
|
? parsed.harness.filter((h: string) => validHarness.includes(h as any))
|
|
@@ -1233,6 +1284,10 @@ export function loadSynkroFile(cwd?: string): SynkroFileConfig {
|
|
|
1233
1284
|
pool: ['auto', 'claude', 'cursor'].includes(parsed.grader?.pool) ? parsed.grader.pool : 'auto',
|
|
1234
1285
|
mode: ['local', 'byok'].includes(parsed.grader?.mode) ? parsed.grader.mode : undefined,
|
|
1235
1286
|
},
|
|
1287
|
+
workers: {
|
|
1288
|
+
...(typeof parsed.workers?.claude === 'number' ? { claude: parsed.workers.claude } : {}),
|
|
1289
|
+
...(typeof parsed.workers?.cursor === 'number' ? { cursor: parsed.workers.cursor } : {}),
|
|
1290
|
+
},
|
|
1236
1291
|
ruleset: typeof parsed.ruleset === 'string' ? parsed.ruleset : 'default',
|
|
1237
1292
|
skills: Array.isArray(parsed.skills) ? parsed.skills.filter((s: unknown) => typeof s === 'string') : [],
|
|
1238
1293
|
scanning: {
|
|
@@ -7108,18 +7163,64 @@ function normalizeProvider(p) {
|
|
|
7108
7163
|
if (v === "cursor") return "cursor";
|
|
7109
7164
|
return null;
|
|
7110
7165
|
}
|
|
7111
|
-
function
|
|
7166
|
+
function parseSynkroYaml(raw) {
|
|
7167
|
+
const result = {};
|
|
7168
|
+
const lines = raw.split("\n");
|
|
7169
|
+
let currentKey = "";
|
|
7170
|
+
let currentObj = null;
|
|
7171
|
+
let currentArr = null;
|
|
7172
|
+
for (const line of lines) {
|
|
7173
|
+
if (!line.trim() || line.trim().startsWith("#")) continue;
|
|
7174
|
+
if (/^\S/.test(line) && line.includes(":")) {
|
|
7175
|
+
if (currentObj && currentKey) result[currentKey] = currentObj;
|
|
7176
|
+
if (currentArr && currentKey) result[currentKey] = currentArr;
|
|
7177
|
+
currentObj = null;
|
|
7178
|
+
currentArr = null;
|
|
7179
|
+
const ci = line.indexOf(":");
|
|
7180
|
+
const key = line.slice(0, ci).trim();
|
|
7181
|
+
const val = line.slice(ci + 1).trim();
|
|
7182
|
+
currentKey = key;
|
|
7183
|
+
if (val) {
|
|
7184
|
+
if (val === "[]") result[key] = [];
|
|
7185
|
+
else if (val === "true") result[key] = true;
|
|
7186
|
+
else if (val === "false") result[key] = false;
|
|
7187
|
+
else if (/^\d+$/.test(val)) result[key] = parseInt(val, 10);
|
|
7188
|
+
else result[key] = val;
|
|
7189
|
+
currentKey = "";
|
|
7190
|
+
}
|
|
7191
|
+
} else if (/^ - /.test(line)) {
|
|
7192
|
+
if (!currentArr) currentArr = [];
|
|
7193
|
+
currentArr.push(line.replace(/^ - /, "").trim());
|
|
7194
|
+
} else if (/^ \S/.test(line) && line.includes(":")) {
|
|
7195
|
+
if (!currentObj) currentObj = {};
|
|
7196
|
+
const ci = line.indexOf(":");
|
|
7197
|
+
const k = line.slice(0, ci).trim();
|
|
7198
|
+
const v = line.slice(ci + 1).trim();
|
|
7199
|
+
if (v === "true") currentObj[k] = true;
|
|
7200
|
+
else if (v === "false") currentObj[k] = false;
|
|
7201
|
+
else if (/^\d+$/.test(v)) currentObj[k] = parseInt(v, 10);
|
|
7202
|
+
else currentObj[k] = v;
|
|
7203
|
+
}
|
|
7204
|
+
}
|
|
7205
|
+
if (currentObj && currentKey) result[currentKey] = currentObj;
|
|
7206
|
+
if (currentArr && currentKey) result[currentKey] = currentArr;
|
|
7207
|
+
return result;
|
|
7208
|
+
}
|
|
7209
|
+
function readSynkroFileConfig() {
|
|
7112
7210
|
try {
|
|
7113
7211
|
const root = execSync4("git rev-parse --show-toplevel 2>/dev/null", { encoding: "utf-8", timeout: 3e3, stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
7114
|
-
if (!root) return "auto";
|
|
7212
|
+
if (!root) return { pool: "auto" };
|
|
7115
7213
|
const fp = join6(root, ".synkro");
|
|
7116
|
-
if (!existsSync8(fp)) return "auto";
|
|
7117
|
-
const
|
|
7118
|
-
const
|
|
7119
|
-
|
|
7214
|
+
if (!existsSync8(fp)) return { pool: "auto" };
|
|
7215
|
+
const raw = readFileSync7(fp, "utf-8");
|
|
7216
|
+
const parsed = raw.trimStart().startsWith("{") ? JSON.parse(raw) : parseSynkroYaml(raw);
|
|
7217
|
+
const pool = ["auto", "claude", "cursor"].includes(parsed?.grader?.pool) ? parsed.grader.pool : "auto";
|
|
7218
|
+
const cw = typeof parsed?.workers?.claude === "number" ? Math.max(0, Math.floor(parsed.workers.claude)) : void 0;
|
|
7219
|
+
const curw = typeof parsed?.workers?.cursor === "number" ? Math.max(0, Math.floor(parsed.workers.cursor)) : void 0;
|
|
7220
|
+
return { pool, claudeWorkers: cw, cursorWorkers: curw };
|
|
7120
7221
|
} catch {
|
|
7121
7222
|
}
|
|
7122
|
-
return "auto";
|
|
7223
|
+
return { pool: "auto" };
|
|
7123
7224
|
}
|
|
7124
7225
|
function resolveWorkerConfig(rest) {
|
|
7125
7226
|
let workers = 8;
|
|
@@ -7154,10 +7255,15 @@ function resolveWorkerConfig(rest) {
|
|
|
7154
7255
|
workers = Math.min(workers, 64);
|
|
7155
7256
|
let provs = providers;
|
|
7156
7257
|
if (provs.length === 0) {
|
|
7157
|
-
const
|
|
7158
|
-
if (
|
|
7258
|
+
const sc = readSynkroFileConfig();
|
|
7259
|
+
if (sc.claudeWorkers != null || sc.cursorWorkers != null) {
|
|
7260
|
+
const cw = sc.claudeWorkers || 0;
|
|
7261
|
+
const curw = sc.cursorWorkers || 0;
|
|
7262
|
+
if (cw + curw > 0) return { claudeWorkers: cw, cursorWorkers: curw, explicit };
|
|
7263
|
+
}
|
|
7264
|
+
if (sc.pool === "cursor") {
|
|
7159
7265
|
provs = ["cursor"];
|
|
7160
|
-
} else if (
|
|
7266
|
+
} else if (sc.pool === "claude") {
|
|
7161
7267
|
provs = ["claude_code"];
|
|
7162
7268
|
} else {
|
|
7163
7269
|
provs = detectAgents().map((a) => a.kind);
|
|
@@ -8178,7 +8284,7 @@ function writeConfigEnv(opts) {
|
|
|
8178
8284
|
`SYNKRO_CREDENTIALS_PATH=${shellQuoteSingle(credsPath)}`,
|
|
8179
8285
|
`SYNKRO_TIER=${shellQuoteSingle(safeTier)}`,
|
|
8180
8286
|
`SYNKRO_INFERENCE=${shellQuoteSingle(safeInference)}`,
|
|
8181
|
-
`SYNKRO_VERSION=${shellQuoteSingle("1.6.
|
|
8287
|
+
`SYNKRO_VERSION=${shellQuoteSingle("1.6.36")}`
|
|
8182
8288
|
];
|
|
8183
8289
|
if (safeSynkroBin) lines.push(`SYNKRO_CLI_BIN=${shellQuoteSingle(safeSynkroBin)}`);
|
|
8184
8290
|
if (safeUserId) lines.push(`SYNKRO_USER_ID=${shellQuoteSingle(safeUserId)}`);
|
|
@@ -8586,19 +8692,32 @@ async function installCommand(opts = {}) {
|
|
|
8586
8692
|
await promptCursorApiKey(opts);
|
|
8587
8693
|
}
|
|
8588
8694
|
console.log("Installing Synkro server container...");
|
|
8589
|
-
const
|
|
8590
|
-
|
|
8591
|
-
let
|
|
8592
|
-
if (
|
|
8593
|
-
|
|
8594
|
-
|
|
8595
|
-
|
|
8695
|
+
const sf = readFullSynkroFile();
|
|
8696
|
+
let claudeWorkers;
|
|
8697
|
+
let cursorWorkers;
|
|
8698
|
+
if (sf && (sf.workers.claude != null || sf.workers.cursor != null)) {
|
|
8699
|
+
claudeWorkers = Math.max(0, Math.floor(sf.workers.claude || 0));
|
|
8700
|
+
cursorWorkers = Math.max(0, Math.floor(sf.workers.cursor || 0));
|
|
8701
|
+
if (claudeWorkers + cursorWorkers === 0) {
|
|
8702
|
+
claudeWorkers = 0;
|
|
8703
|
+
cursorWorkers = 8;
|
|
8704
|
+
}
|
|
8705
|
+
console.log(` .synkro: explicit workers \u2014 ${claudeWorkers} claude + ${cursorWorkers} cursor`);
|
|
8596
8706
|
} else {
|
|
8597
|
-
|
|
8598
|
-
|
|
8707
|
+
const totalWorkers = parseInt(process.env.SYNKRO_WORKERS_PER_POOL || "8", 10);
|
|
8708
|
+
const synkroFilePool = sf?.grader?.pool || readSynkroFilePool();
|
|
8709
|
+
let providers = [];
|
|
8710
|
+
if (synkroFilePool === "cursor") {
|
|
8711
|
+
providers = ["cursor"];
|
|
8712
|
+
} else if (synkroFilePool === "claude") {
|
|
8713
|
+
providers = ["claude_code"];
|
|
8714
|
+
} else {
|
|
8715
|
+
if (hasClaudeCode) providers.push("claude_code");
|
|
8716
|
+
if (hasCursor) providers.push("cursor");
|
|
8717
|
+
}
|
|
8718
|
+
({ claudeWorkers, cursorWorkers } = splitWorkers(totalWorkers, providers));
|
|
8719
|
+
if (synkroFilePool !== "auto") console.log(` .synkro: grader pool set to ${synkroFilePool}`);
|
|
8599
8720
|
}
|
|
8600
|
-
const { claudeWorkers, cursorWorkers } = splitWorkers(totalWorkers, providers);
|
|
8601
|
-
if (synkroFilePool !== "auto") console.log(` .synkro: grader pool set to ${synkroFilePool}`);
|
|
8602
8721
|
console.log(` worker pool: ${claudeWorkers} claude + ${cursorWorkers} cursor`);
|
|
8603
8722
|
const connectedRepo = detectGitRepo2() || void 0;
|
|
8604
8723
|
const { image, hostMcpPort, hostGraderPort, hostCwePort, hostPglitePort } = await dockerInstall({ claudeWorkers, cursorWorkers, connectedRepo });
|
|
@@ -8704,6 +8823,52 @@ async function installCommand(opts = {}) {
|
|
|
8704
8823
|
}
|
|
8705
8824
|
console.log("\u2713 Synkro installed.");
|
|
8706
8825
|
}
|
|
8826
|
+
function parseSynkroYaml2(raw) {
|
|
8827
|
+
const result = {};
|
|
8828
|
+
const lines = raw.split("\n");
|
|
8829
|
+
let currentKey = "";
|
|
8830
|
+
let currentObj = null;
|
|
8831
|
+
let currentArr = null;
|
|
8832
|
+
for (const line of lines) {
|
|
8833
|
+
if (!line.trim() || line.trim().startsWith("#")) continue;
|
|
8834
|
+
if (/^\S/.test(line) && line.includes(":")) {
|
|
8835
|
+
if (currentObj && currentKey) result[currentKey] = currentObj;
|
|
8836
|
+
if (currentArr && currentKey) result[currentKey] = currentArr;
|
|
8837
|
+
currentObj = null;
|
|
8838
|
+
currentArr = null;
|
|
8839
|
+
const colonIdx = line.indexOf(":");
|
|
8840
|
+
const key = line.slice(0, colonIdx).trim();
|
|
8841
|
+
const val = line.slice(colonIdx + 1).trim();
|
|
8842
|
+
currentKey = key;
|
|
8843
|
+
if (val) {
|
|
8844
|
+
if (val === "[]") result[key] = [];
|
|
8845
|
+
else if (val === "true") result[key] = true;
|
|
8846
|
+
else if (val === "false") result[key] = false;
|
|
8847
|
+
else if (/^\d+$/.test(val)) result[key] = parseInt(val, 10);
|
|
8848
|
+
else result[key] = val;
|
|
8849
|
+
currentKey = "";
|
|
8850
|
+
}
|
|
8851
|
+
} else if (/^ - /.test(line)) {
|
|
8852
|
+
if (!currentArr) currentArr = [];
|
|
8853
|
+
currentArr.push(line.replace(/^ - /, "").trim());
|
|
8854
|
+
} else if (/^ \S/.test(line) && line.includes(":")) {
|
|
8855
|
+
if (!currentObj) currentObj = {};
|
|
8856
|
+
const colonIdx = line.indexOf(":");
|
|
8857
|
+
const k = line.slice(0, colonIdx).trim();
|
|
8858
|
+
const v = line.slice(colonIdx + 1).trim();
|
|
8859
|
+
if (v === "true") currentObj[k] = true;
|
|
8860
|
+
else if (v === "false") currentObj[k] = false;
|
|
8861
|
+
else if (/^\d+$/.test(v)) currentObj[k] = parseInt(v, 10);
|
|
8862
|
+
else currentObj[k] = v;
|
|
8863
|
+
}
|
|
8864
|
+
}
|
|
8865
|
+
if (currentObj && currentKey) result[currentKey] = currentObj;
|
|
8866
|
+
if (currentArr && currentKey) result[currentKey] = currentArr;
|
|
8867
|
+
return result;
|
|
8868
|
+
}
|
|
8869
|
+
function parseSynkroFileRaw(content) {
|
|
8870
|
+
return content.trimStart().startsWith("{") ? JSON.parse(content) : parseSynkroYaml2(content);
|
|
8871
|
+
}
|
|
8707
8872
|
function writeSynkroFileIfMissing(opts) {
|
|
8708
8873
|
try {
|
|
8709
8874
|
const root = execSync6("git rev-parse --show-toplevel", { encoding: "utf-8", timeout: 3e3, stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
@@ -8723,28 +8888,38 @@ function writeSynkroFileIfMissing(opts) {
|
|
|
8723
8888
|
harness.push("cursor");
|
|
8724
8889
|
if (!opts.hasClaudeCode) pool = "cursor";
|
|
8725
8890
|
}
|
|
8726
|
-
const
|
|
8727
|
-
|
|
8728
|
-
|
|
8729
|
-
|
|
8730
|
-
|
|
8731
|
-
|
|
8732
|
-
|
|
8733
|
-
|
|
8734
|
-
|
|
8735
|
-
|
|
8736
|
-
|
|
8737
|
-
|
|
8891
|
+
const mode = opts.gradingMode === "byok" ? "byok" : "local";
|
|
8892
|
+
const yaml = [
|
|
8893
|
+
"version: 1",
|
|
8894
|
+
"",
|
|
8895
|
+
"harness:",
|
|
8896
|
+
...harness.map((h) => ` - ${h}`),
|
|
8897
|
+
"",
|
|
8898
|
+
"grader:",
|
|
8899
|
+
` pool: ${pool}`,
|
|
8900
|
+
` mode: ${mode}`,
|
|
8901
|
+
"",
|
|
8902
|
+
"ruleset: default",
|
|
8903
|
+
"",
|
|
8904
|
+
"skills: []",
|
|
8905
|
+
"",
|
|
8906
|
+
"scanning:",
|
|
8907
|
+
" cwe: true",
|
|
8908
|
+
" cve: true",
|
|
8909
|
+
""
|
|
8910
|
+
].join("\n");
|
|
8911
|
+
writeFileSync7(fp, yaml, "utf-8");
|
|
8912
|
+
console.log(` .synkro: wrote ${fp} (pool=${pool}, mode=${mode})`);
|
|
8738
8913
|
} catch {
|
|
8739
8914
|
}
|
|
8740
8915
|
}
|
|
8741
|
-
function
|
|
8916
|
+
function readSynkroFilePool() {
|
|
8742
8917
|
try {
|
|
8743
8918
|
const root = execSync6("git rev-parse --show-toplevel", { encoding: "utf-8", timeout: 3e3, stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
8744
8919
|
if (!root) return "auto";
|
|
8745
8920
|
const fp = join8(root, ".synkro");
|
|
8746
8921
|
if (!existsSync10(fp)) return "auto";
|
|
8747
|
-
const parsed =
|
|
8922
|
+
const parsed = parseSynkroFileRaw(readFileSync9(fp, "utf-8"));
|
|
8748
8923
|
const pool = parsed?.grader?.pool;
|
|
8749
8924
|
if (pool === "cursor" || pool === "claude") return pool;
|
|
8750
8925
|
} catch {
|
|
@@ -8757,7 +8932,7 @@ function readFullSynkroFile() {
|
|
|
8757
8932
|
if (!root) return null;
|
|
8758
8933
|
const fp = join8(root, ".synkro");
|
|
8759
8934
|
if (!existsSync10(fp)) return null;
|
|
8760
|
-
const parsed =
|
|
8935
|
+
const parsed = parseSynkroFileRaw(readFileSync9(fp, "utf-8"));
|
|
8761
8936
|
const valid = ["claude-code", "cursor"];
|
|
8762
8937
|
const harness = Array.isArray(parsed.harness) ? parsed.harness.filter((h) => valid.includes(h)) : ["claude-code", "cursor"];
|
|
8763
8938
|
return {
|
|
@@ -8766,6 +8941,10 @@ function readFullSynkroFile() {
|
|
|
8766
8941
|
pool: ["auto", "claude", "cursor"].includes(parsed.grader?.pool) ? parsed.grader.pool : "auto",
|
|
8767
8942
|
mode: ["local", "byok"].includes(parsed.grader?.mode) ? parsed.grader.mode : "local"
|
|
8768
8943
|
},
|
|
8944
|
+
workers: {
|
|
8945
|
+
...typeof parsed.workers?.claude === "number" ? { claude: parsed.workers.claude } : {},
|
|
8946
|
+
...typeof parsed.workers?.cursor === "number" ? { cursor: parsed.workers.cursor } : {}
|
|
8947
|
+
},
|
|
8769
8948
|
ruleset: parsed.ruleset || "default",
|
|
8770
8949
|
skills: Array.isArray(parsed.skills) ? parsed.skills.filter((s) => typeof s === "string" && s.endsWith(".md")) : [],
|
|
8771
8950
|
scanning: { cwe: parsed.scanning?.cwe !== false, cve: parsed.scanning?.cve !== false },
|
|
@@ -8843,6 +9022,11 @@ function reconcileHarness() {
|
|
|
8843
9022
|
if (uninstallCursorHooks(cursorHooks)) console.log(" \u2717 Cursor hooks removed");
|
|
8844
9023
|
if (uninstallCursorMcpConfig()) console.log(" \u2717 Cursor MCP removed");
|
|
8845
9024
|
}
|
|
9025
|
+
if (sf.workers.claude != null || sf.workers.cursor != null) {
|
|
9026
|
+
const cw = Math.max(0, Math.floor(sf.workers.claude || 0));
|
|
9027
|
+
const curw = Math.max(0, Math.floor(sf.workers.cursor || 0));
|
|
9028
|
+
if (cw + curw > 0) return { claudeWorkers: cw, cursorWorkers: curw };
|
|
9029
|
+
}
|
|
8846
9030
|
const total = parseInt(process.env.SYNKRO_WORKERS_PER_POOL || "8", 10);
|
|
8847
9031
|
const providers = [];
|
|
8848
9032
|
if (sf.grader.pool === "cursor") {
|
|
@@ -11143,7 +11327,7 @@ var args = process.argv.slice(2);
|
|
|
11143
11327
|
var cmd = args[0] || "";
|
|
11144
11328
|
var subArgs = args.slice(1);
|
|
11145
11329
|
function printVersion() {
|
|
11146
|
-
console.log("1.6.
|
|
11330
|
+
console.log("1.6.36");
|
|
11147
11331
|
}
|
|
11148
11332
|
function printHelp2() {
|
|
11149
11333
|
console.log(`Synkro CLI \u2014 runtime safety for AI coding agents
|