@ankurhalder/codebase-snapshot 4.0.5 → 4.0.7

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/bin.js CHANGED
@@ -874,7 +874,7 @@ var DEFAULT_SECRET_PATTERNS = [
874
874
  },
875
875
  {
876
876
  rule: "aws-access-key-id",
877
- pattern: /(?:AKIA|ASIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASCA)[0-9A-Z]{16}/
877
+ pattern: /(?:AKIA|ASIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASCA|ABIA)[0-9A-Z]{16}/
878
878
  },
879
879
  {
880
880
  // The name is no longer limited to the three snake_case spellings: an
@@ -913,7 +913,7 @@ var DEFAULT_SECRET_PATTERNS = [
913
913
  // and batch tokens), `whsec_` (Stripe webhook secret), `dckr_pat_` (Docker
914
914
  // Hub), `hf_` (HuggingFace), `ya29.` (Google OAuth access token).
915
915
  rule: "known-vendor-token-prefix",
916
- pattern: /\b(?:glpat-[A-Za-z0-9_-]{20,64}|hvs\.[A-Za-z0-9_-]{20,128}|s\.[A-Za-z0-9]{20,64}|whsec_[A-Za-z0-9]{20,64}|dckr_pat_[A-Za-z0-9_-]{20,64}|hf_[A-Za-z0-9]{30,64}|ya29\.[A-Za-z0-9_-]{20,128})/
916
+ pattern: /\b(?:glpat-[A-Za-z0-9_-]{20,64}|glrt-[A-Za-z0-9_-]{20,64}|hvs\.[A-Za-z0-9_-]{20,128}|hvb\.[A-Za-z0-9_-]{20,128}|s\.[A-Za-z0-9]{20,64}|whsec_[A-Za-z0-9]{20,64}|dckr_pat_[A-Za-z0-9_-]{20,64}|hf_[A-Za-z0-9]{30,64}|ya29\.[A-Za-z0-9_-]{20,128}|sk_test_[A-Za-z0-9]{16,64}|1\/\/0[A-Za-z0-9_-]{20,64})/
917
917
  },
918
918
  {
919
919
  rule: "slack-webhook-url",
@@ -1945,6 +1945,7 @@ import * as fs4 from "fs";
1945
1945
  import { createHash } from "crypto";
1946
1946
  import * as path4 from "path";
1947
1947
  import { pathToFileURL } from "url";
1948
+ var CONFIG_DIR_SYMBOL = /* @__PURE__ */ Symbol.for("codebase-snapshot.configDir");
1948
1949
  var CONFIG_FILENAMES = [
1949
1950
  "snapshot.config.ts",
1950
1951
  "snapshot.config.js",
@@ -2483,7 +2484,8 @@ function resolveCandidateCwd(userConfig, cliOptions, baseDir) {
2483
2484
  return resolved;
2484
2485
  }
2485
2486
  function resolveConfig(userConfig, cliOptions, baseDir) {
2486
- const cwd = resolveCandidateCwd(userConfig ?? null, cliOptions, baseDir);
2487
+ const configDir = userConfig?.[CONFIG_DIR_SYMBOL];
2488
+ const cwd = resolveCandidateCwd(userConfig ?? null, cliOptions, baseDir ?? configDir);
2487
2489
  const forcedPreset = resolvePresetName(userConfig?.preset);
2488
2490
  if (forcedPreset !== void 0 && !getPreset(forcedPreset)) {
2489
2491
  throw new Error(unknownPresetMessage(forcedPreset));
@@ -2583,7 +2585,11 @@ function resolveConfig(userConfig, cliOptions, baseDir) {
2583
2585
  hooks: resolveHooks(userConfig?.hooks),
2584
2586
  layers,
2585
2587
  kinds,
2586
- excludePatterns: resolveExcludePatterns(userConfig?.excludePatterns),
2588
+ // `exclude` is the flag spelling of the same setting; writing it in a config used to
2589
+ // be ignored without a word.
2590
+ excludePatterns: resolveExcludePatterns(
2591
+ userConfig?.excludePatterns ?? userConfig?.exclude
2592
+ ),
2587
2593
  secretRules
2588
2594
  });
2589
2595
  }
@@ -2730,21 +2736,28 @@ function isBinaryExtension(filePath) {
2730
2736
  return BINARY_EXTENSIONS.has(ext);
2731
2737
  }
2732
2738
  function isBinaryBuffer(buffer) {
2733
- const checkLength = Math.min(buffer.length, 8192);
2734
- for (let index = 0; index < checkLength; index++) {
2739
+ for (let index = 0; index < buffer.length; index++) {
2735
2740
  if (buffer[index] === 0) return true;
2736
2741
  }
2737
2742
  return false;
2738
2743
  }
2744
+ var BINARY_SCAN_BYTES = 8 * 1024 * 1024;
2745
+ var CHUNK = 64 * 1024;
2739
2746
  function isBinaryFile(absolutePath) {
2740
2747
  if (isBinaryExtension(absolutePath)) return true;
2741
2748
  let fd;
2742
2749
  try {
2743
2750
  fd = fs5.openSync(absolutePath, "r");
2744
- const buffer = Buffer.alloc(8192);
2745
- const bytesRead = fs5.readSync(fd, buffer, 0, 8192, 0);
2746
- if (bytesRead === 0) return false;
2747
- return isBinaryBuffer(buffer.subarray(0, bytesRead));
2751
+ const buffer = Buffer.alloc(CHUNK);
2752
+ let position = 0;
2753
+ while (position < BINARY_SCAN_BYTES) {
2754
+ const wanted = Math.min(CHUNK, BINARY_SCAN_BYTES - position);
2755
+ const bytesRead = fs5.readSync(fd, buffer, 0, wanted, position);
2756
+ if (bytesRead === 0) return false;
2757
+ if (isBinaryBuffer(buffer.subarray(0, bytesRead))) return true;
2758
+ position += bytesRead;
2759
+ }
2760
+ return false;
2748
2761
  } catch {
2749
2762
  return false;
2750
2763
  } finally {
@@ -3421,11 +3434,11 @@ function addScripts(cwd, notes) {
3421
3434
  const scripts = parsed.scripts && typeof parsed.scripts === "object" ? parsed.scripts : {};
3422
3435
  const added = [];
3423
3436
  if (!scripts.snapshot) {
3424
- scripts.snapshot = "codebase-snapshot generate";
3437
+ scripts.snapshot = "npx @ankurhalder/codebase-snapshot generate";
3425
3438
  added.push("snapshot");
3426
3439
  }
3427
3440
  if (!scripts["snapshot:validate"]) {
3428
- scripts["snapshot:validate"] = "codebase-snapshot validate";
3441
+ scripts["snapshot:validate"] = "npx @ankurhalder/codebase-snapshot validate";
3429
3442
  added.push("snapshot:validate");
3430
3443
  }
3431
3444
  if (added.length === 0) return [];
@@ -5498,7 +5511,7 @@ function validateSnapshot(configInput) {
5498
5511
 
5499
5512
  // src/index.ts
5500
5513
  var GENERATOR_NAME = "@ankurhalder/codebase-snapshot";
5501
- var GENERATOR_VERSION = "4.0.5";
5514
+ var GENERATOR_VERSION = "4.0.7";
5502
5515
  var SCHEMA_VERSION = "3.0.0";
5503
5516
  function sha256Hex2(input) {
5504
5517
  return crypto3.createHash("sha256").update(input).digest("hex");
@@ -6265,8 +6278,8 @@ function generateSnapshot(configInput, options) {
6265
6278
  const lineCount = countLines(rawContent);
6266
6279
  totalLines += lineCount;
6267
6280
  totalSizeBytes += stats.size;
6268
- const layer2 = classifyLayer(relativePath, config.layers);
6269
- const kind = classifyKind(relativePath, config.kinds);
6281
+ const layer2 = maskPathText(classifyLayer(relativePath, config.layers), config.secretRules);
6282
+ const kind = maskPathText(classifyKind(relativePath, config.kinds), config.secretRules);
6270
6283
  const language = detectLanguage(relativePath);
6271
6284
  bump(layerCounts, layer2);
6272
6285
  bump(kindCounts, kind);
@@ -6359,7 +6372,9 @@ function generateSnapshot(configInput, options) {
6359
6372
  name: GENERATOR_NAME,
6360
6373
  version: GENERATOR_VERSION
6361
6374
  },
6362
- git: gitInfo,
6375
+ // A branch name is user input and can carry a token: it reaches the manifest,
6376
+ // the README and the audit report.
6377
+ git: { ...gitInfo, branch: maskPathText(gitInfo.branch, config.secretRules) },
6363
6378
  budgets: {
6364
6379
  maxPartBytes: config.maxPartBytes,
6365
6380
  largeFileBytes: config.largeFileBytes
@@ -6376,7 +6391,12 @@ function generateSnapshot(configInput, options) {
6376
6391
  include: [...config.include].map(maskName),
6377
6392
  preset: config.preset,
6378
6393
  layersMode: config.layersMode,
6379
- budgets: { default: config.budgets.default, byLayer: { ...config.budgets.byLayer } },
6394
+ budgets: {
6395
+ default: config.budgets.default,
6396
+ byLayer: Object.fromEntries(
6397
+ Object.entries(config.budgets.byLayer).map(([name, bytes]) => [maskName(name), bytes])
6398
+ )
6399
+ },
6380
6400
  excludePatterns: [...config.excludePatterns].map(maskName),
6381
6401
  layers: config.layers.map((layer2) => maskName(layer2.name)),
6382
6402
  kinds: config.kinds.map((kind) => maskName(kind.kind))
@@ -7514,6 +7534,19 @@ function parseCliArgs(argv) {
7514
7534
  }
7515
7535
  command = resolved;
7516
7536
  }
7537
+ if (explicitMode !== void 0) {
7538
+ const resolvedMode = COMMAND_ALIASES.get(explicitMode);
7539
+ if (!resolvedMode) {
7540
+ throw new UsageError(
7541
+ `Unknown --mode "${explicitMode}". Expected one of: ${Array.from(COMMAND_ALIASES.keys()).join(", ")}.`
7542
+ );
7543
+ }
7544
+ if (firstPositional !== void 0 && resolvedMode !== command) {
7545
+ throw new UsageError(
7546
+ `--mode ${explicitMode} contradicts the command "${firstPositional}". Pass one or the other.`
7547
+ );
7548
+ }
7549
+ }
7517
7550
  const expectedArgs = COMMAND_ARITY[command];
7518
7551
  if (args.length !== expectedArgs) {
7519
7552
  if (command === "explain") {
@@ -7532,6 +7565,7 @@ function parseCliArgs(argv) {
7532
7565
  if (rawFormat !== "text" && rawFormat !== "json") {
7533
7566
  throw new UsageError(`--format must be "text" or "json", received "${rawFormat}".`);
7534
7567
  }
7568
+ let onlyNamesMonolith = false;
7535
7569
  const rawSkip = values["skip-artifacts"];
7536
7570
  const rawOnly = values["only-artifacts"];
7537
7571
  if (rawSkip !== void 0 && rawOnly !== void 0) {
@@ -7540,6 +7574,7 @@ function parseCliArgs(argv) {
7540
7574
  let skipArtifacts;
7541
7575
  if (rawOnly !== void 0) {
7542
7576
  const keep = parseArtifactList(String(rawOnly), "--only-artifacts");
7577
+ onlyNamesMonolith = keep.includes("monolith");
7543
7578
  skipArtifacts = ARTIFACT_NAMES.filter(
7544
7579
  (name) => !keep.includes(name)
7545
7580
  );
@@ -7594,7 +7629,7 @@ function parseCliArgs(argv) {
7594
7629
  target: values.target === void 0 ? void 0 : String(values.target),
7595
7630
  cwd: values.cwd === void 0 ? process.cwd() : path12.resolve(String(values.cwd)),
7596
7631
  outDir: values["out-dir"] === void 0 ? void 0 : String(values["out-dir"]),
7597
- includeMonolith: values["include-monolith"] === true ? true : void 0,
7632
+ includeMonolith: values["include-monolith"] === true || onlyNamesMonolith === true ? true : void 0,
7598
7633
  includeSensitiveFiles: values["include-sensitive-files"] === true ? true : void 0,
7599
7634
  maxPartBytes: parseByteOption(
7600
7635
  values["max-part-bytes"],
@@ -1729,7 +1729,7 @@ var DEFAULT_SECRET_PATTERNS = [
1729
1729
  },
1730
1730
  {
1731
1731
  rule: "aws-access-key-id",
1732
- pattern: /(?:AKIA|ASIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASCA)[0-9A-Z]{16}/
1732
+ pattern: /(?:AKIA|ASIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASCA|ABIA)[0-9A-Z]{16}/
1733
1733
  },
1734
1734
  {
1735
1735
  // The name is no longer limited to the three snake_case spellings: an
@@ -1768,7 +1768,7 @@ var DEFAULT_SECRET_PATTERNS = [
1768
1768
  // and batch tokens), `whsec_` (Stripe webhook secret), `dckr_pat_` (Docker
1769
1769
  // Hub), `hf_` (HuggingFace), `ya29.` (Google OAuth access token).
1770
1770
  rule: "known-vendor-token-prefix",
1771
- pattern: /\b(?:glpat-[A-Za-z0-9_-]{20,64}|hvs\.[A-Za-z0-9_-]{20,128}|s\.[A-Za-z0-9]{20,64}|whsec_[A-Za-z0-9]{20,64}|dckr_pat_[A-Za-z0-9_-]{20,64}|hf_[A-Za-z0-9]{30,64}|ya29\.[A-Za-z0-9_-]{20,128})/
1771
+ pattern: /\b(?:glpat-[A-Za-z0-9_-]{20,64}|glrt-[A-Za-z0-9_-]{20,64}|hvs\.[A-Za-z0-9_-]{20,128}|hvb\.[A-Za-z0-9_-]{20,128}|s\.[A-Za-z0-9]{20,64}|whsec_[A-Za-z0-9]{20,64}|dckr_pat_[A-Za-z0-9_-]{20,64}|hf_[A-Za-z0-9]{30,64}|ya29\.[A-Za-z0-9_-]{20,128}|sk_test_[A-Za-z0-9]{16,64}|1\/\/0[A-Za-z0-9_-]{20,64})/
1772
1772
  },
1773
1773
  {
1774
1774
  rule: "slack-webhook-url",
@@ -2665,6 +2665,7 @@ function walkDirectory(dir, baseDir, rootReal, visited, isRoot = false) {
2665
2665
  }
2666
2666
 
2667
2667
  // src/config.ts
2668
+ var CONFIG_DIR_SYMBOL = /* @__PURE__ */ Symbol.for("codebase-snapshot.configDir");
2668
2669
  var CONFIG_FILENAMES = [
2669
2670
  "snapshot.config.ts",
2670
2671
  "snapshot.config.js",
@@ -2925,6 +2926,13 @@ async function loadConfigFileDetailed(cwd) {
2925
2926
  }
2926
2927
  async function loadConfigFile(cwd) {
2927
2928
  const loaded = await loadConfigFileDetailed(cwd);
2929
+ if (loaded.config && loaded.file && typeof loaded.config === "object") {
2930
+ Object.defineProperty(loaded.config, CONFIG_DIR_SYMBOL, {
2931
+ value: path10.dirname(loaded.file),
2932
+ enumerable: false,
2933
+ configurable: true
2934
+ });
2935
+ }
2928
2936
  if (loaded.errors.length > 0) {
2929
2937
  throw new Error(`The config file could not be read: ${loaded.errors.join("; ")}`);
2930
2938
  }
@@ -3210,7 +3218,8 @@ function resolveCandidateCwd(userConfig, cliOptions, baseDir) {
3210
3218
  return resolved;
3211
3219
  }
3212
3220
  function resolveConfig(userConfig, cliOptions, baseDir) {
3213
- const cwd = resolveCandidateCwd(userConfig ?? null, cliOptions, baseDir);
3221
+ const configDir = userConfig?.[CONFIG_DIR_SYMBOL];
3222
+ const cwd = resolveCandidateCwd(userConfig ?? null, cliOptions, baseDir ?? configDir);
3214
3223
  const forcedPreset = resolvePresetName(userConfig?.preset);
3215
3224
  if (forcedPreset !== void 0 && !getPreset(forcedPreset)) {
3216
3225
  throw new Error(unknownPresetMessage(forcedPreset));
@@ -3310,7 +3319,11 @@ function resolveConfig(userConfig, cliOptions, baseDir) {
3310
3319
  hooks: resolveHooks(userConfig?.hooks),
3311
3320
  layers,
3312
3321
  kinds,
3313
- excludePatterns: resolveExcludePatterns(userConfig?.excludePatterns),
3322
+ // `exclude` is the flag spelling of the same setting; writing it in a config used to
3323
+ // be ignored without a word.
3324
+ excludePatterns: resolveExcludePatterns(
3325
+ userConfig?.excludePatterns ?? userConfig?.exclude
3326
+ ),
3314
3327
  secretRules
3315
3328
  });
3316
3329
  }
@@ -4077,21 +4090,28 @@ function isBinaryExtension(filePath) {
4077
4090
  return BINARY_EXTENSIONS.has(ext);
4078
4091
  }
4079
4092
  function isBinaryBuffer(buffer) {
4080
- const checkLength = Math.min(buffer.length, 8192);
4081
- for (let index = 0; index < checkLength; index++) {
4093
+ for (let index = 0; index < buffer.length; index++) {
4082
4094
  if (buffer[index] === 0) return true;
4083
4095
  }
4084
4096
  return false;
4085
4097
  }
4098
+ var BINARY_SCAN_BYTES = 8 * 1024 * 1024;
4099
+ var CHUNK = 64 * 1024;
4086
4100
  function isBinaryFile(absolutePath) {
4087
4101
  if (isBinaryExtension(absolutePath)) return true;
4088
4102
  let fd;
4089
4103
  try {
4090
4104
  fd = fs9.openSync(absolutePath, "r");
4091
- const buffer = Buffer.alloc(8192);
4092
- const bytesRead = fs9.readSync(fd, buffer, 0, 8192, 0);
4093
- if (bytesRead === 0) return false;
4094
- return isBinaryBuffer(buffer.subarray(0, bytesRead));
4105
+ const buffer = Buffer.alloc(CHUNK);
4106
+ let position = 0;
4107
+ while (position < BINARY_SCAN_BYTES) {
4108
+ const wanted = Math.min(CHUNK, BINARY_SCAN_BYTES - position);
4109
+ const bytesRead = fs9.readSync(fd, buffer, 0, wanted, position);
4110
+ if (bytesRead === 0) return false;
4111
+ if (isBinaryBuffer(buffer.subarray(0, bytesRead))) return true;
4112
+ position += bytesRead;
4113
+ }
4114
+ return false;
4095
4115
  } catch {
4096
4116
  return false;
4097
4117
  } finally {
@@ -5261,11 +5281,11 @@ function addScripts(cwd, notes) {
5261
5281
  const scripts = parsed.scripts && typeof parsed.scripts === "object" ? parsed.scripts : {};
5262
5282
  const added = [];
5263
5283
  if (!scripts.snapshot) {
5264
- scripts.snapshot = "codebase-snapshot generate";
5284
+ scripts.snapshot = "npx @ankurhalder/codebase-snapshot generate";
5265
5285
  added.push("snapshot");
5266
5286
  }
5267
5287
  if (!scripts["snapshot:validate"]) {
5268
- scripts["snapshot:validate"] = "codebase-snapshot validate";
5288
+ scripts["snapshot:validate"] = "npx @ankurhalder/codebase-snapshot validate";
5269
5289
  added.push("snapshot:validate");
5270
5290
  }
5271
5291
  if (added.length === 0) return [];
@@ -5461,7 +5481,7 @@ async function runInit(options) {
5461
5481
 
5462
5482
  // src/index.ts
5463
5483
  var GENERATOR_NAME = "@ankurhalder/codebase-snapshot";
5464
- var GENERATOR_VERSION = "4.0.5";
5484
+ var GENERATOR_VERSION = "4.0.7";
5465
5485
  var SCHEMA_VERSION = "3.0.0";
5466
5486
  function sha256Hex2(input) {
5467
5487
  return crypto.createHash("sha256").update(input).digest("hex");
@@ -6228,8 +6248,8 @@ function generateSnapshot(configInput, options) {
6228
6248
  const lineCount = countLines(rawContent);
6229
6249
  totalLines += lineCount;
6230
6250
  totalSizeBytes += stats.size;
6231
- const layer2 = classifyLayer(relativePath, config.layers);
6232
- const kind = classifyKind(relativePath, config.kinds);
6251
+ const layer2 = maskPathText(classifyLayer(relativePath, config.layers), config.secretRules);
6252
+ const kind = maskPathText(classifyKind(relativePath, config.kinds), config.secretRules);
6233
6253
  const language = detectLanguage(relativePath);
6234
6254
  bump(layerCounts, layer2);
6235
6255
  bump(kindCounts, kind);
@@ -6322,7 +6342,9 @@ function generateSnapshot(configInput, options) {
6322
6342
  name: GENERATOR_NAME,
6323
6343
  version: GENERATOR_VERSION
6324
6344
  },
6325
- git: gitInfo,
6345
+ // A branch name is user input and can carry a token: it reaches the manifest,
6346
+ // the README and the audit report.
6347
+ git: { ...gitInfo, branch: maskPathText(gitInfo.branch, config.secretRules) },
6326
6348
  budgets: {
6327
6349
  maxPartBytes: config.maxPartBytes,
6328
6350
  largeFileBytes: config.largeFileBytes
@@ -6339,7 +6361,12 @@ function generateSnapshot(configInput, options) {
6339
6361
  include: [...config.include].map(maskName),
6340
6362
  preset: config.preset,
6341
6363
  layersMode: config.layersMode,
6342
- budgets: { default: config.budgets.default, byLayer: { ...config.budgets.byLayer } },
6364
+ budgets: {
6365
+ default: config.budgets.default,
6366
+ byLayer: Object.fromEntries(
6367
+ Object.entries(config.budgets.byLayer).map(([name, bytes]) => [maskName(name), bytes])
6368
+ )
6369
+ },
6343
6370
  excludePatterns: [...config.excludePatterns].map(maskName),
6344
6371
  layers: config.layers.map((layer2) => maskName(layer2.name)),
6345
6372
  kinds: config.kinds.map((kind) => maskName(kind.kind))
@@ -6522,5 +6549,5 @@ async function generateSnapshotAsync(configInput, options) {
6522
6549
  }
6523
6550
 
6524
6551
  export { ARTIFACT_NAMES, DEFAULT_ANSWERS, DEFAULT_SECRET_PATTERNS, GENERATOR_NAME, GENERATOR_VERSION, LANGUAGE_PROFILES, MIN_MAX_PART_BYTES, PRESETS, PromptCancelled, SCHEMA_VERSION, anchorForPath, assertReplaceable, assertUsableConfigInput, collectFiles, compareManifests, countLines, defineConfig, detectLanguage, detectPreset, explainPath, fenceForContent, fenceForText, generateProjectTree, generateSnapshot, generateSnapshotAsync, getPreset, globToRegExp, isBinaryBuffer, isBinaryExtension, isBinaryFile, isInteractive, isResolvedConfig, isSensitivePath, listPresetNames, loadConfigFile, loadConfigFileDetailed, loadManifest, markResolvedConfig, matchRule, matchesExclude, normalizeResolvedConfig, parseByteSize, partitionFiles, profileForPath, renderConfig, renderDiffText, renderExplainText, renderMinimalConfig, renumberParts, resolveConfig, resolveSafeOutputDirs, runInit, scanAndRedactSecrets, stripJsonComments, summarizeJson, summarizeMarkdown, summarizeTypeScriptSource, summarizeWithProfile, supportsTypeScriptImports, truncatePreview, truncateToBytes, unknownPresetMessage, validateSnapshot };
6525
- //# sourceMappingURL=chunk-PCNDUNKT.js.map
6526
- //# sourceMappingURL=chunk-PCNDUNKT.js.map
6552
+ //# sourceMappingURL=chunk-VRJTXNJV.js.map
6553
+ //# sourceMappingURL=chunk-VRJTXNJV.js.map
package/dist/cli.cjs CHANGED
@@ -896,7 +896,7 @@ var DEFAULT_SECRET_PATTERNS = [
896
896
  },
897
897
  {
898
898
  rule: "aws-access-key-id",
899
- pattern: /(?:AKIA|ASIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASCA)[0-9A-Z]{16}/
899
+ pattern: /(?:AKIA|ASIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASCA|ABIA)[0-9A-Z]{16}/
900
900
  },
901
901
  {
902
902
  // The name is no longer limited to the three snake_case spellings: an
@@ -935,7 +935,7 @@ var DEFAULT_SECRET_PATTERNS = [
935
935
  // and batch tokens), `whsec_` (Stripe webhook secret), `dckr_pat_` (Docker
936
936
  // Hub), `hf_` (HuggingFace), `ya29.` (Google OAuth access token).
937
937
  rule: "known-vendor-token-prefix",
938
- pattern: /\b(?:glpat-[A-Za-z0-9_-]{20,64}|hvs\.[A-Za-z0-9_-]{20,128}|s\.[A-Za-z0-9]{20,64}|whsec_[A-Za-z0-9]{20,64}|dckr_pat_[A-Za-z0-9_-]{20,64}|hf_[A-Za-z0-9]{30,64}|ya29\.[A-Za-z0-9_-]{20,128})/
938
+ pattern: /\b(?:glpat-[A-Za-z0-9_-]{20,64}|glrt-[A-Za-z0-9_-]{20,64}|hvs\.[A-Za-z0-9_-]{20,128}|hvb\.[A-Za-z0-9_-]{20,128}|s\.[A-Za-z0-9]{20,64}|whsec_[A-Za-z0-9]{20,64}|dckr_pat_[A-Za-z0-9_-]{20,64}|hf_[A-Za-z0-9]{30,64}|ya29\.[A-Za-z0-9_-]{20,128}|sk_test_[A-Za-z0-9]{16,64}|1\/\/0[A-Za-z0-9_-]{20,64})/
939
939
  },
940
940
  {
941
941
  rule: "slack-webhook-url",
@@ -1957,6 +1957,7 @@ function renderDiffText(diff) {
1957
1957
  section("changed:", diff.changed);
1958
1958
  return lines.join("\n");
1959
1959
  }
1960
+ var CONFIG_DIR_SYMBOL = /* @__PURE__ */ Symbol.for("codebase-snapshot.configDir");
1960
1961
  var CONFIG_FILENAMES = [
1961
1962
  "snapshot.config.ts",
1962
1963
  "snapshot.config.js",
@@ -2495,7 +2496,8 @@ function resolveCandidateCwd(userConfig, cliOptions, baseDir) {
2495
2496
  return resolved;
2496
2497
  }
2497
2498
  function resolveConfig(userConfig, cliOptions, baseDir) {
2498
- const cwd = resolveCandidateCwd(userConfig ?? null, cliOptions, baseDir);
2499
+ const configDir = userConfig?.[CONFIG_DIR_SYMBOL];
2500
+ const cwd = resolveCandidateCwd(userConfig ?? null, cliOptions, baseDir ?? configDir);
2499
2501
  const forcedPreset = resolvePresetName(userConfig?.preset);
2500
2502
  if (forcedPreset !== void 0 && !getPreset(forcedPreset)) {
2501
2503
  throw new Error(unknownPresetMessage(forcedPreset));
@@ -2595,7 +2597,11 @@ function resolveConfig(userConfig, cliOptions, baseDir) {
2595
2597
  hooks: resolveHooks(userConfig?.hooks),
2596
2598
  layers,
2597
2599
  kinds,
2598
- excludePatterns: resolveExcludePatterns(userConfig?.excludePatterns),
2600
+ // `exclude` is the flag spelling of the same setting; writing it in a config used to
2601
+ // be ignored without a word.
2602
+ excludePatterns: resolveExcludePatterns(
2603
+ userConfig?.excludePatterns ?? userConfig?.exclude
2604
+ ),
2599
2605
  secretRules
2600
2606
  });
2601
2607
  }
@@ -2738,21 +2744,28 @@ function isBinaryExtension(filePath) {
2738
2744
  return BINARY_EXTENSIONS.has(ext);
2739
2745
  }
2740
2746
  function isBinaryBuffer(buffer) {
2741
- const checkLength = Math.min(buffer.length, 8192);
2742
- for (let index = 0; index < checkLength; index++) {
2747
+ for (let index = 0; index < buffer.length; index++) {
2743
2748
  if (buffer[index] === 0) return true;
2744
2749
  }
2745
2750
  return false;
2746
2751
  }
2752
+ var BINARY_SCAN_BYTES = 8 * 1024 * 1024;
2753
+ var CHUNK = 64 * 1024;
2747
2754
  function isBinaryFile(absolutePath) {
2748
2755
  if (isBinaryExtension(absolutePath)) return true;
2749
2756
  let fd;
2750
2757
  try {
2751
2758
  fd = fs9__namespace.openSync(absolutePath, "r");
2752
- const buffer = Buffer.alloc(8192);
2753
- const bytesRead = fs9__namespace.readSync(fd, buffer, 0, 8192, 0);
2754
- if (bytesRead === 0) return false;
2755
- return isBinaryBuffer(buffer.subarray(0, bytesRead));
2759
+ const buffer = Buffer.alloc(CHUNK);
2760
+ let position = 0;
2761
+ while (position < BINARY_SCAN_BYTES) {
2762
+ const wanted = Math.min(CHUNK, BINARY_SCAN_BYTES - position);
2763
+ const bytesRead = fs9__namespace.readSync(fd, buffer, 0, wanted, position);
2764
+ if (bytesRead === 0) return false;
2765
+ if (isBinaryBuffer(buffer.subarray(0, bytesRead))) return true;
2766
+ position += bytesRead;
2767
+ }
2768
+ return false;
2756
2769
  } catch {
2757
2770
  return false;
2758
2771
  } finally {
@@ -3417,11 +3430,11 @@ function addScripts(cwd, notes) {
3417
3430
  const scripts = parsed.scripts && typeof parsed.scripts === "object" ? parsed.scripts : {};
3418
3431
  const added = [];
3419
3432
  if (!scripts.snapshot) {
3420
- scripts.snapshot = "codebase-snapshot generate";
3433
+ scripts.snapshot = "npx @ankurhalder/codebase-snapshot generate";
3421
3434
  added.push("snapshot");
3422
3435
  }
3423
3436
  if (!scripts["snapshot:validate"]) {
3424
- scripts["snapshot:validate"] = "codebase-snapshot validate";
3437
+ scripts["snapshot:validate"] = "npx @ankurhalder/codebase-snapshot validate";
3425
3438
  added.push("snapshot:validate");
3426
3439
  }
3427
3440
  if (added.length === 0) return [];
@@ -5477,7 +5490,7 @@ function validateSnapshot(configInput) {
5477
5490
 
5478
5491
  // src/index.ts
5479
5492
  var GENERATOR_NAME = "@ankurhalder/codebase-snapshot";
5480
- var GENERATOR_VERSION = "4.0.5";
5493
+ var GENERATOR_VERSION = "4.0.7";
5481
5494
  var SCHEMA_VERSION = "3.0.0";
5482
5495
  function sha256Hex2(input) {
5483
5496
  return crypto__namespace.createHash("sha256").update(input).digest("hex");
@@ -6244,8 +6257,8 @@ function generateSnapshot(configInput, options) {
6244
6257
  const lineCount = countLines(rawContent);
6245
6258
  totalLines += lineCount;
6246
6259
  totalSizeBytes += stats.size;
6247
- const layer2 = classifyLayer(relativePath, config.layers);
6248
- const kind = classifyKind(relativePath, config.kinds);
6260
+ const layer2 = maskPathText(classifyLayer(relativePath, config.layers), config.secretRules);
6261
+ const kind = maskPathText(classifyKind(relativePath, config.kinds), config.secretRules);
6249
6262
  const language = detectLanguage(relativePath);
6250
6263
  bump(layerCounts, layer2);
6251
6264
  bump(kindCounts, kind);
@@ -6338,7 +6351,9 @@ function generateSnapshot(configInput, options) {
6338
6351
  name: GENERATOR_NAME,
6339
6352
  version: GENERATOR_VERSION
6340
6353
  },
6341
- git: gitInfo,
6354
+ // A branch name is user input and can carry a token: it reaches the manifest,
6355
+ // the README and the audit report.
6356
+ git: { ...gitInfo, branch: maskPathText(gitInfo.branch, config.secretRules) },
6342
6357
  budgets: {
6343
6358
  maxPartBytes: config.maxPartBytes,
6344
6359
  largeFileBytes: config.largeFileBytes
@@ -6355,7 +6370,12 @@ function generateSnapshot(configInput, options) {
6355
6370
  include: [...config.include].map(maskName),
6356
6371
  preset: config.preset,
6357
6372
  layersMode: config.layersMode,
6358
- budgets: { default: config.budgets.default, byLayer: { ...config.budgets.byLayer } },
6373
+ budgets: {
6374
+ default: config.budgets.default,
6375
+ byLayer: Object.fromEntries(
6376
+ Object.entries(config.budgets.byLayer).map(([name, bytes]) => [maskName(name), bytes])
6377
+ )
6378
+ },
6359
6379
  excludePatterns: [...config.excludePatterns].map(maskName),
6360
6380
  layers: config.layers.map((layer2) => maskName(layer2.name)),
6361
6381
  kinds: config.kinds.map((kind) => maskName(kind.kind))
@@ -7501,6 +7521,19 @@ function parseCliArgs(argv) {
7501
7521
  }
7502
7522
  command = resolved;
7503
7523
  }
7524
+ if (explicitMode !== void 0) {
7525
+ const resolvedMode = COMMAND_ALIASES.get(explicitMode);
7526
+ if (!resolvedMode) {
7527
+ throw new UsageError(
7528
+ `Unknown --mode "${explicitMode}". Expected one of: ${Array.from(COMMAND_ALIASES.keys()).join(", ")}.`
7529
+ );
7530
+ }
7531
+ if (firstPositional !== void 0 && resolvedMode !== command) {
7532
+ throw new UsageError(
7533
+ `--mode ${explicitMode} contradicts the command "${firstPositional}". Pass one or the other.`
7534
+ );
7535
+ }
7536
+ }
7504
7537
  const expectedArgs = COMMAND_ARITY[command];
7505
7538
  if (args.length !== expectedArgs) {
7506
7539
  if (command === "explain") {
@@ -7519,6 +7552,7 @@ function parseCliArgs(argv) {
7519
7552
  if (rawFormat !== "text" && rawFormat !== "json") {
7520
7553
  throw new UsageError(`--format must be "text" or "json", received "${rawFormat}".`);
7521
7554
  }
7555
+ let onlyNamesMonolith = false;
7522
7556
  const rawSkip = values["skip-artifacts"];
7523
7557
  const rawOnly = values["only-artifacts"];
7524
7558
  if (rawSkip !== void 0 && rawOnly !== void 0) {
@@ -7527,6 +7561,7 @@ function parseCliArgs(argv) {
7527
7561
  let skipArtifacts;
7528
7562
  if (rawOnly !== void 0) {
7529
7563
  const keep = parseArtifactList(String(rawOnly), "--only-artifacts");
7564
+ onlyNamesMonolith = keep.includes("monolith");
7530
7565
  skipArtifacts = ARTIFACT_NAMES.filter(
7531
7566
  (name) => !keep.includes(name)
7532
7567
  );
@@ -7581,7 +7616,7 @@ function parseCliArgs(argv) {
7581
7616
  target: values.target === void 0 ? void 0 : String(values.target),
7582
7617
  cwd: values.cwd === void 0 ? process.cwd() : path10__namespace.resolve(String(values.cwd)),
7583
7618
  outDir: values["out-dir"] === void 0 ? void 0 : String(values["out-dir"]),
7584
- includeMonolith: values["include-monolith"] === true ? true : void 0,
7619
+ includeMonolith: values["include-monolith"] === true || onlyNamesMonolith === true ? true : void 0,
7585
7620
  includeSensitiveFiles: values["include-sensitive-files"] === true ? true : void 0,
7586
7621
  maxPartBytes: parseByteOption(
7587
7622
  values["max-part-bytes"],
package/dist/cli.js CHANGED
@@ -1,4 +1,4 @@
1
- import { loadConfigFileDetailed, resolveConfig, validateSnapshot, explainPath, compareManifests, loadManifest, renderDiffText, generateSnapshot, GENERATOR_VERSION, ARTIFACT_NAMES, getPreset, unknownPresetMessage, GENERATOR_NAME, runInit, PromptCancelled, MIN_MAX_PART_BYTES, SCHEMA_VERSION, PRESETS, parseByteSize, renderExplainText } from './chunk-PCNDUNKT.js';
1
+ import { loadConfigFileDetailed, resolveConfig, validateSnapshot, explainPath, compareManifests, loadManifest, renderDiffText, generateSnapshot, GENERATOR_VERSION, ARTIFACT_NAMES, getPreset, unknownPresetMessage, GENERATOR_NAME, runInit, PromptCancelled, MIN_MAX_PART_BYTES, SCHEMA_VERSION, PRESETS, parseByteSize, renderExplainText } from './chunk-VRJTXNJV.js';
2
2
  import * as fs from 'fs';
3
3
  import * as path2 from 'path';
4
4
  import { parseArgs } from 'util';
@@ -970,6 +970,19 @@ function parseCliArgs(argv) {
970
970
  }
971
971
  command = resolved;
972
972
  }
973
+ if (explicitMode !== void 0) {
974
+ const resolvedMode = COMMAND_ALIASES.get(explicitMode);
975
+ if (!resolvedMode) {
976
+ throw new UsageError(
977
+ `Unknown --mode "${explicitMode}". Expected one of: ${Array.from(COMMAND_ALIASES.keys()).join(", ")}.`
978
+ );
979
+ }
980
+ if (firstPositional !== void 0 && resolvedMode !== command) {
981
+ throw new UsageError(
982
+ `--mode ${explicitMode} contradicts the command "${firstPositional}". Pass one or the other.`
983
+ );
984
+ }
985
+ }
973
986
  const expectedArgs = COMMAND_ARITY[command];
974
987
  if (args.length !== expectedArgs) {
975
988
  if (command === "explain") {
@@ -988,6 +1001,7 @@ function parseCliArgs(argv) {
988
1001
  if (rawFormat !== "text" && rawFormat !== "json") {
989
1002
  throw new UsageError(`--format must be "text" or "json", received "${rawFormat}".`);
990
1003
  }
1004
+ let onlyNamesMonolith = false;
991
1005
  const rawSkip = values["skip-artifacts"];
992
1006
  const rawOnly = values["only-artifacts"];
993
1007
  if (rawSkip !== void 0 && rawOnly !== void 0) {
@@ -996,6 +1010,7 @@ function parseCliArgs(argv) {
996
1010
  let skipArtifacts;
997
1011
  if (rawOnly !== void 0) {
998
1012
  const keep = parseArtifactList(String(rawOnly), "--only-artifacts");
1013
+ onlyNamesMonolith = keep.includes("monolith");
999
1014
  skipArtifacts = ARTIFACT_NAMES.filter(
1000
1015
  (name) => !keep.includes(name)
1001
1016
  );
@@ -1050,7 +1065,7 @@ function parseCliArgs(argv) {
1050
1065
  target: values.target === void 0 ? void 0 : String(values.target),
1051
1066
  cwd: values.cwd === void 0 ? process.cwd() : path2.resolve(String(values.cwd)),
1052
1067
  outDir: values["out-dir"] === void 0 ? void 0 : String(values["out-dir"]),
1053
- includeMonolith: values["include-monolith"] === true ? true : void 0,
1068
+ includeMonolith: values["include-monolith"] === true || onlyNamesMonolith === true ? true : void 0,
1054
1069
  includeSensitiveFiles: values["include-sensitive-files"] === true ? true : void 0,
1055
1070
  maxPartBytes: parseByteOption(
1056
1071
  values["max-part-bytes"],
package/dist/index.cjs CHANGED
@@ -1758,7 +1758,7 @@ var DEFAULT_SECRET_PATTERNS = [
1758
1758
  },
1759
1759
  {
1760
1760
  rule: "aws-access-key-id",
1761
- pattern: /(?:AKIA|ASIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASCA)[0-9A-Z]{16}/
1761
+ pattern: /(?:AKIA|ASIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASCA|ABIA)[0-9A-Z]{16}/
1762
1762
  },
1763
1763
  {
1764
1764
  // The name is no longer limited to the three snake_case spellings: an
@@ -1797,7 +1797,7 @@ var DEFAULT_SECRET_PATTERNS = [
1797
1797
  // and batch tokens), `whsec_` (Stripe webhook secret), `dckr_pat_` (Docker
1798
1798
  // Hub), `hf_` (HuggingFace), `ya29.` (Google OAuth access token).
1799
1799
  rule: "known-vendor-token-prefix",
1800
- pattern: /\b(?:glpat-[A-Za-z0-9_-]{20,64}|hvs\.[A-Za-z0-9_-]{20,128}|s\.[A-Za-z0-9]{20,64}|whsec_[A-Za-z0-9]{20,64}|dckr_pat_[A-Za-z0-9_-]{20,64}|hf_[A-Za-z0-9]{30,64}|ya29\.[A-Za-z0-9_-]{20,128})/
1800
+ pattern: /\b(?:glpat-[A-Za-z0-9_-]{20,64}|glrt-[A-Za-z0-9_-]{20,64}|hvs\.[A-Za-z0-9_-]{20,128}|hvb\.[A-Za-z0-9_-]{20,128}|s\.[A-Za-z0-9]{20,64}|whsec_[A-Za-z0-9]{20,64}|dckr_pat_[A-Za-z0-9_-]{20,64}|hf_[A-Za-z0-9]{30,64}|ya29\.[A-Za-z0-9_-]{20,128}|sk_test_[A-Za-z0-9]{16,64}|1\/\/0[A-Za-z0-9_-]{20,64})/
1801
1801
  },
1802
1802
  {
1803
1803
  rule: "slack-webhook-url",
@@ -2694,6 +2694,7 @@ function walkDirectory(dir, baseDir, rootReal, visited, isRoot = false) {
2694
2694
  }
2695
2695
 
2696
2696
  // src/config.ts
2697
+ var CONFIG_DIR_SYMBOL = /* @__PURE__ */ Symbol.for("codebase-snapshot.configDir");
2697
2698
  var CONFIG_FILENAMES = [
2698
2699
  "snapshot.config.ts",
2699
2700
  "snapshot.config.js",
@@ -2954,6 +2955,13 @@ async function loadConfigFileDetailed(cwd) {
2954
2955
  }
2955
2956
  async function loadConfigFile(cwd) {
2956
2957
  const loaded = await loadConfigFileDetailed(cwd);
2958
+ if (loaded.config && loaded.file && typeof loaded.config === "object") {
2959
+ Object.defineProperty(loaded.config, CONFIG_DIR_SYMBOL, {
2960
+ value: path10__namespace.dirname(loaded.file),
2961
+ enumerable: false,
2962
+ configurable: true
2963
+ });
2964
+ }
2957
2965
  if (loaded.errors.length > 0) {
2958
2966
  throw new Error(`The config file could not be read: ${loaded.errors.join("; ")}`);
2959
2967
  }
@@ -3239,7 +3247,8 @@ function resolveCandidateCwd(userConfig, cliOptions, baseDir) {
3239
3247
  return resolved;
3240
3248
  }
3241
3249
  function resolveConfig(userConfig, cliOptions, baseDir) {
3242
- const cwd = resolveCandidateCwd(userConfig ?? null, cliOptions, baseDir);
3250
+ const configDir = userConfig?.[CONFIG_DIR_SYMBOL];
3251
+ const cwd = resolveCandidateCwd(userConfig ?? null, cliOptions, baseDir ?? configDir);
3243
3252
  const forcedPreset = resolvePresetName(userConfig?.preset);
3244
3253
  if (forcedPreset !== void 0 && !getPreset(forcedPreset)) {
3245
3254
  throw new Error(unknownPresetMessage(forcedPreset));
@@ -3339,7 +3348,11 @@ function resolveConfig(userConfig, cliOptions, baseDir) {
3339
3348
  hooks: resolveHooks(userConfig?.hooks),
3340
3349
  layers,
3341
3350
  kinds,
3342
- excludePatterns: resolveExcludePatterns(userConfig?.excludePatterns),
3351
+ // `exclude` is the flag spelling of the same setting; writing it in a config used to
3352
+ // be ignored without a word.
3353
+ excludePatterns: resolveExcludePatterns(
3354
+ userConfig?.excludePatterns ?? userConfig?.exclude
3355
+ ),
3343
3356
  secretRules
3344
3357
  });
3345
3358
  }
@@ -4106,21 +4119,28 @@ function isBinaryExtension(filePath) {
4106
4119
  return BINARY_EXTENSIONS.has(ext);
4107
4120
  }
4108
4121
  function isBinaryBuffer(buffer) {
4109
- const checkLength = Math.min(buffer.length, 8192);
4110
- for (let index = 0; index < checkLength; index++) {
4122
+ for (let index = 0; index < buffer.length; index++) {
4111
4123
  if (buffer[index] === 0) return true;
4112
4124
  }
4113
4125
  return false;
4114
4126
  }
4127
+ var BINARY_SCAN_BYTES = 8 * 1024 * 1024;
4128
+ var CHUNK = 64 * 1024;
4115
4129
  function isBinaryFile(absolutePath) {
4116
4130
  if (isBinaryExtension(absolutePath)) return true;
4117
4131
  let fd;
4118
4132
  try {
4119
4133
  fd = fs9__namespace.openSync(absolutePath, "r");
4120
- const buffer = Buffer.alloc(8192);
4121
- const bytesRead = fs9__namespace.readSync(fd, buffer, 0, 8192, 0);
4122
- if (bytesRead === 0) return false;
4123
- return isBinaryBuffer(buffer.subarray(0, bytesRead));
4134
+ const buffer = Buffer.alloc(CHUNK);
4135
+ let position = 0;
4136
+ while (position < BINARY_SCAN_BYTES) {
4137
+ const wanted = Math.min(CHUNK, BINARY_SCAN_BYTES - position);
4138
+ const bytesRead = fs9__namespace.readSync(fd, buffer, 0, wanted, position);
4139
+ if (bytesRead === 0) return false;
4140
+ if (isBinaryBuffer(buffer.subarray(0, bytesRead))) return true;
4141
+ position += bytesRead;
4142
+ }
4143
+ return false;
4124
4144
  } catch {
4125
4145
  return false;
4126
4146
  } finally {
@@ -5290,11 +5310,11 @@ function addScripts(cwd, notes) {
5290
5310
  const scripts = parsed.scripts && typeof parsed.scripts === "object" ? parsed.scripts : {};
5291
5311
  const added = [];
5292
5312
  if (!scripts.snapshot) {
5293
- scripts.snapshot = "codebase-snapshot generate";
5313
+ scripts.snapshot = "npx @ankurhalder/codebase-snapshot generate";
5294
5314
  added.push("snapshot");
5295
5315
  }
5296
5316
  if (!scripts["snapshot:validate"]) {
5297
- scripts["snapshot:validate"] = "codebase-snapshot validate";
5317
+ scripts["snapshot:validate"] = "npx @ankurhalder/codebase-snapshot validate";
5298
5318
  added.push("snapshot:validate");
5299
5319
  }
5300
5320
  if (added.length === 0) return [];
@@ -5490,7 +5510,7 @@ async function runInit(options) {
5490
5510
 
5491
5511
  // src/index.ts
5492
5512
  var GENERATOR_NAME = "@ankurhalder/codebase-snapshot";
5493
- var GENERATOR_VERSION = "4.0.5";
5513
+ var GENERATOR_VERSION = "4.0.7";
5494
5514
  var SCHEMA_VERSION = "3.0.0";
5495
5515
  function sha256Hex2(input) {
5496
5516
  return crypto__namespace.createHash("sha256").update(input).digest("hex");
@@ -6257,8 +6277,8 @@ function generateSnapshot(configInput, options) {
6257
6277
  const lineCount = countLines(rawContent);
6258
6278
  totalLines += lineCount;
6259
6279
  totalSizeBytes += stats.size;
6260
- const layer2 = classifyLayer(relativePath, config.layers);
6261
- const kind = classifyKind(relativePath, config.kinds);
6280
+ const layer2 = maskPathText(classifyLayer(relativePath, config.layers), config.secretRules);
6281
+ const kind = maskPathText(classifyKind(relativePath, config.kinds), config.secretRules);
6262
6282
  const language = detectLanguage(relativePath);
6263
6283
  bump(layerCounts, layer2);
6264
6284
  bump(kindCounts, kind);
@@ -6351,7 +6371,9 @@ function generateSnapshot(configInput, options) {
6351
6371
  name: GENERATOR_NAME,
6352
6372
  version: GENERATOR_VERSION
6353
6373
  },
6354
- git: gitInfo,
6374
+ // A branch name is user input and can carry a token: it reaches the manifest,
6375
+ // the README and the audit report.
6376
+ git: { ...gitInfo, branch: maskPathText(gitInfo.branch, config.secretRules) },
6355
6377
  budgets: {
6356
6378
  maxPartBytes: config.maxPartBytes,
6357
6379
  largeFileBytes: config.largeFileBytes
@@ -6368,7 +6390,12 @@ function generateSnapshot(configInput, options) {
6368
6390
  include: [...config.include].map(maskName),
6369
6391
  preset: config.preset,
6370
6392
  layersMode: config.layersMode,
6371
- budgets: { default: config.budgets.default, byLayer: { ...config.budgets.byLayer } },
6393
+ budgets: {
6394
+ default: config.budgets.default,
6395
+ byLayer: Object.fromEntries(
6396
+ Object.entries(config.budgets.byLayer).map(([name, bytes]) => [maskName(name), bytes])
6397
+ )
6398
+ },
6372
6399
  excludePatterns: [...config.excludePatterns].map(maskName),
6373
6400
  layers: config.layers.map((layer2) => maskName(layer2.name)),
6374
6401
  kinds: config.kinds.map((kind) => maskName(kind.kind))
package/dist/index.d.cts CHANGED
@@ -495,7 +495,7 @@ declare function matchesExclude(relativePath: string, pattern: string): boolean;
495
495
  declare function collectFiles(cwd: string, options?: CollectOptions): CollectResult;
496
496
 
497
497
  declare const GENERATOR_NAME = "@ankurhalder/codebase-snapshot";
498
- declare const GENERATOR_VERSION = "4.0.5";
498
+ declare const GENERATOR_VERSION = "4.0.7";
499
499
  declare const SCHEMA_VERSION = "3.0.0";
500
500
  interface GenerateOptions {
501
501
  /** Compute the full manifest but write nothing to disk. */
package/dist/index.d.ts CHANGED
@@ -495,7 +495,7 @@ declare function matchesExclude(relativePath: string, pattern: string): boolean;
495
495
  declare function collectFiles(cwd: string, options?: CollectOptions): CollectResult;
496
496
 
497
497
  declare const GENERATOR_NAME = "@ankurhalder/codebase-snapshot";
498
- declare const GENERATOR_VERSION = "4.0.5";
498
+ declare const GENERATOR_VERSION = "4.0.7";
499
499
  declare const SCHEMA_VERSION = "3.0.0";
500
500
  interface GenerateOptions {
501
501
  /** Compute the full manifest but write nothing to disk. */
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- export { ARTIFACT_NAMES, DEFAULT_ANSWERS, DEFAULT_SECRET_PATTERNS, GENERATOR_NAME, GENERATOR_VERSION, LANGUAGE_PROFILES, MIN_MAX_PART_BYTES, PRESETS, PromptCancelled, SCHEMA_VERSION, anchorForPath, assertReplaceable, assertUsableConfigInput, collectFiles, compareManifests, countLines, defineConfig, detectLanguage, detectPreset, explainPath, fenceForContent, fenceForText, generateProjectTree, generateSnapshot, generateSnapshotAsync, getPreset, globToRegExp, isBinaryBuffer, isBinaryExtension, isBinaryFile, isInteractive, isResolvedConfig, isSensitivePath, listPresetNames, loadConfigFile, loadConfigFileDetailed, loadManifest, markResolvedConfig, matchRule, matchesExclude, normalizeResolvedConfig, parseByteSize, partitionFiles, profileForPath, renderConfig, renderDiffText, renderExplainText, renderMinimalConfig, renumberParts, resolveConfig, resolveSafeOutputDirs, runInit, scanAndRedactSecrets, stripJsonComments, summarizeJson, summarizeMarkdown, summarizeTypeScriptSource, summarizeWithProfile, supportsTypeScriptImports, truncatePreview, truncateToBytes, validateSnapshot } from './chunk-PCNDUNKT.js';
1
+ export { ARTIFACT_NAMES, DEFAULT_ANSWERS, DEFAULT_SECRET_PATTERNS, GENERATOR_NAME, GENERATOR_VERSION, LANGUAGE_PROFILES, MIN_MAX_PART_BYTES, PRESETS, PromptCancelled, SCHEMA_VERSION, anchorForPath, assertReplaceable, assertUsableConfigInput, collectFiles, compareManifests, countLines, defineConfig, detectLanguage, detectPreset, explainPath, fenceForContent, fenceForText, generateProjectTree, generateSnapshot, generateSnapshotAsync, getPreset, globToRegExp, isBinaryBuffer, isBinaryExtension, isBinaryFile, isInteractive, isResolvedConfig, isSensitivePath, listPresetNames, loadConfigFile, loadConfigFileDetailed, loadManifest, markResolvedConfig, matchRule, matchesExclude, normalizeResolvedConfig, parseByteSize, partitionFiles, profileForPath, renderConfig, renderDiffText, renderExplainText, renderMinimalConfig, renumberParts, resolveConfig, resolveSafeOutputDirs, runInit, scanAndRedactSecrets, stripJsonComments, summarizeJson, summarizeMarkdown, summarizeTypeScriptSource, summarizeWithProfile, supportsTypeScriptImports, truncatePreview, truncateToBytes, validateSnapshot } from './chunk-VRJTXNJV.js';
2
2
  //# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ankurhalder/codebase-snapshot",
3
- "version": "4.0.5",
3
+ "version": "4.0.7",
4
4
  "description": "Production-grade LLM codebase snapshot generator, auditor, and AST partitioner",
5
5
  "keywords": [
6
6
  "codebase",