@synkro-sh/cli 1.3.20 → 1.3.22

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
@@ -2495,6 +2495,14 @@ var init_workflowTemplate = __esm({
2495
2495
  on:
2496
2496
  pull_request:
2497
2497
  types: [opened, synchronize, reopened]
2498
+ workflow_dispatch:
2499
+ inputs:
2500
+ pr_number:
2501
+ description: PR number to scan
2502
+ required: true
2503
+ sha:
2504
+ description: Commit SHA to scan
2505
+ required: true
2498
2506
 
2499
2507
  jobs:
2500
2508
  scan:
@@ -2507,6 +2515,7 @@ jobs:
2507
2515
  - uses: actions/checkout@v4
2508
2516
  with:
2509
2517
  fetch-depth: 0
2518
+ ref: \${{ inputs.sha || github.event.pull_request.head.sha }}
2510
2519
 
2511
2520
  - name: Cache npm globals
2512
2521
  id: cache-npm-global
@@ -2527,9 +2536,9 @@ jobs:
2527
2536
  CLAUDE_CODE_OAUTH_TOKEN: \${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
2528
2537
  SYNKRO_API_KEY: \${{ secrets.SYNKRO_API_KEY }}
2529
2538
  GH_TOKEN: \${{ secrets.GITHUB_TOKEN }}
2530
- SYNKRO_PR_NUMBER: \${{ github.event.pull_request.number }}
2539
+ SYNKRO_PR_NUMBER: \${{ inputs.pr_number || github.event.pull_request.number }}
2531
2540
  SYNKRO_REPO: \${{ github.repository }}
2532
- SYNKRO_SHA: \${{ github.event.pull_request.head.sha }}
2541
+ SYNKRO_SHA: \${{ inputs.sha || github.event.pull_request.head.sha }}
2533
2542
  SYNKRO_GATEWAY_URL: \${{ vars.SYNKRO_GATEWAY_URL || 'https://api.synkro.sh' }}
2534
2543
  `;
2535
2544
  WORKFLOW_PATH = ".github/workflows/synkro.yml";
@@ -2721,14 +2730,14 @@ function waitForGithubToken() {
2721
2730
  });
2722
2731
  }
2723
2732
  function openBrowser2(url) {
2724
- const { execFile: execFile2 } = __require("child_process");
2733
+ const { execFile: execFile3 } = __require("child_process");
2725
2734
  const plat = process.platform;
2726
2735
  const cb = (err) => {
2727
2736
  if (err) console.log(` Open this URL manually: ${url}`);
2728
2737
  };
2729
- if (plat === "darwin") execFile2("open", [url], cb);
2730
- else if (plat === "win32") execFile2("cmd", ["/c", "start", "", url], cb);
2731
- else execFile2("xdg-open", [url], cb);
2738
+ if (plat === "darwin") execFile3("open", [url], cb);
2739
+ else if (plat === "win32") execFile3("cmd", ["/c", "start", "", url], cb);
2740
+ else execFile3("xdg-open", [url], cb);
2732
2741
  }
2733
2742
  async function connectGithubAndSelectRepos() {
2734
2743
  const url = `${SYNKRO_WEB_AUTH_URL2}/cli-github?port=${GITHUB_PORT}`;
@@ -2862,14 +2871,16 @@ var init_repoConnect = __esm({
2862
2871
  // cli/commands/setupGithub.ts
2863
2872
  var setupGithub_exports = {};
2864
2873
  __export(setupGithub_exports, {
2874
+ connectGitHub: () => connectGitHub,
2865
2875
  setupGithubCommand: () => setupGithubCommand
2866
2876
  });
2867
2877
  import { createInterface as createInterface2 } from "readline/promises";
2868
2878
  import { stdin as input, stdout as output } from "process";
2869
2879
  import { execSync as execSync3, spawn as nodeSpawn } from "child_process";
2870
2880
  import { existsSync as existsSync6, readFileSync as readFileSync4 } from "fs";
2871
- import { homedir as homedir4 } from "os";
2881
+ import { homedir as homedir4, platform as platform2 } from "os";
2872
2882
  import { join as join5 } from "path";
2883
+ import { execFile as execFile2 } from "child_process";
2873
2884
  function readConfig() {
2874
2885
  if (!existsSync6(CONFIG_PATH)) return {};
2875
2886
  const out = {};
@@ -2897,9 +2908,7 @@ async function prompt(rl, q, opts = {}) {
2897
2908
  resolve2(chunk);
2898
2909
  return;
2899
2910
  }
2900
- if (s === "") {
2901
- process.exit(130);
2902
- }
2911
+ if (s === "") process.exit(130);
2903
2912
  if (s === "\x7F" || s === "\b") {
2904
2913
  chunk = chunk.slice(0, -1);
2905
2914
  return;
@@ -2911,6 +2920,30 @@ async function prompt(rl, q, opts = {}) {
2911
2920
  }
2912
2921
  return await rl.question(q);
2913
2922
  }
2923
+ function openBrowser3(url) {
2924
+ const os = platform2();
2925
+ let bin;
2926
+ let args2;
2927
+ switch (os) {
2928
+ case "darwin":
2929
+ bin = "open";
2930
+ args2 = [url];
2931
+ break;
2932
+ case "win32":
2933
+ bin = "cmd";
2934
+ args2 = ["/c", "start", "", url];
2935
+ break;
2936
+ default:
2937
+ bin = "xdg-open";
2938
+ args2 = [url];
2939
+ break;
2940
+ }
2941
+ execFile2(bin, args2, () => {
2942
+ });
2943
+ }
2944
+ function sleep(ms) {
2945
+ return new Promise((r) => setTimeout(r, ms));
2946
+ }
2914
2947
  function captureClaudeSetupToken() {
2915
2948
  return new Promise((resolve2, reject) => {
2916
2949
  const proc = nodeSpawn("script", ["-q", "/dev/null", "claude", "setup-token"], {
@@ -2936,6 +2969,68 @@ function captureClaudeSetupToken() {
2936
2969
  });
2937
2970
  });
2938
2971
  }
2972
+ async function apiCall(gatewayUrl, jwt2, path, opts = {}) {
2973
+ const resp = await fetch(`${gatewayUrl}${path}`, {
2974
+ ...opts,
2975
+ headers: {
2976
+ "Authorization": `Bearer ${jwt2}`,
2977
+ "Content-Type": "application/json",
2978
+ ...opts.headers || {}
2979
+ }
2980
+ });
2981
+ if (!resp.ok) {
2982
+ const text = await resp.text().catch(() => "");
2983
+ throw new Error(`API ${resp.status}: ${text.slice(0, 200)}`);
2984
+ }
2985
+ return resp.json();
2986
+ }
2987
+ async function connectGitHub(gatewayUrl, jwt2, opts = {}) {
2988
+ try {
2989
+ const result = await apiCall(
2990
+ gatewayUrl,
2991
+ jwt2,
2992
+ "/api/v1/cli/github-token"
2993
+ );
2994
+ if (result.connected && result.token) {
2995
+ if (!opts.silent) console.log(" \u2713 GitHub already connected via Synkro.");
2996
+ return result.token;
2997
+ }
2998
+ } catch {
2999
+ }
3000
+ if (!opts.silent) console.log(" Opening browser to authorize GitHub...");
3001
+ try {
3002
+ const authResp = await apiCall(
3003
+ gatewayUrl,
3004
+ jwt2,
3005
+ "/api/pipes-widget/authorize/github",
3006
+ { method: "POST", body: "{}" }
3007
+ );
3008
+ openBrowser3(authResp.url);
3009
+ if (!opts.silent) console.log(" Waiting for authorization...");
3010
+ } catch (err) {
3011
+ if (!opts.silent) console.error(` Failed to start GitHub authorization: ${err.message}`);
3012
+ return null;
3013
+ }
3014
+ const deadline = Date.now() + 12e4;
3015
+ while (Date.now() < deadline) {
3016
+ await sleep(2e3);
3017
+ try {
3018
+ const result = await apiCall(
3019
+ gatewayUrl,
3020
+ jwt2,
3021
+ "/api/v1/cli/github-token"
3022
+ );
3023
+ if (result.connected && result.token) {
3024
+ if (!opts.silent) console.log("\n \u2713 GitHub connected!");
3025
+ return result.token;
3026
+ }
3027
+ } catch {
3028
+ }
3029
+ if (!opts.silent) process.stdout.write(".");
3030
+ }
3031
+ if (!opts.silent) console.error("\n Timed out waiting for GitHub authorization.");
3032
+ return null;
3033
+ }
2939
3034
  async function setupGithubCommand(opts = {}) {
2940
3035
  if (!isAuthenticated()) {
2941
3036
  console.error("Not authenticated. Run `synkro-cli login` first.");
@@ -2951,20 +3046,12 @@ async function setupGithubCommand(opts = {}) {
2951
3046
  console.log("Requesting CI API key from Synkro...");
2952
3047
  let synkroCiApiKey;
2953
3048
  try {
2954
- const resp = await fetch(`${gatewayUrl}/api/v1/cli/ci-api-key`, {
2955
- method: "POST",
2956
- headers: {
2957
- "Authorization": `Bearer ${jwt2}`,
2958
- "Content-Type": "application/json"
2959
- },
2960
- body: "{}"
2961
- });
2962
- if (!resp.ok) {
2963
- const errText = await resp.text().catch(() => "");
2964
- console.error(`Failed to mint CI API key (${resp.status}): ${errText.slice(0, 200)}`);
2965
- process.exit(1);
2966
- }
2967
- const minted = await resp.json();
3049
+ const minted = await apiCall(
3050
+ gatewayUrl,
3051
+ jwt2,
3052
+ "/api/v1/cli/ci-api-key",
3053
+ { method: "POST", body: "{}" }
3054
+ );
2968
3055
  synkroCiApiKey = minted.api_key;
2969
3056
  console.log(` \u2713 Issued CI key (${synkroCiApiKey.slice(0, 18)}\u2026), expires ${minted.expires_at.slice(0, 10)}`);
2970
3057
  } catch (err) {
@@ -2976,24 +3063,33 @@ async function setupGithubCommand(opts = {}) {
2976
3063
  ghToken = opts.githubToken;
2977
3064
  } else if (opts.nonInteractive) {
2978
3065
  try {
2979
- ghToken = execSync3("gh auth token", { encoding: "utf-8", timeout: 5e3 }).trim();
3066
+ const result = await apiCall(
3067
+ gatewayUrl,
3068
+ jwt2,
3069
+ "/api/v1/cli/github-token"
3070
+ );
3071
+ if (result.connected && result.token) {
3072
+ ghToken = result.token;
3073
+ } else {
3074
+ throw new Error("not connected");
3075
+ }
2980
3076
  } catch {
2981
- console.error("Could not get GitHub token from `gh auth token`. Run `gh auth login` first.");
2982
- return;
3077
+ try {
3078
+ ghToken = execSync3("gh auth token", { encoding: "utf-8", timeout: 5e3 }).trim();
3079
+ } catch {
3080
+ console.error("GitHub not connected. Run `synkro-cli setup-github` interactively to connect.");
3081
+ return;
3082
+ }
2983
3083
  }
2984
3084
  } else {
2985
- const rl = createInterface2({ input, output });
2986
- console.log("Synkro PR scan setup\n");
2987
- console.log("Requirements:");
2988
- console.log(" \u2022 Claude Code installed and logged in (Pro, Max, Teams, or Enterprise)");
2989
- console.log(" \u2022 A GitHub personal access token with `repo` scope");
2990
- console.log(" (create at https://github.com/settings/tokens?type=beta)\n");
2991
- ghToken = (await prompt(rl, "GitHub token (paste): ", { silent: true })).trim();
2992
- rl.close();
2993
- if (!ghToken || !ghToken.startsWith("ghp_") && !ghToken.startsWith("github_pat_")) {
2994
- console.error("Invalid GitHub token format. Expected ghp_... or github_pat_...");
3085
+ console.log("\nConnecting to GitHub...");
3086
+ const token = await connectGitHub(gatewayUrl, jwt2);
3087
+ if (!token) {
3088
+ console.error("GitHub connection failed. Try again.");
2995
3089
  process.exit(1);
2996
3090
  }
3091
+ ghToken = token;
3092
+ console.log();
2997
3093
  }
2998
3094
  let claudeToken;
2999
3095
  if (!opts.skipClaudeToken) {
@@ -3043,10 +3139,10 @@ async function setupGithubCommand(opts = {}) {
3043
3139
  selected = [{ owner, repo, full_name: currentFullName }];
3044
3140
  console.log(` Auto-selected repo: ${currentFullName}`);
3045
3141
  } else {
3046
- console.log("\nFetching accessible repos...");
3142
+ console.log("Fetching accessible repos...");
3047
3143
  const repos = await listAccessibleRepos({ token: ghToken });
3048
3144
  if (repos.length === 0) {
3049
- console.error("No accessible repos found. Verify the GitHub token has `repo` scope.");
3145
+ console.error("No accessible repos found. Check your GitHub permissions.");
3050
3146
  process.exit(1);
3051
3147
  }
3052
3148
  console.log(`
@@ -3148,7 +3244,6 @@ function parseArgs(argv) {
3148
3244
  else if (a === "--no-mcp") opts.noMcp = true;
3149
3245
  else if (a === "--force" || a === "-f") opts.force = true;
3150
3246
  else if (a === "--link-repo") opts.linkRepo = true;
3151
- else if (a === "--pr-scan") opts.prScan = true;
3152
3247
  }
3153
3248
  if (!opts.gatewayUrl) {
3154
3249
  const fromEnv = sanitizeGatewayCandidate(process.env.SYNKRO_GATEWAY_URL);
@@ -3238,7 +3333,7 @@ function writeConfigEnv(opts) {
3238
3333
  `SYNKRO_CREDENTIALS_PATH=${shellQuoteSingle(credsPath)}`,
3239
3334
  `SYNKRO_TIER=${shellQuoteSingle(safeTier)}`,
3240
3335
  `SYNKRO_INFERENCE=${shellQuoteSingle(safeInference)}`,
3241
- `SYNKRO_VERSION=${shellQuoteSingle("1.3.20")}`
3336
+ `SYNKRO_VERSION=${shellQuoteSingle("1.3.22")}`
3242
3337
  ];
3243
3338
  if (safeUserId) lines.push(`SYNKRO_USER_ID=${shellQuoteSingle(safeUserId)}`);
3244
3339
  if (safeOrgId) lines.push(`SYNKRO_ORG_ID=${shellQuoteSingle(safeOrgId)}`);
@@ -3258,10 +3353,48 @@ function collectLocalMetadata() {
3258
3353
  }
3259
3354
  try {
3260
3355
  const remote = execSync4("git remote get-url origin", { encoding: "utf-8", timeout: 3e3 }).trim();
3261
- const m = remote.match(/(?:github\.com)[:/](.+?)(?:\.git)?$/);
3356
+ const sshMatch = remote.match(/^git@[^:]+:(.+?)(?:\.git)?$/);
3357
+ const httpMatch = remote.match(/^https?:\/\/[^/]+\/(.+?)(?:\.git)?$/);
3358
+ const m = sshMatch || httpMatch;
3262
3359
  if (m) meta.active_repo = m[1];
3263
3360
  } catch {
3264
3361
  }
3362
+ try {
3363
+ meta.cc_version = execSync4("claude --version", { encoding: "utf-8", timeout: 5e3 }).trim().split("\n")[0];
3364
+ } catch {
3365
+ }
3366
+ const claudeDir = join6(homedir5(), ".claude");
3367
+ try {
3368
+ const settings = JSON.parse(readFileSync5(join6(claudeDir, "settings.json"), "utf-8"));
3369
+ const plugins = Object.keys(settings.enabledPlugins ?? {}).filter((k) => settings.enabledPlugins[k]);
3370
+ if (plugins.length) meta.enabled_plugins = plugins;
3371
+ if (settings.permissions?.defaultMode) meta.permissions_mode = settings.permissions.defaultMode;
3372
+ } catch {
3373
+ }
3374
+ try {
3375
+ const mcpCache = JSON.parse(readFileSync5(join6(claudeDir, "mcp-needs-auth-cache.json"), "utf-8"));
3376
+ const mcpNames = Object.keys(mcpCache);
3377
+ if (mcpNames.length) meta.mcp_servers = mcpNames;
3378
+ } catch {
3379
+ }
3380
+ try {
3381
+ const mcpList = execSync4("claude mcp list 2>/dev/null", { encoding: "utf-8", timeout: 1e4 });
3382
+ const connected = mcpList.split("\n").filter((l) => l.includes("Connected")).map((l) => l.split(":")[0].trim()).filter(Boolean);
3383
+ if (connected.length) meta.mcp_servers_connected = connected;
3384
+ } catch {
3385
+ }
3386
+ try {
3387
+ const sessionsDir = join6(claudeDir, "sessions");
3388
+ const files = readdirSync(sessionsDir).filter((f) => f.endsWith(".json")).slice(-5);
3389
+ for (const f of files) {
3390
+ const s = JSON.parse(readFileSync5(join6(sessionsDir, f), "utf-8"));
3391
+ if (s.version) {
3392
+ meta.cc_version = meta.cc_version || s.version;
3393
+ break;
3394
+ }
3395
+ }
3396
+ } catch {
3397
+ }
3265
3398
  return meta;
3266
3399
  }
3267
3400
  async function fetchUserProfile(gatewayUrl, token) {
@@ -3398,6 +3531,13 @@ async function installCommand(opts = {}) {
3398
3531
  console.error("No access token available after auth.");
3399
3532
  process.exit(1);
3400
3533
  }
3534
+ console.log("\nConnecting to GitHub...");
3535
+ const ghToken = await connectGitHub(gatewayUrl, token);
3536
+ if (!ghToken) {
3537
+ console.error("GitHub connection is required. Re-run `synkro-cli install` to try again.");
3538
+ process.exit(1);
3539
+ }
3540
+ console.log();
3401
3541
  setApiBaseUrl(`${gatewayUrl}/api`);
3402
3542
  await promptRepoConnection({ linkRepo: opts.linkRepo });
3403
3543
  const agents = detectAgents();
@@ -3535,18 +3675,9 @@ async function installCommand(opts = {}) {
3535
3675
  `);
3536
3676
  }
3537
3677
  }
3538
- if (opts.prScan) {
3539
- console.log();
3540
- const { setupGithubCommand: setupGithubCommand2 } = await Promise.resolve().then(() => (init_setupGithub(), setupGithub_exports));
3541
- await setupGithubCommand2({ nonInteractive: true });
3542
- }
3678
+ const { setupGithubCommand: setupGithubCommand2 } = await Promise.resolve().then(() => (init_setupGithub(), setupGithub_exports));
3679
+ await setupGithubCommand2({ nonInteractive: true, githubToken: ghToken });
3543
3680
  console.log("\u2713 Synkro installed.");
3544
- console.log();
3545
- if (!opts.prScan) {
3546
- console.log("Next steps:");
3547
- console.log(" \u2022 synkro-cli setup-github (enable PR scanning)");
3548
- console.log(" \u2022 synkro-cli status (check what is configured)");
3549
- }
3550
3681
  }
3551
3682
  function detectGitRepo2() {
3552
3683
  try {
@@ -3751,6 +3882,7 @@ var init_install = __esm({
3751
3882
  init_stub();
3752
3883
  init_repoConnect();
3753
3884
  init_projects();
3885
+ init_setupGithub();
3754
3886
  SYNKRO_DIR2 = join6(homedir5(), ".synkro");
3755
3887
  HOOKS_DIR = join6(SYNKRO_DIR2, "hooks");
3756
3888
  BIN_DIR = join6(SYNKRO_DIR2, "bin");
@@ -4249,6 +4381,19 @@ function getPrFiles(repo, prNumber) {
4249
4381
  ]);
4250
4382
  return data;
4251
4383
  }
4384
+ async function fetchScanContext(gatewayUrl, apiKey, repo, prNumber, sha) {
4385
+ try {
4386
+ const url = `${gatewayUrl.replace(/\/$/, "")}/api/pr-scans/scan-context?repo=${encodeURIComponent(repo)}&pr_number=${prNumber}&sha=${sha}`;
4387
+ const resp = await fetch(url, {
4388
+ headers: { "x-synkro-api-key": apiKey },
4389
+ signal: AbortSignal.timeout(15e3)
4390
+ });
4391
+ if (!resp.ok) return { scan_all: true };
4392
+ return await resp.json();
4393
+ } catch {
4394
+ return { scan_all: true };
4395
+ }
4396
+ }
4252
4397
  function getFileDiffWithLines(file) {
4253
4398
  if (!file.patch) return { hunks: "", newFileLineMap: /* @__PURE__ */ new Map() };
4254
4399
  const lines = file.patch.split("\n");
@@ -4343,13 +4488,16 @@ ${hunks}`;
4343
4488
  });
4344
4489
  });
4345
4490
  }
4346
- async function processInBatches(items, batchSize, fn) {
4347
- const results = [];
4348
- for (let i = 0; i < items.length; i += batchSize) {
4349
- const batch = items.slice(i, i + batchSize);
4350
- const batchResults = await Promise.all(batch.map(fn));
4351
- results.push(...batchResults);
4491
+ async function processInBatches(items, concurrency, fn) {
4492
+ const results = new Array(items.length);
4493
+ let next = 0;
4494
+ async function worker() {
4495
+ while (next < items.length) {
4496
+ const idx = next++;
4497
+ results[idx] = await fn(items[idx], idx, items.length);
4498
+ }
4352
4499
  }
4500
+ await Promise.all(Array.from({ length: Math.min(concurrency, items.length) }, () => worker()));
4353
4501
  return results;
4354
4502
  }
4355
4503
  function buildConsolidationPrompt(findings) {
@@ -4606,11 +4754,34 @@ async function scanPrCommand() {
4606
4754
  console.error("Failed to fetch PR files:", err.message);
4607
4755
  process.exit(2);
4608
4756
  }
4757
+ const scanCtx = await fetchScanContext(gatewayUrl, synkroApiKey, repo, prNumber, sha);
4758
+ if (scanCtx.skip) {
4759
+ console.log(`Already scanned at ${sha.slice(0, 7)}, skipping.
4760
+ `);
4761
+ postCheckRun(repo, sha, "success", []);
4762
+ await postEventToBackend({
4763
+ gatewayUrl,
4764
+ apiKey: synkroApiKey,
4765
+ repo,
4766
+ prNumber,
4767
+ sha,
4768
+ findings: [],
4769
+ filesScanned: 0,
4770
+ totalLatencyMs: 0
4771
+ });
4772
+ return;
4773
+ }
4774
+ const changedFiles = !scanCtx.scan_all && scanCtx.files ? new Set(scanCtx.files) : null;
4775
+ if (changedFiles) {
4776
+ console.log(`Incremental scan: ${changedFiles.size} file(s) changed since last scan (${scanCtx.last_sha?.slice(0, 7)}).
4777
+ `);
4778
+ }
4609
4779
  const eligible = files.filter((f) => {
4610
4780
  if (f.status === "removed") return false;
4611
4781
  if (shouldSkipFile(f.filename)) return false;
4612
4782
  if (f.additions + f.deletions > MAX_DIFF_LINES_PER_FILE) return false;
4613
4783
  if (!f.patch) return false;
4784
+ if (changedFiles && !changedFiles.has(f.filename)) return false;
4614
4785
  return true;
4615
4786
  });
4616
4787
  console.log(`${files.length} files in PR, ${eligible.length} eligible for scan.
@@ -4631,12 +4802,12 @@ async function scanPrCommand() {
4631
4802
  return;
4632
4803
  }
4633
4804
  const t0 = Date.now();
4634
- const results = await processInBatches(eligible, MAX_PARALLEL_FILES, async (file) => {
4635
- process.stdout.write(`Scanning ${file.filename}...`);
4805
+ const results = await processInBatches(eligible, MAX_PARALLEL_FILES, async (file, idx, total) => {
4806
+ process.stdout.write(`[${idx + 1}/${total}] ${file.filename}...`);
4636
4807
  const literalFindings = applyLiteralMatchNegative(literalNegativeRules, file);
4637
4808
  const llmResult = await spawnClaudeJudge(file, claudeToken, promptHeader);
4638
4809
  const merged = [...literalFindings, ...llmResult.findings];
4639
- console.log(` ${merged.length} finding(s) (${literalFindings.length} literal, ${llmResult.findings.length} llm; ${llmResult.latencyMs}ms)`);
4810
+ console.log(` ${merged.length === 0 ? "clean" : `${merged.length} finding(s)`} (${(llmResult.latencyMs / 1e3).toFixed(1)}s)`);
4640
4811
  return { findings: merged, latencyMs: llmResult.latencyMs };
4641
4812
  });
4642
4813
  const totalLatencyMs = Date.now() - t0;
@@ -4690,7 +4861,7 @@ var init_scanPr = __esm({
4690
4861
  /go\.sum$/
4691
4862
  ];
4692
4863
  MAX_DIFF_LINES_PER_FILE = 1e3;
4693
- MAX_PARALLEL_FILES = 5;
4864
+ MAX_PARALLEL_FILES = 10;
4694
4865
  }
4695
4866
  });
4696
4867