@ankurhalder/codebase-snapshot 4.0.4 → 4.0.6

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
@@ -1942,6 +1942,7 @@ import * as path7 from "path";
1942
1942
 
1943
1943
  // src/config.ts
1944
1944
  import * as fs4 from "fs";
1945
+ import { createHash } from "crypto";
1945
1946
  import * as path4 from "path";
1946
1947
  import { pathToFileURL } from "url";
1947
1948
  var CONFIG_FILENAMES = [
@@ -2621,6 +2622,27 @@ function classifyKind(filePath, kinds) {
2621
2622
  }
2622
2623
  return "other";
2623
2624
  }
2625
+ function configDigest(config) {
2626
+ const material = {
2627
+ maxPartBytes: config.maxPartBytes,
2628
+ largeFileBytes: config.largeFileBytes,
2629
+ previewHeadLines: config.previewHeadLines,
2630
+ previewTailLines: config.previewTailLines,
2631
+ includeMonolith: config.includeMonolith,
2632
+ maxMonolithBytes: config.maxMonolithBytes ?? null,
2633
+ includeSensitiveFiles: config.includeSensitiveFiles,
2634
+ artifacts: config.artifacts,
2635
+ include: config.include,
2636
+ excludePatterns: config.excludePatterns,
2637
+ preset: config.preset,
2638
+ layersMode: config.layersMode,
2639
+ budgets: config.budgets,
2640
+ layers: config.layers.map((layer2) => layer2.name),
2641
+ kinds: config.kinds.map((kind) => kind.kind),
2642
+ secretRules: config.secretRules.map((rule) => `${rule.rule}:${rule.pattern.source}`).sort()
2643
+ };
2644
+ return createHash("sha256").update(JSON.stringify(material)).digest("hex");
2645
+ }
2624
2646
 
2625
2647
  // src/partitioner/preview.ts
2626
2648
  function countLines(content) {
@@ -2708,21 +2730,28 @@ function isBinaryExtension(filePath) {
2708
2730
  return BINARY_EXTENSIONS.has(ext);
2709
2731
  }
2710
2732
  function isBinaryBuffer(buffer) {
2711
- const checkLength = Math.min(buffer.length, 8192);
2712
- for (let index = 0; index < checkLength; index++) {
2733
+ for (let index = 0; index < buffer.length; index++) {
2713
2734
  if (buffer[index] === 0) return true;
2714
2735
  }
2715
2736
  return false;
2716
2737
  }
2738
+ var BINARY_SCAN_BYTES = 8 * 1024 * 1024;
2739
+ var CHUNK = 64 * 1024;
2717
2740
  function isBinaryFile(absolutePath) {
2718
2741
  if (isBinaryExtension(absolutePath)) return true;
2719
2742
  let fd;
2720
2743
  try {
2721
2744
  fd = fs5.openSync(absolutePath, "r");
2722
- const buffer = Buffer.alloc(8192);
2723
- const bytesRead = fs5.readSync(fd, buffer, 0, 8192, 0);
2724
- if (bytesRead === 0) return false;
2725
- return isBinaryBuffer(buffer.subarray(0, bytesRead));
2745
+ const buffer = Buffer.alloc(CHUNK);
2746
+ let position = 0;
2747
+ while (position < BINARY_SCAN_BYTES) {
2748
+ const wanted = Math.min(CHUNK, BINARY_SCAN_BYTES - position);
2749
+ const bytesRead = fs5.readSync(fd, buffer, 0, wanted, position);
2750
+ if (bytesRead === 0) return false;
2751
+ if (isBinaryBuffer(buffer.subarray(0, bytesRead))) return true;
2752
+ position += bytesRead;
2753
+ }
2754
+ return false;
2726
2755
  } catch {
2727
2756
  return false;
2728
2757
  } finally {
@@ -5256,6 +5285,11 @@ function validateSnapshot(configInput) {
5256
5285
  const currentExcludes = config.excludePatterns.map(maskValue);
5257
5286
  const currentInclude = config.include.map(maskValue);
5258
5287
  const recorded = manifest.config;
5288
+ if (recorded?.digest && recorded.digest !== configDigest(config)) {
5289
+ drift.configMismatches.push(
5290
+ "configuration: the settings differ from the ones this snapshot was generated with (run generate)"
5291
+ );
5292
+ }
5259
5293
  if (recorded && typeof recorded === "object") {
5260
5294
  if (recorded.maxPartBytes !== config.maxPartBytes) {
5261
5295
  drift.configMismatches.push(
@@ -5471,7 +5505,7 @@ function validateSnapshot(configInput) {
5471
5505
 
5472
5506
  // src/index.ts
5473
5507
  var GENERATOR_NAME = "@ankurhalder/codebase-snapshot";
5474
- var GENERATOR_VERSION = "4.0.4";
5508
+ var GENERATOR_VERSION = "4.0.6";
5475
5509
  var SCHEMA_VERSION = "3.0.0";
5476
5510
  function sha256Hex2(input) {
5477
5511
  return crypto3.createHash("sha256").update(input).digest("hex");
@@ -6238,8 +6272,8 @@ function generateSnapshot(configInput, options) {
6238
6272
  const lineCount = countLines(rawContent);
6239
6273
  totalLines += lineCount;
6240
6274
  totalSizeBytes += stats.size;
6241
- const layer2 = classifyLayer(relativePath, config.layers);
6242
- const kind = classifyKind(relativePath, config.kinds);
6275
+ const layer2 = maskPathText(classifyLayer(relativePath, config.layers), config.secretRules);
6276
+ const kind = maskPathText(classifyKind(relativePath, config.kinds), config.secretRules);
6243
6277
  const language = detectLanguage(relativePath);
6244
6278
  bump(layerCounts, layer2);
6245
6279
  bump(kindCounts, kind);
@@ -6338,6 +6372,7 @@ function generateSnapshot(configInput, options) {
6338
6372
  largeFileBytes: config.largeFileBytes
6339
6373
  },
6340
6374
  config: {
6375
+ digest: configDigest(config),
6341
6376
  maxPartBytes: config.maxPartBytes,
6342
6377
  largeFileBytes: config.largeFileBytes,
6343
6378
  previewHeadLines: config.previewHeadLines,
@@ -6348,7 +6383,12 @@ function generateSnapshot(configInput, options) {
6348
6383
  include: [...config.include].map(maskName),
6349
6384
  preset: config.preset,
6350
6385
  layersMode: config.layersMode,
6351
- budgets: { default: config.budgets.default, byLayer: { ...config.budgets.byLayer } },
6386
+ budgets: {
6387
+ default: config.budgets.default,
6388
+ byLayer: Object.fromEntries(
6389
+ Object.entries(config.budgets.byLayer).map(([name, bytes]) => [maskName(name), bytes])
6390
+ )
6391
+ },
6352
6392
  excludePatterns: [...config.excludePatterns].map(maskName),
6353
6393
  layers: config.layers.map((layer2) => maskName(layer2.name)),
6354
6394
  kinds: config.kinds.map((kind) => maskName(kind.kind))
@@ -1,4 +1,5 @@
1
1
  import * as crypto from 'crypto';
2
+ import { createHash } from 'crypto';
2
3
  import * as fs9 from 'fs';
3
4
  import * as os from 'os';
4
5
  import * as path10 from 'path';
@@ -3348,6 +3349,27 @@ function classifyKind(filePath, kinds) {
3348
3349
  }
3349
3350
  return "other";
3350
3351
  }
3352
+ function configDigest(config) {
3353
+ const material = {
3354
+ maxPartBytes: config.maxPartBytes,
3355
+ largeFileBytes: config.largeFileBytes,
3356
+ previewHeadLines: config.previewHeadLines,
3357
+ previewTailLines: config.previewTailLines,
3358
+ includeMonolith: config.includeMonolith,
3359
+ maxMonolithBytes: config.maxMonolithBytes ?? null,
3360
+ includeSensitiveFiles: config.includeSensitiveFiles,
3361
+ artifacts: config.artifacts,
3362
+ include: config.include,
3363
+ excludePatterns: config.excludePatterns,
3364
+ preset: config.preset,
3365
+ layersMode: config.layersMode,
3366
+ budgets: config.budgets,
3367
+ layers: config.layers.map((layer2) => layer2.name),
3368
+ kinds: config.kinds.map((kind) => kind.kind),
3369
+ secretRules: config.secretRules.map((rule) => `${rule.rule}:${rule.pattern.source}`).sort()
3370
+ };
3371
+ return createHash("sha256").update(JSON.stringify(material)).digest("hex");
3372
+ }
3351
3373
 
3352
3374
  // src/define-config.ts
3353
3375
  function defineConfig(config) {
@@ -4055,21 +4077,28 @@ function isBinaryExtension(filePath) {
4055
4077
  return BINARY_EXTENSIONS.has(ext);
4056
4078
  }
4057
4079
  function isBinaryBuffer(buffer) {
4058
- const checkLength = Math.min(buffer.length, 8192);
4059
- for (let index = 0; index < checkLength; index++) {
4080
+ for (let index = 0; index < buffer.length; index++) {
4060
4081
  if (buffer[index] === 0) return true;
4061
4082
  }
4062
4083
  return false;
4063
4084
  }
4085
+ var BINARY_SCAN_BYTES = 8 * 1024 * 1024;
4086
+ var CHUNK = 64 * 1024;
4064
4087
  function isBinaryFile(absolutePath) {
4065
4088
  if (isBinaryExtension(absolutePath)) return true;
4066
4089
  let fd;
4067
4090
  try {
4068
4091
  fd = fs9.openSync(absolutePath, "r");
4069
- const buffer = Buffer.alloc(8192);
4070
- const bytesRead = fs9.readSync(fd, buffer, 0, 8192, 0);
4071
- if (bytesRead === 0) return false;
4072
- return isBinaryBuffer(buffer.subarray(0, bytesRead));
4092
+ const buffer = Buffer.alloc(CHUNK);
4093
+ let position = 0;
4094
+ while (position < BINARY_SCAN_BYTES) {
4095
+ const wanted = Math.min(CHUNK, BINARY_SCAN_BYTES - position);
4096
+ const bytesRead = fs9.readSync(fd, buffer, 0, wanted, position);
4097
+ if (bytesRead === 0) return false;
4098
+ if (isBinaryBuffer(buffer.subarray(0, bytesRead))) return true;
4099
+ position += bytesRead;
4100
+ }
4101
+ return false;
4073
4102
  } catch {
4074
4103
  return false;
4075
4104
  } finally {
@@ -4304,6 +4333,11 @@ function validateSnapshot(configInput) {
4304
4333
  const currentExcludes = config.excludePatterns.map(maskValue);
4305
4334
  const currentInclude = config.include.map(maskValue);
4306
4335
  const recorded = manifest.config;
4336
+ if (recorded?.digest && recorded.digest !== configDigest(config)) {
4337
+ drift.configMismatches.push(
4338
+ "configuration: the settings differ from the ones this snapshot was generated with (run generate)"
4339
+ );
4340
+ }
4307
4341
  if (recorded && typeof recorded === "object") {
4308
4342
  if (recorded.maxPartBytes !== config.maxPartBytes) {
4309
4343
  drift.configMismatches.push(
@@ -5434,7 +5468,7 @@ async function runInit(options) {
5434
5468
 
5435
5469
  // src/index.ts
5436
5470
  var GENERATOR_NAME = "@ankurhalder/codebase-snapshot";
5437
- var GENERATOR_VERSION = "4.0.4";
5471
+ var GENERATOR_VERSION = "4.0.6";
5438
5472
  var SCHEMA_VERSION = "3.0.0";
5439
5473
  function sha256Hex2(input) {
5440
5474
  return crypto.createHash("sha256").update(input).digest("hex");
@@ -6201,8 +6235,8 @@ function generateSnapshot(configInput, options) {
6201
6235
  const lineCount = countLines(rawContent);
6202
6236
  totalLines += lineCount;
6203
6237
  totalSizeBytes += stats.size;
6204
- const layer2 = classifyLayer(relativePath, config.layers);
6205
- const kind = classifyKind(relativePath, config.kinds);
6238
+ const layer2 = maskPathText(classifyLayer(relativePath, config.layers), config.secretRules);
6239
+ const kind = maskPathText(classifyKind(relativePath, config.kinds), config.secretRules);
6206
6240
  const language = detectLanguage(relativePath);
6207
6241
  bump(layerCounts, layer2);
6208
6242
  bump(kindCounts, kind);
@@ -6301,6 +6335,7 @@ function generateSnapshot(configInput, options) {
6301
6335
  largeFileBytes: config.largeFileBytes
6302
6336
  },
6303
6337
  config: {
6338
+ digest: configDigest(config),
6304
6339
  maxPartBytes: config.maxPartBytes,
6305
6340
  largeFileBytes: config.largeFileBytes,
6306
6341
  previewHeadLines: config.previewHeadLines,
@@ -6311,7 +6346,12 @@ function generateSnapshot(configInput, options) {
6311
6346
  include: [...config.include].map(maskName),
6312
6347
  preset: config.preset,
6313
6348
  layersMode: config.layersMode,
6314
- budgets: { default: config.budgets.default, byLayer: { ...config.budgets.byLayer } },
6349
+ budgets: {
6350
+ default: config.budgets.default,
6351
+ byLayer: Object.fromEntries(
6352
+ Object.entries(config.budgets.byLayer).map(([name, bytes]) => [maskName(name), bytes])
6353
+ )
6354
+ },
6315
6355
  excludePatterns: [...config.excludePatterns].map(maskName),
6316
6356
  layers: config.layers.map((layer2) => maskName(layer2.name)),
6317
6357
  kinds: config.kinds.map((kind) => maskName(kind.kind))
@@ -6494,5 +6534,5 @@ async function generateSnapshotAsync(configInput, options) {
6494
6534
  }
6495
6535
 
6496
6536
  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 };
6497
- //# sourceMappingURL=chunk-CDZDVU74.js.map
6498
- //# sourceMappingURL=chunk-CDZDVU74.js.map
6537
+ //# sourceMappingURL=chunk-GAY7W5MK.js.map
6538
+ //# sourceMappingURL=chunk-GAY7W5MK.js.map
package/dist/cli.cjs CHANGED
@@ -4,9 +4,9 @@ var fs9 = require('fs');
4
4
  var path10 = require('path');
5
5
  var util = require('util');
6
6
  var childProcess = require('child_process');
7
+ var crypto = require('crypto');
7
8
  var url = require('url');
8
9
  var readline = require('readline');
9
- var crypto = require('crypto');
10
10
  var os = require('os');
11
11
  var ts = require('typescript');
12
12
 
@@ -33,8 +33,8 @@ function _interopNamespace(e) {
33
33
  var fs9__namespace = /*#__PURE__*/_interopNamespace(fs9);
34
34
  var path10__namespace = /*#__PURE__*/_interopNamespace(path10);
35
35
  var childProcess__namespace = /*#__PURE__*/_interopNamespace(childProcess);
36
- var readline__namespace = /*#__PURE__*/_interopNamespace(readline);
37
36
  var crypto__namespace = /*#__PURE__*/_interopNamespace(crypto);
37
+ var readline__namespace = /*#__PURE__*/_interopNamespace(readline);
38
38
  var os__namespace = /*#__PURE__*/_interopNamespace(os);
39
39
  var ts__default = /*#__PURE__*/_interopDefault(ts);
40
40
 
@@ -2634,6 +2634,27 @@ function classifyKind(filePath, kinds) {
2634
2634
  }
2635
2635
  return "other";
2636
2636
  }
2637
+ function configDigest(config) {
2638
+ const material = {
2639
+ maxPartBytes: config.maxPartBytes,
2640
+ largeFileBytes: config.largeFileBytes,
2641
+ previewHeadLines: config.previewHeadLines,
2642
+ previewTailLines: config.previewTailLines,
2643
+ includeMonolith: config.includeMonolith,
2644
+ maxMonolithBytes: config.maxMonolithBytes ?? null,
2645
+ includeSensitiveFiles: config.includeSensitiveFiles,
2646
+ artifacts: config.artifacts,
2647
+ include: config.include,
2648
+ excludePatterns: config.excludePatterns,
2649
+ preset: config.preset,
2650
+ layersMode: config.layersMode,
2651
+ budgets: config.budgets,
2652
+ layers: config.layers.map((layer2) => layer2.name),
2653
+ kinds: config.kinds.map((kind) => kind.kind),
2654
+ secretRules: config.secretRules.map((rule) => `${rule.rule}:${rule.pattern.source}`).sort()
2655
+ };
2656
+ return crypto.createHash("sha256").update(JSON.stringify(material)).digest("hex");
2657
+ }
2637
2658
 
2638
2659
  // src/partitioner/preview.ts
2639
2660
  function countLines(content) {
@@ -2717,21 +2738,28 @@ function isBinaryExtension(filePath) {
2717
2738
  return BINARY_EXTENSIONS.has(ext);
2718
2739
  }
2719
2740
  function isBinaryBuffer(buffer) {
2720
- const checkLength = Math.min(buffer.length, 8192);
2721
- for (let index = 0; index < checkLength; index++) {
2741
+ for (let index = 0; index < buffer.length; index++) {
2722
2742
  if (buffer[index] === 0) return true;
2723
2743
  }
2724
2744
  return false;
2725
2745
  }
2746
+ var BINARY_SCAN_BYTES = 8 * 1024 * 1024;
2747
+ var CHUNK = 64 * 1024;
2726
2748
  function isBinaryFile(absolutePath) {
2727
2749
  if (isBinaryExtension(absolutePath)) return true;
2728
2750
  let fd;
2729
2751
  try {
2730
2752
  fd = fs9__namespace.openSync(absolutePath, "r");
2731
- const buffer = Buffer.alloc(8192);
2732
- const bytesRead = fs9__namespace.readSync(fd, buffer, 0, 8192, 0);
2733
- if (bytesRead === 0) return false;
2734
- return isBinaryBuffer(buffer.subarray(0, bytesRead));
2753
+ const buffer = Buffer.alloc(CHUNK);
2754
+ let position = 0;
2755
+ while (position < BINARY_SCAN_BYTES) {
2756
+ const wanted = Math.min(CHUNK, BINARY_SCAN_BYTES - position);
2757
+ const bytesRead = fs9__namespace.readSync(fd, buffer, 0, wanted, position);
2758
+ if (bytesRead === 0) return false;
2759
+ if (isBinaryBuffer(buffer.subarray(0, bytesRead))) return true;
2760
+ position += bytesRead;
2761
+ }
2762
+ return false;
2735
2763
  } catch {
2736
2764
  return false;
2737
2765
  } finally {
@@ -5236,6 +5264,11 @@ function validateSnapshot(configInput) {
5236
5264
  const currentExcludes = config.excludePatterns.map(maskValue);
5237
5265
  const currentInclude = config.include.map(maskValue);
5238
5266
  const recorded = manifest.config;
5267
+ if (recorded?.digest && recorded.digest !== configDigest(config)) {
5268
+ drift.configMismatches.push(
5269
+ "configuration: the settings differ from the ones this snapshot was generated with (run generate)"
5270
+ );
5271
+ }
5239
5272
  if (recorded && typeof recorded === "object") {
5240
5273
  if (recorded.maxPartBytes !== config.maxPartBytes) {
5241
5274
  drift.configMismatches.push(
@@ -5451,7 +5484,7 @@ function validateSnapshot(configInput) {
5451
5484
 
5452
5485
  // src/index.ts
5453
5486
  var GENERATOR_NAME = "@ankurhalder/codebase-snapshot";
5454
- var GENERATOR_VERSION = "4.0.4";
5487
+ var GENERATOR_VERSION = "4.0.6";
5455
5488
  var SCHEMA_VERSION = "3.0.0";
5456
5489
  function sha256Hex2(input) {
5457
5490
  return crypto__namespace.createHash("sha256").update(input).digest("hex");
@@ -6218,8 +6251,8 @@ function generateSnapshot(configInput, options) {
6218
6251
  const lineCount = countLines(rawContent);
6219
6252
  totalLines += lineCount;
6220
6253
  totalSizeBytes += stats.size;
6221
- const layer2 = classifyLayer(relativePath, config.layers);
6222
- const kind = classifyKind(relativePath, config.kinds);
6254
+ const layer2 = maskPathText(classifyLayer(relativePath, config.layers), config.secretRules);
6255
+ const kind = maskPathText(classifyKind(relativePath, config.kinds), config.secretRules);
6223
6256
  const language = detectLanguage(relativePath);
6224
6257
  bump(layerCounts, layer2);
6225
6258
  bump(kindCounts, kind);
@@ -6318,6 +6351,7 @@ function generateSnapshot(configInput, options) {
6318
6351
  largeFileBytes: config.largeFileBytes
6319
6352
  },
6320
6353
  config: {
6354
+ digest: configDigest(config),
6321
6355
  maxPartBytes: config.maxPartBytes,
6322
6356
  largeFileBytes: config.largeFileBytes,
6323
6357
  previewHeadLines: config.previewHeadLines,
@@ -6328,7 +6362,12 @@ function generateSnapshot(configInput, options) {
6328
6362
  include: [...config.include].map(maskName),
6329
6363
  preset: config.preset,
6330
6364
  layersMode: config.layersMode,
6331
- budgets: { default: config.budgets.default, byLayer: { ...config.budgets.byLayer } },
6365
+ budgets: {
6366
+ default: config.budgets.default,
6367
+ byLayer: Object.fromEntries(
6368
+ Object.entries(config.budgets.byLayer).map(([name, bytes]) => [maskName(name), bytes])
6369
+ )
6370
+ },
6332
6371
  excludePatterns: [...config.excludePatterns].map(maskName),
6333
6372
  layers: config.layers.map((layer2) => maskName(layer2.name)),
6334
6373
  kinds: config.kinds.map((kind) => maskName(kind.kind))
package/dist/cli.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { O as OutputFormat } from './types-LSfwsKE-.cjs';
1
+ import { O as OutputFormat } from './types-x7aogSer.cjs';
2
2
 
3
3
  type Command = "generate" | "validate" | "report" | "init" | "explain" | "diff" | "describe" | "skill";
4
4
  /** A user-input problem: printed without a stack trace, exits 2. */
package/dist/cli.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { O as OutputFormat } from './types-LSfwsKE-.js';
1
+ import { O as OutputFormat } from './types-x7aogSer.js';
2
2
 
3
3
  type Command = "generate" | "validate" | "report" | "init" | "explain" | "diff" | "describe" | "skill";
4
4
  /** A user-input problem: printed without a stack trace, exits 2. */
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-CDZDVU74.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-GAY7W5MK.js';
2
2
  import * as fs from 'fs';
3
3
  import * as path2 from 'path';
4
4
  import { parseArgs } from 'util';
package/dist/index.cjs CHANGED
@@ -3378,6 +3378,27 @@ function classifyKind(filePath, kinds) {
3378
3378
  }
3379
3379
  return "other";
3380
3380
  }
3381
+ function configDigest(config) {
3382
+ const material = {
3383
+ maxPartBytes: config.maxPartBytes,
3384
+ largeFileBytes: config.largeFileBytes,
3385
+ previewHeadLines: config.previewHeadLines,
3386
+ previewTailLines: config.previewTailLines,
3387
+ includeMonolith: config.includeMonolith,
3388
+ maxMonolithBytes: config.maxMonolithBytes ?? null,
3389
+ includeSensitiveFiles: config.includeSensitiveFiles,
3390
+ artifacts: config.artifacts,
3391
+ include: config.include,
3392
+ excludePatterns: config.excludePatterns,
3393
+ preset: config.preset,
3394
+ layersMode: config.layersMode,
3395
+ budgets: config.budgets,
3396
+ layers: config.layers.map((layer2) => layer2.name),
3397
+ kinds: config.kinds.map((kind) => kind.kind),
3398
+ secretRules: config.secretRules.map((rule) => `${rule.rule}:${rule.pattern.source}`).sort()
3399
+ };
3400
+ return crypto.createHash("sha256").update(JSON.stringify(material)).digest("hex");
3401
+ }
3381
3402
 
3382
3403
  // src/define-config.ts
3383
3404
  function defineConfig(config) {
@@ -4085,21 +4106,28 @@ function isBinaryExtension(filePath) {
4085
4106
  return BINARY_EXTENSIONS.has(ext);
4086
4107
  }
4087
4108
  function isBinaryBuffer(buffer) {
4088
- const checkLength = Math.min(buffer.length, 8192);
4089
- for (let index = 0; index < checkLength; index++) {
4109
+ for (let index = 0; index < buffer.length; index++) {
4090
4110
  if (buffer[index] === 0) return true;
4091
4111
  }
4092
4112
  return false;
4093
4113
  }
4114
+ var BINARY_SCAN_BYTES = 8 * 1024 * 1024;
4115
+ var CHUNK = 64 * 1024;
4094
4116
  function isBinaryFile(absolutePath) {
4095
4117
  if (isBinaryExtension(absolutePath)) return true;
4096
4118
  let fd;
4097
4119
  try {
4098
4120
  fd = fs9__namespace.openSync(absolutePath, "r");
4099
- const buffer = Buffer.alloc(8192);
4100
- const bytesRead = fs9__namespace.readSync(fd, buffer, 0, 8192, 0);
4101
- if (bytesRead === 0) return false;
4102
- return isBinaryBuffer(buffer.subarray(0, bytesRead));
4121
+ const buffer = Buffer.alloc(CHUNK);
4122
+ let position = 0;
4123
+ while (position < BINARY_SCAN_BYTES) {
4124
+ const wanted = Math.min(CHUNK, BINARY_SCAN_BYTES - position);
4125
+ const bytesRead = fs9__namespace.readSync(fd, buffer, 0, wanted, position);
4126
+ if (bytesRead === 0) return false;
4127
+ if (isBinaryBuffer(buffer.subarray(0, bytesRead))) return true;
4128
+ position += bytesRead;
4129
+ }
4130
+ return false;
4103
4131
  } catch {
4104
4132
  return false;
4105
4133
  } finally {
@@ -4334,6 +4362,11 @@ function validateSnapshot(configInput) {
4334
4362
  const currentExcludes = config.excludePatterns.map(maskValue);
4335
4363
  const currentInclude = config.include.map(maskValue);
4336
4364
  const recorded = manifest.config;
4365
+ if (recorded?.digest && recorded.digest !== configDigest(config)) {
4366
+ drift.configMismatches.push(
4367
+ "configuration: the settings differ from the ones this snapshot was generated with (run generate)"
4368
+ );
4369
+ }
4337
4370
  if (recorded && typeof recorded === "object") {
4338
4371
  if (recorded.maxPartBytes !== config.maxPartBytes) {
4339
4372
  drift.configMismatches.push(
@@ -5464,7 +5497,7 @@ async function runInit(options) {
5464
5497
 
5465
5498
  // src/index.ts
5466
5499
  var GENERATOR_NAME = "@ankurhalder/codebase-snapshot";
5467
- var GENERATOR_VERSION = "4.0.4";
5500
+ var GENERATOR_VERSION = "4.0.6";
5468
5501
  var SCHEMA_VERSION = "3.0.0";
5469
5502
  function sha256Hex2(input) {
5470
5503
  return crypto__namespace.createHash("sha256").update(input).digest("hex");
@@ -6231,8 +6264,8 @@ function generateSnapshot(configInput, options) {
6231
6264
  const lineCount = countLines(rawContent);
6232
6265
  totalLines += lineCount;
6233
6266
  totalSizeBytes += stats.size;
6234
- const layer2 = classifyLayer(relativePath, config.layers);
6235
- const kind = classifyKind(relativePath, config.kinds);
6267
+ const layer2 = maskPathText(classifyLayer(relativePath, config.layers), config.secretRules);
6268
+ const kind = maskPathText(classifyKind(relativePath, config.kinds), config.secretRules);
6236
6269
  const language = detectLanguage(relativePath);
6237
6270
  bump(layerCounts, layer2);
6238
6271
  bump(kindCounts, kind);
@@ -6331,6 +6364,7 @@ function generateSnapshot(configInput, options) {
6331
6364
  largeFileBytes: config.largeFileBytes
6332
6365
  },
6333
6366
  config: {
6367
+ digest: configDigest(config),
6334
6368
  maxPartBytes: config.maxPartBytes,
6335
6369
  largeFileBytes: config.largeFileBytes,
6336
6370
  previewHeadLines: config.previewHeadLines,
@@ -6341,7 +6375,12 @@ function generateSnapshot(configInput, options) {
6341
6375
  include: [...config.include].map(maskName),
6342
6376
  preset: config.preset,
6343
6377
  layersMode: config.layersMode,
6344
- budgets: { default: config.budgets.default, byLayer: { ...config.budgets.byLayer } },
6378
+ budgets: {
6379
+ default: config.budgets.default,
6380
+ byLayer: Object.fromEntries(
6381
+ Object.entries(config.budgets.byLayer).map(([name, bytes]) => [maskName(name), bytes])
6382
+ )
6383
+ },
6345
6384
  excludePatterns: [...config.excludePatterns].map(maskName),
6346
6385
  layers: config.layers.map((layer2) => maskName(layer2.name)),
6347
6386
  kinds: config.kinds.map((kind) => maskName(kind.kind))
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { J as JsonSummary, M as MarkdownSummary, S as SourceSummary, R as ResolvedSnapshotConfig, a as SnapshotConfig, B as ByteSize, C as CliOptions, F as FileEntry, P as PartMetadata, L as LayerRule, K as KindRule, b as SecretRule, c as SecretFinding, V as ValidationResult, d as Manifest, A as ArtifactSelection, e as SkipRecord } from './types-LSfwsKE-.cjs';
2
- export { f as BudgetConfig, H as HooksConfig, I as InclusionMode, g as ManifestArtifact, h as ManifestConfigSnapshot, i as ManifestIndexes, j as ManifestTotals, k as Mode, O as OutputFormat, l as PartFileEntry, m as ResolvedArtifacts, n as ResolvedBudgets, o as SecretRuleInput, p as SkipReason, q as SummaryQuality, r as ValidationDrift } from './types-LSfwsKE-.cjs';
1
+ import { J as JsonSummary, M as MarkdownSummary, S as SourceSummary, R as ResolvedSnapshotConfig, a as SnapshotConfig, B as ByteSize, C as CliOptions, F as FileEntry, P as PartMetadata, L as LayerRule, K as KindRule, b as SecretRule, c as SecretFinding, V as ValidationResult, d as Manifest, A as ArtifactSelection, e as SkipRecord } from './types-x7aogSer.cjs';
2
+ export { f as BudgetConfig, H as HooksConfig, I as InclusionMode, g as ManifestArtifact, h as ManifestConfigSnapshot, i as ManifestIndexes, j as ManifestTotals, k as Mode, O as OutputFormat, l as PartFileEntry, m as ResolvedArtifacts, n as ResolvedBudgets, o as SecretRuleInput, p as SkipReason, q as SummaryQuality, r as ValidationDrift } from './types-x7aogSer.cjs';
3
3
 
4
4
  /**
5
5
  * Strips `//` and block comments the way JSONC does, without touching anything
@@ -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.4";
498
+ declare const GENERATOR_VERSION = "4.0.6";
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
@@ -1,5 +1,5 @@
1
- import { J as JsonSummary, M as MarkdownSummary, S as SourceSummary, R as ResolvedSnapshotConfig, a as SnapshotConfig, B as ByteSize, C as CliOptions, F as FileEntry, P as PartMetadata, L as LayerRule, K as KindRule, b as SecretRule, c as SecretFinding, V as ValidationResult, d as Manifest, A as ArtifactSelection, e as SkipRecord } from './types-LSfwsKE-.js';
2
- export { f as BudgetConfig, H as HooksConfig, I as InclusionMode, g as ManifestArtifact, h as ManifestConfigSnapshot, i as ManifestIndexes, j as ManifestTotals, k as Mode, O as OutputFormat, l as PartFileEntry, m as ResolvedArtifacts, n as ResolvedBudgets, o as SecretRuleInput, p as SkipReason, q as SummaryQuality, r as ValidationDrift } from './types-LSfwsKE-.js';
1
+ import { J as JsonSummary, M as MarkdownSummary, S as SourceSummary, R as ResolvedSnapshotConfig, a as SnapshotConfig, B as ByteSize, C as CliOptions, F as FileEntry, P as PartMetadata, L as LayerRule, K as KindRule, b as SecretRule, c as SecretFinding, V as ValidationResult, d as Manifest, A as ArtifactSelection, e as SkipRecord } from './types-x7aogSer.js';
2
+ export { f as BudgetConfig, H as HooksConfig, I as InclusionMode, g as ManifestArtifact, h as ManifestConfigSnapshot, i as ManifestIndexes, j as ManifestTotals, k as Mode, O as OutputFormat, l as PartFileEntry, m as ResolvedArtifacts, n as ResolvedBudgets, o as SecretRuleInput, p as SkipReason, q as SummaryQuality, r as ValidationDrift } from './types-x7aogSer.js';
3
3
 
4
4
  /**
5
5
  * Strips `//` and block comments the way JSONC does, without touching anything
@@ -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.4";
498
+ declare const GENERATOR_VERSION = "4.0.6";
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-CDZDVU74.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-GAY7W5MK.js';
2
2
  //# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
@@ -207,6 +207,8 @@ interface ManifestIndexes {
207
207
  }
208
208
  /** Effective configuration recorded so `validate` can detect config drift. */
209
209
  interface ManifestConfigSnapshot {
210
+ /** Digest of the effective settings; see `configDigest`. */
211
+ digest?: string;
210
212
  maxPartBytes: number;
211
213
  largeFileBytes: number;
212
214
  previewHeadLines: number;
@@ -207,6 +207,8 @@ interface ManifestIndexes {
207
207
  }
208
208
  /** Effective configuration recorded so `validate` can detect config drift. */
209
209
  interface ManifestConfigSnapshot {
210
+ /** Digest of the effective settings; see `configDigest`. */
211
+ digest?: string;
210
212
  maxPartBytes: number;
211
213
  largeFileBytes: number;
212
214
  previewHeadLines: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ankurhalder/codebase-snapshot",
3
- "version": "4.0.4",
3
+ "version": "4.0.6",
4
4
  "description": "Production-grade LLM codebase snapshot generator, auditor, and AST partitioner",
5
5
  "keywords": [
6
6
  "codebase",