code-auditor-mcp 4.1.0 → 4.1.1

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.
Files changed (47) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +36 -0
  3. package/dist/analyzers/universal/UniversalDRYAnalyzer.d.ts +1 -12
  4. package/dist/analyzers/universal/UniversalDRYAnalyzer.d.ts.map +1 -1
  5. package/dist/analyzers/universal/UniversalDRYAnalyzer.js +1 -66
  6. package/dist/analyzers/universal/UniversalDRYAnalyzer.js.map +1 -1
  7. package/dist/auditRunner.d.ts.map +1 -1
  8. package/dist/auditRunner.js +1 -20
  9. package/dist/auditRunner.js.map +1 -1
  10. package/dist/cli.js +54 -17
  11. package/dist/cli.js.map +1 -1
  12. package/dist/codeIndexDB.d.ts +1 -9
  13. package/dist/codeIndexDB.d.ts.map +1 -1
  14. package/dist/codeIndexDB.js +0 -20
  15. package/dist/codeIndexDB.js.map +1 -1
  16. package/dist/config/configLoader.d.ts +1 -1
  17. package/dist/config/configLoader.d.ts.map +1 -1
  18. package/dist/config/configLoader.js +11 -7
  19. package/dist/config/configLoader.js.map +1 -1
  20. package/dist/config/defaults.d.ts.map +1 -1
  21. package/dist/config/defaults.js +5 -6
  22. package/dist/config/defaults.js.map +1 -1
  23. package/dist/constants.d.ts +1 -1
  24. package/dist/constants.d.ts.map +1 -1
  25. package/dist/constants.js +10 -5
  26. package/dist/constants.js.map +1 -1
  27. package/dist/daemon/resolve.d.ts +4 -4
  28. package/dist/daemon/resolve.js +4 -4
  29. package/dist/dataPaths.d.ts +10 -0
  30. package/dist/dataPaths.d.ts.map +1 -1
  31. package/dist/dataPaths.js +12 -0
  32. package/dist/dataPaths.js.map +1 -1
  33. package/dist/mcp.js +6 -2
  34. package/dist/mcp.js.map +1 -1
  35. package/dist/pipelineAdapters.d.ts +1 -1
  36. package/dist/pipelineAdapters.d.ts.map +1 -1
  37. package/dist/pipelineAdapters.js +2 -5
  38. package/dist/pipelineAdapters.js.map +1 -1
  39. package/dist/types.d.ts +5 -21
  40. package/dist/types.d.ts.map +1 -1
  41. package/dist/types.js.map +1 -1
  42. package/dist/version.generated.d.ts +1 -1
  43. package/dist/version.generated.js +1 -1
  44. package/package.json +4 -4
  45. package/plugin/.claude-plugin/plugin.json +1 -1
  46. package/plugin/skills/code-auditor/SKILL.md +1 -1
  47. package/server.json +2 -2
package/dist/cli.js CHANGED
@@ -96,6 +96,7 @@ program
96
96
  .option('-c, --config <config>', 'Configuration name')
97
97
  .option('-o, --output <dir>', 'Output directory for reports')
98
98
  .option('-f, --format <format>', 'Report format: html, json, csv, or sarif')
99
+ .option('--overwrite', 'Overwrite an existing report file at --output (default: refuse)')
99
100
  .option('--fail-on <severity>', 'Exit code 2 when violations at or above this severity exist')
100
101
  .option('--full', 'Show full violation inventory (overrides default delta view when baseline exists)')
101
102
  .option('--include-baseline', 'Evaluate baseline-known violations in --fail-on checks')
@@ -456,12 +457,33 @@ program
456
457
  ? { rootDir, ...readVersionControlProvenance(rootDir) }
457
458
  : { rootDir };
458
459
  const report = generateReport(result, options.format, config);
459
- const outputDir = options.output || process.cwd();
460
460
  const ext = options.format === 'sarif' ? 'sarif' : options.format;
461
- const reportPath = join(outputDir, `audit-report.${ext}`);
462
- await fs.mkdir(dirname(reportPath), { recursive: true });
463
- await fs.writeFile(reportPath, report, 'utf-8');
464
- console.log(chalk.green(`\nReport written to ${reportPath}`));
461
+ if (options.output) {
462
+ // Explicit output path — write a file. Refuse to clobber an existing
463
+ // report unless --overwrite is passed. A report write is destructive;
464
+ // a silent overwrite of `audit-report.json` in a consuming repo is the
465
+ // defect this guard removes.
466
+ const outputDir = resolve(options.output);
467
+ const reportPath = join(outputDir, `audit-report.${ext}`);
468
+ let exists = false;
469
+ try {
470
+ await fs.access(reportPath);
471
+ exists = true;
472
+ }
473
+ catch { /* ok */ }
474
+ if (exists && !options.overwrite) {
475
+ console.error(chalk.red(`Refusing to overwrite existing report ${reportPath} — pass --overwrite to replace it.`));
476
+ process.exit(1);
477
+ }
478
+ await fs.mkdir(dirname(reportPath), { recursive: true });
479
+ await fs.writeFile(reportPath, report, 'utf-8');
480
+ console.log(chalk.green(`\nReport written to ${reportPath}`));
481
+ }
482
+ else {
483
+ // No output path — default to stdout. Never write a report into the
484
+ // audited project without an explicit --output on the command line.
485
+ process.stdout.write(report + '\n');
486
+ }
465
487
  }
466
488
  // ── Fail-on logic (Spec 18 R3) ───────────────────────────────
467
489
  // --fail-on-regression: compare total high debt to baseline snapshot
@@ -1198,8 +1220,9 @@ program
1198
1220
  .description('Generate a .codeauditor.json scaffold with invariant rules')
1199
1221
  .option('-o, --output <dir>', 'Output directory', '.')
1200
1222
  .option('-i, --interactive', 'Interactive rule builder')
1201
- .option('-f, --force', 'Force overwrite existing file without confirmation')
1202
- .option('-y, --yes', 'Skip confirmation prompts (same as --force)')
1223
+ .option('--overwrite', 'Overwrite an existing .codeauditor.json without confirmation')
1224
+ .option('-f, --force', 'Alias for --overwrite')
1225
+ .option('-y, --yes', 'Alias for --overwrite')
1203
1226
  .action(async (options) => {
1204
1227
  console.log(chalk.blue('🛠️ Code Auditor Config Generator'));
1205
1228
  console.log(chalk.gray('════════════════════════════════════════════════════'));
@@ -1795,6 +1818,7 @@ program
1795
1818
  .option('--no-unused-imports', 'Hide unused import warnings')
1796
1819
  .option('--min-complexity <threshold>', 'Minimum complexity threshold for warnings', '7')
1797
1820
  .option('-o, --output <file>', 'Save output to file instead of displaying')
1821
+ .option('--overwrite', 'Overwrite an existing output file (default: refuse)')
1798
1822
  .action(async (options) => {
1799
1823
  console.log(chalk.blue('🗺️ Codebase Map Generator'));
1800
1824
  console.log(chalk.gray('════════════════════════════════════════════════════'));
@@ -3155,9 +3179,6 @@ program
3155
3179
  // normalizes the real config, so path keys compare cleanly instead of
3156
3180
  // reading as "user-set" because one side is absolute and the other is not.
3157
3181
  const pristine = { ...getDefaultConfig(), codeIndex: { ...DEFAULT_CODE_INDEX_CONFIG } };
3158
- if (pristine.outputDirectory) {
3159
- pristine.outputDirectory = pathModule.resolve(projectRoot, pristine.outputDirectory);
3160
- }
3161
3182
  pristine.includePaths = (pristine.includePaths ?? []).map((p) => pathModule.isAbsolute(p) ? p : pathModule.resolve(projectRoot, p));
3162
3183
  pristine.excludePaths = (pristine.excludePaths ?? []).map((p) => pathModule.isAbsolute(p) ? p : pathModule.resolve(projectRoot, p));
3163
3184
  // Load the project config (defaults when no config file exists).
@@ -3534,6 +3555,9 @@ const SCAFFOLD_CONFIG = {
3534
3555
  async function generateConfigurations(options) {
3535
3556
  const outputDir = resolve(options.output || '.');
3536
3557
  const outputPath = join(outputDir, '.codeauditor.json');
3558
+ // One consent spelling across the CLI: `--overwrite`. `--force`/`--yes` are
3559
+ // retained as aliases for back-compat.
3560
+ const overwrite = Boolean(options.overwrite || options.force || options.yes);
3537
3561
  let config;
3538
3562
  if (options.interactive) {
3539
3563
  // --- Interactive rule builder ---
@@ -3553,7 +3577,7 @@ async function generateConfigurations(options) {
3553
3577
  config = await buildRulesInteractively();
3554
3578
  }
3555
3579
  // Confirm output directory
3556
- if (!options.force && !options.yes) {
3580
+ if (!overwrite) {
3557
3581
  const { dir } = await inquirer.prompt({
3558
3582
  dir: {
3559
3583
  type: 'input',
@@ -3598,12 +3622,12 @@ async function generateConfigurations(options) {
3598
3622
  exists = true;
3599
3623
  }
3600
3624
  catch { /* ok */ }
3601
- if (exists && !options.force && !options.yes) {
3625
+ if (exists && !overwrite) {
3602
3626
  console.log(chalk.yellow(`.codeauditor.json already exists at ${outputPath}`));
3603
- console.log(chalk.gray('Use --force or --yes to overwrite, or --interactive to build a custom config.'));
3627
+ console.log(chalk.gray('Use --overwrite to replace it, or --interactive to build a custom config.'));
3604
3628
  return;
3605
3629
  }
3606
- if (exists && (options.force || options.yes)) {
3630
+ if (exists && overwrite) {
3607
3631
  console.log(chalk.yellow('Overwriting existing .codeauditor.json...'));
3608
3632
  }
3609
3633
  config = SCAFFOLD_CONFIG;
@@ -3877,9 +3901,22 @@ async function generateCodeMap(options) {
3877
3901
  const textOutput = mapGenerator.formatAsText(completeCodeMap, mapOptions);
3878
3902
  // Output results
3879
3903
  if (options.output) {
3880
- // Save to file
3881
- await fs.writeFile(options.output, textOutput);
3882
- console.log(chalk.green(`✓ Code map saved to: ${options.output}`));
3904
+ // Save to file. Refuse to clobber an existing file unless --overwrite is
3905
+ // passed — same guard as the report writer, so `map -o` cannot silently
3906
+ // destroy a file the developer did not consent to replacing.
3907
+ const outPath = resolve(options.output);
3908
+ let exists = false;
3909
+ try {
3910
+ await fs.access(outPath);
3911
+ exists = true;
3912
+ }
3913
+ catch { /* ok */ }
3914
+ if (exists && !options.overwrite) {
3915
+ console.error(chalk.red(`Refusing to overwrite existing file ${outPath} — pass --overwrite to replace it.`));
3916
+ process.exit(1);
3917
+ }
3918
+ await fs.writeFile(outPath, textOutput);
3919
+ console.log(chalk.green(`✓ Code map saved to: ${outPath}`));
3883
3920
  // Show summary
3884
3921
  console.log('');
3885
3922
  console.log(chalk.blue('Summary:'));