@ankurhalder/codebase-snapshot 4.0.3 → 4.0.5

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) {
@@ -4514,7 +4536,31 @@ function generateAuditReport(manifest, secretFindings, secretRules) {
4514
4536
  }
4515
4537
  lines.push("");
4516
4538
  }
4517
- lines.push("## 2. Large Files Analysis", "");
4539
+ const parseIssues = manifest.files.filter(
4540
+ (file) => file.summary !== void 0 && typeof file.summary === "object" && "parseErrors" in file.summary && typeof file.summary.parseErrors === "number" && file.summary.parseErrors > 0
4541
+ );
4542
+ lines.push("## 2. Parse & AST Diagnostics", "");
4543
+ if (parseIssues.length === 0) {
4544
+ lines.push("\u2705 Every parsed file produced a complete structural summary.", "");
4545
+ } else {
4546
+ lines.push(
4547
+ `${parseIssues.length} file(s) produced an incomplete summary:`,
4548
+ "",
4549
+ "| File | Parse Errors |",
4550
+ "| :--- | ---: |"
4551
+ );
4552
+ for (const file of parseIssues) {
4553
+ const errors = file.summary.parseErrors;
4554
+ lines.push(`| \`${mask(file.relativePath)}\` | ${errors} |`);
4555
+ }
4556
+ lines.push(
4557
+ "",
4558
+ "A parse error here means the summary is incomplete, not that the file is excluded \u2014",
4559
+ "the content is still in the parts.",
4560
+ ""
4561
+ );
4562
+ }
4563
+ lines.push("## 3. Large Files Analysis", "");
4518
4564
  const largeFiles = manifest.files.filter((file) => file.isLarge);
4519
4565
  if (largeFiles.length === 0) {
4520
4566
  lines.push("\u2705 No files exceeded the large file budget.", "");
@@ -4533,7 +4579,7 @@ function generateAuditReport(manifest, secretFindings, secretRules) {
4533
4579
  lines.push("");
4534
4580
  }
4535
4581
  lines.push(
4536
- "## 3. Architecture Layer Distribution",
4582
+ "## 4. Architecture Layer Distribution",
4537
4583
  "",
4538
4584
  "| Layer | File Count | Percentage |",
4539
4585
  "| :--- | :--- | :--- |"
@@ -4547,7 +4593,7 @@ function generateAuditReport(manifest, secretFindings, secretRules) {
4547
4593
  }
4548
4594
  lines.push("");
4549
4595
  lines.push(
4550
- "## 4. File Kind Distribution",
4596
+ "## 5. File Kind Distribution",
4551
4597
  "",
4552
4598
  "| Kind | File Count | Percentage |",
4553
4599
  "| :--- | :--- | :--- |"
@@ -4559,7 +4605,7 @@ function generateAuditReport(manifest, secretFindings, secretRules) {
4559
4605
  lines.push(`| \`${kind}\` | ${count} | ${pct}% |`);
4560
4606
  }
4561
4607
  lines.push("");
4562
- lines.push("## 5. Skipped / Non-Text Files", "");
4608
+ lines.push("## 6. Skipped / Non-Text Files", "");
4563
4609
  if (manifest.skipped.length === 0) {
4564
4610
  lines.push("No files were skipped.", "");
4565
4611
  } else {
@@ -5232,6 +5278,11 @@ function validateSnapshot(configInput) {
5232
5278
  const currentExcludes = config.excludePatterns.map(maskValue);
5233
5279
  const currentInclude = config.include.map(maskValue);
5234
5280
  const recorded = manifest.config;
5281
+ if (recorded?.digest && recorded.digest !== configDigest(config)) {
5282
+ drift.configMismatches.push(
5283
+ "configuration: the settings differ from the ones this snapshot was generated with (run generate)"
5284
+ );
5285
+ }
5235
5286
  if (recorded && typeof recorded === "object") {
5236
5287
  if (recorded.maxPartBytes !== config.maxPartBytes) {
5237
5288
  drift.configMismatches.push(
@@ -5447,7 +5498,7 @@ function validateSnapshot(configInput) {
5447
5498
 
5448
5499
  // src/index.ts
5449
5500
  var GENERATOR_NAME = "@ankurhalder/codebase-snapshot";
5450
- var GENERATOR_VERSION = "4.0.3";
5501
+ var GENERATOR_VERSION = "4.0.5";
5451
5502
  var SCHEMA_VERSION = "3.0.0";
5452
5503
  function sha256Hex2(input) {
5453
5504
  return crypto3.createHash("sha256").update(input).digest("hex");
@@ -5654,6 +5705,18 @@ function resolveSafeOutputDirs(config) {
5654
5705
  var PLACEHOLDER_ENTRIES = /* @__PURE__ */ new Set([".gitkeep", ".gitignore", ".DS_Store"]);
5655
5706
  var RUN_DIR_PREFIX = "run-";
5656
5707
  var STALE_RUN_MS = 60 * 60 * 1e3;
5708
+ function maskSummaryStrings(value, secretRules) {
5709
+ if (typeof value === "string") return maskPathText(value, secretRules);
5710
+ if (Array.isArray(value)) return value.map((item) => maskSummaryStrings(item, secretRules));
5711
+ if (value && typeof value === "object") {
5712
+ const out = {};
5713
+ for (const [key, item] of Object.entries(value)) {
5714
+ out[key] = maskSummaryStrings(item, secretRules);
5715
+ }
5716
+ return out;
5717
+ }
5718
+ return value;
5719
+ }
5657
5720
  function maskPathText(value, secretRules) {
5658
5721
  return findSecretInPath(value, secretRules)?.masked ?? value;
5659
5722
  }
@@ -6234,8 +6297,8 @@ function generateSnapshot(configInput, options) {
6234
6297
  let summary;
6235
6298
  let summaryQuality;
6236
6299
  try {
6237
- const outcome = summarizeFile(relativePath, redacted);
6238
- summary = outcome?.summary;
6300
+ const outcome = summarizeFile(relativePath, rawContent);
6301
+ summary = outcome?.summary ? maskSummaryStrings(outcome.summary, config.secretRules) : void 0;
6239
6302
  summaryQuality = outcome?.quality;
6240
6303
  if (isSourceSummary(summary) && summary.parseErrors) {
6241
6304
  warnings.push(
@@ -6302,6 +6365,7 @@ function generateSnapshot(configInput, options) {
6302
6365
  largeFileBytes: config.largeFileBytes
6303
6366
  },
6304
6367
  config: {
6368
+ digest: configDigest(config),
6305
6369
  maxPartBytes: config.maxPartBytes,
6306
6370
  largeFileBytes: config.largeFileBytes,
6307
6371
  previewHeadLines: config.previewHeadLines,
@@ -7782,7 +7846,7 @@ ${USAGE}
7782
7846
  info(` - Schema: ${manifest.schemaVersion}`);
7783
7847
  info(` - Fingerprint: ${manifest.fingerprint}`);
7784
7848
  info(` - Files included: ${manifest.counts.totalFiles}`);
7785
- info(` - Total lines: ${manifest.counts.totalLines.toLocaleString()}`);
7849
+ info(` - Total lines: ${manifest.counts.totalLines.toLocaleString("en-US")}`);
7786
7850
  info(
7787
7851
  ` - Total size: ${(manifest.counts.totalSizeBytes / (1024 * 1024)).toFixed(2)} MB`
7788
7852
  );
@@ -7834,14 +7898,14 @@ ${USAGE}
7834
7898
  info(`
7835
7899
  \u2705 Snapshot generated in ${elapsed}s:`);
7836
7900
  info(` - Tracked files: ${manifest.counts.totalFiles}`);
7837
- info(` - Total lines: ${manifest.counts.totalLines.toLocaleString()}`);
7901
+ info(` - Total lines: ${manifest.counts.totalLines.toLocaleString("en-US")}`);
7838
7902
  info(
7839
7903
  ` - Total size: ${(manifest.counts.totalSizeBytes / (1024 * 1024)).toFixed(2)} MB`
7840
7904
  );
7841
7905
  const { artifacts } = resolved;
7842
7906
  if (artifacts.parts) {
7843
7907
  info(
7844
- ` - Parts written: ${manifest.counts.partsCount} under ${displayOutPath(resolved.cwd, resolved.outDir, "parts")}/`
7908
+ ` - Parts written: ${manifest.counts.partsCount} under ${displayOutPath(resolved.cwd, resolved.outDir, "parts")}`
7845
7909
  );
7846
7910
  }
7847
7911
  const reports = [
@@ -7851,7 +7915,7 @@ ${USAGE}
7851
7915
  ].filter(Boolean);
7852
7916
  if (reports.length > 0) {
7853
7917
  info(
7854
- ` - Reports: ${displayOutPath(resolved.cwd, resolved.outDir, "reports")}/ (${reports.join(", ")})`
7918
+ ` - Reports: ${displayOutPath(resolved.cwd, resolved.outDir, "reports")} (${reports.join(", ")})`
7855
7919
  );
7856
7920
  }
7857
7921
  if (artifacts.manifest) {
@@ -7979,6 +8043,21 @@ async function runWatchLoop(invocation, resolved) {
7979
8043
  });
7980
8044
  return 0;
7981
8045
  }
8046
+ var entryFile = process.argv[1] ?? "";
8047
+ var entryName = path12.basename(entryFile).toLowerCase();
8048
+ var invokedDirectly = entryName === "cli.js" || entryName === "cli.cjs";
8049
+ if (invokedDirectly) {
8050
+ void main().then(
8051
+ (code) => {
8052
+ process.exitCode = code;
8053
+ },
8054
+ (err) => {
8055
+ process.stderr.write(`\u274C ${err.message}
8056
+ `);
8057
+ process.exitCode = 1;
8058
+ }
8059
+ );
8060
+ }
7982
8061
 
7983
8062
  // src/bin.ts
7984
8063
  main().then(
@@ -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) {
@@ -3399,7 +3421,31 @@ function generateAuditReport(manifest, secretFindings, secretRules) {
3399
3421
  }
3400
3422
  lines.push("");
3401
3423
  }
3402
- lines.push("## 2. Large Files Analysis", "");
3424
+ const parseIssues = manifest.files.filter(
3425
+ (file) => file.summary !== void 0 && typeof file.summary === "object" && "parseErrors" in file.summary && typeof file.summary.parseErrors === "number" && file.summary.parseErrors > 0
3426
+ );
3427
+ lines.push("## 2. Parse & AST Diagnostics", "");
3428
+ if (parseIssues.length === 0) {
3429
+ lines.push("\u2705 Every parsed file produced a complete structural summary.", "");
3430
+ } else {
3431
+ lines.push(
3432
+ `${parseIssues.length} file(s) produced an incomplete summary:`,
3433
+ "",
3434
+ "| File | Parse Errors |",
3435
+ "| :--- | ---: |"
3436
+ );
3437
+ for (const file of parseIssues) {
3438
+ const errors = file.summary.parseErrors;
3439
+ lines.push(`| \`${mask(file.relativePath)}\` | ${errors} |`);
3440
+ }
3441
+ lines.push(
3442
+ "",
3443
+ "A parse error here means the summary is incomplete, not that the file is excluded \u2014",
3444
+ "the content is still in the parts.",
3445
+ ""
3446
+ );
3447
+ }
3448
+ lines.push("## 3. Large Files Analysis", "");
3403
3449
  const largeFiles = manifest.files.filter((file) => file.isLarge);
3404
3450
  if (largeFiles.length === 0) {
3405
3451
  lines.push("\u2705 No files exceeded the large file budget.", "");
@@ -3418,7 +3464,7 @@ function generateAuditReport(manifest, secretFindings, secretRules) {
3418
3464
  lines.push("");
3419
3465
  }
3420
3466
  lines.push(
3421
- "## 3. Architecture Layer Distribution",
3467
+ "## 4. Architecture Layer Distribution",
3422
3468
  "",
3423
3469
  "| Layer | File Count | Percentage |",
3424
3470
  "| :--- | :--- | :--- |"
@@ -3432,7 +3478,7 @@ function generateAuditReport(manifest, secretFindings, secretRules) {
3432
3478
  }
3433
3479
  lines.push("");
3434
3480
  lines.push(
3435
- "## 4. File Kind Distribution",
3481
+ "## 5. File Kind Distribution",
3436
3482
  "",
3437
3483
  "| Kind | File Count | Percentage |",
3438
3484
  "| :--- | :--- | :--- |"
@@ -3444,7 +3490,7 @@ function generateAuditReport(manifest, secretFindings, secretRules) {
3444
3490
  lines.push(`| \`${kind}\` | ${count} | ${pct}% |`);
3445
3491
  }
3446
3492
  lines.push("");
3447
- lines.push("## 5. Skipped / Non-Text Files", "");
3493
+ lines.push("## 6. Skipped / Non-Text Files", "");
3448
3494
  if (manifest.skipped.length === 0) {
3449
3495
  lines.push("No files were skipped.", "");
3450
3496
  } else {
@@ -4280,6 +4326,11 @@ function validateSnapshot(configInput) {
4280
4326
  const currentExcludes = config.excludePatterns.map(maskValue);
4281
4327
  const currentInclude = config.include.map(maskValue);
4282
4328
  const recorded = manifest.config;
4329
+ if (recorded?.digest && recorded.digest !== configDigest(config)) {
4330
+ drift.configMismatches.push(
4331
+ "configuration: the settings differ from the ones this snapshot was generated with (run generate)"
4332
+ );
4333
+ }
4283
4334
  if (recorded && typeof recorded === "object") {
4284
4335
  if (recorded.maxPartBytes !== config.maxPartBytes) {
4285
4336
  drift.configMismatches.push(
@@ -5410,7 +5461,7 @@ async function runInit(options) {
5410
5461
 
5411
5462
  // src/index.ts
5412
5463
  var GENERATOR_NAME = "@ankurhalder/codebase-snapshot";
5413
- var GENERATOR_VERSION = "4.0.3";
5464
+ var GENERATOR_VERSION = "4.0.5";
5414
5465
  var SCHEMA_VERSION = "3.0.0";
5415
5466
  function sha256Hex2(input) {
5416
5467
  return crypto.createHash("sha256").update(input).digest("hex");
@@ -5617,6 +5668,18 @@ function resolveSafeOutputDirs(config) {
5617
5668
  var PLACEHOLDER_ENTRIES = /* @__PURE__ */ new Set([".gitkeep", ".gitignore", ".DS_Store"]);
5618
5669
  var RUN_DIR_PREFIX = "run-";
5619
5670
  var STALE_RUN_MS = 60 * 60 * 1e3;
5671
+ function maskSummaryStrings(value, secretRules) {
5672
+ if (typeof value === "string") return maskPathText(value, secretRules);
5673
+ if (Array.isArray(value)) return value.map((item) => maskSummaryStrings(item, secretRules));
5674
+ if (value && typeof value === "object") {
5675
+ const out = {};
5676
+ for (const [key, item] of Object.entries(value)) {
5677
+ out[key] = maskSummaryStrings(item, secretRules);
5678
+ }
5679
+ return out;
5680
+ }
5681
+ return value;
5682
+ }
5620
5683
  function maskPathText(value, secretRules) {
5621
5684
  return findSecretInPath(value, secretRules)?.masked ?? value;
5622
5685
  }
@@ -6197,8 +6260,8 @@ function generateSnapshot(configInput, options) {
6197
6260
  let summary;
6198
6261
  let summaryQuality;
6199
6262
  try {
6200
- const outcome = summarizeFile(relativePath, redacted);
6201
- summary = outcome?.summary;
6263
+ const outcome = summarizeFile(relativePath, rawContent);
6264
+ summary = outcome?.summary ? maskSummaryStrings(outcome.summary, config.secretRules) : void 0;
6202
6265
  summaryQuality = outcome?.quality;
6203
6266
  if (isSourceSummary(summary) && summary.parseErrors) {
6204
6267
  warnings.push(
@@ -6265,6 +6328,7 @@ function generateSnapshot(configInput, options) {
6265
6328
  largeFileBytes: config.largeFileBytes
6266
6329
  },
6267
6330
  config: {
6331
+ digest: configDigest(config),
6268
6332
  maxPartBytes: config.maxPartBytes,
6269
6333
  largeFileBytes: config.largeFileBytes,
6270
6334
  previewHeadLines: config.previewHeadLines,
@@ -6458,5 +6522,5 @@ async function generateSnapshotAsync(configInput, options) {
6458
6522
  }
6459
6523
 
6460
6524
  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 };
6461
- //# sourceMappingURL=chunk-L7QBLC4C.js.map
6462
- //# sourceMappingURL=chunk-L7QBLC4C.js.map
6525
+ //# sourceMappingURL=chunk-PCNDUNKT.js.map
6526
+ //# sourceMappingURL=chunk-PCNDUNKT.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) {
@@ -4502,7 +4523,31 @@ function generateAuditReport(manifest, secretFindings, secretRules) {
4502
4523
  }
4503
4524
  lines.push("");
4504
4525
  }
4505
- lines.push("## 2. Large Files Analysis", "");
4526
+ const parseIssues = manifest.files.filter(
4527
+ (file) => file.summary !== void 0 && typeof file.summary === "object" && "parseErrors" in file.summary && typeof file.summary.parseErrors === "number" && file.summary.parseErrors > 0
4528
+ );
4529
+ lines.push("## 2. Parse & AST Diagnostics", "");
4530
+ if (parseIssues.length === 0) {
4531
+ lines.push("\u2705 Every parsed file produced a complete structural summary.", "");
4532
+ } else {
4533
+ lines.push(
4534
+ `${parseIssues.length} file(s) produced an incomplete summary:`,
4535
+ "",
4536
+ "| File | Parse Errors |",
4537
+ "| :--- | ---: |"
4538
+ );
4539
+ for (const file of parseIssues) {
4540
+ const errors = file.summary.parseErrors;
4541
+ lines.push(`| \`${mask(file.relativePath)}\` | ${errors} |`);
4542
+ }
4543
+ lines.push(
4544
+ "",
4545
+ "A parse error here means the summary is incomplete, not that the file is excluded \u2014",
4546
+ "the content is still in the parts.",
4547
+ ""
4548
+ );
4549
+ }
4550
+ lines.push("## 3. Large Files Analysis", "");
4506
4551
  const largeFiles = manifest.files.filter((file) => file.isLarge);
4507
4552
  if (largeFiles.length === 0) {
4508
4553
  lines.push("\u2705 No files exceeded the large file budget.", "");
@@ -4521,7 +4566,7 @@ function generateAuditReport(manifest, secretFindings, secretRules) {
4521
4566
  lines.push("");
4522
4567
  }
4523
4568
  lines.push(
4524
- "## 3. Architecture Layer Distribution",
4569
+ "## 4. Architecture Layer Distribution",
4525
4570
  "",
4526
4571
  "| Layer | File Count | Percentage |",
4527
4572
  "| :--- | :--- | :--- |"
@@ -4535,7 +4580,7 @@ function generateAuditReport(manifest, secretFindings, secretRules) {
4535
4580
  }
4536
4581
  lines.push("");
4537
4582
  lines.push(
4538
- "## 4. File Kind Distribution",
4583
+ "## 5. File Kind Distribution",
4539
4584
  "",
4540
4585
  "| Kind | File Count | Percentage |",
4541
4586
  "| :--- | :--- | :--- |"
@@ -4547,7 +4592,7 @@ function generateAuditReport(manifest, secretFindings, secretRules) {
4547
4592
  lines.push(`| \`${kind}\` | ${count} | ${pct}% |`);
4548
4593
  }
4549
4594
  lines.push("");
4550
- lines.push("## 5. Skipped / Non-Text Files", "");
4595
+ lines.push("## 6. Skipped / Non-Text Files", "");
4551
4596
  if (manifest.skipped.length === 0) {
4552
4597
  lines.push("No files were skipped.", "");
4553
4598
  } else {
@@ -5212,6 +5257,11 @@ function validateSnapshot(configInput) {
5212
5257
  const currentExcludes = config.excludePatterns.map(maskValue);
5213
5258
  const currentInclude = config.include.map(maskValue);
5214
5259
  const recorded = manifest.config;
5260
+ if (recorded?.digest && recorded.digest !== configDigest(config)) {
5261
+ drift.configMismatches.push(
5262
+ "configuration: the settings differ from the ones this snapshot was generated with (run generate)"
5263
+ );
5264
+ }
5215
5265
  if (recorded && typeof recorded === "object") {
5216
5266
  if (recorded.maxPartBytes !== config.maxPartBytes) {
5217
5267
  drift.configMismatches.push(
@@ -5427,7 +5477,7 @@ function validateSnapshot(configInput) {
5427
5477
 
5428
5478
  // src/index.ts
5429
5479
  var GENERATOR_NAME = "@ankurhalder/codebase-snapshot";
5430
- var GENERATOR_VERSION = "4.0.3";
5480
+ var GENERATOR_VERSION = "4.0.5";
5431
5481
  var SCHEMA_VERSION = "3.0.0";
5432
5482
  function sha256Hex2(input) {
5433
5483
  return crypto__namespace.createHash("sha256").update(input).digest("hex");
@@ -5634,6 +5684,18 @@ function resolveSafeOutputDirs(config) {
5634
5684
  var PLACEHOLDER_ENTRIES = /* @__PURE__ */ new Set([".gitkeep", ".gitignore", ".DS_Store"]);
5635
5685
  var RUN_DIR_PREFIX = "run-";
5636
5686
  var STALE_RUN_MS = 60 * 60 * 1e3;
5687
+ function maskSummaryStrings(value, secretRules) {
5688
+ if (typeof value === "string") return maskPathText(value, secretRules);
5689
+ if (Array.isArray(value)) return value.map((item) => maskSummaryStrings(item, secretRules));
5690
+ if (value && typeof value === "object") {
5691
+ const out = {};
5692
+ for (const [key, item] of Object.entries(value)) {
5693
+ out[key] = maskSummaryStrings(item, secretRules);
5694
+ }
5695
+ return out;
5696
+ }
5697
+ return value;
5698
+ }
5637
5699
  function maskPathText(value, secretRules) {
5638
5700
  return findSecretInPath(value, secretRules)?.masked ?? value;
5639
5701
  }
@@ -6214,8 +6276,8 @@ function generateSnapshot(configInput, options) {
6214
6276
  let summary;
6215
6277
  let summaryQuality;
6216
6278
  try {
6217
- const outcome = summarizeFile(relativePath, redacted);
6218
- summary = outcome?.summary;
6279
+ const outcome = summarizeFile(relativePath, rawContent);
6280
+ summary = outcome?.summary ? maskSummaryStrings(outcome.summary, config.secretRules) : void 0;
6219
6281
  summaryQuality = outcome?.quality;
6220
6282
  if (isSourceSummary(summary) && summary.parseErrors) {
6221
6283
  warnings.push(
@@ -6282,6 +6344,7 @@ function generateSnapshot(configInput, options) {
6282
6344
  largeFileBytes: config.largeFileBytes
6283
6345
  },
6284
6346
  config: {
6347
+ digest: configDigest(config),
6285
6348
  maxPartBytes: config.maxPartBytes,
6286
6349
  largeFileBytes: config.largeFileBytes,
6287
6350
  previewHeadLines: config.previewHeadLines,
@@ -7770,7 +7833,7 @@ ${USAGE}
7770
7833
  info(` - Schema: ${manifest.schemaVersion}`);
7771
7834
  info(` - Fingerprint: ${manifest.fingerprint}`);
7772
7835
  info(` - Files included: ${manifest.counts.totalFiles}`);
7773
- info(` - Total lines: ${manifest.counts.totalLines.toLocaleString()}`);
7836
+ info(` - Total lines: ${manifest.counts.totalLines.toLocaleString("en-US")}`);
7774
7837
  info(
7775
7838
  ` - Total size: ${(manifest.counts.totalSizeBytes / (1024 * 1024)).toFixed(2)} MB`
7776
7839
  );
@@ -7822,14 +7885,14 @@ ${USAGE}
7822
7885
  info(`
7823
7886
  \u2705 Snapshot generated in ${elapsed}s:`);
7824
7887
  info(` - Tracked files: ${manifest.counts.totalFiles}`);
7825
- info(` - Total lines: ${manifest.counts.totalLines.toLocaleString()}`);
7888
+ info(` - Total lines: ${manifest.counts.totalLines.toLocaleString("en-US")}`);
7826
7889
  info(
7827
7890
  ` - Total size: ${(manifest.counts.totalSizeBytes / (1024 * 1024)).toFixed(2)} MB`
7828
7891
  );
7829
7892
  const { artifacts } = resolved;
7830
7893
  if (artifacts.parts) {
7831
7894
  info(
7832
- ` - Parts written: ${manifest.counts.partsCount} under ${displayOutPath(resolved.cwd, resolved.outDir, "parts")}/`
7895
+ ` - Parts written: ${manifest.counts.partsCount} under ${displayOutPath(resolved.cwd, resolved.outDir, "parts")}`
7833
7896
  );
7834
7897
  }
7835
7898
  const reports = [
@@ -7839,7 +7902,7 @@ ${USAGE}
7839
7902
  ].filter(Boolean);
7840
7903
  if (reports.length > 0) {
7841
7904
  info(
7842
- ` - Reports: ${displayOutPath(resolved.cwd, resolved.outDir, "reports")}/ (${reports.join(", ")})`
7905
+ ` - Reports: ${displayOutPath(resolved.cwd, resolved.outDir, "reports")} (${reports.join(", ")})`
7843
7906
  );
7844
7907
  }
7845
7908
  if (artifacts.manifest) {
@@ -7967,6 +8030,21 @@ async function runWatchLoop(invocation, resolved) {
7967
8030
  });
7968
8031
  return 0;
7969
8032
  }
8033
+ var entryFile = process.argv[1] ?? "";
8034
+ var entryName = path10__namespace.basename(entryFile).toLowerCase();
8035
+ var invokedDirectly = entryName === "cli.js" || entryName === "cli.cjs";
8036
+ if (invokedDirectly) {
8037
+ void main().then(
8038
+ (code) => {
8039
+ process.exitCode = code;
8040
+ },
8041
+ (err) => {
8042
+ process.stderr.write(`\u274C ${err.message}
8043
+ `);
8044
+ process.exitCode = 1;
8045
+ }
8046
+ );
8047
+ }
7970
8048
 
7971
8049
  exports.UsageError = UsageError;
7972
8050
  exports.main = main;
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 { parseByteSize, GENERATOR_VERSION, ARTIFACT_NAMES, getPreset, unknownPresetMessage, MIN_MAX_PART_BYTES, loadConfigFileDetailed, resolveConfig, validateSnapshot, explainPath, compareManifests, loadManifest, renderDiffText, generateSnapshot, GENERATOR_NAME, runInit, PromptCancelled, SCHEMA_VERSION, PRESETS, renderExplainText } from './chunk-L7QBLC4C.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-PCNDUNKT.js';
2
2
  import * as fs from 'fs';
3
3
  import * as path2 from 'path';
4
4
  import { parseArgs } from 'util';
@@ -1302,7 +1302,7 @@ ${USAGE}
1302
1302
  info(` - Schema: ${manifest.schemaVersion}`);
1303
1303
  info(` - Fingerprint: ${manifest.fingerprint}`);
1304
1304
  info(` - Files included: ${manifest.counts.totalFiles}`);
1305
- info(` - Total lines: ${manifest.counts.totalLines.toLocaleString()}`);
1305
+ info(` - Total lines: ${manifest.counts.totalLines.toLocaleString("en-US")}`);
1306
1306
  info(
1307
1307
  ` - Total size: ${(manifest.counts.totalSizeBytes / (1024 * 1024)).toFixed(2)} MB`
1308
1308
  );
@@ -1354,14 +1354,14 @@ ${USAGE}
1354
1354
  info(`
1355
1355
  \u2705 Snapshot generated in ${elapsed}s:`);
1356
1356
  info(` - Tracked files: ${manifest.counts.totalFiles}`);
1357
- info(` - Total lines: ${manifest.counts.totalLines.toLocaleString()}`);
1357
+ info(` - Total lines: ${manifest.counts.totalLines.toLocaleString("en-US")}`);
1358
1358
  info(
1359
1359
  ` - Total size: ${(manifest.counts.totalSizeBytes / (1024 * 1024)).toFixed(2)} MB`
1360
1360
  );
1361
1361
  const { artifacts } = resolved;
1362
1362
  if (artifacts.parts) {
1363
1363
  info(
1364
- ` - Parts written: ${manifest.counts.partsCount} under ${displayOutPath(resolved.cwd, resolved.outDir, "parts")}/`
1364
+ ` - Parts written: ${manifest.counts.partsCount} under ${displayOutPath(resolved.cwd, resolved.outDir, "parts")}`
1365
1365
  );
1366
1366
  }
1367
1367
  const reports = [
@@ -1371,7 +1371,7 @@ ${USAGE}
1371
1371
  ].filter(Boolean);
1372
1372
  if (reports.length > 0) {
1373
1373
  info(
1374
- ` - Reports: ${displayOutPath(resolved.cwd, resolved.outDir, "reports")}/ (${reports.join(", ")})`
1374
+ ` - Reports: ${displayOutPath(resolved.cwd, resolved.outDir, "reports")} (${reports.join(", ")})`
1375
1375
  );
1376
1376
  }
1377
1377
  if (artifacts.manifest) {
@@ -1499,6 +1499,21 @@ async function runWatchLoop(invocation, resolved) {
1499
1499
  });
1500
1500
  return 0;
1501
1501
  }
1502
+ var entryFile = process.argv[1] ?? "";
1503
+ var entryName = path2.basename(entryFile).toLowerCase();
1504
+ var invokedDirectly = entryName === "cli.js" || entryName === "cli.cjs";
1505
+ if (invokedDirectly) {
1506
+ void main().then(
1507
+ (code) => {
1508
+ process.exitCode = code;
1509
+ },
1510
+ (err) => {
1511
+ process.stderr.write(`\u274C ${err.message}
1512
+ `);
1513
+ process.exitCode = 1;
1514
+ }
1515
+ );
1516
+ }
1502
1517
 
1503
1518
  export { UsageError, main, parseByteOption, parseCliArgs, parsePositiveInteger };
1504
1519
  //# sourceMappingURL=cli.js.map
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) {
@@ -3429,7 +3450,31 @@ function generateAuditReport(manifest, secretFindings, secretRules) {
3429
3450
  }
3430
3451
  lines.push("");
3431
3452
  }
3432
- lines.push("## 2. Large Files Analysis", "");
3453
+ const parseIssues = manifest.files.filter(
3454
+ (file) => file.summary !== void 0 && typeof file.summary === "object" && "parseErrors" in file.summary && typeof file.summary.parseErrors === "number" && file.summary.parseErrors > 0
3455
+ );
3456
+ lines.push("## 2. Parse & AST Diagnostics", "");
3457
+ if (parseIssues.length === 0) {
3458
+ lines.push("\u2705 Every parsed file produced a complete structural summary.", "");
3459
+ } else {
3460
+ lines.push(
3461
+ `${parseIssues.length} file(s) produced an incomplete summary:`,
3462
+ "",
3463
+ "| File | Parse Errors |",
3464
+ "| :--- | ---: |"
3465
+ );
3466
+ for (const file of parseIssues) {
3467
+ const errors = file.summary.parseErrors;
3468
+ lines.push(`| \`${mask(file.relativePath)}\` | ${errors} |`);
3469
+ }
3470
+ lines.push(
3471
+ "",
3472
+ "A parse error here means the summary is incomplete, not that the file is excluded \u2014",
3473
+ "the content is still in the parts.",
3474
+ ""
3475
+ );
3476
+ }
3477
+ lines.push("## 3. Large Files Analysis", "");
3433
3478
  const largeFiles = manifest.files.filter((file) => file.isLarge);
3434
3479
  if (largeFiles.length === 0) {
3435
3480
  lines.push("\u2705 No files exceeded the large file budget.", "");
@@ -3448,7 +3493,7 @@ function generateAuditReport(manifest, secretFindings, secretRules) {
3448
3493
  lines.push("");
3449
3494
  }
3450
3495
  lines.push(
3451
- "## 3. Architecture Layer Distribution",
3496
+ "## 4. Architecture Layer Distribution",
3452
3497
  "",
3453
3498
  "| Layer | File Count | Percentage |",
3454
3499
  "| :--- | :--- | :--- |"
@@ -3462,7 +3507,7 @@ function generateAuditReport(manifest, secretFindings, secretRules) {
3462
3507
  }
3463
3508
  lines.push("");
3464
3509
  lines.push(
3465
- "## 4. File Kind Distribution",
3510
+ "## 5. File Kind Distribution",
3466
3511
  "",
3467
3512
  "| Kind | File Count | Percentage |",
3468
3513
  "| :--- | :--- | :--- |"
@@ -3474,7 +3519,7 @@ function generateAuditReport(manifest, secretFindings, secretRules) {
3474
3519
  lines.push(`| \`${kind}\` | ${count} | ${pct}% |`);
3475
3520
  }
3476
3521
  lines.push("");
3477
- lines.push("## 5. Skipped / Non-Text Files", "");
3522
+ lines.push("## 6. Skipped / Non-Text Files", "");
3478
3523
  if (manifest.skipped.length === 0) {
3479
3524
  lines.push("No files were skipped.", "");
3480
3525
  } else {
@@ -4310,6 +4355,11 @@ function validateSnapshot(configInput) {
4310
4355
  const currentExcludes = config.excludePatterns.map(maskValue);
4311
4356
  const currentInclude = config.include.map(maskValue);
4312
4357
  const recorded = manifest.config;
4358
+ if (recorded?.digest && recorded.digest !== configDigest(config)) {
4359
+ drift.configMismatches.push(
4360
+ "configuration: the settings differ from the ones this snapshot was generated with (run generate)"
4361
+ );
4362
+ }
4313
4363
  if (recorded && typeof recorded === "object") {
4314
4364
  if (recorded.maxPartBytes !== config.maxPartBytes) {
4315
4365
  drift.configMismatches.push(
@@ -5440,7 +5490,7 @@ async function runInit(options) {
5440
5490
 
5441
5491
  // src/index.ts
5442
5492
  var GENERATOR_NAME = "@ankurhalder/codebase-snapshot";
5443
- var GENERATOR_VERSION = "4.0.3";
5493
+ var GENERATOR_VERSION = "4.0.5";
5444
5494
  var SCHEMA_VERSION = "3.0.0";
5445
5495
  function sha256Hex2(input) {
5446
5496
  return crypto__namespace.createHash("sha256").update(input).digest("hex");
@@ -5647,6 +5697,18 @@ function resolveSafeOutputDirs(config) {
5647
5697
  var PLACEHOLDER_ENTRIES = /* @__PURE__ */ new Set([".gitkeep", ".gitignore", ".DS_Store"]);
5648
5698
  var RUN_DIR_PREFIX = "run-";
5649
5699
  var STALE_RUN_MS = 60 * 60 * 1e3;
5700
+ function maskSummaryStrings(value, secretRules) {
5701
+ if (typeof value === "string") return maskPathText(value, secretRules);
5702
+ if (Array.isArray(value)) return value.map((item) => maskSummaryStrings(item, secretRules));
5703
+ if (value && typeof value === "object") {
5704
+ const out = {};
5705
+ for (const [key, item] of Object.entries(value)) {
5706
+ out[key] = maskSummaryStrings(item, secretRules);
5707
+ }
5708
+ return out;
5709
+ }
5710
+ return value;
5711
+ }
5650
5712
  function maskPathText(value, secretRules) {
5651
5713
  return findSecretInPath(value, secretRules)?.masked ?? value;
5652
5714
  }
@@ -6227,8 +6289,8 @@ function generateSnapshot(configInput, options) {
6227
6289
  let summary;
6228
6290
  let summaryQuality;
6229
6291
  try {
6230
- const outcome = summarizeFile(relativePath, redacted);
6231
- summary = outcome?.summary;
6292
+ const outcome = summarizeFile(relativePath, rawContent);
6293
+ summary = outcome?.summary ? maskSummaryStrings(outcome.summary, config.secretRules) : void 0;
6232
6294
  summaryQuality = outcome?.quality;
6233
6295
  if (isSourceSummary(summary) && summary.parseErrors) {
6234
6296
  warnings.push(
@@ -6295,6 +6357,7 @@ function generateSnapshot(configInput, options) {
6295
6357
  largeFileBytes: config.largeFileBytes
6296
6358
  },
6297
6359
  config: {
6360
+ digest: configDigest(config),
6298
6361
  maxPartBytes: config.maxPartBytes,
6299
6362
  largeFileBytes: config.largeFileBytes,
6300
6363
  previewHeadLines: config.previewHeadLines,
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.3";
498
+ declare const GENERATOR_VERSION = "4.0.5";
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.3";
498
+ declare const GENERATOR_VERSION = "4.0.5";
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-L7QBLC4C.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-PCNDUNKT.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.3",
3
+ "version": "4.0.5",
4
4
  "description": "Production-grade LLM codebase snapshot generator, auditor, and AST partitioner",
5
5
  "keywords": [
6
6
  "codebase",