mobbdev 1.4.20 → 1.4.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/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
@@ -9325,8 +9327,8 @@ function handleGitHubError(error, scmType = "GitHub" /* GitHub */) {
9325
9327
  (Number.parseInt(headers["x-ratelimit-reset"], 10) * 1e3 - Date.now()) / 1e3
9326
9328
  )
9327
9329
  ) : 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")) {
9330
+ const errorMessage3 = errorObj.message || (error instanceof Error ? error.message : String(error));
9331
+ if (status === 403 && retryAfter !== void 0 || errorMessage3.toLowerCase().includes("rate limit") || errorMessage3.toLowerCase().includes("api rate limit exceeded")) {
9330
9332
  throw new RateLimitError(
9331
9333
  "GitHub API rate limit exceeded",
9332
9334
  scmType,
@@ -9354,7 +9356,7 @@ function handleGitHubError(error, scmType = "GitHub" /* GitHub */) {
9354
9356
  const errorCode = errorObj.code || errorObj.response?.code;
9355
9357
  if (errorCode === "ECONNREFUSED" || errorCode === "ETIMEDOUT" || errorCode === "ENOTFOUND" || errorCode === "EAI_AGAIN") {
9356
9358
  throw new NetworkError(
9357
- `GitHub network error: ${errorMessage}`,
9359
+ `GitHub network error: ${errorMessage3}`,
9358
9360
  scmType,
9359
9361
  errorCode
9360
9362
  );
@@ -9362,7 +9364,7 @@ function handleGitHubError(error, scmType = "GitHub" /* GitHub */) {
9362
9364
  if (error instanceof RateLimitError || error instanceof InvalidAccessTokenError || error instanceof ScmBadCredentialsError || error instanceof InvalidRepoUrlError || error instanceof NetworkError || error instanceof InvalidUrlPatternError) {
9363
9365
  throw error;
9364
9366
  }
9365
- throw new Error(`GitHub API error: ${errorMessage}`);
9367
+ throw new Error(`GitHub API error: ${errorMessage3}`);
9366
9368
  }
9367
9369
  async function githubValidateParams(url, accessToken) {
9368
9370
  try {
@@ -13112,7 +13114,7 @@ import path10 from "path";
13112
13114
  import { env as env2 } from "process";
13113
13115
  import { pipeline } from "stream/promises";
13114
13116
  import chalk7 from "chalk";
13115
- import Debug21 from "debug";
13117
+ import Debug22 from "debug";
13116
13118
  import extract from "extract-zip";
13117
13119
  import { createSpinner as createSpinner4 } from "nanospinner";
13118
13120
  import fetch4 from "node-fetch";
@@ -13123,7 +13125,7 @@ import { z as z31 } from "zod";
13123
13125
  // src/commands/AuthManager.ts
13124
13126
  import crypto from "crypto";
13125
13127
  import os3 from "os";
13126
- import Debug10 from "debug";
13128
+ import Debug11 from "debug";
13127
13129
  import open from "open";
13128
13130
 
13129
13131
  // src/features/analysis/graphql/gql.ts
@@ -13778,11 +13780,11 @@ var GQLClient = class {
13778
13780
  {
13779
13781
  next: async (data) => {
13780
13782
  if (!data.analysis?.state || data.analysis?.state === "Failed" /* Failed */) {
13781
- const errorMessage = data.analysis?.failReason || `Analysis failed with id: ${data.analysis?.id}`;
13783
+ const errorMessage3 = data.analysis?.failReason || `Analysis failed with id: ${data.analysis?.id}`;
13782
13784
  subscription.unsubscribe();
13783
13785
  reject(
13784
13786
  new ReportDigestError(
13785
- errorMessage,
13787
+ errorMessage3,
13786
13788
  data.analysis?.failReason ?? ""
13787
13789
  )
13788
13790
  );
@@ -13846,9 +13848,9 @@ var GQLClient = class {
13846
13848
  `[pollForAnalysisState] Poll #${pollCount} - current state: ${analysis.state}`
13847
13849
  );
13848
13850
  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 ?? "");
13851
+ const errorMessage3 = analysis.failReason || `Analysis failed with id: ${analysis.id}`;
13852
+ debug7(`[pollForAnalysisState] Analysis failed: ${errorMessage3}`);
13853
+ throw new ReportDigestError(errorMessage3, analysis.failReason ?? "");
13852
13854
  }
13853
13855
  if (callbackStates.includes(analysis.state)) {
13854
13856
  debug7(
@@ -13949,7 +13951,7 @@ var GQLClient = class {
13949
13951
  };
13950
13952
 
13951
13953
  // src/features/analysis/graphql/tracy-batch-upload.ts
13952
- import Debug9 from "debug";
13954
+ import Debug10 from "debug";
13953
13955
 
13954
13956
  // src/args/commands/upload_ai_blame.ts
13955
13957
  import fsPromises2 from "fs/promises";
@@ -14068,12 +14070,28 @@ init_urlParser2();
14068
14070
  import Debug8 from "debug";
14069
14071
  import fetch3, { File, fileFrom, FormData } from "node-fetch";
14070
14072
  var debug9 = Debug8("mobbdev:upload-file");
14073
+ var S3UploadError = class extends Error {
14074
+ constructor(status, s3Code, s3Message) {
14075
+ super(`Failed to upload the file: ${status}`);
14076
+ this.status = status;
14077
+ this.s3Code = s3Code;
14078
+ this.s3Message = s3Message;
14079
+ this.name = "S3UploadError";
14080
+ }
14081
+ };
14082
+ function parseS3ErrorBody(body) {
14083
+ return {
14084
+ code: body.match(/<Code>([^<]+)<\/Code>/)?.[1],
14085
+ message: body.match(/<Message>([^<]+)<\/Message>/)?.[1]
14086
+ };
14087
+ }
14071
14088
  async function uploadFile({
14072
14089
  file,
14073
14090
  url,
14074
14091
  uploadKey,
14075
14092
  uploadFields,
14076
- logger: logger3
14093
+ logger: logger3,
14094
+ signal
14077
14095
  }) {
14078
14096
  const logInfo2 = logger3 || ((_message, _data) => {
14079
14097
  });
@@ -14095,18 +14113,44 @@ async function uploadFile({
14095
14113
  } else {
14096
14114
  debug9("upload file from buffer");
14097
14115
  logInfo2(`FileUpload: upload file from buffer`);
14098
- form.append("file", new File([new Uint8Array(file)], "file"));
14116
+ form.append(
14117
+ "file",
14118
+ new File(
14119
+ [
14120
+ new Uint8Array(
14121
+ file.buffer,
14122
+ file.byteOffset,
14123
+ file.byteLength
14124
+ )
14125
+ ],
14126
+ "file"
14127
+ )
14128
+ );
14099
14129
  }
14100
14130
  const agent = getProxyAgent(url);
14101
14131
  const response = await fetch3(url, {
14102
14132
  method: "POST",
14103
14133
  body: form,
14104
- agent
14134
+ agent,
14135
+ signal
14105
14136
  });
14106
14137
  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}`);
14138
+ let bodyText = "";
14139
+ try {
14140
+ bodyText = await response.text();
14141
+ } catch {
14142
+ }
14143
+ const { code, message } = parseS3ErrorBody(bodyText);
14144
+ debug9(
14145
+ "error from S3 status=%d code=%s message=%s",
14146
+ response.status,
14147
+ code,
14148
+ message
14149
+ );
14150
+ logInfo2(
14151
+ `FileUpload: error from S3 status=${response.status} code=${code ?? "unknown"}`
14152
+ );
14153
+ throw new S3UploadError(response.status, code, message);
14110
14154
  }
14111
14155
  debug9("upload file done");
14112
14156
  logInfo2(`FileUpload: upload file done`);
@@ -14772,39 +14816,240 @@ function withTimeout(promise, ms, label) {
14772
14816
  ]);
14773
14817
  }
14774
14818
 
14819
+ // src/features/analysis/graphql/s3-raw-data-upload.ts
14820
+ import { setTimeout as sleep2 } from "timers/promises";
14821
+ import Debug9 from "debug";
14822
+ var debug10 = Debug9("mobbdev:tracy-s3-upload");
14823
+ var S3_OP_TIMEOUT_MS = 3e4;
14824
+ var MAX_TOTAL_S3_UPLOAD_MS = 12e4;
14825
+ var MAX_CONCURRENT_S3_UPLOADS = 5;
14826
+ var URL_REFRESH_MS = 20 * 60 * 1e3;
14827
+ var MAX_UPLOAD_ATTEMPTS = 3;
14828
+ var RETRY_BACKOFF_MS = 500;
14829
+ var MAX_S3_MESSAGE_CHARS = 120;
14830
+ var errorMessage = (e) => e instanceof Error ? e.message : String(e);
14831
+ function classifyUploadError(reason) {
14832
+ if (reason instanceof S3UploadError) {
14833
+ return {
14834
+ status: reason.status,
14835
+ s3Code: reason.s3Code,
14836
+ s3Message: reason.s3Message,
14837
+ retryable: reason.status !== 400 && reason.status !== 401
14838
+ };
14839
+ }
14840
+ return { retryable: true };
14841
+ }
14842
+ function createPresignedUrlProvider(client) {
14843
+ let creds = null;
14844
+ let fetchedAt = 0;
14845
+ const fetchFresh = async () => {
14846
+ let res;
14847
+ try {
14848
+ res = await withTimeout(
14849
+ client.getTracyRawDataUploadUrl(),
14850
+ S3_OP_TIMEOUT_MS,
14851
+ "[step:s3-url] getTracyRawDataUploadUrl"
14852
+ );
14853
+ } catch (err) {
14854
+ throw new Error(
14855
+ `[step:s3-url] Failed to fetch S3 upload URL: ${errorMessage(err)}`
14856
+ );
14857
+ }
14858
+ const { url, uploadFieldsJSON, keyPrefix } = res.getTracyRawDataUploadUrl;
14859
+ if (!url || !uploadFieldsJSON || !keyPrefix) {
14860
+ throw new Error(
14861
+ `[step:s3-url] Missing S3 upload fields (url=${!!url}, fields=${!!uploadFieldsJSON}, prefix=${!!keyPrefix})`
14862
+ );
14863
+ }
14864
+ try {
14865
+ return { url, uploadFields: JSON.parse(uploadFieldsJSON), keyPrefix };
14866
+ } catch {
14867
+ throw new Error("[step:s3-url] Malformed uploadFieldsJSON from server");
14868
+ }
14869
+ };
14870
+ const refresh = async () => {
14871
+ creds = await fetchFresh();
14872
+ fetchedAt = Date.now();
14873
+ return creds;
14874
+ };
14875
+ return {
14876
+ refresh,
14877
+ /** Cached creds, refreshed if missing or near expiry. */
14878
+ async current() {
14879
+ if (!creds || Date.now() - fetchedAt > URL_REFRESH_MS) return refresh();
14880
+ return creds;
14881
+ }
14882
+ };
14883
+ }
14884
+ async function uploadRawDataToS3(client, entries, serializedByIndex) {
14885
+ const uploaded = /* @__PURE__ */ new Map();
14886
+ const urls = createPresignedUrlProvider(client);
14887
+ debug10(
14888
+ "[step:s3-upload] Uploading %d files to S3 (concurrency=%d)",
14889
+ entries.length,
14890
+ MAX_CONCURRENT_S3_UPLOADS
14891
+ );
14892
+ const start = Date.now();
14893
+ const deadline = start + MAX_TOTAL_S3_UPLOAD_MS;
14894
+ const uploadPass = async (pass) => {
14895
+ const failures = [];
14896
+ for (let i = 0; i < pass.length; i += MAX_CONCURRENT_S3_UPLOADS) {
14897
+ if (Date.now() > deadline) {
14898
+ for (const entry of pass.slice(i)) {
14899
+ failures.push({
14900
+ entry,
14901
+ kind: { retryable: false },
14902
+ message: `[step:s3-upload] aborted: exceeded ${MAX_TOTAL_S3_UPLOAD_MS}ms total upload budget`
14903
+ });
14904
+ }
14905
+ break;
14906
+ }
14907
+ const { url, uploadFields, keyPrefix } = await urls.current();
14908
+ const chunk = pass.slice(i, i + MAX_CONCURRENT_S3_UPLOADS);
14909
+ const settled = await Promise.allSettled(
14910
+ chunk.map(async (entry) => {
14911
+ const rawDataJson = serializedByIndex.get(entry.index);
14912
+ if (!rawDataJson) {
14913
+ debug10("No serialized rawData for recordId=%s", entry.recordId);
14914
+ return;
14915
+ }
14916
+ const uploadKey = `${keyPrefix}${entry.recordId}.json`;
14917
+ const signal = AbortSignal.timeout(S3_OP_TIMEOUT_MS);
14918
+ try {
14919
+ await uploadFile({
14920
+ file: Buffer.from(rawDataJson, "utf-8"),
14921
+ url,
14922
+ uploadKey,
14923
+ uploadFields,
14924
+ signal
14925
+ });
14926
+ } catch (err) {
14927
+ if (signal.aborted) {
14928
+ throw new Error(
14929
+ `[step:s3-upload] uploadFile ${entry.recordId} timed out after ${S3_OP_TIMEOUT_MS}ms`
14930
+ );
14931
+ }
14932
+ throw err;
14933
+ }
14934
+ uploaded.set(entry.index, uploadKey);
14935
+ serializedByIndex.delete(entry.index);
14936
+ })
14937
+ );
14938
+ settled.forEach((outcome, idx) => {
14939
+ if (outcome.status === "rejected") {
14940
+ failures.push({
14941
+ entry: chunk[idx],
14942
+ kind: classifyUploadError(outcome.reason),
14943
+ message: errorMessage(outcome.reason)
14944
+ });
14945
+ }
14946
+ });
14947
+ }
14948
+ return failures;
14949
+ };
14950
+ const failuresByRecord = /* @__PURE__ */ new Map();
14951
+ try {
14952
+ await urls.refresh();
14953
+ let pending = entries;
14954
+ for (let attempt = 1; attempt <= MAX_UPLOAD_ATTEMPTS; attempt++) {
14955
+ const failures = await uploadPass(pending);
14956
+ for (const entry of pending) failuresByRecord.delete(entry.recordId);
14957
+ for (const failure of failures)
14958
+ failuresByRecord.set(failure.entry.recordId, failure);
14959
+ const retryable = failures.filter((failure) => failure.kind.retryable);
14960
+ if (retryable.length === 0 || attempt === MAX_UPLOAD_ATTEMPTS || Date.now() > deadline) {
14961
+ break;
14962
+ }
14963
+ debug10(
14964
+ "[step:s3-upload] attempt %d failed for %d record(s); refreshing URL and retrying",
14965
+ attempt,
14966
+ retryable.length
14967
+ );
14968
+ await sleep2(RETRY_BACKOFF_MS * attempt);
14969
+ await urls.refresh();
14970
+ pending = retryable.map((failure) => failure.entry);
14971
+ }
14972
+ } catch (err) {
14973
+ return { uploaded, errors: [errorMessage(err)] };
14974
+ }
14975
+ debug10("[perf] s3-upload %d files: %dms", entries.length, Date.now() - start);
14976
+ const missing = entries.filter((entry) => !uploaded.has(entry.index));
14977
+ if (missing.length === 0) {
14978
+ debug10("[step:s3-upload] S3 uploads complete");
14979
+ return { uploaded, errors: null };
14980
+ }
14981
+ const detail = missing.map((entry) => {
14982
+ const failure = failuresByRecord.get(entry.recordId);
14983
+ const code = failure?.kind.s3Code ? ` ${failure.kind.s3Code}` : "";
14984
+ const message = failure?.kind.s3Message ? ` "${failure.kind.s3Message.slice(0, MAX_S3_MESSAGE_CHARS)}"` : "";
14985
+ return `[step:s3-upload] ${entry.recordId}: HTTP ${failure?.kind.status ?? "n/a"}${code}${message} (${failure?.message ?? "unknown"})`;
14986
+ });
14987
+ debug10(
14988
+ "[step:s3-upload] Records missing S3 keys: %O",
14989
+ missing.map((entry) => entry.recordId)
14990
+ );
14991
+ return {
14992
+ uploaded,
14993
+ errors: [
14994
+ `[step:s3-upload] Failed to upload rawData for ${missing.length} record(s): ${missing.map((entry) => entry.recordId).join(", ")}`,
14995
+ ...detail
14996
+ ]
14997
+ };
14998
+ }
14999
+
14775
15000
  // src/features/analysis/graphql/tracy-batch-upload.ts
14776
- var debug10 = Debug9("mobbdev:tracy-batch-upload");
15001
+ var debug11 = Debug10("mobbdev:tracy-batch-upload");
15002
+ var errorMessage2 = (e) => e instanceof Error ? e.message : String(e);
14777
15003
  function timedStep(label, fn) {
14778
15004
  const start = Date.now();
14779
15005
  const result = fn();
14780
15006
  const maybePromise = result instanceof Promise ? result : Promise.resolve(result);
14781
15007
  return maybePromise.then(
14782
15008
  (val) => {
14783
- debug10("[perf] %s: %dms", label, Date.now() - start);
15009
+ debug11("[perf] %s: %dms", label, Date.now() - start);
14784
15010
  return val;
14785
15011
  },
14786
15012
  (err) => {
14787
- debug10("[perf] %s FAILED: %dms", label, Date.now() - start);
15013
+ debug11("[perf] %s FAILED: %dms", label, Date.now() - start);
14788
15014
  throw err;
14789
15015
  }
14790
15016
  );
14791
15017
  }
14792
15018
  var BATCH_TIMEOUT_MS = 3e4;
15019
+ var MIN_RAWDATA_BYTES = 5;
15020
+ var MAX_DEGENERATE_SAMPLE_CHARS = 500;
15021
+ var REDACTED_SAMPLE = "<redacted: sanitization disabled>";
15022
+ var MAX_DEGENERATE_LOG_RECORDS = 20;
15023
+ var DEGENERATE_RECORDS_LOG_MESSAGE = "Skipped empty/degenerate rawData records before S3 upload";
15024
+ function degenerateRecordsLogFields(degenerate) {
15025
+ return {
15026
+ count: degenerate.length,
15027
+ records: degenerate.slice(0, MAX_DEGENERATE_LOG_RECORDS)
15028
+ };
15029
+ }
15030
+ function isStructurallyEmptyPayload(serialized) {
15031
+ const trimmed = serialized.trim();
15032
+ if (trimmed === "" || trimmed === "null" || trimmed === '""') return true;
15033
+ const isObject = trimmed.startsWith("{") && trimmed.endsWith("}");
15034
+ const isArray = trimmed.startsWith("[") && trimmed.endsWith("]");
15035
+ if (isObject || isArray) return trimmed.slice(1, -1).trim() === "";
15036
+ return false;
15037
+ }
14793
15038
  async function sanitizeRawData(rawData) {
14794
15039
  const start = Date.now();
14795
15040
  try {
14796
15041
  const sanitized = await sanitizeData(rawData);
14797
15042
  const serialized = JSON.stringify(sanitized);
14798
- debug10(
15043
+ debug11(
14799
15044
  "[perf] sanitizeRawData: %dms (%d bytes)",
14800
15045
  Date.now() - start,
14801
15046
  serialized.length
14802
15047
  );
14803
15048
  return serialized;
14804
15049
  } catch (err) {
14805
- console.warn(
14806
- "[tracy] sanitizeRawData failed, falling back to unsanitized:",
14807
- err.message
15050
+ debug11(
15051
+ "[tracy] sanitizeRawData failed, falling back to unsanitized: %s",
15052
+ errorMessage2(err)
14808
15053
  );
14809
15054
  return JSON.stringify(rawData);
14810
15055
  }
@@ -14814,12 +15059,13 @@ async function prepareAndSendTracyRecords(client, rawRecords, workingDir, option
14814
15059
  const defaultClientVersion = packageJson.version;
14815
15060
  const shouldSanitize = options?.sanitize ?? true;
14816
15061
  const defaults = workingDir != null ? await readRepoState(workingDir) : { repositoryUrl: null, branch: null, commitSha: null };
14817
- debug10(
15062
+ debug11(
14818
15063
  "[step:sanitize] %s %d records",
14819
15064
  shouldSanitize ? "Sanitizing" : "Serializing",
14820
15065
  rawRecords.length
14821
15066
  );
14822
15067
  const serializedRawDataByIndex = /* @__PURE__ */ new Map();
15068
+ const degenerate = [];
14823
15069
  const records = await timedStep(
14824
15070
  `${shouldSanitize ? "sanitize" : "serialize"} ${rawRecords.length} records`,
14825
15071
  async () => {
@@ -14828,7 +15074,19 @@ async function prepareAndSendTracyRecords(client, rawRecords, workingDir, option
14828
15074
  const record = rawRecords[index];
14829
15075
  if (record.rawData != null && record.rawDataS3Key == null) {
14830
15076
  const serialized = shouldSanitize ? await sanitizeRawData(record.rawData) : JSON.stringify(record.rawData);
14831
- serializedRawDataByIndex.set(index, serialized);
15077
+ const bytes = Buffer.byteLength(serialized, "utf-8");
15078
+ if (bytes < MIN_RAWDATA_BYTES || isStructurallyEmptyPayload(serialized)) {
15079
+ degenerate.push({
15080
+ recordId: record.recordId,
15081
+ platform: record.platform,
15082
+ filePath: record.filePath,
15083
+ editType: record.editType,
15084
+ bytes,
15085
+ sample: shouldSanitize ? serialized.slice(0, MAX_DEGENERATE_SAMPLE_CHARS) : REDACTED_SAMPLE
15086
+ });
15087
+ } else {
15088
+ serializedRawDataByIndex.set(index, serialized);
15089
+ }
14832
15090
  }
14833
15091
  const { rawData: _rawData, ...rest } = record;
14834
15092
  results.push({
@@ -14844,104 +15102,19 @@ async function prepareAndSendTracyRecords(client, rawRecords, workingDir, option
14844
15102
  return results;
14845
15103
  }
14846
15104
  );
14847
- const recordsWithRawData = rawRecords.map((r, i) => ({ recordId: r.recordId, index: i })).filter((entry) => serializedRawDataByIndex.has(entry.index));
15105
+ const degenerateOut = degenerate.length > 0 ? degenerate : void 0;
15106
+ const finish = (result) => ({ ...result, degenerate: degenerateOut });
15107
+ const recordsWithRawData = rawRecords.map((record, index) => ({ recordId: record.recordId, index })).filter((entry) => serializedRawDataByIndex.has(entry.index));
14848
15108
  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
14891
- );
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
15109
+ const { uploaded, errors } = await uploadRawDataToS3(
15110
+ client,
15111
+ recordsWithRawData,
15112
+ serializedRawDataByIndex
14923
15113
  );
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");
15114
+ for (const [index, key] of uploaded) records[index].rawDataS3Key = key;
15115
+ if (errors) return finish({ ok: false, errors });
14943
15116
  }
14944
- debug10("[step:gql-submit] Submitting %d records via GraphQL", records.length);
15117
+ debug11("[step:gql-submit] Submitting %d records via GraphQL", records.length);
14945
15118
  try {
14946
15119
  const result = await timedStep(
14947
15120
  `gql-submit ${records.length} records`,
@@ -14952,21 +15125,21 @@ async function prepareAndSendTracyRecords(client, rawRecords, workingDir, option
14952
15125
  )
14953
15126
  );
14954
15127
  if (result.uploadTracyRecords.status !== "OK") {
14955
- return {
15128
+ return finish({
14956
15129
  ok: false,
14957
15130
  errors: [
14958
15131
  `[step:gql-submit] Server rejected: ${result.uploadTracyRecords.error ?? "Unknown server error"}`
14959
15132
  ]
14960
- };
15133
+ });
14961
15134
  }
14962
15135
  } catch (err) {
14963
- debug10("[step:gql-submit] Upload failed: %s", err.message);
14964
- return {
15136
+ debug11("[step:gql-submit] Upload failed: %s", errorMessage2(err));
15137
+ return finish({
14965
15138
  ok: false,
14966
- errors: [`[step:gql-submit] ${err.message}`]
14967
- };
15139
+ errors: [`[step:gql-submit] ${errorMessage2(err)}`]
15140
+ });
14968
15141
  }
14969
- return { ok: true, errors: null };
15142
+ return finish({ ok: true, errors: null });
14970
15143
  }
14971
15144
 
14972
15145
  // src/mcp/services/types.ts
@@ -15002,7 +15175,7 @@ function buildLoginUrl(baseUrl, loginId, hostname, context) {
15002
15175
  }
15003
15176
 
15004
15177
  // src/commands/AuthManager.ts
15005
- var debug11 = Debug10("mobbdev:auth");
15178
+ var debug12 = Debug11("mobbdev:auth");
15006
15179
  var LOGIN_MAX_WAIT = 2 * 60 * 1e3;
15007
15180
  var LOGIN_CHECK_DELAY = 2 * 1e3;
15008
15181
  var _AuthManager = class _AuthManager {
@@ -15032,7 +15205,7 @@ var _AuthManager = class _AuthManager {
15032
15205
  return false;
15033
15206
  }
15034
15207
  if (_AuthManager.browserCooldownMs > 0 && Date.now() - _AuthManager.lastBrowserOpenTime < _AuthManager.browserCooldownMs) {
15035
- debug11("browser cooldown active, skipping open");
15208
+ debug12("browser cooldown active, skipping open");
15036
15209
  return false;
15037
15210
  }
15038
15211
  open(this.currentBrowserUrl);
@@ -15085,7 +15258,7 @@ var _AuthManager = class _AuthManager {
15085
15258
  const result = await this.checkAuthentication();
15086
15259
  this.authenticated = result.isAuthenticated;
15087
15260
  if (!result.isAuthenticated) {
15088
- debug11("isAuthenticated: false \u2014 %s (%s)", result.message, result.reason);
15261
+ debug12("isAuthenticated: false \u2014 %s (%s)", result.message, result.reason);
15089
15262
  }
15090
15263
  }
15091
15264
  return this.authenticated;
@@ -15173,9 +15346,9 @@ var _AuthManager = class _AuthManager {
15173
15346
  return null;
15174
15347
  } catch (error) {
15175
15348
  if (isTransientError(error)) {
15176
- debug11("getApiToken: transient error, will retry");
15349
+ debug12("getApiToken: transient error, will retry");
15177
15350
  } else {
15178
- debug11("getApiToken: unexpected error: %O", error);
15351
+ debug12("getApiToken: unexpected error: %O", error);
15179
15352
  }
15180
15353
  return null;
15181
15354
  }
@@ -15228,10 +15401,10 @@ __publicField(_AuthManager, "lastBrowserOpenTime", 0);
15228
15401
  var AuthManager = _AuthManager;
15229
15402
 
15230
15403
  // src/features/analysis/add_fix_comments_for_pr/add_fix_comments_for_pr.ts
15231
- import Debug14 from "debug";
15404
+ import Debug15 from "debug";
15232
15405
 
15233
15406
  // src/features/analysis/add_fix_comments_for_pr/utils/utils.ts
15234
- import Debug13 from "debug";
15407
+ import Debug14 from "debug";
15235
15408
  import parseDiff from "parse-diff";
15236
15409
  import { z as z29 } from "zod";
15237
15410
 
@@ -15243,9 +15416,9 @@ function keyBy(array, keyBy2) {
15243
15416
  }
15244
15417
 
15245
15418
  // src/features/analysis/utils/send_report.ts
15246
- import Debug11 from "debug";
15419
+ import Debug12 from "debug";
15247
15420
  init_client_generates();
15248
- var debug12 = Debug11("mobbdev:index");
15421
+ var debug13 = Debug12("mobbdev:index");
15249
15422
  async function sendReport({
15250
15423
  spinner,
15251
15424
  submitVulnerabilityReportVariables,
@@ -15257,7 +15430,7 @@ async function sendReport({
15257
15430
  submitVulnerabilityReportVariables
15258
15431
  );
15259
15432
  if (submitRes.submitVulnerabilityReport.__typename !== "VulnerabilityReport") {
15260
- debug12("error submit vul report %s", submitRes);
15433
+ debug13("error submit vul report %s", submitRes);
15261
15434
  throw new Error("\u{1F575}\uFE0F\u200D\u2642\uFE0F Mobb analysis failed");
15262
15435
  }
15263
15436
  spinner.update({ text: progressMassages.processingVulnerabilityReport });
@@ -15269,7 +15442,7 @@ async function sendReport({
15269
15442
  "Finished" /* Finished */
15270
15443
  ];
15271
15444
  if (polling) {
15272
- debug12("[sendReport] Using POLLING mode for analysis state updates");
15445
+ debug13("[sendReport] Using POLLING mode for analysis state updates");
15273
15446
  await gqlClient.pollForAnalysisState({
15274
15447
  analysisId: submitRes.submitVulnerabilityReport.fixReportId,
15275
15448
  callback,
@@ -15277,7 +15450,7 @@ async function sendReport({
15277
15450
  timeoutInMs: VUL_REPORT_DIGEST_TIMEOUT_MS
15278
15451
  });
15279
15452
  } else {
15280
- debug12("[sendReport] Using WEBSOCKET mode for analysis state updates");
15453
+ debug13("[sendReport] Using WEBSOCKET mode for analysis state updates");
15281
15454
  await gqlClient.subscribeToAnalysis({
15282
15455
  subscribeToAnalysisParams: {
15283
15456
  analysisId: submitRes.submitVulnerabilityReport.fixReportId
@@ -15321,10 +15494,10 @@ var scannerToFriendlyString = {
15321
15494
  };
15322
15495
 
15323
15496
  // src/features/analysis/add_fix_comments_for_pr/utils/buildCommentBody.ts
15324
- import Debug12 from "debug";
15497
+ import Debug13 from "debug";
15325
15498
  import { z as z28 } from "zod";
15326
15499
  init_client_generates();
15327
- var debug13 = Debug12("mobbdev:handle-finished-analysis");
15500
+ var debug14 = Debug13("mobbdev:handle-finished-analysis");
15328
15501
  var getCommitFixButton = (commitUrl) => `<a href="${commitUrl}"><img src=${COMMIT_FIX_SVG}></a>`;
15329
15502
  function buildFixCommentBody({
15330
15503
  fix,
@@ -15375,7 +15548,7 @@ function buildFixCommentBody({
15375
15548
  safeIssueType: z28.nativeEnum(IssueType_Enum)
15376
15549
  }).safeParse(fix);
15377
15550
  if (!validFixParseRes.success) {
15378
- debug13(
15551
+ debug14(
15379
15552
  `fix ${fixId} has custom issue type or language, therefore the commit description will not be added`,
15380
15553
  validFixParseRes.error
15381
15554
  );
@@ -15439,7 +15612,7 @@ ${issuePageLink}`;
15439
15612
  }
15440
15613
 
15441
15614
  // src/features/analysis/add_fix_comments_for_pr/utils/utils.ts
15442
- var debug14 = Debug13("mobbdev:handle-finished-analysis");
15615
+ var debug15 = Debug14("mobbdev:handle-finished-analysis");
15443
15616
  function calculateRanges(integers) {
15444
15617
  if (integers.length === 0) {
15445
15618
  return [];
@@ -15473,7 +15646,7 @@ function deleteAllPreviousComments({
15473
15646
  try {
15474
15647
  return scm.deleteComment({ comment_id: comment.id });
15475
15648
  } catch (e) {
15476
- debug14("delete comment failed %s", e);
15649
+ debug15("delete comment failed %s", e);
15477
15650
  return Promise.resolve();
15478
15651
  }
15479
15652
  });
@@ -15489,7 +15662,7 @@ function deleteAllPreviousGeneralPrComments(params) {
15489
15662
  try {
15490
15663
  return scm.deleteGeneralPrComment({ commentId: comment.id });
15491
15664
  } catch (e) {
15492
- debug14("delete comment failed %s", e);
15665
+ debug15("delete comment failed %s", e);
15493
15666
  return Promise.resolve();
15494
15667
  }
15495
15668
  });
@@ -15633,7 +15806,7 @@ async function postAnalysisInsightComment(params) {
15633
15806
  fixablePrVuls,
15634
15807
  nonFixablePrVuls
15635
15808
  } = prVulenrabilities;
15636
- debug14({
15809
+ debug15({
15637
15810
  fixablePrVuls,
15638
15811
  nonFixablePrVuls,
15639
15812
  vulnerabilitiesOutsidePr,
@@ -15688,7 +15861,7 @@ ${contactUsMarkdown}`;
15688
15861
  }
15689
15862
 
15690
15863
  // src/features/analysis/add_fix_comments_for_pr/add_fix_comments_for_pr.ts
15691
- var debug15 = Debug14("mobbdev:handle-finished-analysis");
15864
+ var debug16 = Debug15("mobbdev:handle-finished-analysis");
15692
15865
  async function addFixCommentsForPr({
15693
15866
  analysisId,
15694
15867
  scm: _scm,
@@ -15700,7 +15873,7 @@ async function addFixCommentsForPr({
15700
15873
  }
15701
15874
  const scm = _scm;
15702
15875
  const getAnalysisRes = await gqlClient.getAnalysis(analysisId);
15703
- debug15("getAnalysis %o", getAnalysisRes);
15876
+ debug16("getAnalysis %o", getAnalysisRes);
15704
15877
  const {
15705
15878
  vulnerabilityReport: {
15706
15879
  projectId,
@@ -15810,8 +15983,8 @@ ${contextString}` : description;
15810
15983
 
15811
15984
  // src/features/analysis/auto_pr_handler.ts
15812
15985
  init_client_generates();
15813
- import Debug15 from "debug";
15814
- var debug16 = Debug15("mobbdev:handleAutoPr");
15986
+ import Debug16 from "debug";
15987
+ var debug17 = Debug16("mobbdev:handleAutoPr");
15815
15988
  async function handleAutoPr(params) {
15816
15989
  const {
15817
15990
  gqlClient,
@@ -15832,7 +16005,7 @@ async function handleAutoPr(params) {
15832
16005
  prId,
15833
16006
  prStrategy: createOnePr ? "CONDENSE" /* Condense */ : "SPREAD" /* Spread */
15834
16007
  });
15835
- debug16("auto pr analysis res %o", autoPrAnalysisRes);
16008
+ debug17("auto pr analysis res %o", autoPrAnalysisRes);
15836
16009
  if (autoPrAnalysisRes.autoPrAnalysis?.__typename === "AutoPrError") {
15837
16010
  createAutoPrSpinner.error({
15838
16011
  text: `\u{1F504} Automatic pull request failed - ${autoPrAnalysisRes.autoPrAnalysis.error}`
@@ -15854,14 +16027,14 @@ async function handleAutoPr(params) {
15854
16027
  };
15855
16028
  const callbackStates = ["Finished" /* Finished */];
15856
16029
  if (polling) {
15857
- debug16("[handleAutoPr] Using POLLING mode for analysis state updates");
16030
+ debug17("[handleAutoPr] Using POLLING mode for analysis state updates");
15858
16031
  return await gqlClient.pollForAnalysisState({
15859
16032
  analysisId,
15860
16033
  callback,
15861
16034
  callbackStates
15862
16035
  });
15863
16036
  } else {
15864
- debug16("[handleAutoPr] Using WEBSOCKET mode for analysis state updates");
16037
+ debug17("[handleAutoPr] Using WEBSOCKET mode for analysis state updates");
15865
16038
  return await gqlClient.subscribeToAnalysis({
15866
16039
  subscribeToAnalysisParams: {
15867
16040
  analysisId
@@ -15874,15 +16047,15 @@ async function handleAutoPr(params) {
15874
16047
 
15875
16048
  // src/features/analysis/git.ts
15876
16049
  init_GitService();
15877
- import Debug16 from "debug";
15878
- var debug17 = Debug16("mobbdev:git");
16050
+ import Debug17 from "debug";
16051
+ var debug18 = Debug17("mobbdev:git");
15879
16052
  async function getGitInfo(srcDirPath) {
15880
- debug17("getting git info for %s", srcDirPath);
16053
+ debug18("getting git info for %s", srcDirPath);
15881
16054
  const gitService = new GitService(srcDirPath);
15882
16055
  try {
15883
16056
  const validationResult = await gitService.validateRepository();
15884
16057
  if (!validationResult.isValid) {
15885
- debug17("folder is not a git repo");
16058
+ debug18("folder is not a git repo");
15886
16059
  return {
15887
16060
  success: false,
15888
16061
  hash: void 0,
@@ -15897,9 +16070,9 @@ async function getGitInfo(srcDirPath) {
15897
16070
  };
15898
16071
  } catch (e) {
15899
16072
  if (e instanceof Error) {
15900
- debug17("failed to run git %o", e);
16073
+ debug18("failed to run git %o", e);
15901
16074
  if (e.message.includes(" spawn ")) {
15902
- debug17("git cli not installed");
16075
+ debug18("git cli not installed");
15903
16076
  } else {
15904
16077
  throw e;
15905
16078
  }
@@ -15913,13 +16086,13 @@ init_configs();
15913
16086
  import fs9 from "fs";
15914
16087
  import path8 from "path";
15915
16088
  import AdmZip from "adm-zip";
15916
- import Debug17 from "debug";
16089
+ import Debug18 from "debug";
15917
16090
  import { globby } from "globby";
15918
16091
  import { isBinary as isBinary2 } from "istextorbinary";
15919
16092
  import { simpleGit as simpleGit3 } from "simple-git";
15920
16093
  import { parseStringPromise } from "xml2js";
15921
16094
  import { z as z30 } from "zod";
15922
- var debug18 = Debug17("mobbdev:pack");
16095
+ var debug19 = Debug18("mobbdev:pack");
15923
16096
  var FPR_SOURCE_CODE_FILE_MAPPING_SCHEMA = z30.object({
15924
16097
  properties: z30.object({
15925
16098
  entry: z30.array(
@@ -15941,7 +16114,7 @@ function getManifestFilesSuffixes() {
15941
16114
  return ["package.json", "pom.xml"];
15942
16115
  }
15943
16116
  async function pack(srcDirPath, vulnFiles, isIncludeAllFiles = false) {
15944
- debug18("pack folder %s", srcDirPath);
16117
+ debug19("pack folder %s", srcDirPath);
15945
16118
  let git;
15946
16119
  try {
15947
16120
  git = simpleGit3({
@@ -15951,13 +16124,13 @@ async function pack(srcDirPath, vulnFiles, isIncludeAllFiles = false) {
15951
16124
  });
15952
16125
  await git.status();
15953
16126
  } catch (e) {
15954
- debug18("failed to run git %o", e);
16127
+ debug19("failed to run git %o", e);
15955
16128
  git = void 0;
15956
16129
  if (e instanceof Error) {
15957
16130
  if (e.message.includes(" spawn ")) {
15958
- debug18("git cli not installed");
16131
+ debug19("git cli not installed");
15959
16132
  } else if (e.message.includes("not a git repository")) {
15960
- debug18("folder is not a git repo");
16133
+ debug19("folder is not a git repo");
15961
16134
  } else {
15962
16135
  throw e;
15963
16136
  }
@@ -15972,9 +16145,9 @@ async function pack(srcDirPath, vulnFiles, isIncludeAllFiles = false) {
15972
16145
  followSymbolicLinks: false,
15973
16146
  dot: true
15974
16147
  });
15975
- debug18("files found %d", filepaths.length);
16148
+ debug19("files found %d", filepaths.length);
15976
16149
  const zip = new AdmZip();
15977
- debug18("compressing files");
16150
+ debug19("compressing files");
15978
16151
  for (const filepath of filepaths) {
15979
16152
  const absFilepath = path8.join(srcDirPath, filepath.toString());
15980
16153
  if (!isIncludeAllFiles) {
@@ -15983,12 +16156,12 @@ async function pack(srcDirPath, vulnFiles, isIncludeAllFiles = false) {
15983
16156
  absFilepath.toString().replaceAll(path8.win32.sep, path8.posix.sep),
15984
16157
  vulnFiles
15985
16158
  )) {
15986
- debug18("ignoring %s because it is not a vulnerability file", filepath);
16159
+ debug19("ignoring %s because it is not a vulnerability file", filepath);
15987
16160
  continue;
15988
16161
  }
15989
16162
  }
15990
16163
  if (fs9.lstatSync(absFilepath).size > MCP_MAX_FILE_SIZE) {
15991
- debug18(
16164
+ debug19(
15992
16165
  "ignoring %s \u2014 file size exceeds MCP_MAX_FILE_SIZE (%d bytes)",
15993
16166
  filepath,
15994
16167
  MCP_MAX_FILE_SIZE
@@ -16006,16 +16179,16 @@ async function pack(srcDirPath, vulnFiles, isIncludeAllFiles = false) {
16006
16179
  data = fs9.readFileSync(absFilepath);
16007
16180
  }
16008
16181
  if (isBinary2(null, data)) {
16009
- debug18("ignoring %s because is seems to be a binary file", filepath);
16182
+ debug19("ignoring %s because is seems to be a binary file", filepath);
16010
16183
  continue;
16011
16184
  }
16012
16185
  zip.addFile(filepath.toString(), data);
16013
16186
  }
16014
- debug18("get zip file buffer");
16187
+ debug19("get zip file buffer");
16015
16188
  return zip.toBuffer();
16016
16189
  }
16017
16190
  async function repackFpr(fprPath) {
16018
- debug18("repack fpr file %s", fprPath);
16191
+ debug19("repack fpr file %s", fprPath);
16019
16192
  const zipIn = new AdmZip(fprPath);
16020
16193
  const zipOut = new AdmZip();
16021
16194
  const mappingXML = zipIn.readAsText("src-archive/index.xml", "utf-8");
@@ -16030,7 +16203,7 @@ async function repackFpr(fprPath) {
16030
16203
  zipOut.addFile(realPath, buf);
16031
16204
  }
16032
16205
  }
16033
- debug18("get repacked zip file buffer");
16206
+ debug19("get repacked zip file buffer");
16034
16207
  return zipOut.toBuffer();
16035
16208
  }
16036
16209
 
@@ -16101,7 +16274,7 @@ async function snykArticlePrompt() {
16101
16274
  // src/features/analysis/scanners/checkmarx.ts
16102
16275
  import { createRequire } from "module";
16103
16276
  import chalk5 from "chalk";
16104
- import Debug19 from "debug";
16277
+ import Debug20 from "debug";
16105
16278
  import { existsSync } from "fs";
16106
16279
  import { createSpinner as createSpinner2 } from "nanospinner";
16107
16280
  import { type } from "os";
@@ -16113,7 +16286,7 @@ var cxOperatingSystemSupportMessage = `Your operating system does not support ch
16113
16286
 
16114
16287
  // src/utils/child_process.ts
16115
16288
  import cp from "child_process";
16116
- import Debug18 from "debug";
16289
+ import Debug19 from "debug";
16117
16290
  import * as process2 from "process";
16118
16291
  function createFork({ args, processPath, name }, options) {
16119
16292
  const child = cp.fork(processPath, args, {
@@ -16131,16 +16304,16 @@ function createSpawn({ args, processPath, name, cwd, env: env3 }, options) {
16131
16304
  return createChildProcess({ childProcess: child, name }, options);
16132
16305
  }
16133
16306
  function createChildProcess({ childProcess, name }, options) {
16134
- const debug23 = Debug18(`mobbdev:${name}`);
16307
+ const debug24 = Debug19(`mobbdev:${name}`);
16135
16308
  const { display } = options;
16136
16309
  return new Promise((resolve, reject) => {
16137
16310
  let out = "";
16138
16311
  const onData = (chunk) => {
16139
- debug23(`chunk received from ${name} std ${chunk}`);
16312
+ debug24(`chunk received from ${name} std ${chunk}`);
16140
16313
  out += chunk;
16141
16314
  };
16142
16315
  if (!childProcess?.stdout || !childProcess?.stderr) {
16143
- debug23(`unable to fork ${name}`);
16316
+ debug24(`unable to fork ${name}`);
16144
16317
  reject(new Error(`unable to fork ${name}`));
16145
16318
  }
16146
16319
  childProcess.stdout?.on("data", onData);
@@ -16150,18 +16323,18 @@ function createChildProcess({ childProcess, name }, options) {
16150
16323
  childProcess.stderr?.pipe(process2.stderr);
16151
16324
  }
16152
16325
  childProcess.on("exit", (code) => {
16153
- debug23(`${name} exit code ${code}`);
16326
+ debug24(`${name} exit code ${code}`);
16154
16327
  resolve({ message: out, code });
16155
16328
  });
16156
16329
  childProcess.on("error", (err) => {
16157
- debug23(`${name} error %o`, err);
16330
+ debug24(`${name} error %o`, err);
16158
16331
  reject(err);
16159
16332
  });
16160
16333
  });
16161
16334
  }
16162
16335
 
16163
16336
  // src/features/analysis/scanners/checkmarx.ts
16164
- var debug19 = Debug19("mobbdev:checkmarx");
16337
+ var debug20 = Debug20("mobbdev:checkmarx");
16165
16338
  var moduleUrl;
16166
16339
  if (typeof __filename !== "undefined") {
16167
16340
  moduleUrl = __filename;
@@ -16220,14 +16393,14 @@ function validateCheckmarxInstallation() {
16220
16393
  existsSync(getCheckmarxPath());
16221
16394
  }
16222
16395
  async function forkCheckmarx(args, { display }) {
16223
- debug19("fork checkmarx with args %o %s", args.join(" "), display);
16396
+ debug20("fork checkmarx with args %o %s", args.join(" "), display);
16224
16397
  return createSpawn(
16225
16398
  { args, processPath: getCheckmarxPath(), name: "checkmarx" },
16226
16399
  { display }
16227
16400
  );
16228
16401
  }
16229
16402
  async function getCheckmarxReport({ reportPath, repositoryRoot, branch, projectName }, { skipPrompts = false }) {
16230
- debug19("get checkmarx report start %s %s", reportPath, repositoryRoot);
16403
+ debug20("get checkmarx report start %s %s", reportPath, repositoryRoot);
16231
16404
  const { code: loginCode } = await forkCheckmarx(VALIDATE_COMMAND, {
16232
16405
  display: false
16233
16406
  });
@@ -16295,10 +16468,10 @@ async function validateCheckamxCredentials() {
16295
16468
  // src/features/analysis/scanners/snyk.ts
16296
16469
  import { createRequire as createRequire2 } from "module";
16297
16470
  import chalk6 from "chalk";
16298
- import Debug20 from "debug";
16471
+ import Debug21 from "debug";
16299
16472
  import { createSpinner as createSpinner3 } from "nanospinner";
16300
16473
  import open2 from "open";
16301
- var debug20 = Debug20("mobbdev:snyk");
16474
+ var debug21 = Debug21("mobbdev:snyk");
16302
16475
  var moduleUrl2;
16303
16476
  if (typeof __filename !== "undefined") {
16304
16477
  moduleUrl2 = __filename;
@@ -16320,13 +16493,13 @@ if (typeof __filename !== "undefined") {
16320
16493
  var costumeRequire2 = createRequire2(moduleUrl2);
16321
16494
  var SNYK_PATH = costumeRequire2.resolve("snyk/bin/snyk");
16322
16495
  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);
16496
+ debug21("snyk executable path %s", SNYK_PATH);
16324
16497
  async function forkSnyk(args, { display }) {
16325
- debug20("fork snyk with args %o %s", args, display);
16498
+ debug21("fork snyk with args %o %s", args, display);
16326
16499
  return createFork({ args, processPath: SNYK_PATH, name: "snyk" }, { display });
16327
16500
  }
16328
16501
  async function getSnykReport(reportPath, repoRoot, { skipPrompts = false }) {
16329
- debug20("get snyk report start %s %s", reportPath, repoRoot);
16502
+ debug21("get snyk report start %s %s", reportPath, repoRoot);
16330
16503
  const config2 = await forkSnyk(["config"], { display: false });
16331
16504
  const { message: configMessage } = config2;
16332
16505
  if (!configMessage.includes("api: ")) {
@@ -16340,7 +16513,7 @@ async function getSnykReport(reportPath, repoRoot, { skipPrompts = false }) {
16340
16513
  snykLoginSpinner.update({
16341
16514
  text: "\u{1F513} Waiting for Snyk login to complete"
16342
16515
  });
16343
- debug20("no token in the config %s", config2);
16516
+ debug21("no token in the config %s", config2);
16344
16517
  await forkSnyk(["auth"], { display: true });
16345
16518
  snykLoginSpinner.success({ text: "\u{1F513} Login to Snyk Successful" });
16346
16519
  }
@@ -16350,12 +16523,12 @@ async function getSnykReport(reportPath, repoRoot, { skipPrompts = false }) {
16350
16523
  { display: true }
16351
16524
  );
16352
16525
  if (scanOutput.includes("Snyk Code is not supported for org")) {
16353
- debug20("snyk code is not enabled %s", scanOutput);
16526
+ debug21("snyk code is not enabled %s", scanOutput);
16354
16527
  snykSpinner.error({ text: "\u{1F50D} Snyk configuration needed" });
16355
16528
  const answer = await snykArticlePrompt();
16356
- debug20("answer %s", answer);
16529
+ debug21("answer %s", answer);
16357
16530
  if (answer) {
16358
- debug20("opening the browser");
16531
+ debug21("opening the browser");
16359
16532
  await open2(SNYK_ARTICLE_URL);
16360
16533
  }
16361
16534
  console.log(
@@ -16403,9 +16576,9 @@ async function downloadRepo({
16403
16576
  }) {
16404
16577
  const { createSpinner: createSpinner5 } = Spinner2({ ci });
16405
16578
  const repoSpinner = createSpinner5("\u{1F4BE} Downloading Repo").start();
16406
- debug21("download repo %s %s %s", repoUrl, dirname);
16579
+ debug22("download repo %s %s %s", repoUrl, dirname);
16407
16580
  const zipFilePath = path10.join(dirname, "repo.zip");
16408
- debug21("download URL: %s auth headers: %o", downloadUrl, authHeaders);
16581
+ debug22("download URL: %s auth headers: %o", downloadUrl, authHeaders);
16409
16582
  const response = await fetch4(downloadUrl, {
16410
16583
  method: "GET",
16411
16584
  headers: {
@@ -16413,7 +16586,7 @@ async function downloadRepo({
16413
16586
  }
16414
16587
  });
16415
16588
  if (!response.ok) {
16416
- debug21("SCM zipball request failed %s %s", response.body, response.status);
16589
+ debug22("SCM zipball request failed %s %s", response.body, response.status);
16417
16590
  repoSpinner.error({ text: "\u{1F4BE} Repo download failed" });
16418
16591
  throw new Error(`Can't access ${chalk7.bold(repoUrl)}`);
16419
16592
  }
@@ -16427,7 +16600,7 @@ async function downloadRepo({
16427
16600
  if (!repoRoot) {
16428
16601
  throw new Error("Repo root not found");
16429
16602
  }
16430
- debug21("repo root %s", repoRoot);
16603
+ debug22("repo root %s", repoRoot);
16431
16604
  repoSpinner.success({ text: "\u{1F4BE} Repo downloaded successfully" });
16432
16605
  return path10.join(dirname, repoRoot);
16433
16606
  }
@@ -16436,7 +16609,7 @@ var getReportUrl = ({
16436
16609
  projectId,
16437
16610
  fixReportId
16438
16611
  }) => `${WEB_APP_URL}/organization/${organizationId}/project/${projectId}/report/${fixReportId}`;
16439
- var debug21 = Debug21("mobbdev:index");
16612
+ var debug22 = Debug22("mobbdev:index");
16440
16613
  async function runAnalysis(params, options) {
16441
16614
  const tmpObj = tmp2.dirSync({
16442
16615
  unsafeCleanup: true
@@ -16583,7 +16756,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
16583
16756
  polling,
16584
16757
  baselineCommit
16585
16758
  } = params;
16586
- debug21("start %s %s", dirname, repo);
16759
+ debug22("start %s %s", dirname, repo);
16587
16760
  const { createSpinner: createSpinner5 } = Spinner2({ ci });
16588
16761
  skipPrompts = skipPrompts || ci;
16589
16762
  const gqlClient = await getAuthenticatedGQLClient({
@@ -16623,8 +16796,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
16623
16796
  });
16624
16797
  if (!isRepoAvailable) {
16625
16798
  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);
16799
+ 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`;
16800
+ throw new Error(errorMessage3);
16628
16801
  }
16629
16802
  if (cloudScmLibType && scmAuthUrl) {
16630
16803
  await handleScmIntegration(tokenInfo.accessToken, scmAuthUrl, repo);
@@ -16656,8 +16829,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
16656
16829
  );
16657
16830
  }
16658
16831
  const { sha } = getReferenceDataRes.gitReference;
16659
- debug21("project id %s", projectId);
16660
- debug21("default branch %s", reference);
16832
+ debug22("project id %s", projectId);
16833
+ debug22("default branch %s", reference);
16661
16834
  if (command === "scan") {
16662
16835
  reportPath = await getReport(
16663
16836
  {
@@ -16994,7 +17167,7 @@ async function _digestReport({
16994
17167
  text: progressMassages.processingVulnerabilityReportSuccess
16995
17168
  });
16996
17169
  if (polling) {
16997
- debug21(
17170
+ debug22(
16998
17171
  "[_digestReport] Using POLLING mode for analysis state updates (--polling flag enabled)"
16999
17172
  );
17000
17173
  console.log(
@@ -17009,7 +17182,7 @@ async function _digestReport({
17009
17182
  timeoutInMs: VUL_REPORT_DIGEST_TIMEOUT_MS
17010
17183
  });
17011
17184
  } else {
17012
- debug21(
17185
+ debug22(
17013
17186
  "[_digestReport] Using WEBSOCKET mode for analysis state updates (default)"
17014
17187
  );
17015
17188
  console.log(
@@ -17034,9 +17207,9 @@ async function _digestReport({
17034
17207
  });
17035
17208
  return vulnFiles;
17036
17209
  } catch (e) {
17037
- const errorMessage = e instanceof ReportDigestError ? e.getDisplayMessage() : ReportDigestError.defaultMessage;
17210
+ const errorMessage3 = e instanceof ReportDigestError ? e.getDisplayMessage() : ReportDigestError.defaultMessage;
17038
17211
  digestSpinner.error({
17039
- text: errorMessage
17212
+ text: errorMessage3
17040
17213
  });
17041
17214
  throw e;
17042
17215
  }
@@ -17073,7 +17246,7 @@ async function waitForAnaysisAndReviewPr({
17073
17246
  });
17074
17247
  };
17075
17248
  if (polling) {
17076
- debug21(
17249
+ debug22(
17077
17250
  "[waitForAnaysisAndReviewPr] Using POLLING mode for analysis state updates"
17078
17251
  );
17079
17252
  console.log(
@@ -17087,7 +17260,7 @@ async function waitForAnaysisAndReviewPr({
17087
17260
  callbackStates: ["Finished" /* Finished */]
17088
17261
  });
17089
17262
  } else {
17090
- debug21(
17263
+ debug22(
17091
17264
  "[waitForAnaysisAndReviewPr] Using WEBSOCKET mode for analysis state updates"
17092
17265
  );
17093
17266
  console.log(
@@ -17391,11 +17564,11 @@ function throwRepoUrlErrorMessage({
17391
17564
  repoUrl,
17392
17565
  command
17393
17566
  }) {
17394
- const errorMessage = error.issues[error.issues.length - 1]?.message;
17567
+ const errorMessage3 = error.issues[error.issues.length - 1]?.message;
17395
17568
  const formattedErrorMessage = `
17396
17569
  Error: ${chalk9.bold(
17397
17570
  repoUrl
17398
- )} is ${errorMessage}
17571
+ )} is ${errorMessage3}
17399
17572
  Example:
17400
17573
  mobbdev ${command} -r ${chalk9.bold(
17401
17574
  "https://github.com/WebGoat/WebGoat"
@@ -17523,7 +17696,7 @@ import { spawn } from "child_process";
17523
17696
  import { readFileSync, writeFileSync as writeFileSync2 } from "fs";
17524
17697
  import * as os8 from "os";
17525
17698
  import path24 from "path";
17526
- import { setTimeout as sleep2 } from "timers/promises";
17699
+ import { setTimeout as sleep3 } from "timers/promises";
17527
17700
  import Configstore3 from "configstore";
17528
17701
 
17529
17702
  // src/features/analysis/skill_quarantine/runQuarantineCheck.ts
@@ -19410,7 +19583,7 @@ function createLogger(config2) {
19410
19583
  const info = pinoLogger.info.bind(pinoLogger);
19411
19584
  const warn = pinoLogger.warn.bind(pinoLogger);
19412
19585
  const error = pinoLogger.error.bind(pinoLogger);
19413
- const debug23 = pinoLogger.debug.bind(pinoLogger);
19586
+ const debug24 = pinoLogger.debug.bind(pinoLogger);
19414
19587
  function heartbeat(message, data) {
19415
19588
  pinoLogger.info({ data, heartbeat: true }, message);
19416
19589
  }
@@ -19453,7 +19626,7 @@ function createLogger(config2) {
19453
19626
  info,
19454
19627
  warn,
19455
19628
  error,
19456
- debug: debug23,
19629
+ debug: debug24,
19457
19630
  heartbeat,
19458
19631
  timed,
19459
19632
  flushLogs,
@@ -19468,7 +19641,7 @@ function createLogger(config2) {
19468
19641
 
19469
19642
  // src/features/claude_code/hook_logger.ts
19470
19643
  var DD_RUM_TOKEN = true ? "pubf59c0182545bfb4c299175119f1abf9b" : "";
19471
- var CLI_VERSION = true ? "1.4.20" : "unknown";
19644
+ var CLI_VERSION = true ? "1.4.22" : "unknown";
19472
19645
  var NAMESPACE = "mobbdev-claude-code-hook-logs";
19473
19646
  var claudeCodeVersion;
19474
19647
  function buildDdTags() {
@@ -19996,6 +20169,12 @@ async function processTranscript(input, sessionStore, log2, maxEntries = DAEMON_
19996
20169
  sanitize
19997
20170
  })
19998
20171
  );
20172
+ if (result.degenerate?.length) {
20173
+ log2.warn(
20174
+ { data: degenerateRecordsLogFields(result.degenerate) },
20175
+ DEGENERATE_RECORDS_LOG_MESSAGE
20176
+ );
20177
+ }
19999
20178
  if (result.ok) {
20000
20179
  const lastRawEntry = rawEntries[rawEntries.length - 1];
20001
20180
  const cursor = {
@@ -20566,7 +20745,7 @@ async function startDaemon() {
20566
20745
  },
20567
20746
  "daemon poll cycle"
20568
20747
  );
20569
- await sleep2(DAEMON_POLL_INTERVAL_MS);
20748
+ await sleep3(DAEMON_POLL_INTERVAL_MS);
20570
20749
  }
20571
20750
  }
20572
20751
  async function acquirePidFile() {
@@ -21289,7 +21468,7 @@ var McpGQLClient = class extends GQLClient {
21289
21468
  { data }
21290
21469
  );
21291
21470
  if (!data.analysis?.state || data.analysis?.state === "Failed" /* Failed */) {
21292
- const errorMessage = data.analysis?.failReason || `Analysis failed with id: ${data.analysis?.id}`;
21471
+ const errorMessage3 = data.analysis?.failReason || `Analysis failed with id: ${data.analysis?.id}`;
21293
21472
  logError(`[${scanContext}] GraphQL: Analysis failed`, {
21294
21473
  analysisId: data.analysis?.id,
21295
21474
  state: data.analysis?.state,
@@ -21297,7 +21476,7 @@ var McpGQLClient = class extends GQLClient {
21297
21476
  ...this.getErrorContext()
21298
21477
  });
21299
21478
  subscription.unsubscribe();
21300
- reject(new Error(errorMessage));
21479
+ reject(new Error(errorMessage3));
21301
21480
  return;
21302
21481
  }
21303
21482
  if (callbackStates.includes(data.analysis?.state)) {
@@ -21409,17 +21588,17 @@ var McpGQLClient = class extends GQLClient {
21409
21588
  });
21410
21589
  return createdProject.createProject.projectId;
21411
21590
  } catch (createError) {
21412
- const errorMessage = createError instanceof Error ? createError.message : String(createError);
21413
- const isConstraintViolation = errorMessage.includes(
21591
+ const errorMessage3 = createError instanceof Error ? createError.message : String(createError);
21592
+ const isConstraintViolation = errorMessage3.includes(
21414
21593
  "duplicate key value violates unique constraint"
21415
- ) && errorMessage.includes("project_name_organization_id_key");
21594
+ ) && errorMessage3.includes("project_name_organization_id_key");
21416
21595
  if (isConstraintViolation) {
21417
21596
  logDebug(
21418
21597
  "[GraphQL] Project creation failed due to constraint violation, retrying fetch",
21419
21598
  {
21420
21599
  organizationId: organization.id,
21421
21600
  projectName,
21422
- error: errorMessage
21601
+ error: errorMessage3
21423
21602
  }
21424
21603
  );
21425
21604
  const retryOrgAndProjectRes = await this._clientSdk.getLastOrgAndNamedProject({
@@ -22829,8 +23008,8 @@ var McpServer = class {
22829
23008
  });
22830
23009
  return serializedResponse;
22831
23010
  } catch (error) {
22832
- const errorMessage = error instanceof Error ? error.message : String(error);
22833
- logError(`Error executing tool ${name}: ${errorMessage}`, {
23011
+ const errorMessage3 = error instanceof Error ? error.message : String(error);
23012
+ logError(`Error executing tool ${name}: ${errorMessage3}`, {
22834
23013
  error,
22835
23014
  toolName: name,
22836
23015
  args
@@ -22885,8 +23064,8 @@ var McpServer = class {
22885
23064
  });
22886
23065
  return response;
22887
23066
  } catch (error) {
22888
- const errorMessage = error instanceof Error ? error.message : String(error);
22889
- logError(`Error generating prompt ${name}: ${errorMessage}`, {
23067
+ const errorMessage3 = error instanceof Error ? error.message : String(error);
23068
+ logError(`Error generating prompt ${name}: ${errorMessage3}`, {
22890
23069
  error,
22891
23070
  promptName: name,
22892
23071
  args
@@ -23023,8 +23202,8 @@ var BasePrompt = class {
23023
23202
  const message = e.message === "Required" ? `Missing required argument '${fieldPath}'` : `Invalid value for '${fieldPath}': ${e.message}`;
23024
23203
  return message;
23025
23204
  });
23026
- const errorMessage = `Invalid arguments: ${errorDetails.join(", ")}`;
23027
- throw new Error(errorMessage);
23205
+ const errorMessage3 = `Invalid arguments: ${errorDetails.join(", ")}`;
23206
+ throw new Error(errorMessage3);
23028
23207
  }
23029
23208
  throw error;
23030
23209
  }
@@ -24733,9 +24912,9 @@ async function validatePath(inputPath) {
24733
24912
  logDebug("Stored validated path in WorkspaceService", { inputPath });
24734
24913
  return { isValid: true, path: inputPath };
24735
24914
  } 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 };
24915
+ const errorMessage3 = `Path does not exist or is not accessible: ${inputPath}`;
24916
+ logError(errorMessage3, { error });
24917
+ return { isValid: false, error: errorMessage3, path: inputPath };
24739
24918
  }
24740
24919
  }
24741
24920
 
@@ -24773,8 +24952,8 @@ var BaseTool = class {
24773
24952
  const message = e.message === "Required" ? `Missing required parameter '${fieldPath}'` : `Invalid value for '${fieldPath}': ${e.message}`;
24774
24953
  return message;
24775
24954
  });
24776
- const errorMessage = `Invalid arguments: ${errorDetails.join(", ")}`;
24777
- throw new Error(errorMessage);
24955
+ const errorMessage3 = `Invalid arguments: ${errorDetails.join(", ")}`;
24956
+ throw new Error(errorMessage3);
24778
24957
  }
24779
24958
  throw error;
24780
24959
  }
@@ -25746,9 +25925,9 @@ var LocalMobbFolderService = class {
25746
25925
  });
25747
25926
  return mobbFolderPath;
25748
25927
  } catch (error) {
25749
- const errorMessage = `Failed to get/create .mobb folder: ${error}`;
25750
- logError(errorMessage, { repoPath: this.repoPath, error });
25751
- throw new Error(errorMessage);
25928
+ const errorMessage3 = `Failed to get/create .mobb folder: ${error}`;
25929
+ logError(errorMessage3, { repoPath: this.repoPath, error });
25930
+ throw new Error(errorMessage3);
25752
25931
  }
25753
25932
  }
25754
25933
  /**
@@ -25909,8 +26088,8 @@ var LocalMobbFolderService = class {
25909
26088
  message: `Patch saved successfully as ${uniqueFileName}`
25910
26089
  };
25911
26090
  } catch (error) {
25912
- const errorMessage = `Failed to save patch for fix ${fix.id}: ${error}`;
25913
- logError(errorMessage, {
26091
+ const errorMessage3 = `Failed to save patch for fix ${fix.id}: ${error}`;
26092
+ logError(errorMessage3, {
25914
26093
  fixId: fix.id,
25915
26094
  fileName,
25916
26095
  severity,
@@ -25920,8 +26099,8 @@ var LocalMobbFolderService = class {
25920
26099
  });
25921
26100
  return {
25922
26101
  success: false,
25923
- error: errorMessage,
25924
- message: errorMessage
26102
+ error: errorMessage3,
26103
+ message: errorMessage3
25925
26104
  };
25926
26105
  }
25927
26106
  }
@@ -26011,12 +26190,12 @@ var LocalMobbFolderService = class {
26011
26190
  message: `Fix details logged to patchInfo.md`
26012
26191
  };
26013
26192
  } catch (error) {
26014
- const errorMessage = `Failed to log patch info: ${error}`;
26015
- logError(errorMessage, { fixId: fix.id, error });
26193
+ const errorMessage3 = `Failed to log patch info: ${error}`;
26194
+ logError(errorMessage3, { fixId: fix.id, error });
26016
26195
  return {
26017
26196
  success: false,
26018
- error: errorMessage,
26019
- message: errorMessage
26197
+ error: errorMessage3,
26198
+ message: errorMessage3
26020
26199
  };
26021
26200
  }
26022
26201
  }
@@ -26711,12 +26890,12 @@ var PatchApplicationService = class {
26711
26890
  failedFixes.push({ fix, error: result.error || "Unknown error" });
26712
26891
  }
26713
26892
  } catch (error) {
26714
- const errorMessage = error instanceof Error ? error.message : String(error);
26893
+ const errorMessage3 = error instanceof Error ? error.message : String(error);
26715
26894
  logError(`[${scanContext}] Failed to apply standalone fix ${fix.id}`, {
26716
- error: errorMessage,
26895
+ error: errorMessage3,
26717
26896
  issueType: fix.safeIssueType
26718
26897
  });
26719
- failedFixes.push({ fix, error: errorMessage });
26898
+ failedFixes.push({ fix, error: errorMessage3 });
26720
26899
  }
26721
26900
  }
26722
26901
  }
@@ -26767,17 +26946,17 @@ var PatchApplicationService = class {
26767
26946
  return { success: false, error: result.error };
26768
26947
  }
26769
26948
  } catch (error) {
26770
- const errorMessage = error instanceof Error ? error.message : String(error);
26949
+ const errorMessage3 = error instanceof Error ? error.message : String(error);
26771
26950
  logInfo(
26772
26951
  `[${scanContext}] Fix ${fix.id} threw exception for ${targetFile}, trying next option if available`,
26773
26952
  {
26774
- error: errorMessage,
26953
+ error: errorMessage3,
26775
26954
  issueType: fix.safeIssueType,
26776
26955
  attemptNumber,
26777
26956
  remainingOptions: totalAttempts - attemptNumber
26778
26957
  }
26779
26958
  );
26780
- return { success: false, error: errorMessage };
26959
+ return { success: false, error: errorMessage3 };
26781
26960
  }
26782
26961
  }
26783
26962
  /**
@@ -27281,18 +27460,18 @@ var PatchApplicationService = class {
27281
27460
  );
27282
27461
  return { success: true };
27283
27462
  } catch (patchError) {
27284
- const errorMessage = patchError instanceof Error ? patchError.message : String(patchError);
27463
+ const errorMessage3 = patchError instanceof Error ? patchError.message : String(patchError);
27285
27464
  logError(
27286
27465
  `[${scanContext}] In-memory patch application failed for fix ${fix.id}`,
27287
27466
  {
27288
- errorMessage,
27467
+ errorMessage: errorMessage3,
27289
27468
  patchErrorType: patchError instanceof Error ? patchError.name : typeof patchError,
27290
27469
  targetFiles
27291
27470
  }
27292
27471
  );
27293
27472
  return {
27294
27473
  success: false,
27295
- error: `Patch application failed: ${errorMessage}`
27474
+ error: `Patch application failed: ${errorMessage3}`
27296
27475
  };
27297
27476
  }
27298
27477
  }
@@ -27912,22 +28091,22 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
27912
28091
  this.updateFilesScanTimestamps(filesToScan);
27913
28092
  this.isInitialScanComplete = true;
27914
28093
  } catch (error) {
27915
- const errorMessage = error.message;
27916
- if (errorMessage.includes("Authentication failed") || errorMessage.includes("access-denied") || errorMessage.includes("Authentication hook unauthorized")) {
28094
+ const errorMessage3 = error.message;
28095
+ if (errorMessage3.includes("Authentication failed") || errorMessage3.includes("access-denied") || errorMessage3.includes("Authentication hook unauthorized")) {
27917
28096
  logError(
27918
28097
  `[${scanContext}] Periodic scan skipped due to authentication failure. Please re-authenticate by running a manual scan.`,
27919
28098
  {
27920
- error: errorMessage
28099
+ error: errorMessage3
27921
28100
  }
27922
28101
  );
27923
28102
  this.hasAuthenticationFailed = true;
27924
28103
  return;
27925
28104
  }
27926
- if (errorMessage.includes("ReportInitializationError")) {
28105
+ if (errorMessage3.includes("ReportInitializationError")) {
27927
28106
  logError(
27928
28107
  `[${scanContext}] Periodic scan failed during report initialization`,
27929
28108
  {
27930
- error: errorMessage
28109
+ error: errorMessage3
27931
28110
  }
27932
28111
  );
27933
28112
  return;
@@ -28162,12 +28341,12 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
28162
28341
  const loginContext = createMcpLoginContext("check_new_fixes");
28163
28342
  this.gqlClient = await createAuthenticatedMcpGQLClient({ loginContext });
28164
28343
  } catch (error) {
28165
- const errorMessage = error.message;
28166
- if (errorMessage.includes("Authentication failed") || errorMessage.includes("access-denied") || errorMessage.includes("Authentication hook unauthorized")) {
28344
+ const errorMessage3 = error.message;
28345
+ if (errorMessage3.includes("Authentication failed") || errorMessage3.includes("access-denied") || errorMessage3.includes("Authentication hook unauthorized")) {
28167
28346
  logError(
28168
28347
  `[${scanContext}] Failed to create authenticated client due to authentication failure`,
28169
28348
  {
28170
- error: errorMessage
28349
+ error: errorMessage3
28171
28350
  }
28172
28351
  );
28173
28352
  this.hasAuthenticationFailed = true;
@@ -30037,13 +30216,13 @@ var parseArgs = async (args) => {
30037
30216
  };
30038
30217
 
30039
30218
  // src/index.ts
30040
- var debug22 = Debug22("mobbdev:index");
30219
+ var debug23 = Debug23("mobbdev:index");
30041
30220
  async function run() {
30042
30221
  return parseArgs(hideBin(process.argv));
30043
30222
  }
30044
30223
  (async () => {
30045
30224
  try {
30046
- debug22("Bugsy CLI v%s running...", packageJson.version);
30225
+ debug23("Bugsy CLI v%s running...", packageJson.version);
30047
30226
  await run();
30048
30227
  process.exit(0);
30049
30228
  } catch (err) {