mobbdev 1.4.21 → 1.4.23

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/index.mjs CHANGED
@@ -417,6 +417,7 @@ var init_client_generates = __esm({
417
417
  return Vulnerability_Report_Issue_State_Enum2;
418
418
  })(Vulnerability_Report_Issue_State_Enum || {});
419
419
  Vulnerability_Report_Issue_Tag_Enum = /* @__PURE__ */ ((Vulnerability_Report_Issue_Tag_Enum3) => {
420
+ Vulnerability_Report_Issue_Tag_Enum3["AgenticRemediationInProgress"] = "AGENTIC_REMEDIATION_IN_PROGRESS";
420
421
  Vulnerability_Report_Issue_Tag_Enum3["AutogeneratedCode"] = "AUTOGENERATED_CODE";
421
422
  Vulnerability_Report_Issue_Tag_Enum3["AuxiliaryCode"] = "AUXILIARY_CODE";
422
423
  Vulnerability_Report_Issue_Tag_Enum3["FalsePositive"] = "FALSE_POSITIVE";
@@ -1592,7 +1593,8 @@ var init_getIssueType = __esm({
1592
1593
  ["TEST_CODE" /* TestCode */]: "The flagged code resides in a test-specific path or context. This categorization indicates that **it supports testing scenarios and is isolated from production use**.",
1593
1594
  ["UNFIXABLE" /* Unfixable */]: "The flagged code cannot be fixed",
1594
1595
  ["VENDOR_CODE" /* VendorCode */]: "The flagged code originates from a third-party library or dependency maintained externally. This categorization suggests that **the issue lies outside the application's direct control** and should be addressed by the vendor if necessary.",
1595
- ["SUPPRESSED" /* Suppressed */]: "Suppressed in the scan report."
1596
+ ["SUPPRESSED" /* Suppressed */]: "Suppressed in the scan report.",
1597
+ ["AGENTIC_REMEDIATION_IN_PROGRESS" /* AgenticRemediationInProgress */]: "Mobb is currently retrying remediation on this issue. The state will refresh automatically once the run finishes."
1596
1598
  };
1597
1599
  }
1598
1600
  });
@@ -3872,9 +3874,9 @@ var init_GitService = __esm({
3872
3874
  this.log("[GitService] Git repository validation successful", "debug");
3873
3875
  return { isValid: true };
3874
3876
  } catch (error) {
3875
- const errorMessage = `Failed to verify git repository: ${error.message}`;
3876
- this.log(`[GitService] ${errorMessage}`, "error", { error });
3877
- return { isValid: false, error: errorMessage };
3877
+ const errorMessage3 = `Failed to verify git repository: ${error.message}`;
3878
+ this.log(`[GitService] ${errorMessage3}`, "error", { error });
3879
+ return { isValid: false, error: errorMessage3 };
3878
3880
  }
3879
3881
  }
3880
3882
  /**
@@ -3920,9 +3922,9 @@ var init_GitService = __esm({
3920
3922
  });
3921
3923
  return { files, deletedFiles, status };
3922
3924
  } catch (error) {
3923
- const errorMessage = `Failed to get git status: ${error.message}`;
3924
- this.log(`[GitService] ${errorMessage}`, "error", { error });
3925
- throw new Error(errorMessage);
3925
+ const errorMessage3 = `Failed to get git status: ${error.message}`;
3926
+ this.log(`[GitService] ${errorMessage3}`, "error", { error });
3927
+ throw new Error(errorMessage3);
3926
3928
  }
3927
3929
  }
3928
3930
  /**
@@ -3948,9 +3950,9 @@ var init_GitService = __esm({
3948
3950
  reference
3949
3951
  };
3950
3952
  } catch (error) {
3951
- const errorMessage = `Failed to get git repository information: ${error.message}`;
3952
- this.log(`[GitService] ${errorMessage}`, "error", { error });
3953
- throw new Error(errorMessage);
3953
+ const errorMessage3 = `Failed to get git repository information: ${error.message}`;
3954
+ this.log(`[GitService] ${errorMessage3}`, "error", { error });
3955
+ throw new Error(errorMessage3);
3954
3956
  }
3955
3957
  }
3956
3958
  /**
@@ -3988,9 +3990,9 @@ var init_GitService = __esm({
3988
3990
  this.log("[GitService] Current branch retrieved", "debug", { branch });
3989
3991
  return branch;
3990
3992
  } catch (error) {
3991
- const errorMessage = `Failed to get current branch: ${error.message}`;
3992
- this.log(`[GitService] ${errorMessage}`, "error", { error });
3993
- throw new Error(errorMessage);
3993
+ const errorMessage3 = `Failed to get current branch: ${error.message}`;
3994
+ this.log(`[GitService] ${errorMessage3}`, "error", { error });
3995
+ throw new Error(errorMessage3);
3994
3996
  }
3995
3997
  }
3996
3998
  /**
@@ -4003,9 +4005,9 @@ var init_GitService = __esm({
4003
4005
  this.log("[GitService] Current commit hash retrieved", "debug", { hash });
4004
4006
  return hash;
4005
4007
  } catch (error) {
4006
- const errorMessage = `Failed to get current commit hash: ${error.message}`;
4007
- this.log(`[GitService] ${errorMessage}`, "error", { error });
4008
- throw new Error(errorMessage);
4008
+ const errorMessage3 = `Failed to get current commit hash: ${error.message}`;
4009
+ this.log(`[GitService] ${errorMessage3}`, "error", { error });
4010
+ throw new Error(errorMessage3);
4009
4011
  }
4010
4012
  }
4011
4013
  /**
@@ -4053,8 +4055,8 @@ var init_GitService = __esm({
4053
4055
  );
4054
4056
  return { hash, branch };
4055
4057
  } catch (error) {
4056
- const errorMessage = `Failed to get current commit hash and branch: ${error.message}`;
4057
- this.log(`[GitService] ${errorMessage}`, "error", { error });
4058
+ const errorMessage3 = `Failed to get current commit hash and branch: ${error.message}`;
4059
+ this.log(`[GitService] ${errorMessage3}`, "error", { error });
4058
4060
  return { hash: "", branch: "" };
4059
4061
  }
4060
4062
  }
@@ -4072,9 +4074,9 @@ var init_GitService = __esm({
4072
4074
  });
4073
4075
  return normalizedUrl;
4074
4076
  } catch (error) {
4075
- const errorMessage = `Failed to get remote repository URL: ${error.message}`;
4076
- this.log(`[GitService] ${errorMessage}`, "error", { error });
4077
- throw new Error(errorMessage);
4077
+ const errorMessage3 = `Failed to get remote repository URL: ${error.message}`;
4078
+ this.log(`[GitService] ${errorMessage3}`, "error", { error });
4079
+ throw new Error(errorMessage3);
4078
4080
  }
4079
4081
  }
4080
4082
  /**
@@ -4195,9 +4197,9 @@ var init_GitService = __esm({
4195
4197
  commitCount: commitsProcessed
4196
4198
  };
4197
4199
  } catch (error) {
4198
- const errorMessage = `Failed to get recently changed files: ${error.message}`;
4199
- this.log(`[GitService] ${errorMessage}`, "error", { error });
4200
- throw new Error(errorMessage);
4200
+ const errorMessage3 = `Failed to get recently changed files: ${error.message}`;
4201
+ this.log(`[GitService] ${errorMessage3}`, "error", { error });
4202
+ throw new Error(errorMessage3);
4201
4203
  }
4202
4204
  }
4203
4205
  /**
@@ -4241,8 +4243,8 @@ ${rootContent}`;
4241
4243
  );
4242
4244
  return combinedContent.trimEnd();
4243
4245
  } catch (error) {
4244
- const errorMessage = `Failed to get .gitignore contents: ${error.message}`;
4245
- this.log(`[GitService] ${errorMessage}`, "error", { error });
4246
+ const errorMessage3 = `Failed to get .gitignore contents: ${error.message}`;
4247
+ this.log(`[GitService] ${errorMessage3}`, "error", { error });
4246
4248
  return null;
4247
4249
  }
4248
4250
  }
@@ -4262,9 +4264,9 @@ ${rootContent}`;
4262
4264
  this.log("[GitService] Git root retrieved", "debug", { gitRoot });
4263
4265
  return gitRoot;
4264
4266
  } catch (error) {
4265
- const errorMessage = `Failed to get git repository root: ${error.message}`;
4266
- this.log(`[GitService] ${errorMessage}`, "error", { error });
4267
- throw new Error(errorMessage);
4267
+ const errorMessage3 = `Failed to get git repository root: ${error.message}`;
4268
+ this.log(`[GitService] ${errorMessage3}`, "error", { error });
4269
+ throw new Error(errorMessage3);
4268
4270
  }
4269
4271
  }
4270
4272
  /**
@@ -4303,9 +4305,9 @@ ${rootContent}`;
4303
4305
  });
4304
4306
  return true;
4305
4307
  } catch (error) {
4306
- const errorMessage = `Failed to ensure .gitignore entry: ${error.message}`;
4307
- this.log(`[GitService] ${errorMessage}`, "error", { error, entry });
4308
- throw new Error(errorMessage);
4308
+ const errorMessage3 = `Failed to ensure .gitignore entry: ${error.message}`;
4309
+ this.log(`[GitService] ${errorMessage3}`, "error", { error, entry });
4310
+ throw new Error(errorMessage3);
4309
4311
  }
4310
4312
  }
4311
4313
  /**
@@ -4323,9 +4325,9 @@ ${rootContent}`;
4323
4325
  });
4324
4326
  return exists2;
4325
4327
  } catch (error) {
4326
- const errorMessage = `Failed to check .gitignore existence: ${error.message}`;
4327
- this.log(`[GitService] ${errorMessage}`, "error", { error });
4328
- throw new Error(errorMessage);
4328
+ const errorMessage3 = `Failed to check .gitignore existence: ${error.message}`;
4329
+ this.log(`[GitService] ${errorMessage3}`, "error", { error });
4330
+ throw new Error(errorMessage3);
4329
4331
  }
4330
4332
  }
4331
4333
  /**
@@ -4385,8 +4387,8 @@ ${rootContent}`;
4385
4387
  coAuthors: parsed.coAuthors
4386
4388
  };
4387
4389
  } catch (error) {
4388
- const errorMessage = `Failed to get local commit data: ${error.message}`;
4389
- this.log(`[GitService] ${errorMessage}`, "debug", { error, commitSha });
4390
+ const errorMessage3 = `Failed to get local commit data: ${error.message}`;
4391
+ this.log(`[GitService] ${errorMessage3}`, "debug", { error, commitSha });
4390
4392
  return null;
4391
4393
  }
4392
4394
  }
@@ -4395,7 +4397,7 @@ ${rootContent}`;
4395
4397
  });
4396
4398
 
4397
4399
  // src/index.ts
4398
- import Debug22 from "debug";
4400
+ import Debug23 from "debug";
4399
4401
  import { hideBin } from "yargs/helpers";
4400
4402
 
4401
4403
  // src/args/yargs.ts
@@ -5231,6 +5233,48 @@ var languages = {
5231
5233
  init_client_generates();
5232
5234
  import { z as z4 } from "zod";
5233
5235
 
5236
+ // src/features/analysis/scm/shared/src/storedQuestionData/cpp/index.ts
5237
+ init_client_generates();
5238
+
5239
+ // src/features/analysis/scm/shared/src/storedQuestionData/cpp/commandInjection.ts
5240
+ var commandInjection = {
5241
+ isUnixShellCommandPart: {
5242
+ content: () => "Is the input data interpolated into a shell command (not the program name or shell structure)?",
5243
+ description: () => `\`system()\` / \`popen()\` hand the whole string to \`/bin/sh -c\`. Answer **yes** when the input is *data* placed into a fixed command, for example:
5244
+
5245
+ - \`sprintf(cmd, "grep %s file.txt", input); system(cmd);\`
5246
+ - \`sprintf(cmd, "ping -c 5 %s", input); system(cmd);\`
5247
+
5248
+ Answer **no** (the input is not plain data) when the input is:
5249
+
5250
+ 1. The program/executable itself:
5251
+ - \`system(input);\`
5252
+ - \`sprintf(cmd, "%s -x", input);\`
5253
+ 2. A command after a pipe or redirect:
5254
+ - \`sprintf(cmd, "cat file.txt | %s", input);\`
5255
+ 3. A part of a non-Unix or cross-platform shell command.
5256
+ 4. A part of embedded code in another language:
5257
+ - \`sprintf(cmd, "php -r \\"echo '%s';\\"", input);\`
5258
+ - \`sprintf(cmd, "awk '%s' file", input);\`
5259
+ 5. A flag/option that controls a tool's behaviour:
5260
+ - \`sprintf(cmd, "git --upload-pack %s", input);\``,
5261
+ guidance: () => "If yes and the command can run without a shell, it is rewritten to a no-shell argument-vector call (`posix_spawn`); if it needs the shell, the tainted argument is escaped in place so the shell keeps working. If the answer is no (the input controls the program or shell structure), there is no safe automatic rewrite, so the fix is withheld and the sink is left for manual review."
5262
+ },
5263
+ executableLocationPath: {
5264
+ content: () => "What is the absolute path of the directory containing the executable?",
5265
+ description: () => `When \`system()\` is rewritten to an \`execv()\` argument-vector call, the program is run by its path with **no \`$PATH\` search**, so a relative program name (e.g. \`tail\`) cannot be resolved and a poisoned \`PATH\` cannot be used to run a look-alike binary.
5266
+
5267
+ Provide the absolute directory that contains the executable (e.g. \`/usr/bin\`); the fix prepends it to the bare program name to form an absolute path.`,
5268
+ guidance: () => "Only asked when the program name in the command has no `/`. A program that is already an absolute or relative path (contains `/`) is used as written."
5269
+ }
5270
+ };
5271
+
5272
+ // src/features/analysis/scm/shared/src/storedQuestionData/cpp/index.ts
5273
+ var vulnerabilities11 = {
5274
+ ["CMDi" /* CmDi */]: commandInjection
5275
+ };
5276
+ var cpp_default = vulnerabilities11;
5277
+
5234
5278
  // src/features/analysis/scm/shared/src/storedQuestionData/csharp/index.ts
5235
5279
  init_client_generates();
5236
5280
 
@@ -5527,7 +5571,7 @@ var xxe = {
5527
5571
  };
5528
5572
 
5529
5573
  // src/features/analysis/scm/shared/src/storedQuestionData/csharp/index.ts
5530
- var vulnerabilities11 = {
5574
+ var vulnerabilities12 = {
5531
5575
  ["LOG_FORGING" /* LogForging */]: logForging,
5532
5576
  ["SSRF" /* Ssrf */]: ssrf2,
5533
5577
  ["XXE" /* Xxe */]: xxe,
@@ -5548,7 +5592,7 @@ var vulnerabilities11 = {
5548
5592
  ["SQL_Injection" /* SqlInjection */]: sqlInjection2,
5549
5593
  ["REQUEST_PARAMETERS_BOUND_VIA_INPUT" /* RequestParametersBoundViaInput */]: requestParametersBoundViaInput
5550
5594
  };
5551
- var csharp_default2 = vulnerabilities11;
5595
+ var csharp_default2 = vulnerabilities12;
5552
5596
 
5553
5597
  // src/features/analysis/scm/shared/src/storedQuestionData/go/index.ts
5554
5598
  init_client_generates();
@@ -5581,18 +5625,18 @@ var websocketMissingOriginCheck = {
5581
5625
  };
5582
5626
 
5583
5627
  // src/features/analysis/scm/shared/src/storedQuestionData/go/index.ts
5584
- var vulnerabilities12 = {
5628
+ var vulnerabilities13 = {
5585
5629
  ["LOG_FORGING" /* LogForging */]: logForging2,
5586
5630
  ["MISSING_SSL_MINVERSION" /* MissingSslMinversion */]: missingSslMinversion,
5587
5631
  ["WEBSOCKET_MISSING_ORIGIN_CHECK" /* WebsocketMissingOriginCheck */]: websocketMissingOriginCheck
5588
5632
  };
5589
- var go_default2 = vulnerabilities12;
5633
+ var go_default2 = vulnerabilities13;
5590
5634
 
5591
5635
  // src/features/analysis/scm/shared/src/storedQuestionData/java/index.ts
5592
5636
  init_client_generates();
5593
5637
 
5594
5638
  // src/features/analysis/scm/shared/src/storedQuestionData/java/commandInjection.ts
5595
- var commandInjection = {
5639
+ var commandInjection2 = {
5596
5640
  isUnixShellCommandPart: {
5597
5641
  content: () => "Is the input part of Unix shell command?",
5598
5642
  description: () => `For example:
@@ -6046,10 +6090,10 @@ var xxe2 = {
6046
6090
  };
6047
6091
 
6048
6092
  // src/features/analysis/scm/shared/src/storedQuestionData/java/index.ts
6049
- var vulnerabilities13 = {
6093
+ var vulnerabilities14 = {
6050
6094
  ["SQL_Injection" /* SqlInjection */]: sqlInjection3,
6051
6095
  ["CMDi_relative_path_command" /* CmDiRelativePathCommand */]: relativePathCommand,
6052
- ["CMDi" /* CmDi */]: commandInjection,
6096
+ ["CMDi" /* CmDi */]: commandInjection2,
6053
6097
  ["CONFUSING_NAMING" /* ConfusingNaming */]: confusingNaming,
6054
6098
  ["ERROR_CONDTION_WITHOUT_ACTION" /* ErrorCondtionWithoutAction */]: errorConditionWithoutAction,
6055
6099
  ["XXE" /* Xxe */]: xxe2,
@@ -6074,7 +6118,7 @@ var vulnerabilities13 = {
6074
6118
  ["ERRONEOUS_STRING_COMPARE" /* ErroneousStringCompare */]: erroneousStringCompare,
6075
6119
  ["DUPLICATED_STRINGS" /* DuplicatedStrings */]: duplicatedStrings
6076
6120
  };
6077
- var java_default2 = vulnerabilities13;
6121
+ var java_default2 = vulnerabilities14;
6078
6122
 
6079
6123
  // src/features/analysis/scm/shared/src/storedQuestionData/js/index.ts
6080
6124
  init_client_generates();
@@ -6089,7 +6133,7 @@ var csrf2 = {
6089
6133
  };
6090
6134
 
6091
6135
  // src/features/analysis/scm/shared/src/storedQuestionData/js/commandInjection.ts
6092
- var commandInjection2 = {
6136
+ var commandInjection3 = {
6093
6137
  isCommandExecutable: {
6094
6138
  content: () => "Commands can be intrinsically unsafe if they call out to other executables or run arbitary code",
6095
6139
  description: () => `Does the command fall into one of the following categories:
@@ -6403,8 +6447,8 @@ var xss3 = {
6403
6447
  };
6404
6448
 
6405
6449
  // src/features/analysis/scm/shared/src/storedQuestionData/js/index.ts
6406
- var vulnerabilities14 = {
6407
- ["CMDi" /* CmDi */]: commandInjection2,
6450
+ var vulnerabilities15 = {
6451
+ ["CMDi" /* CmDi */]: commandInjection3,
6408
6452
  ["GRAPHQL_DEPTH_LIMIT" /* GraphqlDepthLimit */]: graphqlDepthLimit,
6409
6453
  ["INSECURE_RANDOMNESS" /* InsecureRandomness */]: insecureRandomness2,
6410
6454
  ["SSRF" /* Ssrf */]: ssrf4,
@@ -6426,7 +6470,7 @@ var vulnerabilities14 = {
6426
6470
  ["HARDCODED_DOMAIN_IN_HTML" /* HardcodedDomainInHtml */]: hardcodedDomainInHtml,
6427
6471
  ["CSRF" /* Csrf */]: csrf2
6428
6472
  };
6429
- var js_default = vulnerabilities14;
6473
+ var js_default = vulnerabilities15;
6430
6474
 
6431
6475
  // src/features/analysis/scm/shared/src/storedQuestionData/python/index.ts
6432
6476
  init_client_generates();
@@ -6500,7 +6544,7 @@ var uncheckedLoopCondition3 = {
6500
6544
  };
6501
6545
 
6502
6546
  // src/features/analysis/scm/shared/src/storedQuestionData/python/index.ts
6503
- var vulnerabilities15 = {
6547
+ var vulnerabilities16 = {
6504
6548
  ["CSRF" /* Csrf */]: csrf2,
6505
6549
  ["LOG_FORGING" /* LogForging */]: logForging5,
6506
6550
  ["OPEN_REDIRECT" /* OpenRedirect */]: openRedirect3,
@@ -6509,7 +6553,7 @@ var vulnerabilities15 = {
6509
6553
  ["MISSING_ENCODING_FILE_OPEN" /* MissingEncodingFileOpen */]: missingEncoding,
6510
6554
  ["SSRF" /* Ssrf */]: ssrf5
6511
6555
  };
6512
- var python_default2 = vulnerabilities15;
6556
+ var python_default2 = vulnerabilities16;
6513
6557
 
6514
6558
  // src/features/analysis/scm/shared/src/storedQuestionData/xml/index.ts
6515
6559
  init_client_generates();
@@ -6526,10 +6570,10 @@ A value too high will cause performance issues up to and including denial of ser
6526
6570
  };
6527
6571
 
6528
6572
  // src/features/analysis/scm/shared/src/storedQuestionData/xml/index.ts
6529
- var vulnerabilities16 = {
6573
+ var vulnerabilities17 = {
6530
6574
  ["WEAK_XML_SCHEMA_UNBOUNDED_OCCURRENCES" /* WeakXmlSchemaUnboundedOccurrences */]: unboundedOccurrences
6531
6575
  };
6532
- var xml_default2 = vulnerabilities16;
6576
+ var xml_default2 = vulnerabilities17;
6533
6577
 
6534
6578
  // src/features/analysis/scm/shared/src/storedQuestionData/yaml/index.ts
6535
6579
  init_client_generates();
@@ -6562,12 +6606,12 @@ var writableFilesystemService = {
6562
6606
  };
6563
6607
 
6564
6608
  // src/features/analysis/scm/shared/src/storedQuestionData/yaml/index.ts
6565
- var vulnerabilities17 = {
6609
+ var vulnerabilities18 = {
6566
6610
  ["PORT_ALL_INTERFACES" /* PortAllInterfaces */]: portAllInterfaces,
6567
6611
  ["WRITABLE_FILESYSTEM_SERVICE" /* WritableFilesystemService */]: writableFilesystemService,
6568
6612
  ["NO_NEW_PRIVILEGES" /* NoNewPrivileges */]: noNewPrivileges
6569
6613
  };
6570
- var yaml_default = vulnerabilities17;
6614
+ var yaml_default = vulnerabilities18;
6571
6615
 
6572
6616
  // src/features/analysis/scm/shared/src/storedQuestionData/index.ts
6573
6617
  var StoredQuestionDataItemZ = z4.object({
@@ -6582,6 +6626,7 @@ var languages2 = {
6582
6626
  ["CSharp" /* CSharp */]: csharp_default2,
6583
6627
  ["Python" /* Python */]: python_default2,
6584
6628
  ["Go" /* Go */]: go_default2,
6629
+ ["Cpp" /* Cpp */]: cpp_default,
6585
6630
  ["YAML" /* Yaml */]: yaml_default
6586
6631
  };
6587
6632
  var storedQuestionData_default = languages2;
@@ -9325,8 +9370,8 @@ function handleGitHubError(error, scmType = "GitHub" /* GitHub */) {
9325
9370
  (Number.parseInt(headers["x-ratelimit-reset"], 10) * 1e3 - Date.now()) / 1e3
9326
9371
  )
9327
9372
  ) : void 0;
9328
- const errorMessage = errorObj.message || (error instanceof Error ? error.message : String(error));
9329
- if (status === 403 && retryAfter !== void 0 || errorMessage.toLowerCase().includes("rate limit") || errorMessage.toLowerCase().includes("api rate limit exceeded")) {
9373
+ const errorMessage3 = errorObj.message || (error instanceof Error ? error.message : String(error));
9374
+ if (status === 403 && retryAfter !== void 0 || errorMessage3.toLowerCase().includes("rate limit") || errorMessage3.toLowerCase().includes("api rate limit exceeded")) {
9330
9375
  throw new RateLimitError(
9331
9376
  "GitHub API rate limit exceeded",
9332
9377
  scmType,
@@ -9354,7 +9399,7 @@ function handleGitHubError(error, scmType = "GitHub" /* GitHub */) {
9354
9399
  const errorCode = errorObj.code || errorObj.response?.code;
9355
9400
  if (errorCode === "ECONNREFUSED" || errorCode === "ETIMEDOUT" || errorCode === "ENOTFOUND" || errorCode === "EAI_AGAIN") {
9356
9401
  throw new NetworkError(
9357
- `GitHub network error: ${errorMessage}`,
9402
+ `GitHub network error: ${errorMessage3}`,
9358
9403
  scmType,
9359
9404
  errorCode
9360
9405
  );
@@ -9362,7 +9407,7 @@ function handleGitHubError(error, scmType = "GitHub" /* GitHub */) {
9362
9407
  if (error instanceof RateLimitError || error instanceof InvalidAccessTokenError || error instanceof ScmBadCredentialsError || error instanceof InvalidRepoUrlError || error instanceof NetworkError || error instanceof InvalidUrlPatternError) {
9363
9408
  throw error;
9364
9409
  }
9365
- throw new Error(`GitHub API error: ${errorMessage}`);
9410
+ throw new Error(`GitHub API error: ${errorMessage3}`);
9366
9411
  }
9367
9412
  async function githubValidateParams(url, accessToken) {
9368
9413
  try {
@@ -9596,48 +9641,65 @@ function getGithubSdk(params = {}) {
9596
9641
  return false;
9597
9642
  }
9598
9643
  },
9599
- async getGithubRepoList() {
9644
+ async listAuthenticatedUserReposPage(params2) {
9645
+ const {
9646
+ sort = { field: "updated", order: "desc" },
9647
+ perPage = 10,
9648
+ page = 1
9649
+ } = params2;
9650
+ const githubSort = sort.field === "name" ? "full_name" : sort.field === "created" ? "created" : "updated";
9600
9651
  try {
9601
- const allRepos = [];
9602
- let page = 1;
9603
- const perPage = 100;
9604
- let hasMore = true;
9605
- while (hasMore) {
9606
- const githubRepos = await octokit.request(GET_USER_REPOS, {
9607
- sort: "updated",
9608
- per_page: perPage,
9609
- page
9610
- });
9611
- for (const repo of githubRepos.data) {
9612
- allRepos.push({
9613
- repoName: repo.name,
9614
- repoUrl: repo.html_url,
9615
- repoOwner: repo.owner.login,
9616
- repoLanguages: repo.language ? [repo.language] : [],
9617
- repoIsPublic: !repo.private,
9618
- repoUpdatedAt: repo.updated_at
9619
- });
9620
- }
9621
- hasMore = githubRepos.data.length >= perPage;
9622
- page++;
9623
- }
9624
- return allRepos;
9652
+ const githubRepos = await octokit.request(GET_USER_REPOS, {
9653
+ sort: githubSort,
9654
+ direction: sort.order,
9655
+ per_page: perPage,
9656
+ page
9657
+ });
9658
+ const items = githubRepos.data.map((repo) => ({
9659
+ repoName: repo.name,
9660
+ repoUrl: repo.html_url,
9661
+ repoOwner: repo.owner.login,
9662
+ repoLanguages: repo.language ? [repo.language] : [],
9663
+ repoIsPublic: !repo.private,
9664
+ repoUpdatedAt: repo.updated_at
9665
+ }));
9666
+ return {
9667
+ items,
9668
+ hasMore: githubRepos.data.length >= perPage
9669
+ };
9625
9670
  } catch (e) {
9626
9671
  if (e instanceof RequestError && e.status === 401) {
9627
9672
  console.warn(
9628
9673
  "GitHub API returned 401 Unauthorized when listing repos - token may be expired or lack repo scope"
9629
9674
  );
9630
- return [];
9675
+ return { items: [], hasMore: false };
9631
9676
  }
9632
9677
  if (e instanceof RequestError && e.status === 404) {
9633
9678
  console.warn(
9634
9679
  "GitHub API returned 404 Not Found when listing repos - user may not exist"
9635
9680
  );
9636
- return [];
9681
+ return { items: [], hasMore: false };
9637
9682
  }
9638
9683
  throw e;
9639
9684
  }
9640
9685
  },
9686
+ async getGithubRepoList() {
9687
+ const allRepos = [];
9688
+ let page = 1;
9689
+ const perPage = 100;
9690
+ let hasMore = true;
9691
+ while (hasMore) {
9692
+ const pageResult = await this.listAuthenticatedUserReposPage({
9693
+ sort: { field: "updated", order: "desc" },
9694
+ perPage,
9695
+ page
9696
+ });
9697
+ allRepos.push(...pageResult.items);
9698
+ hasMore = pageResult.hasMore;
9699
+ page++;
9700
+ }
9701
+ return allRepos;
9702
+ },
9641
9703
  async getGithubRepoDefaultBranch(repoUrl) {
9642
9704
  const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
9643
9705
  const repos = await octokit.rest.repos.get({ repo, owner });
@@ -10697,23 +10759,25 @@ var GithubSCMLib = class extends SCMLib {
10697
10759
  });
10698
10760
  }
10699
10761
  /**
10700
- * Override searchRepos to use GitHub's Search API for efficient pagination.
10701
- * This is much faster than fetching all repos and filtering in-memory.
10702
- *
10703
- * Note: GitHub Search API doesn't support sorting by name, so when name sorting
10704
- * is requested, we fall back to fetching all repos and sorting in-memory.
10762
+ * Override searchRepos for efficient server-side pagination.
10763
+ * - With scmOrg: GitHub Search API (`org:…`)
10764
+ * - Without scmOrg: paginated `GET /user/repos`
10765
+ * - Name sort: in-memory over full list
10705
10766
  */
10706
10767
  async searchRepos(params) {
10707
10768
  this._validateAccessToken();
10708
10769
  const sort = params.sort || { field: "updated", order: "desc" };
10709
- if (!params.scmOrg || sort.field === "name") {
10770
+ if (sort.field === "name") {
10710
10771
  return this.searchReposInMemory(params);
10711
10772
  }
10773
+ if (!params.scmOrg) {
10774
+ return this.searchReposWithUserReposApi(params);
10775
+ }
10712
10776
  return this.searchReposWithApi(params);
10713
10777
  }
10714
10778
  /**
10715
10779
  * Search repos by fetching all and sorting/paginating in-memory.
10716
- * Used when name sorting is requested or no organization is provided.
10780
+ * Used only when name sorting is requested.
10717
10781
  */
10718
10782
  async searchReposInMemory(params) {
10719
10783
  const repos = await this.getRepoList(params.scmOrg);
@@ -10741,6 +10805,24 @@ var GithubSCMLib = class extends SCMLib {
10741
10805
  hasMore: nextOffset < sortedRepos.length
10742
10806
  };
10743
10807
  }
10808
+ /**
10809
+ * Paginated repo list for authenticated user when no GitHub org is configured.
10810
+ */
10811
+ async searchReposWithUserReposApi(params) {
10812
+ const page = parseCursorSafe(params.cursor, 1);
10813
+ const perPage = params.limit || 10;
10814
+ const sort = params.sort || { field: "updated", order: "desc" };
10815
+ const pageResult = await this.githubSdk.listAuthenticatedUserReposPage({
10816
+ sort,
10817
+ perPage,
10818
+ page
10819
+ });
10820
+ return {
10821
+ results: pageResult.items,
10822
+ nextCursor: pageResult.hasMore ? String(page + 1) : void 0,
10823
+ hasMore: pageResult.hasMore
10824
+ };
10825
+ }
10744
10826
  /**
10745
10827
  * Search repos using GitHub Search API for efficient server-side pagination.
10746
10828
  * Only supports date-based sorting (updated/created).
@@ -13112,7 +13194,7 @@ import path10 from "path";
13112
13194
  import { env as env2 } from "process";
13113
13195
  import { pipeline } from "stream/promises";
13114
13196
  import chalk7 from "chalk";
13115
- import Debug21 from "debug";
13197
+ import Debug22 from "debug";
13116
13198
  import extract from "extract-zip";
13117
13199
  import { createSpinner as createSpinner4 } from "nanospinner";
13118
13200
  import fetch4 from "node-fetch";
@@ -13123,7 +13205,7 @@ import { z as z31 } from "zod";
13123
13205
  // src/commands/AuthManager.ts
13124
13206
  import crypto from "crypto";
13125
13207
  import os3 from "os";
13126
- import Debug10 from "debug";
13208
+ import Debug11 from "debug";
13127
13209
  import open from "open";
13128
13210
 
13129
13211
  // src/features/analysis/graphql/gql.ts
@@ -13778,11 +13860,11 @@ var GQLClient = class {
13778
13860
  {
13779
13861
  next: async (data) => {
13780
13862
  if (!data.analysis?.state || data.analysis?.state === "Failed" /* Failed */) {
13781
- const errorMessage = data.analysis?.failReason || `Analysis failed with id: ${data.analysis?.id}`;
13863
+ const errorMessage3 = data.analysis?.failReason || `Analysis failed with id: ${data.analysis?.id}`;
13782
13864
  subscription.unsubscribe();
13783
13865
  reject(
13784
13866
  new ReportDigestError(
13785
- errorMessage,
13867
+ errorMessage3,
13786
13868
  data.analysis?.failReason ?? ""
13787
13869
  )
13788
13870
  );
@@ -13846,9 +13928,9 @@ var GQLClient = class {
13846
13928
  `[pollForAnalysisState] Poll #${pollCount} - current state: ${analysis.state}`
13847
13929
  );
13848
13930
  if (!analysis.state || analysis.state === "Failed" /* Failed */) {
13849
- const errorMessage = analysis.failReason || `Analysis failed with id: ${analysis.id}`;
13850
- debug7(`[pollForAnalysisState] Analysis failed: ${errorMessage}`);
13851
- throw new ReportDigestError(errorMessage, analysis.failReason ?? "");
13931
+ const errorMessage3 = analysis.failReason || `Analysis failed with id: ${analysis.id}`;
13932
+ debug7(`[pollForAnalysisState] Analysis failed: ${errorMessage3}`);
13933
+ throw new ReportDigestError(errorMessage3, analysis.failReason ?? "");
13852
13934
  }
13853
13935
  if (callbackStates.includes(analysis.state)) {
13854
13936
  debug7(
@@ -13949,7 +14031,7 @@ var GQLClient = class {
13949
14031
  };
13950
14032
 
13951
14033
  // src/features/analysis/graphql/tracy-batch-upload.ts
13952
- import Debug9 from "debug";
14034
+ import Debug10 from "debug";
13953
14035
 
13954
14036
  // src/args/commands/upload_ai_blame.ts
13955
14037
  import fsPromises2 from "fs/promises";
@@ -14068,12 +14150,28 @@ init_urlParser2();
14068
14150
  import Debug8 from "debug";
14069
14151
  import fetch3, { File, fileFrom, FormData } from "node-fetch";
14070
14152
  var debug9 = Debug8("mobbdev:upload-file");
14153
+ var S3UploadError = class extends Error {
14154
+ constructor(status, s3Code, s3Message) {
14155
+ super(`Failed to upload the file: ${status}`);
14156
+ this.status = status;
14157
+ this.s3Code = s3Code;
14158
+ this.s3Message = s3Message;
14159
+ this.name = "S3UploadError";
14160
+ }
14161
+ };
14162
+ function parseS3ErrorBody(body) {
14163
+ return {
14164
+ code: body.match(/<Code>([^<]+)<\/Code>/)?.[1],
14165
+ message: body.match(/<Message>([^<]+)<\/Message>/)?.[1]
14166
+ };
14167
+ }
14071
14168
  async function uploadFile({
14072
14169
  file,
14073
14170
  url,
14074
14171
  uploadKey,
14075
14172
  uploadFields,
14076
- logger: logger3
14173
+ logger: logger3,
14174
+ signal
14077
14175
  }) {
14078
14176
  const logInfo2 = logger3 || ((_message, _data) => {
14079
14177
  });
@@ -14095,18 +14193,44 @@ async function uploadFile({
14095
14193
  } else {
14096
14194
  debug9("upload file from buffer");
14097
14195
  logInfo2(`FileUpload: upload file from buffer`);
14098
- form.append("file", new File([new Uint8Array(file)], "file"));
14196
+ form.append(
14197
+ "file",
14198
+ new File(
14199
+ [
14200
+ new Uint8Array(
14201
+ file.buffer,
14202
+ file.byteOffset,
14203
+ file.byteLength
14204
+ )
14205
+ ],
14206
+ "file"
14207
+ )
14208
+ );
14099
14209
  }
14100
14210
  const agent = getProxyAgent(url);
14101
14211
  const response = await fetch3(url, {
14102
14212
  method: "POST",
14103
14213
  body: form,
14104
- agent
14214
+ agent,
14215
+ signal
14105
14216
  });
14106
14217
  if (!response.ok) {
14107
- debug9("error from S3 %s %s", response.body, response.status);
14108
- logInfo2(`FileUpload: error from S3 ${response.body} ${response.status}`);
14109
- throw new Error(`Failed to upload the file: ${response.status}`);
14218
+ let bodyText = "";
14219
+ try {
14220
+ bodyText = await response.text();
14221
+ } catch {
14222
+ }
14223
+ const { code, message } = parseS3ErrorBody(bodyText);
14224
+ debug9(
14225
+ "error from S3 status=%d code=%s message=%s",
14226
+ response.status,
14227
+ code,
14228
+ message
14229
+ );
14230
+ logInfo2(
14231
+ `FileUpload: error from S3 status=${response.status} code=${code ?? "unknown"}`
14232
+ );
14233
+ throw new S3UploadError(response.status, code, message);
14110
14234
  }
14111
14235
  debug9("upload file done");
14112
14236
  logInfo2(`FileUpload: upload file done`);
@@ -14772,39 +14896,240 @@ function withTimeout(promise, ms, label) {
14772
14896
  ]);
14773
14897
  }
14774
14898
 
14899
+ // src/features/analysis/graphql/s3-raw-data-upload.ts
14900
+ import { setTimeout as sleep2 } from "timers/promises";
14901
+ import Debug9 from "debug";
14902
+ var debug10 = Debug9("mobbdev:tracy-s3-upload");
14903
+ var S3_OP_TIMEOUT_MS = 3e4;
14904
+ var MAX_TOTAL_S3_UPLOAD_MS = 12e4;
14905
+ var MAX_CONCURRENT_S3_UPLOADS = 5;
14906
+ var URL_REFRESH_MS = 20 * 60 * 1e3;
14907
+ var MAX_UPLOAD_ATTEMPTS = 3;
14908
+ var RETRY_BACKOFF_MS = 500;
14909
+ var MAX_S3_MESSAGE_CHARS = 120;
14910
+ var errorMessage = (e) => e instanceof Error ? e.message : String(e);
14911
+ function classifyUploadError(reason) {
14912
+ if (reason instanceof S3UploadError) {
14913
+ return {
14914
+ status: reason.status,
14915
+ s3Code: reason.s3Code,
14916
+ s3Message: reason.s3Message,
14917
+ retryable: reason.status !== 400 && reason.status !== 401
14918
+ };
14919
+ }
14920
+ return { retryable: true };
14921
+ }
14922
+ function createPresignedUrlProvider(client) {
14923
+ let creds = null;
14924
+ let fetchedAt = 0;
14925
+ const fetchFresh = async () => {
14926
+ let res;
14927
+ try {
14928
+ res = await withTimeout(
14929
+ client.getTracyRawDataUploadUrl(),
14930
+ S3_OP_TIMEOUT_MS,
14931
+ "[step:s3-url] getTracyRawDataUploadUrl"
14932
+ );
14933
+ } catch (err) {
14934
+ throw new Error(
14935
+ `[step:s3-url] Failed to fetch S3 upload URL: ${errorMessage(err)}`
14936
+ );
14937
+ }
14938
+ const { url, uploadFieldsJSON, keyPrefix } = res.getTracyRawDataUploadUrl;
14939
+ if (!url || !uploadFieldsJSON || !keyPrefix) {
14940
+ throw new Error(
14941
+ `[step:s3-url] Missing S3 upload fields (url=${!!url}, fields=${!!uploadFieldsJSON}, prefix=${!!keyPrefix})`
14942
+ );
14943
+ }
14944
+ try {
14945
+ return { url, uploadFields: JSON.parse(uploadFieldsJSON), keyPrefix };
14946
+ } catch {
14947
+ throw new Error("[step:s3-url] Malformed uploadFieldsJSON from server");
14948
+ }
14949
+ };
14950
+ const refresh = async () => {
14951
+ creds = await fetchFresh();
14952
+ fetchedAt = Date.now();
14953
+ return creds;
14954
+ };
14955
+ return {
14956
+ refresh,
14957
+ /** Cached creds, refreshed if missing or near expiry. */
14958
+ async current() {
14959
+ if (!creds || Date.now() - fetchedAt > URL_REFRESH_MS) return refresh();
14960
+ return creds;
14961
+ }
14962
+ };
14963
+ }
14964
+ async function uploadRawDataToS3(client, entries, serializedByIndex) {
14965
+ const uploaded = /* @__PURE__ */ new Map();
14966
+ const urls = createPresignedUrlProvider(client);
14967
+ debug10(
14968
+ "[step:s3-upload] Uploading %d files to S3 (concurrency=%d)",
14969
+ entries.length,
14970
+ MAX_CONCURRENT_S3_UPLOADS
14971
+ );
14972
+ const start = Date.now();
14973
+ const deadline = start + MAX_TOTAL_S3_UPLOAD_MS;
14974
+ const uploadPass = async (pass) => {
14975
+ const failures = [];
14976
+ for (let i = 0; i < pass.length; i += MAX_CONCURRENT_S3_UPLOADS) {
14977
+ if (Date.now() > deadline) {
14978
+ for (const entry of pass.slice(i)) {
14979
+ failures.push({
14980
+ entry,
14981
+ kind: { retryable: false },
14982
+ message: `[step:s3-upload] aborted: exceeded ${MAX_TOTAL_S3_UPLOAD_MS}ms total upload budget`
14983
+ });
14984
+ }
14985
+ break;
14986
+ }
14987
+ const { url, uploadFields, keyPrefix } = await urls.current();
14988
+ const chunk = pass.slice(i, i + MAX_CONCURRENT_S3_UPLOADS);
14989
+ const settled = await Promise.allSettled(
14990
+ chunk.map(async (entry) => {
14991
+ const rawDataJson = serializedByIndex.get(entry.index);
14992
+ if (!rawDataJson) {
14993
+ debug10("No serialized rawData for recordId=%s", entry.recordId);
14994
+ return;
14995
+ }
14996
+ const uploadKey = `${keyPrefix}${entry.recordId}.json`;
14997
+ const signal = AbortSignal.timeout(S3_OP_TIMEOUT_MS);
14998
+ try {
14999
+ await uploadFile({
15000
+ file: Buffer.from(rawDataJson, "utf-8"),
15001
+ url,
15002
+ uploadKey,
15003
+ uploadFields,
15004
+ signal
15005
+ });
15006
+ } catch (err) {
15007
+ if (signal.aborted) {
15008
+ throw new Error(
15009
+ `[step:s3-upload] uploadFile ${entry.recordId} timed out after ${S3_OP_TIMEOUT_MS}ms`
15010
+ );
15011
+ }
15012
+ throw err;
15013
+ }
15014
+ uploaded.set(entry.index, uploadKey);
15015
+ serializedByIndex.delete(entry.index);
15016
+ })
15017
+ );
15018
+ settled.forEach((outcome, idx) => {
15019
+ if (outcome.status === "rejected") {
15020
+ failures.push({
15021
+ entry: chunk[idx],
15022
+ kind: classifyUploadError(outcome.reason),
15023
+ message: errorMessage(outcome.reason)
15024
+ });
15025
+ }
15026
+ });
15027
+ }
15028
+ return failures;
15029
+ };
15030
+ const failuresByRecord = /* @__PURE__ */ new Map();
15031
+ try {
15032
+ await urls.refresh();
15033
+ let pending = entries;
15034
+ for (let attempt = 1; attempt <= MAX_UPLOAD_ATTEMPTS; attempt++) {
15035
+ const failures = await uploadPass(pending);
15036
+ for (const entry of pending) failuresByRecord.delete(entry.recordId);
15037
+ for (const failure of failures)
15038
+ failuresByRecord.set(failure.entry.recordId, failure);
15039
+ const retryable = failures.filter((failure) => failure.kind.retryable);
15040
+ if (retryable.length === 0 || attempt === MAX_UPLOAD_ATTEMPTS || Date.now() > deadline) {
15041
+ break;
15042
+ }
15043
+ debug10(
15044
+ "[step:s3-upload] attempt %d failed for %d record(s); refreshing URL and retrying",
15045
+ attempt,
15046
+ retryable.length
15047
+ );
15048
+ await sleep2(RETRY_BACKOFF_MS * attempt);
15049
+ await urls.refresh();
15050
+ pending = retryable.map((failure) => failure.entry);
15051
+ }
15052
+ } catch (err) {
15053
+ return { uploaded, errors: [errorMessage(err)] };
15054
+ }
15055
+ debug10("[perf] s3-upload %d files: %dms", entries.length, Date.now() - start);
15056
+ const missing = entries.filter((entry) => !uploaded.has(entry.index));
15057
+ if (missing.length === 0) {
15058
+ debug10("[step:s3-upload] S3 uploads complete");
15059
+ return { uploaded, errors: null };
15060
+ }
15061
+ const detail = missing.map((entry) => {
15062
+ const failure = failuresByRecord.get(entry.recordId);
15063
+ const code = failure?.kind.s3Code ? ` ${failure.kind.s3Code}` : "";
15064
+ const message = failure?.kind.s3Message ? ` "${failure.kind.s3Message.slice(0, MAX_S3_MESSAGE_CHARS)}"` : "";
15065
+ return `[step:s3-upload] ${entry.recordId}: HTTP ${failure?.kind.status ?? "n/a"}${code}${message} (${failure?.message ?? "unknown"})`;
15066
+ });
15067
+ debug10(
15068
+ "[step:s3-upload] Records missing S3 keys: %O",
15069
+ missing.map((entry) => entry.recordId)
15070
+ );
15071
+ return {
15072
+ uploaded,
15073
+ errors: [
15074
+ `[step:s3-upload] Failed to upload rawData for ${missing.length} record(s): ${missing.map((entry) => entry.recordId).join(", ")}`,
15075
+ ...detail
15076
+ ]
15077
+ };
15078
+ }
15079
+
14775
15080
  // src/features/analysis/graphql/tracy-batch-upload.ts
14776
- var debug10 = Debug9("mobbdev:tracy-batch-upload");
15081
+ var debug11 = Debug10("mobbdev:tracy-batch-upload");
15082
+ var errorMessage2 = (e) => e instanceof Error ? e.message : String(e);
14777
15083
  function timedStep(label, fn) {
14778
15084
  const start = Date.now();
14779
15085
  const result = fn();
14780
15086
  const maybePromise = result instanceof Promise ? result : Promise.resolve(result);
14781
15087
  return maybePromise.then(
14782
15088
  (val) => {
14783
- debug10("[perf] %s: %dms", label, Date.now() - start);
15089
+ debug11("[perf] %s: %dms", label, Date.now() - start);
14784
15090
  return val;
14785
15091
  },
14786
15092
  (err) => {
14787
- debug10("[perf] %s FAILED: %dms", label, Date.now() - start);
15093
+ debug11("[perf] %s FAILED: %dms", label, Date.now() - start);
14788
15094
  throw err;
14789
15095
  }
14790
15096
  );
14791
15097
  }
14792
15098
  var BATCH_TIMEOUT_MS = 3e4;
15099
+ var MIN_RAWDATA_BYTES = 5;
15100
+ var MAX_DEGENERATE_SAMPLE_CHARS = 500;
15101
+ var REDACTED_SAMPLE = "<redacted: sanitization disabled>";
15102
+ var MAX_DEGENERATE_LOG_RECORDS = 20;
15103
+ var DEGENERATE_RECORDS_LOG_MESSAGE = "Skipped empty/degenerate rawData records before S3 upload";
15104
+ function degenerateRecordsLogFields(degenerate) {
15105
+ return {
15106
+ count: degenerate.length,
15107
+ records: degenerate.slice(0, MAX_DEGENERATE_LOG_RECORDS)
15108
+ };
15109
+ }
15110
+ function isStructurallyEmptyPayload(serialized) {
15111
+ const trimmed = serialized.trim();
15112
+ if (trimmed === "" || trimmed === "null" || trimmed === '""') return true;
15113
+ const isObject = trimmed.startsWith("{") && trimmed.endsWith("}");
15114
+ const isArray = trimmed.startsWith("[") && trimmed.endsWith("]");
15115
+ if (isObject || isArray) return trimmed.slice(1, -1).trim() === "";
15116
+ return false;
15117
+ }
14793
15118
  async function sanitizeRawData(rawData) {
14794
15119
  const start = Date.now();
14795
15120
  try {
14796
15121
  const sanitized = await sanitizeData(rawData);
14797
15122
  const serialized = JSON.stringify(sanitized);
14798
- debug10(
15123
+ debug11(
14799
15124
  "[perf] sanitizeRawData: %dms (%d bytes)",
14800
15125
  Date.now() - start,
14801
15126
  serialized.length
14802
15127
  );
14803
15128
  return serialized;
14804
15129
  } catch (err) {
14805
- console.warn(
14806
- "[tracy] sanitizeRawData failed, falling back to unsanitized:",
14807
- err.message
15130
+ debug11(
15131
+ "[tracy] sanitizeRawData failed, falling back to unsanitized: %s",
15132
+ errorMessage2(err)
14808
15133
  );
14809
15134
  return JSON.stringify(rawData);
14810
15135
  }
@@ -14814,12 +15139,13 @@ async function prepareAndSendTracyRecords(client, rawRecords, workingDir, option
14814
15139
  const defaultClientVersion = packageJson.version;
14815
15140
  const shouldSanitize = options?.sanitize ?? true;
14816
15141
  const defaults = workingDir != null ? await readRepoState(workingDir) : { repositoryUrl: null, branch: null, commitSha: null };
14817
- debug10(
15142
+ debug11(
14818
15143
  "[step:sanitize] %s %d records",
14819
15144
  shouldSanitize ? "Sanitizing" : "Serializing",
14820
15145
  rawRecords.length
14821
15146
  );
14822
15147
  const serializedRawDataByIndex = /* @__PURE__ */ new Map();
15148
+ const degenerate = [];
14823
15149
  const records = await timedStep(
14824
15150
  `${shouldSanitize ? "sanitize" : "serialize"} ${rawRecords.length} records`,
14825
15151
  async () => {
@@ -14828,7 +15154,19 @@ async function prepareAndSendTracyRecords(client, rawRecords, workingDir, option
14828
15154
  const record = rawRecords[index];
14829
15155
  if (record.rawData != null && record.rawDataS3Key == null) {
14830
15156
  const serialized = shouldSanitize ? await sanitizeRawData(record.rawData) : JSON.stringify(record.rawData);
14831
- serializedRawDataByIndex.set(index, serialized);
15157
+ const bytes = Buffer.byteLength(serialized, "utf-8");
15158
+ if (bytes < MIN_RAWDATA_BYTES || isStructurallyEmptyPayload(serialized)) {
15159
+ degenerate.push({
15160
+ recordId: record.recordId,
15161
+ platform: record.platform,
15162
+ filePath: record.filePath,
15163
+ editType: record.editType,
15164
+ bytes,
15165
+ sample: shouldSanitize ? serialized.slice(0, MAX_DEGENERATE_SAMPLE_CHARS) : REDACTED_SAMPLE
15166
+ });
15167
+ } else {
15168
+ serializedRawDataByIndex.set(index, serialized);
15169
+ }
14832
15170
  }
14833
15171
  const { rawData: _rawData, ...rest } = record;
14834
15172
  results.push({
@@ -14844,104 +15182,19 @@ async function prepareAndSendTracyRecords(client, rawRecords, workingDir, option
14844
15182
  return results;
14845
15183
  }
14846
15184
  );
14847
- const recordsWithRawData = rawRecords.map((r, i) => ({ recordId: r.recordId, index: i })).filter((entry) => serializedRawDataByIndex.has(entry.index));
15185
+ const degenerateOut = degenerate.length > 0 ? degenerate : void 0;
15186
+ const finish = (result) => ({ ...result, degenerate: degenerateOut });
15187
+ const recordsWithRawData = rawRecords.map((record, index) => ({ recordId: record.recordId, index })).filter((entry) => serializedRawDataByIndex.has(entry.index));
14848
15188
  if (recordsWithRawData.length > 0) {
14849
- debug10(
14850
- "[step:s3-url] Requesting presigned URL for %d rawData files",
14851
- recordsWithRawData.length
14852
- );
14853
- let uploadUrlResult;
14854
- try {
14855
- uploadUrlResult = await withTimeout(
14856
- client.getTracyRawDataUploadUrl(),
14857
- BATCH_TIMEOUT_MS,
14858
- "[step:s3-url] getTracyRawDataUploadUrl"
14859
- );
14860
- } catch (err) {
14861
- return {
14862
- ok: false,
14863
- errors: [
14864
- `[step:s3-url] Failed to fetch S3 upload URL: ${err.message}`
14865
- ]
14866
- };
14867
- }
14868
- const { url, uploadFieldsJSON, keyPrefix } = uploadUrlResult.getTracyRawDataUploadUrl;
14869
- if (!url || !uploadFieldsJSON || !keyPrefix) {
14870
- return {
14871
- ok: false,
14872
- errors: [
14873
- `[step:s3-url] Missing S3 upload fields (url=${!!url}, fields=${!!uploadFieldsJSON}, prefix=${!!keyPrefix})`
14874
- ]
14875
- };
14876
- }
14877
- let uploadFields;
14878
- try {
14879
- uploadFields = JSON.parse(uploadFieldsJSON);
14880
- } catch {
14881
- return {
14882
- ok: false,
14883
- errors: ["[step:s3-url] Malformed uploadFieldsJSON from server"]
14884
- };
14885
- }
14886
- const MAX_CONCURRENT_S3_UPLOADS = 5;
14887
- debug10(
14888
- "[step:s3-upload] Uploading %d files to S3 (concurrency=%d)",
14889
- recordsWithRawData.length,
14890
- MAX_CONCURRENT_S3_UPLOADS
15189
+ const { uploaded, errors } = await uploadRawDataToS3(
15190
+ client,
15191
+ recordsWithRawData,
15192
+ serializedRawDataByIndex
14891
15193
  );
14892
- const s3Start = Date.now();
14893
- const uploadResults = [];
14894
- for (let i = 0; i < recordsWithRawData.length; i += MAX_CONCURRENT_S3_UPLOADS) {
14895
- const chunk = recordsWithRawData.slice(i, i + MAX_CONCURRENT_S3_UPLOADS);
14896
- const chunkResults = await Promise.allSettled(
14897
- chunk.map(async (entry) => {
14898
- const rawDataJson = serializedRawDataByIndex.get(entry.index);
14899
- if (!rawDataJson) {
14900
- debug10("No serialized rawData for recordId=%s", entry.recordId);
14901
- return;
14902
- }
14903
- const uploadKey = `${keyPrefix}${entry.recordId}.json`;
14904
- await withTimeout(
14905
- uploadFile({
14906
- file: Buffer.from(rawDataJson, "utf-8"),
14907
- url,
14908
- uploadKey,
14909
- uploadFields
14910
- }),
14911
- BATCH_TIMEOUT_MS,
14912
- `[step:s3-upload] uploadFile ${entry.recordId}`
14913
- );
14914
- records[entry.index].rawDataS3Key = uploadKey;
14915
- })
14916
- );
14917
- uploadResults.push(...chunkResults);
14918
- }
14919
- debug10(
14920
- "[perf] s3-upload %d files: %dms",
14921
- recordsWithRawData.length,
14922
- Date.now() - s3Start
14923
- );
14924
- const uploadErrors = uploadResults.filter((r) => r.status === "rejected").map((r) => r.reason.message);
14925
- if (uploadErrors.length > 0) {
14926
- debug10("[step:s3-upload] S3 upload errors: %O", uploadErrors);
14927
- }
14928
- const missingS3Keys = recordsWithRawData.filter(
14929
- (entry) => !records[entry.index].rawDataS3Key
14930
- );
14931
- if (missingS3Keys.length > 0) {
14932
- const missingIds = missingS3Keys.map((e) => e.recordId);
14933
- debug10("[step:s3-upload] Records missing S3 keys: %O", missingIds);
14934
- return {
14935
- ok: false,
14936
- errors: [
14937
- `[step:s3-upload] Failed to upload rawData for ${missingS3Keys.length} record(s): ${missingIds.join(", ")}`,
14938
- ...uploadErrors
14939
- ]
14940
- };
14941
- }
14942
- debug10("[step:s3-upload] S3 uploads complete");
15194
+ for (const [index, key] of uploaded) records[index].rawDataS3Key = key;
15195
+ if (errors) return finish({ ok: false, errors });
14943
15196
  }
14944
- debug10("[step:gql-submit] Submitting %d records via GraphQL", records.length);
15197
+ debug11("[step:gql-submit] Submitting %d records via GraphQL", records.length);
14945
15198
  try {
14946
15199
  const result = await timedStep(
14947
15200
  `gql-submit ${records.length} records`,
@@ -14952,21 +15205,21 @@ async function prepareAndSendTracyRecords(client, rawRecords, workingDir, option
14952
15205
  )
14953
15206
  );
14954
15207
  if (result.uploadTracyRecords.status !== "OK") {
14955
- return {
15208
+ return finish({
14956
15209
  ok: false,
14957
15210
  errors: [
14958
15211
  `[step:gql-submit] Server rejected: ${result.uploadTracyRecords.error ?? "Unknown server error"}`
14959
15212
  ]
14960
- };
15213
+ });
14961
15214
  }
14962
15215
  } catch (err) {
14963
- debug10("[step:gql-submit] Upload failed: %s", err.message);
14964
- return {
15216
+ debug11("[step:gql-submit] Upload failed: %s", errorMessage2(err));
15217
+ return finish({
14965
15218
  ok: false,
14966
- errors: [`[step:gql-submit] ${err.message}`]
14967
- };
15219
+ errors: [`[step:gql-submit] ${errorMessage2(err)}`]
15220
+ });
14968
15221
  }
14969
- return { ok: true, errors: null };
15222
+ return finish({ ok: true, errors: null });
14970
15223
  }
14971
15224
 
14972
15225
  // src/mcp/services/types.ts
@@ -15002,7 +15255,7 @@ function buildLoginUrl(baseUrl, loginId, hostname, context) {
15002
15255
  }
15003
15256
 
15004
15257
  // src/commands/AuthManager.ts
15005
- var debug11 = Debug10("mobbdev:auth");
15258
+ var debug12 = Debug11("mobbdev:auth");
15006
15259
  var LOGIN_MAX_WAIT = 2 * 60 * 1e3;
15007
15260
  var LOGIN_CHECK_DELAY = 2 * 1e3;
15008
15261
  var _AuthManager = class _AuthManager {
@@ -15032,7 +15285,7 @@ var _AuthManager = class _AuthManager {
15032
15285
  return false;
15033
15286
  }
15034
15287
  if (_AuthManager.browserCooldownMs > 0 && Date.now() - _AuthManager.lastBrowserOpenTime < _AuthManager.browserCooldownMs) {
15035
- debug11("browser cooldown active, skipping open");
15288
+ debug12("browser cooldown active, skipping open");
15036
15289
  return false;
15037
15290
  }
15038
15291
  open(this.currentBrowserUrl);
@@ -15085,7 +15338,7 @@ var _AuthManager = class _AuthManager {
15085
15338
  const result = await this.checkAuthentication();
15086
15339
  this.authenticated = result.isAuthenticated;
15087
15340
  if (!result.isAuthenticated) {
15088
- debug11("isAuthenticated: false \u2014 %s (%s)", result.message, result.reason);
15341
+ debug12("isAuthenticated: false \u2014 %s (%s)", result.message, result.reason);
15089
15342
  }
15090
15343
  }
15091
15344
  return this.authenticated;
@@ -15173,9 +15426,9 @@ var _AuthManager = class _AuthManager {
15173
15426
  return null;
15174
15427
  } catch (error) {
15175
15428
  if (isTransientError(error)) {
15176
- debug11("getApiToken: transient error, will retry");
15429
+ debug12("getApiToken: transient error, will retry");
15177
15430
  } else {
15178
- debug11("getApiToken: unexpected error: %O", error);
15431
+ debug12("getApiToken: unexpected error: %O", error);
15179
15432
  }
15180
15433
  return null;
15181
15434
  }
@@ -15228,10 +15481,10 @@ __publicField(_AuthManager, "lastBrowserOpenTime", 0);
15228
15481
  var AuthManager = _AuthManager;
15229
15482
 
15230
15483
  // src/features/analysis/add_fix_comments_for_pr/add_fix_comments_for_pr.ts
15231
- import Debug14 from "debug";
15484
+ import Debug15 from "debug";
15232
15485
 
15233
15486
  // src/features/analysis/add_fix_comments_for_pr/utils/utils.ts
15234
- import Debug13 from "debug";
15487
+ import Debug14 from "debug";
15235
15488
  import parseDiff from "parse-diff";
15236
15489
  import { z as z29 } from "zod";
15237
15490
 
@@ -15243,9 +15496,9 @@ function keyBy(array, keyBy2) {
15243
15496
  }
15244
15497
 
15245
15498
  // src/features/analysis/utils/send_report.ts
15246
- import Debug11 from "debug";
15499
+ import Debug12 from "debug";
15247
15500
  init_client_generates();
15248
- var debug12 = Debug11("mobbdev:index");
15501
+ var debug13 = Debug12("mobbdev:index");
15249
15502
  async function sendReport({
15250
15503
  spinner,
15251
15504
  submitVulnerabilityReportVariables,
@@ -15257,7 +15510,7 @@ async function sendReport({
15257
15510
  submitVulnerabilityReportVariables
15258
15511
  );
15259
15512
  if (submitRes.submitVulnerabilityReport.__typename !== "VulnerabilityReport") {
15260
- debug12("error submit vul report %s", submitRes);
15513
+ debug13("error submit vul report %s", submitRes);
15261
15514
  throw new Error("\u{1F575}\uFE0F\u200D\u2642\uFE0F Mobb analysis failed");
15262
15515
  }
15263
15516
  spinner.update({ text: progressMassages.processingVulnerabilityReport });
@@ -15269,7 +15522,7 @@ async function sendReport({
15269
15522
  "Finished" /* Finished */
15270
15523
  ];
15271
15524
  if (polling) {
15272
- debug12("[sendReport] Using POLLING mode for analysis state updates");
15525
+ debug13("[sendReport] Using POLLING mode for analysis state updates");
15273
15526
  await gqlClient.pollForAnalysisState({
15274
15527
  analysisId: submitRes.submitVulnerabilityReport.fixReportId,
15275
15528
  callback,
@@ -15277,7 +15530,7 @@ async function sendReport({
15277
15530
  timeoutInMs: VUL_REPORT_DIGEST_TIMEOUT_MS
15278
15531
  });
15279
15532
  } else {
15280
- debug12("[sendReport] Using WEBSOCKET mode for analysis state updates");
15533
+ debug13("[sendReport] Using WEBSOCKET mode for analysis state updates");
15281
15534
  await gqlClient.subscribeToAnalysis({
15282
15535
  subscribeToAnalysisParams: {
15283
15536
  analysisId: submitRes.submitVulnerabilityReport.fixReportId
@@ -15321,10 +15574,10 @@ var scannerToFriendlyString = {
15321
15574
  };
15322
15575
 
15323
15576
  // src/features/analysis/add_fix_comments_for_pr/utils/buildCommentBody.ts
15324
- import Debug12 from "debug";
15577
+ import Debug13 from "debug";
15325
15578
  import { z as z28 } from "zod";
15326
15579
  init_client_generates();
15327
- var debug13 = Debug12("mobbdev:handle-finished-analysis");
15580
+ var debug14 = Debug13("mobbdev:handle-finished-analysis");
15328
15581
  var getCommitFixButton = (commitUrl) => `<a href="${commitUrl}"><img src=${COMMIT_FIX_SVG}></a>`;
15329
15582
  function buildFixCommentBody({
15330
15583
  fix,
@@ -15375,7 +15628,7 @@ function buildFixCommentBody({
15375
15628
  safeIssueType: z28.nativeEnum(IssueType_Enum)
15376
15629
  }).safeParse(fix);
15377
15630
  if (!validFixParseRes.success) {
15378
- debug13(
15631
+ debug14(
15379
15632
  `fix ${fixId} has custom issue type or language, therefore the commit description will not be added`,
15380
15633
  validFixParseRes.error
15381
15634
  );
@@ -15439,7 +15692,7 @@ ${issuePageLink}`;
15439
15692
  }
15440
15693
 
15441
15694
  // src/features/analysis/add_fix_comments_for_pr/utils/utils.ts
15442
- var debug14 = Debug13("mobbdev:handle-finished-analysis");
15695
+ var debug15 = Debug14("mobbdev:handle-finished-analysis");
15443
15696
  function calculateRanges(integers) {
15444
15697
  if (integers.length === 0) {
15445
15698
  return [];
@@ -15473,7 +15726,7 @@ function deleteAllPreviousComments({
15473
15726
  try {
15474
15727
  return scm.deleteComment({ comment_id: comment.id });
15475
15728
  } catch (e) {
15476
- debug14("delete comment failed %s", e);
15729
+ debug15("delete comment failed %s", e);
15477
15730
  return Promise.resolve();
15478
15731
  }
15479
15732
  });
@@ -15489,7 +15742,7 @@ function deleteAllPreviousGeneralPrComments(params) {
15489
15742
  try {
15490
15743
  return scm.deleteGeneralPrComment({ commentId: comment.id });
15491
15744
  } catch (e) {
15492
- debug14("delete comment failed %s", e);
15745
+ debug15("delete comment failed %s", e);
15493
15746
  return Promise.resolve();
15494
15747
  }
15495
15748
  });
@@ -15633,7 +15886,7 @@ async function postAnalysisInsightComment(params) {
15633
15886
  fixablePrVuls,
15634
15887
  nonFixablePrVuls
15635
15888
  } = prVulenrabilities;
15636
- debug14({
15889
+ debug15({
15637
15890
  fixablePrVuls,
15638
15891
  nonFixablePrVuls,
15639
15892
  vulnerabilitiesOutsidePr,
@@ -15688,7 +15941,7 @@ ${contactUsMarkdown}`;
15688
15941
  }
15689
15942
 
15690
15943
  // src/features/analysis/add_fix_comments_for_pr/add_fix_comments_for_pr.ts
15691
- var debug15 = Debug14("mobbdev:handle-finished-analysis");
15944
+ var debug16 = Debug15("mobbdev:handle-finished-analysis");
15692
15945
  async function addFixCommentsForPr({
15693
15946
  analysisId,
15694
15947
  scm: _scm,
@@ -15700,7 +15953,7 @@ async function addFixCommentsForPr({
15700
15953
  }
15701
15954
  const scm = _scm;
15702
15955
  const getAnalysisRes = await gqlClient.getAnalysis(analysisId);
15703
- debug15("getAnalysis %o", getAnalysisRes);
15956
+ debug16("getAnalysis %o", getAnalysisRes);
15704
15957
  const {
15705
15958
  vulnerabilityReport: {
15706
15959
  projectId,
@@ -15810,8 +16063,8 @@ ${contextString}` : description;
15810
16063
 
15811
16064
  // src/features/analysis/auto_pr_handler.ts
15812
16065
  init_client_generates();
15813
- import Debug15 from "debug";
15814
- var debug16 = Debug15("mobbdev:handleAutoPr");
16066
+ import Debug16 from "debug";
16067
+ var debug17 = Debug16("mobbdev:handleAutoPr");
15815
16068
  async function handleAutoPr(params) {
15816
16069
  const {
15817
16070
  gqlClient,
@@ -15832,7 +16085,7 @@ async function handleAutoPr(params) {
15832
16085
  prId,
15833
16086
  prStrategy: createOnePr ? "CONDENSE" /* Condense */ : "SPREAD" /* Spread */
15834
16087
  });
15835
- debug16("auto pr analysis res %o", autoPrAnalysisRes);
16088
+ debug17("auto pr analysis res %o", autoPrAnalysisRes);
15836
16089
  if (autoPrAnalysisRes.autoPrAnalysis?.__typename === "AutoPrError") {
15837
16090
  createAutoPrSpinner.error({
15838
16091
  text: `\u{1F504} Automatic pull request failed - ${autoPrAnalysisRes.autoPrAnalysis.error}`
@@ -15854,14 +16107,14 @@ async function handleAutoPr(params) {
15854
16107
  };
15855
16108
  const callbackStates = ["Finished" /* Finished */];
15856
16109
  if (polling) {
15857
- debug16("[handleAutoPr] Using POLLING mode for analysis state updates");
16110
+ debug17("[handleAutoPr] Using POLLING mode for analysis state updates");
15858
16111
  return await gqlClient.pollForAnalysisState({
15859
16112
  analysisId,
15860
16113
  callback,
15861
16114
  callbackStates
15862
16115
  });
15863
16116
  } else {
15864
- debug16("[handleAutoPr] Using WEBSOCKET mode for analysis state updates");
16117
+ debug17("[handleAutoPr] Using WEBSOCKET mode for analysis state updates");
15865
16118
  return await gqlClient.subscribeToAnalysis({
15866
16119
  subscribeToAnalysisParams: {
15867
16120
  analysisId
@@ -15874,15 +16127,15 @@ async function handleAutoPr(params) {
15874
16127
 
15875
16128
  // src/features/analysis/git.ts
15876
16129
  init_GitService();
15877
- import Debug16 from "debug";
15878
- var debug17 = Debug16("mobbdev:git");
16130
+ import Debug17 from "debug";
16131
+ var debug18 = Debug17("mobbdev:git");
15879
16132
  async function getGitInfo(srcDirPath) {
15880
- debug17("getting git info for %s", srcDirPath);
16133
+ debug18("getting git info for %s", srcDirPath);
15881
16134
  const gitService = new GitService(srcDirPath);
15882
16135
  try {
15883
16136
  const validationResult = await gitService.validateRepository();
15884
16137
  if (!validationResult.isValid) {
15885
- debug17("folder is not a git repo");
16138
+ debug18("folder is not a git repo");
15886
16139
  return {
15887
16140
  success: false,
15888
16141
  hash: void 0,
@@ -15897,9 +16150,9 @@ async function getGitInfo(srcDirPath) {
15897
16150
  };
15898
16151
  } catch (e) {
15899
16152
  if (e instanceof Error) {
15900
- debug17("failed to run git %o", e);
16153
+ debug18("failed to run git %o", e);
15901
16154
  if (e.message.includes(" spawn ")) {
15902
- debug17("git cli not installed");
16155
+ debug18("git cli not installed");
15903
16156
  } else {
15904
16157
  throw e;
15905
16158
  }
@@ -15913,13 +16166,13 @@ init_configs();
15913
16166
  import fs9 from "fs";
15914
16167
  import path8 from "path";
15915
16168
  import AdmZip from "adm-zip";
15916
- import Debug17 from "debug";
16169
+ import Debug18 from "debug";
15917
16170
  import { globby } from "globby";
15918
16171
  import { isBinary as isBinary2 } from "istextorbinary";
15919
16172
  import { simpleGit as simpleGit3 } from "simple-git";
15920
16173
  import { parseStringPromise } from "xml2js";
15921
16174
  import { z as z30 } from "zod";
15922
- var debug18 = Debug17("mobbdev:pack");
16175
+ var debug19 = Debug18("mobbdev:pack");
15923
16176
  var FPR_SOURCE_CODE_FILE_MAPPING_SCHEMA = z30.object({
15924
16177
  properties: z30.object({
15925
16178
  entry: z30.array(
@@ -15941,7 +16194,7 @@ function getManifestFilesSuffixes() {
15941
16194
  return ["package.json", "pom.xml"];
15942
16195
  }
15943
16196
  async function pack(srcDirPath, vulnFiles, isIncludeAllFiles = false) {
15944
- debug18("pack folder %s", srcDirPath);
16197
+ debug19("pack folder %s", srcDirPath);
15945
16198
  let git;
15946
16199
  try {
15947
16200
  git = simpleGit3({
@@ -15951,13 +16204,13 @@ async function pack(srcDirPath, vulnFiles, isIncludeAllFiles = false) {
15951
16204
  });
15952
16205
  await git.status();
15953
16206
  } catch (e) {
15954
- debug18("failed to run git %o", e);
16207
+ debug19("failed to run git %o", e);
15955
16208
  git = void 0;
15956
16209
  if (e instanceof Error) {
15957
16210
  if (e.message.includes(" spawn ")) {
15958
- debug18("git cli not installed");
16211
+ debug19("git cli not installed");
15959
16212
  } else if (e.message.includes("not a git repository")) {
15960
- debug18("folder is not a git repo");
16213
+ debug19("folder is not a git repo");
15961
16214
  } else {
15962
16215
  throw e;
15963
16216
  }
@@ -15972,9 +16225,9 @@ async function pack(srcDirPath, vulnFiles, isIncludeAllFiles = false) {
15972
16225
  followSymbolicLinks: false,
15973
16226
  dot: true
15974
16227
  });
15975
- debug18("files found %d", filepaths.length);
16228
+ debug19("files found %d", filepaths.length);
15976
16229
  const zip = new AdmZip();
15977
- debug18("compressing files");
16230
+ debug19("compressing files");
15978
16231
  for (const filepath of filepaths) {
15979
16232
  const absFilepath = path8.join(srcDirPath, filepath.toString());
15980
16233
  if (!isIncludeAllFiles) {
@@ -15983,12 +16236,12 @@ async function pack(srcDirPath, vulnFiles, isIncludeAllFiles = false) {
15983
16236
  absFilepath.toString().replaceAll(path8.win32.sep, path8.posix.sep),
15984
16237
  vulnFiles
15985
16238
  )) {
15986
- debug18("ignoring %s because it is not a vulnerability file", filepath);
16239
+ debug19("ignoring %s because it is not a vulnerability file", filepath);
15987
16240
  continue;
15988
16241
  }
15989
16242
  }
15990
16243
  if (fs9.lstatSync(absFilepath).size > MCP_MAX_FILE_SIZE) {
15991
- debug18(
16244
+ debug19(
15992
16245
  "ignoring %s \u2014 file size exceeds MCP_MAX_FILE_SIZE (%d bytes)",
15993
16246
  filepath,
15994
16247
  MCP_MAX_FILE_SIZE
@@ -16006,16 +16259,16 @@ async function pack(srcDirPath, vulnFiles, isIncludeAllFiles = false) {
16006
16259
  data = fs9.readFileSync(absFilepath);
16007
16260
  }
16008
16261
  if (isBinary2(null, data)) {
16009
- debug18("ignoring %s because is seems to be a binary file", filepath);
16262
+ debug19("ignoring %s because is seems to be a binary file", filepath);
16010
16263
  continue;
16011
16264
  }
16012
16265
  zip.addFile(filepath.toString(), data);
16013
16266
  }
16014
- debug18("get zip file buffer");
16267
+ debug19("get zip file buffer");
16015
16268
  return zip.toBuffer();
16016
16269
  }
16017
16270
  async function repackFpr(fprPath) {
16018
- debug18("repack fpr file %s", fprPath);
16271
+ debug19("repack fpr file %s", fprPath);
16019
16272
  const zipIn = new AdmZip(fprPath);
16020
16273
  const zipOut = new AdmZip();
16021
16274
  const mappingXML = zipIn.readAsText("src-archive/index.xml", "utf-8");
@@ -16030,7 +16283,7 @@ async function repackFpr(fprPath) {
16030
16283
  zipOut.addFile(realPath, buf);
16031
16284
  }
16032
16285
  }
16033
- debug18("get repacked zip file buffer");
16286
+ debug19("get repacked zip file buffer");
16034
16287
  return zipOut.toBuffer();
16035
16288
  }
16036
16289
 
@@ -16101,7 +16354,7 @@ async function snykArticlePrompt() {
16101
16354
  // src/features/analysis/scanners/checkmarx.ts
16102
16355
  import { createRequire } from "module";
16103
16356
  import chalk5 from "chalk";
16104
- import Debug19 from "debug";
16357
+ import Debug20 from "debug";
16105
16358
  import { existsSync } from "fs";
16106
16359
  import { createSpinner as createSpinner2 } from "nanospinner";
16107
16360
  import { type } from "os";
@@ -16113,7 +16366,7 @@ var cxOperatingSystemSupportMessage = `Your operating system does not support ch
16113
16366
 
16114
16367
  // src/utils/child_process.ts
16115
16368
  import cp from "child_process";
16116
- import Debug18 from "debug";
16369
+ import Debug19 from "debug";
16117
16370
  import * as process2 from "process";
16118
16371
  function createFork({ args, processPath, name }, options) {
16119
16372
  const child = cp.fork(processPath, args, {
@@ -16131,16 +16384,16 @@ function createSpawn({ args, processPath, name, cwd, env: env3 }, options) {
16131
16384
  return createChildProcess({ childProcess: child, name }, options);
16132
16385
  }
16133
16386
  function createChildProcess({ childProcess, name }, options) {
16134
- const debug23 = Debug18(`mobbdev:${name}`);
16387
+ const debug24 = Debug19(`mobbdev:${name}`);
16135
16388
  const { display } = options;
16136
16389
  return new Promise((resolve, reject) => {
16137
16390
  let out = "";
16138
16391
  const onData = (chunk) => {
16139
- debug23(`chunk received from ${name} std ${chunk}`);
16392
+ debug24(`chunk received from ${name} std ${chunk}`);
16140
16393
  out += chunk;
16141
16394
  };
16142
16395
  if (!childProcess?.stdout || !childProcess?.stderr) {
16143
- debug23(`unable to fork ${name}`);
16396
+ debug24(`unable to fork ${name}`);
16144
16397
  reject(new Error(`unable to fork ${name}`));
16145
16398
  }
16146
16399
  childProcess.stdout?.on("data", onData);
@@ -16150,18 +16403,18 @@ function createChildProcess({ childProcess, name }, options) {
16150
16403
  childProcess.stderr?.pipe(process2.stderr);
16151
16404
  }
16152
16405
  childProcess.on("exit", (code) => {
16153
- debug23(`${name} exit code ${code}`);
16406
+ debug24(`${name} exit code ${code}`);
16154
16407
  resolve({ message: out, code });
16155
16408
  });
16156
16409
  childProcess.on("error", (err) => {
16157
- debug23(`${name} error %o`, err);
16410
+ debug24(`${name} error %o`, err);
16158
16411
  reject(err);
16159
16412
  });
16160
16413
  });
16161
16414
  }
16162
16415
 
16163
16416
  // src/features/analysis/scanners/checkmarx.ts
16164
- var debug19 = Debug19("mobbdev:checkmarx");
16417
+ var debug20 = Debug20("mobbdev:checkmarx");
16165
16418
  var moduleUrl;
16166
16419
  if (typeof __filename !== "undefined") {
16167
16420
  moduleUrl = __filename;
@@ -16220,14 +16473,14 @@ function validateCheckmarxInstallation() {
16220
16473
  existsSync(getCheckmarxPath());
16221
16474
  }
16222
16475
  async function forkCheckmarx(args, { display }) {
16223
- debug19("fork checkmarx with args %o %s", args.join(" "), display);
16476
+ debug20("fork checkmarx with args %o %s", args.join(" "), display);
16224
16477
  return createSpawn(
16225
16478
  { args, processPath: getCheckmarxPath(), name: "checkmarx" },
16226
16479
  { display }
16227
16480
  );
16228
16481
  }
16229
16482
  async function getCheckmarxReport({ reportPath, repositoryRoot, branch, projectName }, { skipPrompts = false }) {
16230
- debug19("get checkmarx report start %s %s", reportPath, repositoryRoot);
16483
+ debug20("get checkmarx report start %s %s", reportPath, repositoryRoot);
16231
16484
  const { code: loginCode } = await forkCheckmarx(VALIDATE_COMMAND, {
16232
16485
  display: false
16233
16486
  });
@@ -16295,10 +16548,10 @@ async function validateCheckamxCredentials() {
16295
16548
  // src/features/analysis/scanners/snyk.ts
16296
16549
  import { createRequire as createRequire2 } from "module";
16297
16550
  import chalk6 from "chalk";
16298
- import Debug20 from "debug";
16551
+ import Debug21 from "debug";
16299
16552
  import { createSpinner as createSpinner3 } from "nanospinner";
16300
16553
  import open2 from "open";
16301
- var debug20 = Debug20("mobbdev:snyk");
16554
+ var debug21 = Debug21("mobbdev:snyk");
16302
16555
  var moduleUrl2;
16303
16556
  if (typeof __filename !== "undefined") {
16304
16557
  moduleUrl2 = __filename;
@@ -16320,13 +16573,13 @@ if (typeof __filename !== "undefined") {
16320
16573
  var costumeRequire2 = createRequire2(moduleUrl2);
16321
16574
  var SNYK_PATH = costumeRequire2.resolve("snyk/bin/snyk");
16322
16575
  var SNYK_ARTICLE_URL = "https://docs.snyk.io/scan-using-snyk/snyk-code/configure-snyk-code#enable-snyk-code";
16323
- debug20("snyk executable path %s", SNYK_PATH);
16576
+ debug21("snyk executable path %s", SNYK_PATH);
16324
16577
  async function forkSnyk(args, { display }) {
16325
- debug20("fork snyk with args %o %s", args, display);
16578
+ debug21("fork snyk with args %o %s", args, display);
16326
16579
  return createFork({ args, processPath: SNYK_PATH, name: "snyk" }, { display });
16327
16580
  }
16328
16581
  async function getSnykReport(reportPath, repoRoot, { skipPrompts = false }) {
16329
- debug20("get snyk report start %s %s", reportPath, repoRoot);
16582
+ debug21("get snyk report start %s %s", reportPath, repoRoot);
16330
16583
  const config2 = await forkSnyk(["config"], { display: false });
16331
16584
  const { message: configMessage } = config2;
16332
16585
  if (!configMessage.includes("api: ")) {
@@ -16340,7 +16593,7 @@ async function getSnykReport(reportPath, repoRoot, { skipPrompts = false }) {
16340
16593
  snykLoginSpinner.update({
16341
16594
  text: "\u{1F513} Waiting for Snyk login to complete"
16342
16595
  });
16343
- debug20("no token in the config %s", config2);
16596
+ debug21("no token in the config %s", config2);
16344
16597
  await forkSnyk(["auth"], { display: true });
16345
16598
  snykLoginSpinner.success({ text: "\u{1F513} Login to Snyk Successful" });
16346
16599
  }
@@ -16350,12 +16603,12 @@ async function getSnykReport(reportPath, repoRoot, { skipPrompts = false }) {
16350
16603
  { display: true }
16351
16604
  );
16352
16605
  if (scanOutput.includes("Snyk Code is not supported for org")) {
16353
- debug20("snyk code is not enabled %s", scanOutput);
16606
+ debug21("snyk code is not enabled %s", scanOutput);
16354
16607
  snykSpinner.error({ text: "\u{1F50D} Snyk configuration needed" });
16355
16608
  const answer = await snykArticlePrompt();
16356
- debug20("answer %s", answer);
16609
+ debug21("answer %s", answer);
16357
16610
  if (answer) {
16358
- debug20("opening the browser");
16611
+ debug21("opening the browser");
16359
16612
  await open2(SNYK_ARTICLE_URL);
16360
16613
  }
16361
16614
  console.log(
@@ -16403,9 +16656,9 @@ async function downloadRepo({
16403
16656
  }) {
16404
16657
  const { createSpinner: createSpinner5 } = Spinner2({ ci });
16405
16658
  const repoSpinner = createSpinner5("\u{1F4BE} Downloading Repo").start();
16406
- debug21("download repo %s %s %s", repoUrl, dirname);
16659
+ debug22("download repo %s %s %s", repoUrl, dirname);
16407
16660
  const zipFilePath = path10.join(dirname, "repo.zip");
16408
- debug21("download URL: %s auth headers: %o", downloadUrl, authHeaders);
16661
+ debug22("download URL: %s auth headers: %o", downloadUrl, authHeaders);
16409
16662
  const response = await fetch4(downloadUrl, {
16410
16663
  method: "GET",
16411
16664
  headers: {
@@ -16413,7 +16666,7 @@ async function downloadRepo({
16413
16666
  }
16414
16667
  });
16415
16668
  if (!response.ok) {
16416
- debug21("SCM zipball request failed %s %s", response.body, response.status);
16669
+ debug22("SCM zipball request failed %s %s", response.body, response.status);
16417
16670
  repoSpinner.error({ text: "\u{1F4BE} Repo download failed" });
16418
16671
  throw new Error(`Can't access ${chalk7.bold(repoUrl)}`);
16419
16672
  }
@@ -16427,7 +16680,7 @@ async function downloadRepo({
16427
16680
  if (!repoRoot) {
16428
16681
  throw new Error("Repo root not found");
16429
16682
  }
16430
- debug21("repo root %s", repoRoot);
16683
+ debug22("repo root %s", repoRoot);
16431
16684
  repoSpinner.success({ text: "\u{1F4BE} Repo downloaded successfully" });
16432
16685
  return path10.join(dirname, repoRoot);
16433
16686
  }
@@ -16436,7 +16689,7 @@ var getReportUrl = ({
16436
16689
  projectId,
16437
16690
  fixReportId
16438
16691
  }) => `${WEB_APP_URL}/organization/${organizationId}/project/${projectId}/report/${fixReportId}`;
16439
- var debug21 = Debug21("mobbdev:index");
16692
+ var debug22 = Debug22("mobbdev:index");
16440
16693
  async function runAnalysis(params, options) {
16441
16694
  const tmpObj = tmp2.dirSync({
16442
16695
  unsafeCleanup: true
@@ -16583,7 +16836,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
16583
16836
  polling,
16584
16837
  baselineCommit
16585
16838
  } = params;
16586
- debug21("start %s %s", dirname, repo);
16839
+ debug22("start %s %s", dirname, repo);
16587
16840
  const { createSpinner: createSpinner5 } = Spinner2({ ci });
16588
16841
  skipPrompts = skipPrompts || ci;
16589
16842
  const gqlClient = await getAuthenticatedGQLClient({
@@ -16623,8 +16876,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
16623
16876
  });
16624
16877
  if (!isRepoAvailable) {
16625
16878
  if (ci || !cloudScmLibType || !scmAuthUrl) {
16626
- const errorMessage = scmAuthUrl ? `Cannot access repo ${repo}. Make sure that the repo is accessible and the SCM token configured on Mobb is correct.` : `Cannot access repo ${repo} with the provided token, please visit ${scmAuthUrl} to refresh your source control management system token`;
16627
- throw new Error(errorMessage);
16879
+ const errorMessage3 = scmAuthUrl ? `Cannot access repo ${repo}. Make sure that the repo is accessible and the SCM token configured on Mobb is correct.` : `Cannot access repo ${repo} with the provided token, please visit ${scmAuthUrl} to refresh your source control management system token`;
16880
+ throw new Error(errorMessage3);
16628
16881
  }
16629
16882
  if (cloudScmLibType && scmAuthUrl) {
16630
16883
  await handleScmIntegration(tokenInfo.accessToken, scmAuthUrl, repo);
@@ -16656,8 +16909,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
16656
16909
  );
16657
16910
  }
16658
16911
  const { sha } = getReferenceDataRes.gitReference;
16659
- debug21("project id %s", projectId);
16660
- debug21("default branch %s", reference);
16912
+ debug22("project id %s", projectId);
16913
+ debug22("default branch %s", reference);
16661
16914
  if (command === "scan") {
16662
16915
  reportPath = await getReport(
16663
16916
  {
@@ -16994,7 +17247,7 @@ async function _digestReport({
16994
17247
  text: progressMassages.processingVulnerabilityReportSuccess
16995
17248
  });
16996
17249
  if (polling) {
16997
- debug21(
17250
+ debug22(
16998
17251
  "[_digestReport] Using POLLING mode for analysis state updates (--polling flag enabled)"
16999
17252
  );
17000
17253
  console.log(
@@ -17009,7 +17262,7 @@ async function _digestReport({
17009
17262
  timeoutInMs: VUL_REPORT_DIGEST_TIMEOUT_MS
17010
17263
  });
17011
17264
  } else {
17012
- debug21(
17265
+ debug22(
17013
17266
  "[_digestReport] Using WEBSOCKET mode for analysis state updates (default)"
17014
17267
  );
17015
17268
  console.log(
@@ -17034,9 +17287,9 @@ async function _digestReport({
17034
17287
  });
17035
17288
  return vulnFiles;
17036
17289
  } catch (e) {
17037
- const errorMessage = e instanceof ReportDigestError ? e.getDisplayMessage() : ReportDigestError.defaultMessage;
17290
+ const errorMessage3 = e instanceof ReportDigestError ? e.getDisplayMessage() : ReportDigestError.defaultMessage;
17038
17291
  digestSpinner.error({
17039
- text: errorMessage
17292
+ text: errorMessage3
17040
17293
  });
17041
17294
  throw e;
17042
17295
  }
@@ -17073,7 +17326,7 @@ async function waitForAnaysisAndReviewPr({
17073
17326
  });
17074
17327
  };
17075
17328
  if (polling) {
17076
- debug21(
17329
+ debug22(
17077
17330
  "[waitForAnaysisAndReviewPr] Using POLLING mode for analysis state updates"
17078
17331
  );
17079
17332
  console.log(
@@ -17087,7 +17340,7 @@ async function waitForAnaysisAndReviewPr({
17087
17340
  callbackStates: ["Finished" /* Finished */]
17088
17341
  });
17089
17342
  } else {
17090
- debug21(
17343
+ debug22(
17091
17344
  "[waitForAnaysisAndReviewPr] Using WEBSOCKET mode for analysis state updates"
17092
17345
  );
17093
17346
  console.log(
@@ -17391,11 +17644,11 @@ function throwRepoUrlErrorMessage({
17391
17644
  repoUrl,
17392
17645
  command
17393
17646
  }) {
17394
- const errorMessage = error.issues[error.issues.length - 1]?.message;
17647
+ const errorMessage3 = error.issues[error.issues.length - 1]?.message;
17395
17648
  const formattedErrorMessage = `
17396
17649
  Error: ${chalk9.bold(
17397
17650
  repoUrl
17398
- )} is ${errorMessage}
17651
+ )} is ${errorMessage3}
17399
17652
  Example:
17400
17653
  mobbdev ${command} -r ${chalk9.bold(
17401
17654
  "https://github.com/WebGoat/WebGoat"
@@ -17523,7 +17776,7 @@ import { spawn } from "child_process";
17523
17776
  import { readFileSync, writeFileSync as writeFileSync2 } from "fs";
17524
17777
  import * as os8 from "os";
17525
17778
  import path24 from "path";
17526
- import { setTimeout as sleep2 } from "timers/promises";
17779
+ import { setTimeout as sleep3 } from "timers/promises";
17527
17780
  import Configstore3 from "configstore";
17528
17781
 
17529
17782
  // src/features/analysis/skill_quarantine/runQuarantineCheck.ts
@@ -19410,7 +19663,7 @@ function createLogger(config2) {
19410
19663
  const info = pinoLogger.info.bind(pinoLogger);
19411
19664
  const warn = pinoLogger.warn.bind(pinoLogger);
19412
19665
  const error = pinoLogger.error.bind(pinoLogger);
19413
- const debug23 = pinoLogger.debug.bind(pinoLogger);
19666
+ const debug24 = pinoLogger.debug.bind(pinoLogger);
19414
19667
  function heartbeat(message, data) {
19415
19668
  pinoLogger.info({ data, heartbeat: true }, message);
19416
19669
  }
@@ -19453,7 +19706,7 @@ function createLogger(config2) {
19453
19706
  info,
19454
19707
  warn,
19455
19708
  error,
19456
- debug: debug23,
19709
+ debug: debug24,
19457
19710
  heartbeat,
19458
19711
  timed,
19459
19712
  flushLogs,
@@ -19468,7 +19721,7 @@ function createLogger(config2) {
19468
19721
 
19469
19722
  // src/features/claude_code/hook_logger.ts
19470
19723
  var DD_RUM_TOKEN = true ? "pubf59c0182545bfb4c299175119f1abf9b" : "";
19471
- var CLI_VERSION = true ? "1.4.21" : "unknown";
19724
+ var CLI_VERSION = true ? "1.4.23" : "unknown";
19472
19725
  var NAMESPACE = "mobbdev-claude-code-hook-logs";
19473
19726
  var claudeCodeVersion;
19474
19727
  function buildDdTags() {
@@ -19996,6 +20249,12 @@ async function processTranscript(input, sessionStore, log2, maxEntries = DAEMON_
19996
20249
  sanitize
19997
20250
  })
19998
20251
  );
20252
+ if (result.degenerate?.length) {
20253
+ log2.warn(
20254
+ { data: degenerateRecordsLogFields(result.degenerate) },
20255
+ DEGENERATE_RECORDS_LOG_MESSAGE
20256
+ );
20257
+ }
19999
20258
  if (result.ok) {
20000
20259
  const lastRawEntry = rawEntries[rawEntries.length - 1];
20001
20260
  const cursor = {
@@ -20566,7 +20825,7 @@ async function startDaemon() {
20566
20825
  },
20567
20826
  "daemon poll cycle"
20568
20827
  );
20569
- await sleep2(DAEMON_POLL_INTERVAL_MS);
20828
+ await sleep3(DAEMON_POLL_INTERVAL_MS);
20570
20829
  }
20571
20830
  }
20572
20831
  async function acquirePidFile() {
@@ -21289,7 +21548,7 @@ var McpGQLClient = class extends GQLClient {
21289
21548
  { data }
21290
21549
  );
21291
21550
  if (!data.analysis?.state || data.analysis?.state === "Failed" /* Failed */) {
21292
- const errorMessage = data.analysis?.failReason || `Analysis failed with id: ${data.analysis?.id}`;
21551
+ const errorMessage3 = data.analysis?.failReason || `Analysis failed with id: ${data.analysis?.id}`;
21293
21552
  logError(`[${scanContext}] GraphQL: Analysis failed`, {
21294
21553
  analysisId: data.analysis?.id,
21295
21554
  state: data.analysis?.state,
@@ -21297,7 +21556,7 @@ var McpGQLClient = class extends GQLClient {
21297
21556
  ...this.getErrorContext()
21298
21557
  });
21299
21558
  subscription.unsubscribe();
21300
- reject(new Error(errorMessage));
21559
+ reject(new Error(errorMessage3));
21301
21560
  return;
21302
21561
  }
21303
21562
  if (callbackStates.includes(data.analysis?.state)) {
@@ -21409,17 +21668,17 @@ var McpGQLClient = class extends GQLClient {
21409
21668
  });
21410
21669
  return createdProject.createProject.projectId;
21411
21670
  } catch (createError) {
21412
- const errorMessage = createError instanceof Error ? createError.message : String(createError);
21413
- const isConstraintViolation = errorMessage.includes(
21671
+ const errorMessage3 = createError instanceof Error ? createError.message : String(createError);
21672
+ const isConstraintViolation = errorMessage3.includes(
21414
21673
  "duplicate key value violates unique constraint"
21415
- ) && errorMessage.includes("project_name_organization_id_key");
21674
+ ) && errorMessage3.includes("project_name_organization_id_key");
21416
21675
  if (isConstraintViolation) {
21417
21676
  logDebug(
21418
21677
  "[GraphQL] Project creation failed due to constraint violation, retrying fetch",
21419
21678
  {
21420
21679
  organizationId: organization.id,
21421
21680
  projectName,
21422
- error: errorMessage
21681
+ error: errorMessage3
21423
21682
  }
21424
21683
  );
21425
21684
  const retryOrgAndProjectRes = await this._clientSdk.getLastOrgAndNamedProject({
@@ -22829,8 +23088,8 @@ var McpServer = class {
22829
23088
  });
22830
23089
  return serializedResponse;
22831
23090
  } catch (error) {
22832
- const errorMessage = error instanceof Error ? error.message : String(error);
22833
- logError(`Error executing tool ${name}: ${errorMessage}`, {
23091
+ const errorMessage3 = error instanceof Error ? error.message : String(error);
23092
+ logError(`Error executing tool ${name}: ${errorMessage3}`, {
22834
23093
  error,
22835
23094
  toolName: name,
22836
23095
  args
@@ -22885,8 +23144,8 @@ var McpServer = class {
22885
23144
  });
22886
23145
  return response;
22887
23146
  } catch (error) {
22888
- const errorMessage = error instanceof Error ? error.message : String(error);
22889
- logError(`Error generating prompt ${name}: ${errorMessage}`, {
23147
+ const errorMessage3 = error instanceof Error ? error.message : String(error);
23148
+ logError(`Error generating prompt ${name}: ${errorMessage3}`, {
22890
23149
  error,
22891
23150
  promptName: name,
22892
23151
  args
@@ -23023,8 +23282,8 @@ var BasePrompt = class {
23023
23282
  const message = e.message === "Required" ? `Missing required argument '${fieldPath}'` : `Invalid value for '${fieldPath}': ${e.message}`;
23024
23283
  return message;
23025
23284
  });
23026
- const errorMessage = `Invalid arguments: ${errorDetails.join(", ")}`;
23027
- throw new Error(errorMessage);
23285
+ const errorMessage3 = `Invalid arguments: ${errorDetails.join(", ")}`;
23286
+ throw new Error(errorMessage3);
23028
23287
  }
23029
23288
  throw error;
23030
23289
  }
@@ -24733,9 +24992,9 @@ async function validatePath(inputPath) {
24733
24992
  logDebug("Stored validated path in WorkspaceService", { inputPath });
24734
24993
  return { isValid: true, path: inputPath };
24735
24994
  } catch (error) {
24736
- const errorMessage = `Path does not exist or is not accessible: ${inputPath}`;
24737
- logError(errorMessage, { error });
24738
- return { isValid: false, error: errorMessage, path: inputPath };
24995
+ const errorMessage3 = `Path does not exist or is not accessible: ${inputPath}`;
24996
+ logError(errorMessage3, { error });
24997
+ return { isValid: false, error: errorMessage3, path: inputPath };
24739
24998
  }
24740
24999
  }
24741
25000
 
@@ -24773,8 +25032,8 @@ var BaseTool = class {
24773
25032
  const message = e.message === "Required" ? `Missing required parameter '${fieldPath}'` : `Invalid value for '${fieldPath}': ${e.message}`;
24774
25033
  return message;
24775
25034
  });
24776
- const errorMessage = `Invalid arguments: ${errorDetails.join(", ")}`;
24777
- throw new Error(errorMessage);
25035
+ const errorMessage3 = `Invalid arguments: ${errorDetails.join(", ")}`;
25036
+ throw new Error(errorMessage3);
24778
25037
  }
24779
25038
  throw error;
24780
25039
  }
@@ -25746,9 +26005,9 @@ var LocalMobbFolderService = class {
25746
26005
  });
25747
26006
  return mobbFolderPath;
25748
26007
  } catch (error) {
25749
- const errorMessage = `Failed to get/create .mobb folder: ${error}`;
25750
- logError(errorMessage, { repoPath: this.repoPath, error });
25751
- throw new Error(errorMessage);
26008
+ const errorMessage3 = `Failed to get/create .mobb folder: ${error}`;
26009
+ logError(errorMessage3, { repoPath: this.repoPath, error });
26010
+ throw new Error(errorMessage3);
25752
26011
  }
25753
26012
  }
25754
26013
  /**
@@ -25909,8 +26168,8 @@ var LocalMobbFolderService = class {
25909
26168
  message: `Patch saved successfully as ${uniqueFileName}`
25910
26169
  };
25911
26170
  } catch (error) {
25912
- const errorMessage = `Failed to save patch for fix ${fix.id}: ${error}`;
25913
- logError(errorMessage, {
26171
+ const errorMessage3 = `Failed to save patch for fix ${fix.id}: ${error}`;
26172
+ logError(errorMessage3, {
25914
26173
  fixId: fix.id,
25915
26174
  fileName,
25916
26175
  severity,
@@ -25920,8 +26179,8 @@ var LocalMobbFolderService = class {
25920
26179
  });
25921
26180
  return {
25922
26181
  success: false,
25923
- error: errorMessage,
25924
- message: errorMessage
26182
+ error: errorMessage3,
26183
+ message: errorMessage3
25925
26184
  };
25926
26185
  }
25927
26186
  }
@@ -26011,12 +26270,12 @@ var LocalMobbFolderService = class {
26011
26270
  message: `Fix details logged to patchInfo.md`
26012
26271
  };
26013
26272
  } catch (error) {
26014
- const errorMessage = `Failed to log patch info: ${error}`;
26015
- logError(errorMessage, { fixId: fix.id, error });
26273
+ const errorMessage3 = `Failed to log patch info: ${error}`;
26274
+ logError(errorMessage3, { fixId: fix.id, error });
26016
26275
  return {
26017
26276
  success: false,
26018
- error: errorMessage,
26019
- message: errorMessage
26277
+ error: errorMessage3,
26278
+ message: errorMessage3
26020
26279
  };
26021
26280
  }
26022
26281
  }
@@ -26711,12 +26970,12 @@ var PatchApplicationService = class {
26711
26970
  failedFixes.push({ fix, error: result.error || "Unknown error" });
26712
26971
  }
26713
26972
  } catch (error) {
26714
- const errorMessage = error instanceof Error ? error.message : String(error);
26973
+ const errorMessage3 = error instanceof Error ? error.message : String(error);
26715
26974
  logError(`[${scanContext}] Failed to apply standalone fix ${fix.id}`, {
26716
- error: errorMessage,
26975
+ error: errorMessage3,
26717
26976
  issueType: fix.safeIssueType
26718
26977
  });
26719
- failedFixes.push({ fix, error: errorMessage });
26978
+ failedFixes.push({ fix, error: errorMessage3 });
26720
26979
  }
26721
26980
  }
26722
26981
  }
@@ -26767,17 +27026,17 @@ var PatchApplicationService = class {
26767
27026
  return { success: false, error: result.error };
26768
27027
  }
26769
27028
  } catch (error) {
26770
- const errorMessage = error instanceof Error ? error.message : String(error);
27029
+ const errorMessage3 = error instanceof Error ? error.message : String(error);
26771
27030
  logInfo(
26772
27031
  `[${scanContext}] Fix ${fix.id} threw exception for ${targetFile}, trying next option if available`,
26773
27032
  {
26774
- error: errorMessage,
27033
+ error: errorMessage3,
26775
27034
  issueType: fix.safeIssueType,
26776
27035
  attemptNumber,
26777
27036
  remainingOptions: totalAttempts - attemptNumber
26778
27037
  }
26779
27038
  );
26780
- return { success: false, error: errorMessage };
27039
+ return { success: false, error: errorMessage3 };
26781
27040
  }
26782
27041
  }
26783
27042
  /**
@@ -27281,18 +27540,18 @@ var PatchApplicationService = class {
27281
27540
  );
27282
27541
  return { success: true };
27283
27542
  } catch (patchError) {
27284
- const errorMessage = patchError instanceof Error ? patchError.message : String(patchError);
27543
+ const errorMessage3 = patchError instanceof Error ? patchError.message : String(patchError);
27285
27544
  logError(
27286
27545
  `[${scanContext}] In-memory patch application failed for fix ${fix.id}`,
27287
27546
  {
27288
- errorMessage,
27547
+ errorMessage: errorMessage3,
27289
27548
  patchErrorType: patchError instanceof Error ? patchError.name : typeof patchError,
27290
27549
  targetFiles
27291
27550
  }
27292
27551
  );
27293
27552
  return {
27294
27553
  success: false,
27295
- error: `Patch application failed: ${errorMessage}`
27554
+ error: `Patch application failed: ${errorMessage3}`
27296
27555
  };
27297
27556
  }
27298
27557
  }
@@ -27912,22 +28171,22 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
27912
28171
  this.updateFilesScanTimestamps(filesToScan);
27913
28172
  this.isInitialScanComplete = true;
27914
28173
  } catch (error) {
27915
- const errorMessage = error.message;
27916
- if (errorMessage.includes("Authentication failed") || errorMessage.includes("access-denied") || errorMessage.includes("Authentication hook unauthorized")) {
28174
+ const errorMessage3 = error.message;
28175
+ if (errorMessage3.includes("Authentication failed") || errorMessage3.includes("access-denied") || errorMessage3.includes("Authentication hook unauthorized")) {
27917
28176
  logError(
27918
28177
  `[${scanContext}] Periodic scan skipped due to authentication failure. Please re-authenticate by running a manual scan.`,
27919
28178
  {
27920
- error: errorMessage
28179
+ error: errorMessage3
27921
28180
  }
27922
28181
  );
27923
28182
  this.hasAuthenticationFailed = true;
27924
28183
  return;
27925
28184
  }
27926
- if (errorMessage.includes("ReportInitializationError")) {
28185
+ if (errorMessage3.includes("ReportInitializationError")) {
27927
28186
  logError(
27928
28187
  `[${scanContext}] Periodic scan failed during report initialization`,
27929
28188
  {
27930
- error: errorMessage
28189
+ error: errorMessage3
27931
28190
  }
27932
28191
  );
27933
28192
  return;
@@ -28162,12 +28421,12 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
28162
28421
  const loginContext = createMcpLoginContext("check_new_fixes");
28163
28422
  this.gqlClient = await createAuthenticatedMcpGQLClient({ loginContext });
28164
28423
  } catch (error) {
28165
- const errorMessage = error.message;
28166
- if (errorMessage.includes("Authentication failed") || errorMessage.includes("access-denied") || errorMessage.includes("Authentication hook unauthorized")) {
28424
+ const errorMessage3 = error.message;
28425
+ if (errorMessage3.includes("Authentication failed") || errorMessage3.includes("access-denied") || errorMessage3.includes("Authentication hook unauthorized")) {
28167
28426
  logError(
28168
28427
  `[${scanContext}] Failed to create authenticated client due to authentication failure`,
28169
28428
  {
28170
- error: errorMessage
28429
+ error: errorMessage3
28171
28430
  }
28172
28431
  );
28173
28432
  this.hasAuthenticationFailed = true;
@@ -30037,13 +30296,13 @@ var parseArgs = async (args) => {
30037
30296
  };
30038
30297
 
30039
30298
  // src/index.ts
30040
- var debug22 = Debug22("mobbdev:index");
30299
+ var debug23 = Debug23("mobbdev:index");
30041
30300
  async function run() {
30042
30301
  return parseArgs(hideBin(process.argv));
30043
30302
  }
30044
30303
  (async () => {
30045
30304
  try {
30046
- debug22("Bugsy CLI v%s running...", packageJson.version);
30305
+ debug23("Bugsy CLI v%s running...", packageJson.version);
30047
30306
  await run();
30048
30307
  process.exit(0);
30049
30308
  } catch (err) {