eslint-plugin-ai-guard 1.2.1 → 1.2.2

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/cli/index.js CHANGED
@@ -30,6 +30,154 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
30
30
  mod
31
31
  ));
32
32
 
33
+ // cli/utils/debug.ts
34
+ var debug_exports = {};
35
+ __export(debug_exports, {
36
+ debugLog: () => debugLog,
37
+ printCIDebug: () => printCIDebug,
38
+ printGitDebug: () => printGitDebug
39
+ });
40
+ function debugLog(message) {
41
+ process.stderr.write(`${DIM("[debug]")} ${message}
42
+ `);
43
+ }
44
+ function printGitDebug(result) {
45
+ const d = result.debugInfo;
46
+ process.stderr.write("\n");
47
+ process.stderr.write(`${LABEL(" Git Resolution Trace")}
48
+ `);
49
+ process.stderr.write(`${DIM(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}
50
+ `);
51
+ process.stderr.write(` ${DIM("Mode:")} ${import_chalk4.default.white(result.mode)}
52
+ `);
53
+ if (d.resolvedBase) {
54
+ process.stderr.write(` ${DIM("Base branch:")} ${import_chalk4.default.white(d.resolvedBase)}
55
+ `);
56
+ } else {
57
+ process.stderr.write(` ${DIM("Base branch:")} ${import_chalk4.default.dim("(none \u2014 uncommitted mode)")}
58
+ `);
59
+ }
60
+ if (d.mergeBase) {
61
+ process.stderr.write(` ${DIM("Merge base:")} ${import_chalk4.default.white(d.mergeBase.slice(0, 12))}\u2026
62
+ `);
63
+ }
64
+ if (d.isShallowClone) {
65
+ process.stderr.write(` ${WARN} ${import_chalk4.default.yellow("Shallow clone detected")} \u2014 use fetch-depth: 0 in workflow
66
+ `);
67
+ }
68
+ if (d.isDetachedHead) {
69
+ process.stderr.write(` ${WARN} ${import_chalk4.default.yellow("Detached HEAD")} \u2014 branch context unavailable
70
+ `);
71
+ }
72
+ process.stderr.write("\n");
73
+ process.stderr.write(` ${DIM("Strategies attempted:")}
74
+ `);
75
+ for (const strategy of d.strategiesAttempted) {
76
+ const succeeded = strategy === d.strategySucceeded;
77
+ const icon = succeeded ? OK : ERR;
78
+ const label = succeeded ? import_chalk4.default.green(strategy) : import_chalk4.default.dim(strategy);
79
+ process.stderr.write(` ${icon} ${label}
80
+ `);
81
+ }
82
+ if (d.strategySucceeded) {
83
+ process.stderr.write(`
84
+ ${OK} ${import_chalk4.default.green("Succeeded:")} ${d.strategySucceeded}
85
+ `);
86
+ } else {
87
+ process.stderr.write(`
88
+ ${ERR} ${import_chalk4.default.red("All strategies failed")}
89
+ `);
90
+ }
91
+ process.stderr.write("\n");
92
+ process.stderr.write(` ${DIM("Files:")}
93
+ `);
94
+ process.stderr.write(` ${ARROW} Detected raw: ${import_chalk4.default.white(d.rawFileCount)}
95
+ `);
96
+ process.stderr.write(` ${ARROW} Kept: ${import_chalk4.default.green(result.files.length)}
97
+ `);
98
+ if (d.droppedByExtension > 0) {
99
+ process.stderr.write(` ${ARROW} Dropped (ext): ${import_chalk4.default.dim(d.droppedByExtension)}
100
+ `);
101
+ }
102
+ if (d.droppedByIgnore > 0) {
103
+ process.stderr.write(` ${ARROW} Dropped (ignored): ${import_chalk4.default.dim(d.droppedByIgnore)}
104
+ `);
105
+ }
106
+ if (d.droppedByWorkingDir > 0) {
107
+ process.stderr.write(` ${ARROW} Dropped (dir): ${import_chalk4.default.dim(d.droppedByWorkingDir)}
108
+ `);
109
+ }
110
+ if (d.droppedMissing > 0) {
111
+ process.stderr.write(` ${ARROW} Dropped (missing): ${import_chalk4.default.dim(d.droppedMissing)}
112
+ `);
113
+ }
114
+ if (result.zeroFilesReason) {
115
+ process.stderr.write("\n");
116
+ process.stderr.write(` ${WARN} ${import_chalk4.default.yellow("Zero files reason:")}
117
+ `);
118
+ process.stderr.write(` ${import_chalk4.default.dim(result.zeroFilesReason)}
119
+ `);
120
+ }
121
+ if (result.files.length > 0) {
122
+ process.stderr.write("\n");
123
+ process.stderr.write(` ${DIM("Changed files (first 20):")}
124
+ `);
125
+ for (const f of result.files.slice(0, 20)) {
126
+ process.stderr.write(` ${import_chalk4.default.dim("\xB7")} ${import_chalk4.default.white(f)}
127
+ `);
128
+ }
129
+ if (result.files.length > 20) {
130
+ process.stderr.write(` ${import_chalk4.default.dim(`\u2026 and ${result.files.length - 20} more`)}
131
+ `);
132
+ }
133
+ }
134
+ process.stderr.write("\n");
135
+ }
136
+ function printCIDebug(info) {
137
+ process.stderr.write("\n");
138
+ process.stderr.write(`${LABEL(" CI Environment")}
139
+ `);
140
+ process.stderr.write(`${DIM(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}
141
+ `);
142
+ const env = (name, value) => {
143
+ const val = value ? import_chalk4.default.white(value) : import_chalk4.default.dim("(not set)");
144
+ process.stderr.write(` ${DIM(name.padEnd(26))} ${val}
145
+ `);
146
+ };
147
+ env("GITHUB_ACTIONS:", info.isGitHubActions ? "true" : "false");
148
+ env("GITHUB_BASE_REF:", info.githubBaseRef);
149
+ env("GITHUB_SHA:", info.githubSha);
150
+ env("GITHUB_REF:", info.githubRef);
151
+ env("GITHUB_REPOSITORY:", info.githubRepository);
152
+ env("GITHUB_WORKFLOW:", info.githubWorkflow);
153
+ env("GITHUB_RUN_ID:", info.githubRunId);
154
+ env("GITHUB_EVENT_NAME:", info.githubEventName);
155
+ process.stderr.write("\n");
156
+ env("GITHUB_STEP_SUMMARY:", info.githubStepSummary);
157
+ env("GITHUB_OUTPUT:", info.githubOutput);
158
+ process.stderr.write("\n");
159
+ env("Scan preset:", info.preset);
160
+ env("Fail on:", info.failOn);
161
+ env("Scan mode:", info.scanMode);
162
+ if (info.sarifOutputPath) {
163
+ env("SARIF output:", info.sarifOutputPath);
164
+ }
165
+ process.stderr.write("\n");
166
+ }
167
+ var import_chalk4, DIM, LABEL, OK, WARN, ERR, ARROW;
168
+ var init_debug = __esm({
169
+ "cli/utils/debug.ts"() {
170
+ "use strict";
171
+ import_chalk4 = __toESM(require("chalk"));
172
+ DIM = import_chalk4.default.dim;
173
+ LABEL = import_chalk4.default.cyan.bold;
174
+ OK = import_chalk4.default.green("\u2714");
175
+ WARN = import_chalk4.default.yellow("\u26A0");
176
+ ERR = import_chalk4.default.red("\u2716");
177
+ ARROW = import_chalk4.default.dim("\u2192");
178
+ }
179
+ });
180
+
33
181
  // cli/utils/config-manager.ts
34
182
  var config_manager_exports = {};
35
183
  __export(config_manager_exports, {
@@ -266,19 +414,19 @@ function addIgnoresToLegacyConfig(existing) {
266
414
  function getConfigFilePath(configType, cwd = process.cwd()) {
267
415
  switch (configType) {
268
416
  case "flat-js":
269
- return import_path5.default.join(cwd, "eslint.config.js");
417
+ return import_path6.default.join(cwd, "eslint.config.js");
270
418
  case "flat-mjs":
271
- return import_path5.default.join(cwd, "eslint.config.mjs");
419
+ return import_path6.default.join(cwd, "eslint.config.mjs");
272
420
  case "flat-cjs":
273
- return import_path5.default.join(cwd, "eslint.config.cjs");
421
+ return import_path6.default.join(cwd, "eslint.config.cjs");
274
422
  case "eslintrc-js":
275
- return import_path5.default.join(cwd, ".eslintrc.js");
423
+ return import_path6.default.join(cwd, ".eslintrc.js");
276
424
  case "eslintrc-cjs":
277
- return import_path5.default.join(cwd, ".eslintrc.cjs");
425
+ return import_path6.default.join(cwd, ".eslintrc.cjs");
278
426
  case "eslintrc-json":
279
- return import_path5.default.join(cwd, ".eslintrc.json");
427
+ return import_path6.default.join(cwd, ".eslintrc.json");
280
428
  default:
281
- return import_path5.default.join(cwd, ".eslintrc.js");
429
+ return import_path6.default.join(cwd, ".eslintrc.js");
282
430
  }
283
431
  }
284
432
  function validateFlatConfigText(content) {
@@ -313,12 +461,12 @@ function validateLegacyConfigText(content) {
313
461
  }
314
462
  return problems;
315
463
  }
316
- var import_fs6, import_path5, AI_GUARD_MARKER, DEFAULT_FLAT_IGNORES, DEFAULT_LEGACY_IGNORES;
464
+ var import_fs6, import_path6, AI_GUARD_MARKER, DEFAULT_FLAT_IGNORES, DEFAULT_LEGACY_IGNORES;
317
465
  var init_config_manager = __esm({
318
466
  "cli/utils/config-manager.ts"() {
319
467
  "use strict";
320
468
  import_fs6 = __toESM(require("fs"));
321
- import_path5 = __toESM(require("path"));
469
+ import_path6 = __toESM(require("path"));
322
470
  AI_GUARD_MARKER = "eslint-plugin-ai-guard";
323
471
  DEFAULT_FLAT_IGNORES = [
324
472
  "node_modules/**",
@@ -342,7 +490,7 @@ var init_config_manager = __esm({
342
490
  // cli/index.ts
343
491
  var import_commander = require("commander");
344
492
  var import_fs11 = __toESM(require("fs"));
345
- var import_path13 = __toESM(require("path"));
493
+ var import_path14 = __toESM(require("path"));
346
494
 
347
495
  // cli/commands/run.ts
348
496
  var import_ora = __toESM(require("ora"));
@@ -544,24 +692,46 @@ var log = {
544
692
 
545
693
  // cli/utils/eslint-runner.ts
546
694
  var ISSUE_CONFIDENCE = {
695
+ // HIGH — near-certain bugs: false positive rate <2% in real-world codebases
547
696
  "ai-guard/no-hardcoded-secret": "high",
697
+ // Literal credential string in source: almost always a mistake
548
698
  "ai-guard/no-eval-dynamic": "high",
699
+ // Dynamic eval: no legitimate modern use case
549
700
  "ai-guard/no-floating-promise": "high",
550
- "ai-guard/no-empty-catch": "high",
701
+ // Unhandled promise: async failures silently swallowed
702
+ // MEDIUM — likely bugs, but legitimate patterns exist
703
+ "ai-guard/no-empty-catch": "medium",
704
+ // CHANGED from high: empty catch is valid for optional ops (JSON.parse, feature detection)
551
705
  "ai-guard/no-sql-string-concat": "medium",
706
+ // SQL injection risk, but ORM template literals can FP
552
707
  "ai-guard/no-await-in-loop": "medium",
708
+ // Sequential await is often intentional (rate limiting, ordering)
553
709
  "ai-guard/require-auth-middleware": "medium",
710
+ // Context-blind: public routes are valid
554
711
  "ai-guard/require-authz-check": "medium",
712
+ // Context-blind: some resources are public
555
713
  "ai-guard/no-catch-log-rethrow": "medium",
714
+ // Log-then-rethrow is a known antipattern but sometimes intentional
556
715
  "ai-guard/no-catch-without-use": "medium",
716
+ // Unused catch param common in TS
557
717
  "ai-guard/no-unsafe-deserialize": "medium",
718
+ // JSON.parse is sometimes safe with trusted input
719
+ // LOW — possible improvement, high false-positive rate
558
720
  "ai-guard/no-async-array-callback": "low",
721
+ // Promise.all is better, but forEach async is not always a bug
559
722
  "ai-guard/no-dead-branch": "low",
723
+ // Static analysis of conditions is inherently imprecise
560
724
  "ai-guard/no-broad-exception": "low",
725
+ // Catching Error is common and sometimes correct
561
726
  "ai-guard/no-console-in-handler": "low",
727
+ // Stylistic: debug logs left in vs intentional logging
562
728
  "ai-guard/no-duplicate-logic-block": "low",
729
+ // May be coincidental similarity, not true duplication
730
+ // INFORMATIONAL — hints only, never fail CI
563
731
  "ai-guard/no-async-without-await": "informational",
732
+ // Framework patterns (Next.js RSC, etc.) make this very noisy
564
733
  "ai-guard/no-redundant-await": "informational"
734
+ // Explicit await in return is idiomatic in many codebases
565
735
  };
566
736
  var ISSUE_CATEGORY = {
567
737
  "ai-guard/no-floating-promise": "Async Reliability",
@@ -742,8 +912,8 @@ function classifyEcosystemType(msg) {
742
912
  return "foreign-rule";
743
913
  }
744
914
  async function loadPluginModuleFromCwd(cwd) {
745
- const { createRequire: createRequire2 } = await import("module");
746
- const requireFromCwd = createRequire2(import_path.default.join(cwd, "package.json"));
915
+ const { createRequire: createRequire3 } = await import("module");
916
+ const requireFromCwd = createRequire3(import_path.default.join(cwd, "package.json"));
747
917
  try {
748
918
  const resolved = requireFromCwd.resolve("eslint-plugin-ai-guard");
749
919
  return import((0, import_url.pathToFileURL)(resolved).href);
@@ -1034,6 +1204,30 @@ async function runEslint(options) {
1034
1204
  };
1035
1205
  }
1036
1206
 
1207
+ // cli/utils/version.ts
1208
+ var import_module = require("module");
1209
+ var import_url2 = require("url");
1210
+ var import_path2 = __toESM(require("path"));
1211
+ var import_meta = {};
1212
+ var _version;
1213
+ function readVersion() {
1214
+ try {
1215
+ const require_ = (0, import_module.createRequire)(import_meta.url);
1216
+ const pkgPath = import_path2.default.resolve(
1217
+ import_path2.default.dirname((0, import_url2.fileURLToPath)(import_meta.url)),
1218
+ "../../package.json"
1219
+ );
1220
+ const pkg = require_(pkgPath);
1221
+ if (pkg.version) return pkg.version;
1222
+ } catch {
1223
+ }
1224
+ if (typeof __PKG_VERSION__ !== "undefined") {
1225
+ return __PKG_VERSION__;
1226
+ }
1227
+ return "0.0.0";
1228
+ }
1229
+ var PKG_VERSION = _version ?? (_version = readVersion());
1230
+
1037
1231
  // cli/utils/sarif.ts
1038
1232
  var RULE_DOCS = {
1039
1233
  "ai-guard/no-empty-catch": { shortDesc: "Empty catch block silently swallows errors", tags: ["reliability"] },
@@ -1183,7 +1377,7 @@ function buildSarifResult(issue, file) {
1183
1377
  }
1184
1378
  };
1185
1379
  }
1186
- function buildSarifLog(result, version = "1.3.0") {
1380
+ function buildSarifLog(result, version = PKG_VERSION) {
1187
1381
  const usedRuleIds = collectUsedRuleIds(result);
1188
1382
  const rules = buildRuleDescriptors(usedRuleIds);
1189
1383
  const sarifResults = [];
@@ -1223,6 +1417,13 @@ function sarifToJson(log2) {
1223
1417
 
1224
1418
  // cli/utils/github-summary.ts
1225
1419
  var import_fs2 = __toESM(require("fs"));
1420
+ function warnEnvIssue(name, filePath, err) {
1421
+ const msg = err instanceof Error ? err.message : String(err);
1422
+ process.stderr.write(
1423
+ `[ai-guard] Warning: Could not write to ${name}=${filePath}: ${msg}
1424
+ `
1425
+ );
1426
+ }
1226
1427
  function escapeMarkdown(text) {
1227
1428
  return text.replace(/[|`*_[\]<>]/g, "\\$&");
1228
1429
  }
@@ -1413,8 +1614,9 @@ function writeGitHubSummary(result, options) {
1413
1614
  if (!summaryPath) return;
1414
1615
  try {
1415
1616
  const markdown = buildGitHubSummaryMarkdown(result, options);
1416
- import_fs2.default.appendFileSync(summaryPath, markdown + "\n");
1417
- } catch {
1617
+ import_fs2.default.appendFileSync(summaryPath, markdown + "\n", { encoding: "utf-8" });
1618
+ } catch (err) {
1619
+ warnEnvIssue("GITHUB_STEP_SUMMARY", summaryPath, err);
1418
1620
  }
1419
1621
  }
1420
1622
  function writeGitHubOutputs(result, sarifPath) {
@@ -1432,14 +1634,15 @@ function writeGitHubOutputs(result, sarifPath) {
1432
1634
  ...sarifPath ? [`sarif-file=${sarifPath}`] : []
1433
1635
  ];
1434
1636
  try {
1435
- import_fs2.default.appendFileSync(outputPath, outputs.join("\n") + "\n");
1436
- } catch {
1637
+ import_fs2.default.appendFileSync(outputPath, outputs.join("\n") + "\n", { encoding: "utf-8" });
1638
+ } catch (err) {
1639
+ warnEnvIssue("GITHUB_OUTPUT", outputPath, err);
1437
1640
  }
1438
1641
  }
1439
1642
 
1440
1643
  // cli/utils/git-diff.ts
1441
1644
  var import_child_process = require("child_process");
1442
- var import_path2 = __toESM(require("path"));
1645
+ var import_path3 = __toESM(require("path"));
1443
1646
  var import_fs3 = __toESM(require("fs"));
1444
1647
  var DEFAULT_EXTENSIONS = [".js", ".jsx", ".ts", ".tsx", ".mjs", ".cjs", ".mts", ".cts"];
1445
1648
  var IGNORE_PREFIXES = [
@@ -1466,7 +1669,8 @@ function runGit(args, cwd) {
1466
1669
  return (0, import_child_process.execSync)(`git ${args}`, {
1467
1670
  cwd,
1468
1671
  encoding: "utf-8",
1469
- stdio: ["pipe", "pipe", "pipe"]
1672
+ stdio: ["pipe", "pipe", "pipe"],
1673
+ timeout: 15e3
1470
1674
  }).trim();
1471
1675
  } catch {
1472
1676
  return null;
@@ -1475,35 +1679,103 @@ function runGit(args, cwd) {
1475
1679
  function isGitAvailable(cwd) {
1476
1680
  return runGit("rev-parse --is-inside-work-tree", cwd) === "true";
1477
1681
  }
1478
- function filterFiles(rawFiles, extensions, workingDirectory, cwd) {
1479
- let dropped = 0;
1682
+ function isShallowClone(cwd) {
1683
+ return runGit("rev-parse --is-shallow-repository", cwd) === "true";
1684
+ }
1685
+ function isDetachedHead(cwd) {
1686
+ const result = runGit("symbolic-ref --quiet HEAD", cwd);
1687
+ return result === null;
1688
+ }
1689
+ function normalizeBranchName(ref) {
1690
+ return ref.replace(/^origin\//, "").trim();
1691
+ }
1692
+ function tryPrDiff(branch, cwd, debugInfo) {
1693
+ const rawBranch = normalizeBranchName(branch);
1694
+ {
1695
+ const strategy = `merge-base HEAD origin/${rawBranch}`;
1696
+ debugInfo.strategiesAttempted.push(strategy);
1697
+ const mergeBase = runGit(`merge-base HEAD origin/${rawBranch}`, cwd);
1698
+ if (mergeBase) {
1699
+ debugInfo.mergeBase = mergeBase;
1700
+ const out = runGit(`diff --name-only --diff-filter=ACMRT ${mergeBase}`, cwd);
1701
+ if (out !== null) {
1702
+ debugInfo.strategySucceeded = strategy;
1703
+ return { output: out, strategy, mergeBase };
1704
+ }
1705
+ }
1706
+ }
1707
+ {
1708
+ const strategy = `merge-base HEAD ${rawBranch}`;
1709
+ debugInfo.strategiesAttempted.push(strategy);
1710
+ const mergeBase = runGit(`merge-base HEAD ${rawBranch}`, cwd);
1711
+ if (mergeBase) {
1712
+ if (!debugInfo.mergeBase) debugInfo.mergeBase = mergeBase;
1713
+ const out = runGit(`diff --name-only --diff-filter=ACMRT ${mergeBase}`, cwd);
1714
+ if (out !== null) {
1715
+ debugInfo.strategySucceeded = strategy;
1716
+ return { output: out, strategy, mergeBase };
1717
+ }
1718
+ }
1719
+ }
1720
+ {
1721
+ const strategy = `diff origin/${rawBranch}...HEAD`;
1722
+ debugInfo.strategiesAttempted.push(strategy);
1723
+ const out = runGit(`diff --name-only --diff-filter=ACMRT origin/${rawBranch}...HEAD`, cwd);
1724
+ if (out !== null) {
1725
+ debugInfo.strategySucceeded = strategy;
1726
+ return { output: out, strategy };
1727
+ }
1728
+ }
1729
+ {
1730
+ const strategy = `diff ${rawBranch}...HEAD`;
1731
+ debugInfo.strategiesAttempted.push(strategy);
1732
+ const out = runGit(`diff --name-only --diff-filter=ACMRT ${rawBranch}...HEAD`, cwd);
1733
+ if (out !== null) {
1734
+ debugInfo.strategySucceeded = strategy;
1735
+ return { output: out, strategy };
1736
+ }
1737
+ }
1738
+ {
1739
+ const strategy = "diff HEAD~1 (shallow fallback)";
1740
+ debugInfo.strategiesAttempted.push(strategy);
1741
+ const out = runGit("diff --name-only --diff-filter=ACMRT HEAD~1", cwd);
1742
+ if (out !== null) {
1743
+ debugInfo.strategySucceeded = strategy;
1744
+ return { output: out, strategy };
1745
+ }
1746
+ }
1747
+ debugInfo.strategySucceeded = null;
1748
+ return null;
1749
+ }
1750
+ function filterFiles(rawFiles, extensions, workingDirectory, cwd, debugInfo) {
1480
1751
  const kept = [];
1481
1752
  for (const rel of rawFiles) {
1482
- const ext = import_path2.default.extname(rel).toLowerCase();
1753
+ const normalized = rel.replace(/\\/g, "/").trim();
1754
+ if (!normalized) continue;
1755
+ const ext = import_path3.default.extname(normalized).toLowerCase();
1483
1756
  if (!extensions.includes(ext)) {
1484
- dropped++;
1757
+ debugInfo.droppedByExtension++;
1485
1758
  continue;
1486
1759
  }
1487
- const normalized = rel.replace(/\\/g, "/");
1488
1760
  if (IGNORE_PREFIXES.some((prefix) => normalized.startsWith(prefix))) {
1489
- dropped++;
1761
+ debugInfo.droppedByIgnore++;
1490
1762
  continue;
1491
1763
  }
1492
1764
  if (workingDirectory) {
1493
1765
  const wdNorm = workingDirectory.replace(/\\/g, "/").replace(/\/$/, "");
1494
1766
  if (!normalized.startsWith(wdNorm + "/") && normalized !== wdNorm) {
1495
- dropped++;
1767
+ debugInfo.droppedByWorkingDir++;
1496
1768
  continue;
1497
1769
  }
1498
1770
  }
1499
- const abs = import_path2.default.resolve(cwd, rel);
1771
+ const abs = import_path3.default.resolve(cwd, normalized);
1500
1772
  if (!import_fs3.default.existsSync(abs)) {
1501
- dropped++;
1773
+ debugInfo.droppedMissing++;
1502
1774
  continue;
1503
1775
  }
1504
1776
  kept.push(abs);
1505
1777
  }
1506
- return { kept, dropped };
1778
+ return kept;
1507
1779
  }
1508
1780
  function parseFileList(output) {
1509
1781
  return output.split("\n").map((f) => f.trim()).filter(Boolean);
@@ -1514,46 +1786,96 @@ function getChangedFiles(options = {}) {
1514
1786
  base,
1515
1787
  cwd = process.cwd(),
1516
1788
  extensions = DEFAULT_EXTENSIONS,
1517
- workingDirectory
1789
+ workingDirectory,
1790
+ debug = false
1518
1791
  } = options;
1519
- const effectiveBase = base ?? process.env.GITHUB_BASE_REF ? `origin/${process.env.GITHUB_BASE_REF ?? ""}` : void 0;
1792
+ const debugInfo = {
1793
+ strategiesAttempted: [],
1794
+ strategySucceeded: null,
1795
+ isShallowClone: false,
1796
+ isDetachedHead: false,
1797
+ rawFileCount: 0,
1798
+ droppedByExtension: 0,
1799
+ droppedByIgnore: 0,
1800
+ droppedMissing: 0,
1801
+ droppedByWorkingDir: 0
1802
+ };
1520
1803
  if (!isGitAvailable(cwd)) {
1521
- return { files: [], mode: "fallback", totalDetected: 0, filteredOut: 0 };
1804
+ return {
1805
+ files: [],
1806
+ mode: "fallback",
1807
+ totalDetected: 0,
1808
+ filteredOut: 0,
1809
+ debugInfo,
1810
+ zeroFilesReason: "Git is not available in this directory. Run inside a git repository."
1811
+ };
1522
1812
  }
1813
+ debugInfo.isShallowClone = isShallowClone(cwd);
1814
+ debugInfo.isDetachedHead = isDetachedHead(cwd);
1815
+ const envBase = process.env.GITHUB_BASE_REF ? normalizeBranchName(process.env.GITHUB_BASE_REF) : void 0;
1816
+ const resolvedBranch = base ? normalizeBranchName(base) : envBase;
1817
+ debugInfo.resolvedBase = resolvedBranch;
1523
1818
  let rawOutput = null;
1524
1819
  let mode;
1525
1820
  let usedBase;
1526
- if (effectiveBase && !staged) {
1527
- const mergeBase = runGit(`merge-base HEAD ${effectiveBase}`, cwd);
1528
- if (mergeBase) {
1529
- rawOutput = runGit(`diff --name-only --diff-filter=ACMRT ${mergeBase}...HEAD`, cwd);
1530
- }
1821
+ let zeroFilesReason;
1822
+ if (staged) {
1823
+ rawOutput = runGit("diff --name-only --cached --diff-filter=ACMRT", cwd);
1824
+ mode = "staged";
1825
+ debugInfo.strategiesAttempted.push("git diff --cached");
1826
+ if (rawOutput !== null) debugInfo.strategySucceeded = "git diff --cached";
1531
1827
  if (!rawOutput) {
1532
- rawOutput = runGit(`diff --name-only --diff-filter=ACMRT ${effectiveBase}`, cwd);
1828
+ zeroFilesReason = "No staged files found. Run `git add <files>` before using --staged.";
1533
1829
  }
1830
+ } else if (resolvedBranch) {
1534
1831
  mode = "pr-diff";
1535
- usedBase = effectiveBase;
1536
- } else if (staged) {
1537
- rawOutput = runGit("diff --name-only --cached --diff-filter=ACMRT", cwd);
1538
- mode = "staged";
1832
+ usedBase = resolvedBranch;
1833
+ const diffResult = tryPrDiff(resolvedBranch, cwd, debugInfo);
1834
+ if (diffResult) {
1835
+ rawOutput = diffResult.output;
1836
+ } else {
1837
+ const shallow = debugInfo.isShallowClone ? " Shallow clone detected \u2014 try fetch-depth: 0 in your workflow." : "";
1838
+ const detached = debugInfo.isDetachedHead ? " HEAD is detached \u2014 ensure checkout fetches the branch." : "";
1839
+ zeroFilesReason = `PR diff failed against "${resolvedBranch}". Tried: ${debugInfo.strategiesAttempted.join(", ")}.${shallow}${detached} Run with --debug-git for full diagnosis.`;
1840
+ }
1539
1841
  } else {
1842
+ mode = "uncommitted";
1540
1843
  const staged_ = runGit("diff --name-only --cached --diff-filter=ACMRT", cwd) ?? "";
1541
1844
  const unstaged = runGit("diff --name-only --diff-filter=ACMRT", cwd) ?? "";
1845
+ debugInfo.strategiesAttempted.push("git diff --cached", "git diff (unstaged)");
1542
1846
  const combined = /* @__PURE__ */ new Set([...parseFileList(staged_), ...parseFileList(unstaged)]);
1543
1847
  rawOutput = [...combined].join("\n");
1544
- mode = "uncommitted";
1848
+ if (rawOutput) debugInfo.strategySucceeded = "uncommitted changes";
1849
+ if (!rawOutput) {
1850
+ zeroFilesReason = "No uncommitted changes found. Use --pr to scan PR changes, or --staged for staged files.";
1851
+ }
1545
1852
  }
1546
1853
  if (!rawOutput) {
1547
- return { files: [], mode, base: usedBase, totalDetected: 0, filteredOut: 0 };
1854
+ return {
1855
+ files: [],
1856
+ mode,
1857
+ base: usedBase,
1858
+ totalDetected: 0,
1859
+ filteredOut: 0,
1860
+ debugInfo,
1861
+ zeroFilesReason
1862
+ };
1548
1863
  }
1549
1864
  const rawFiles = parseFileList(rawOutput);
1550
- const { kept, dropped } = filterFiles(rawFiles, extensions, workingDirectory, cwd);
1865
+ debugInfo.rawFileCount = rawFiles.length;
1866
+ const kept = filterFiles(rawFiles, extensions, workingDirectory, cwd, debugInfo);
1867
+ const dropped = debugInfo.droppedByExtension + debugInfo.droppedByIgnore + debugInfo.droppedByWorkingDir + debugInfo.droppedMissing;
1868
+ if (kept.length === 0 && rawFiles.length > 0) {
1869
+ zeroFilesReason = `${rawFiles.length} changed file${rawFiles.length !== 1 ? "s" : ""} detected but all filtered out. Extension filter: ${debugInfo.droppedByExtension}, ignored paths: ${debugInfo.droppedByIgnore}, missing from disk: ${debugInfo.droppedMissing}.`;
1870
+ }
1551
1871
  return {
1552
1872
  files: kept,
1553
1873
  mode,
1554
1874
  base: usedBase,
1555
1875
  totalDetected: rawFiles.length,
1556
- filteredOut: dropped
1876
+ filteredOut: dropped,
1877
+ debugInfo,
1878
+ zeroFilesReason: kept.length === 0 ? zeroFilesReason : void 0
1557
1879
  };
1558
1880
  }
1559
1881
  function isGitHubActions() {
@@ -1957,32 +2279,58 @@ function resolveExitCode(result, failOn, maxWarnings) {
1957
2279
  }
1958
2280
 
1959
2281
  // cli/commands/changed.ts
1960
- var import_path3 = __toESM(require("path"));
2282
+ var import_path4 = __toESM(require("path"));
1961
2283
  var import_fs4 = __toESM(require("fs"));
1962
2284
  var import_ora2 = __toESM(require("ora"));
1963
- var import_chalk4 = __toESM(require("chalk"));
2285
+ var import_chalk5 = __toESM(require("chalk"));
1964
2286
  function registerChangedCommand(program2) {
1965
- program2.command("changed").description("Scan only changed files in the current PR or working tree (fastest CI mode)").option("--pr", "Scan files changed vs base branch (auto-detects GITHUB_BASE_REF in CI)").option("--staged", "Scan only staged (git add'd) files").option("--base <branch>", "Base branch to diff against (e.g. main, origin/main)").option("--path <dir>", "Root path / working directory for scanning", ".").option("--strict", "Use the strict rule preset (all rules at error)").option("--security", "Use the security-only rule preset").option("--fail-on <level>", "Fail CI on: high | medium | any | none", "high").option("--json", "Output results as JSON").option("--sarif", "Output results as SARIF 2.1.0 (for GitHub Code Scanning)").option("--sarif-output <file>", "Write SARIF to file instead of stdout").option("--github-summary", "Write GitHub step summary (auto-enabled in GitHub Actions)").option(
2287
+ program2.command("changed").description("Scan only changed files in the current PR or working tree (fastest CI mode)").option("--pr", "Scan files changed vs base branch (auto-detects GITHUB_BASE_REF in CI)").option("--staged", "Scan only staged (git add'd) files").option("--base <branch>", "Base branch to diff against (raw name: main, develop \u2014 not origin/main)").option("--path <dir>", "Root path / working directory for scanning", ".").option("--strict", "Use the strict rule preset (all rules at error)").option("--security", "Use the security-only rule preset").option("--fail-on <level>", "Fail CI on: high | medium | any | errors | none", "high").option("--json", "Output results as JSON").option("--sarif", "Output results as SARIF 2.1.0 (for GitHub Code Scanning)").option("--sarif-output <file>", "Write SARIF to this file path").option("--sarif-stdout", "Force SARIF to stdout even in CI (overrides auto-file behavior)").option("--github-summary", "Write GitHub step summary (auto-enabled in GitHub Actions)").option(
1966
2288
  "--max-warnings <n>",
1967
2289
  "Fail if warnings exceed this count",
1968
2290
  (v) => Number.parseInt(v, 10)
1969
- ).option("--verbose", "Expand all findings (disable grouping)").option("--quiet", "Show errors only").option("--debug-timing", "Print per-phase timing diagnostics").action(async (opts) => {
2291
+ ).option("--verbose", "Expand all findings (disable grouping)").option("--quiet", "Show errors only").option("--debug-timing", "Print per-phase timing diagnostics").option("--debug-git", "Print full git resolution trace (useful for diagnosing zero-file issues)").option("--debug-ci", "Print CI environment state (GITHUB_* vars, SARIF path, summary path)").action(async (opts) => {
1970
2292
  const preset = opts.strict ? "strict" : opts.security ? "security" : "recommended";
1971
2293
  const inCI = isGitHubActions();
1972
2294
  const baseRef = opts.base ?? (opts.pr || inCI ? getGitHubBaseRef() : void 0);
2295
+ const sarifToFile = opts.sarif && !opts.sarifStdout && (opts.sarifOutput || inCI);
2296
+ const resolvedSarifPath = opts.sarifOutput ?? (sarifToFile ? "ai-guard-results.sarif" : void 0);
1973
2297
  if (!opts.json && !opts.sarif) {
1974
2298
  log.banner("AI GUARD");
1975
2299
  }
2300
+ if (opts.debugCi) {
2301
+ const { printCIDebug: printCIDebug2 } = await Promise.resolve().then(() => (init_debug(), debug_exports));
2302
+ printCIDebug2({
2303
+ isGitHubActions: inCI,
2304
+ githubBaseRef: process.env.GITHUB_BASE_REF,
2305
+ githubSha: process.env.GITHUB_SHA,
2306
+ githubRef: process.env.GITHUB_REF,
2307
+ githubRepository: process.env.GITHUB_REPOSITORY,
2308
+ githubWorkflow: process.env.GITHUB_WORKFLOW,
2309
+ githubRunId: process.env.GITHUB_RUN_ID,
2310
+ githubEventName: process.env.GITHUB_EVENT_NAME,
2311
+ githubStepSummary: process.env.GITHUB_STEP_SUMMARY,
2312
+ githubOutput: process.env.GITHUB_OUTPUT,
2313
+ sarifOutputPath: resolvedSarifPath,
2314
+ preset,
2315
+ failOn: opts.failOn,
2316
+ scanMode: opts.staged ? "staged" : baseRef ? "pr-diff" : "uncommitted"
2317
+ });
2318
+ }
1976
2319
  const cwd = process.cwd();
1977
- const resolvedPath = import_path3.default.resolve(opts.path);
2320
+ const resolvedPath = import_path4.default.resolve(opts.path);
1978
2321
  const workingDirectory = opts.path !== "." ? opts.path : void 0;
1979
- const spinner = opts.json || opts.sarif ? null : (0, import_ora2.default)({ text: import_chalk4.default.dim("Detecting changed files\u2026"), color: "cyan" }).start();
2322
+ const spinner = opts.json || opts.sarif ? null : (0, import_ora2.default)({ text: import_chalk5.default.dim("Detecting changed files\u2026"), color: "cyan" }).start();
1980
2323
  const changedResult = getChangedFiles({
1981
2324
  staged: opts.staged ?? false,
1982
- base: baseRef ? `origin/${baseRef}` : opts.base,
2325
+ base: baseRef,
1983
2326
  cwd,
1984
- workingDirectory
2327
+ workingDirectory,
2328
+ debug: opts.debugGit
1985
2329
  });
2330
+ if (opts.debugGit) {
2331
+ const { printGitDebug: printGitDebug2 } = await Promise.resolve().then(() => (init_debug(), debug_exports));
2332
+ printGitDebug2(changedResult);
2333
+ }
1986
2334
  if (changedResult.files.length === 0) {
1987
2335
  spinner?.stop();
1988
2336
  if (changedResult.mode === "fallback") {
@@ -1995,18 +2343,25 @@ function registerChangedCommand(program2) {
1995
2343
  targetPath: resolvedPath.toString(),
1996
2344
  debugTiming: opts.debugTiming
1997
2345
  });
1998
- handleResults(result2, opts, preset, "full", 0, inCI);
2346
+ handleResults(result2, opts, preset, "full", 0, inCI, resolvedSarifPath);
1999
2347
  return;
2000
2348
  }
2001
2349
  if (!opts.json && !opts.sarif) {
2002
2350
  log.blank();
2003
- log.print(` ${import_chalk4.default.green("\u2714")} No changed JS/TS files detected \u2014 nothing to scan`);
2351
+ log.print(` ${import_chalk5.default.yellow("\u26A0")} No changed JS/TS files detected \u2014 nothing to scan`);
2352
+ if (changedResult.zeroFilesReason) {
2353
+ log.print(import_chalk5.default.dim(` ${changedResult.zeroFilesReason}`));
2354
+ }
2004
2355
  if (changedResult.filteredOut > 0) {
2005
- log.print(import_chalk4.default.dim(` (${changedResult.filteredOut} changed file${changedResult.filteredOut !== 1 ? "s" : ""} skipped \u2014 not JS/TS)`));
2356
+ log.print(import_chalk5.default.dim(` (${changedResult.filteredOut} file${changedResult.filteredOut !== 1 ? "s" : ""} filtered out)`));
2357
+ }
2358
+ if (!opts.debugGit) {
2359
+ log.print(import_chalk5.default.dim(" Run with --debug-git for full git resolution trace."));
2006
2360
  }
2007
2361
  log.blank();
2008
2362
  } else if (opts.json) {
2009
2363
  console.log(JSON.stringify({
2364
+ version: PKG_VERSION,
2010
2365
  preset,
2011
2366
  scanMode: changedResult.mode,
2012
2367
  changedFiles: 0,
@@ -2014,6 +2369,8 @@ function registerChangedCommand(program2) {
2014
2369
  totalIssues: 0,
2015
2370
  totalErrors: 0,
2016
2371
  totalWarnings: 0,
2372
+ zeroFilesReason: changedResult.zeroFilesReason,
2373
+ debugInfo: opts.debugGit ? changedResult.debugInfo : void 0,
2017
2374
  signalSummary: { high: 0, medium: 0, low: 0, informational: 0, ecosystemIssues: 0, parserErrors: 0 }
2018
2375
  }, null, 2));
2019
2376
  }
@@ -2021,7 +2378,7 @@ function registerChangedCommand(program2) {
2021
2378
  return;
2022
2379
  }
2023
2380
  if (spinner) {
2024
- spinner.text = import_chalk4.default.dim(`Scanning ${changedResult.files.length} changed file${changedResult.files.length !== 1 ? "s" : ""}\u2026`);
2381
+ spinner.text = import_chalk5.default.dim(`Scanning ${changedResult.files.length} changed file${changedResult.files.length !== 1 ? "s" : ""}\u2026`);
2025
2382
  }
2026
2383
  const result = await runEslint({
2027
2384
  preset,
@@ -2030,10 +2387,11 @@ function registerChangedCommand(program2) {
2030
2387
  debugTiming: opts.debugTiming
2031
2388
  });
2032
2389
  spinner?.stop();
2033
- handleResults(result, opts, preset, changedResult.mode === "pr-diff" ? "changed" : changedResult.mode === "staged" ? "staged" : "changed", changedResult.files.length, inCI);
2390
+ const scanMode = changedResult.mode === "staged" ? "staged" : "changed";
2391
+ handleResults(result, opts, preset, scanMode, changedResult.files.length, inCI, resolvedSarifPath);
2034
2392
  });
2035
2393
  }
2036
- function handleResults(result, opts, preset, scanMode, changedFilesCount, inCI) {
2394
+ function handleResults(result, opts, preset, scanMode, changedFilesCount, inCI, resolvedSarifPath) {
2037
2395
  if (inCI || opts.githubSummary) {
2038
2396
  writeGitHubSummary(result, { preset, scanMode, changedFilesCount });
2039
2397
  writeGitHubOutputs(result, opts.sarifOutput);
@@ -2042,8 +2400,8 @@ function handleResults(result, opts, preset, scanMode, changedFilesCount, inCI)
2042
2400
  if (opts.sarif) {
2043
2401
  const sarifLog = buildSarifLog(result);
2044
2402
  const sarifJson = sarifToJson(sarifLog);
2045
- if (opts.sarifOutput) {
2046
- import_fs4.default.writeFileSync(opts.sarifOutput, sarifJson, "utf-8");
2403
+ if (resolvedSarifPath) {
2404
+ import_fs4.default.writeFileSync(resolvedSarifPath, sarifJson, "utf-8");
2047
2405
  } else {
2048
2406
  console.log(sarifJson);
2049
2407
  }
@@ -2053,7 +2411,7 @@ function handleResults(result, opts, preset, scanMode, changedFilesCount, inCI)
2053
2411
  if (opts.json) {
2054
2412
  const signalSummary = buildSignalSummary(result);
2055
2413
  const jsonOutput = {
2056
- version: "1.3.0",
2414
+ version: PKG_VERSION,
2057
2415
  preset,
2058
2416
  scanMode,
2059
2417
  scannedPath: opts.path,
@@ -2115,7 +2473,7 @@ function handleResults(result, opts, preset, scanMode, changedFilesCount, inCI)
2115
2473
  log.category(icon, cat, categoryErrors[cat] ?? 0, categoryWarnings[cat] ?? 0);
2116
2474
  }
2117
2475
  log.blank();
2118
- log.print(` ${import_chalk4.default.bold("Total:")} ${formatIssueCount(result.totalErrors, result.totalWarnings)}`);
2476
+ log.print(` ${import_chalk5.default.bold("Total:")} ${formatIssueCount(result.totalErrors, result.totalWarnings)}`);
2119
2477
  log.blank();
2120
2478
  if (actionableFiles.length > 0) {
2121
2479
  log.section("Issues by File");
@@ -2126,18 +2484,18 @@ function handleResults(result, opts, preset, scanMode, changedFilesCount, inCI)
2126
2484
  if (totalInfoCount > 0 && !quiet) {
2127
2485
  if (verbose) {
2128
2486
  log.section("Informational Hints");
2129
- log.print(import_chalk4.default.dim(" Stylistic hints with higher false-positive rate \u2014 review before acting."));
2487
+ log.print(import_chalk5.default.dim(" Stylistic hints with higher false-positive rate \u2014 review before acting."));
2130
2488
  log.blank();
2131
2489
  renderIssuesByFile({ ...result, files: informationalFiles }, true, false);
2132
2490
  } else {
2133
2491
  log.blank();
2134
- log.print(` ${import_chalk4.default.gray("\u25B8")} ${import_chalk4.default.gray(`${totalInfoCount} informational hint${totalInfoCount !== 1 ? "s" : ""} \u2014 run with ${import_chalk4.default.cyan("--verbose")} to expand`)}`);
2492
+ log.print(` ${import_chalk5.default.gray("\u25B8")} ${import_chalk5.default.gray(`${totalInfoCount} informational hint${totalInfoCount !== 1 ? "s" : ""} \u2014 run with ${import_chalk5.default.cyan("--verbose")} to expand`)}`);
2135
2493
  }
2136
2494
  }
2137
2495
  }
2138
2496
  if (result.ecosystemIssues.length > 0) {
2139
2497
  log.ecosystemSection("ESLint Config Issues");
2140
- log.print(import_chalk4.default.dim(" These issues come from your project's ESLint config, not from ai-guard."));
2498
+ log.print(import_chalk5.default.dim(" These issues come from your project's ESLint config, not from ai-guard."));
2141
2499
  log.blank();
2142
2500
  const seen = /* @__PURE__ */ new Map();
2143
2501
  for (const issue of result.ecosystemIssues) {
@@ -2158,11 +2516,11 @@ function handleResults(result, opts, preset, scanMode, changedFilesCount, inCI)
2158
2516
  log.blank();
2159
2517
  log.section("Next Steps");
2160
2518
  if (result.totalIssues > 0) {
2161
- log.info(`Run ${import_chalk4.default.cyan("ai-guard baseline")} to save these issues and track only new ones`);
2162
- log.info(`Run ${import_chalk4.default.cyan("ai-guard report")} to generate a shareable HTML report`);
2519
+ log.info(`Run ${import_chalk5.default.cyan("ai-guard baseline")} to save these issues and track only new ones`);
2520
+ log.info(`Run ${import_chalk5.default.cyan("ai-guard report")} to generate a shareable HTML report`);
2163
2521
  }
2164
2522
  if (result.ecosystemIssues.length > 0) {
2165
- log.info(`Run ${import_chalk4.default.cyan("ai-guard doctor")} to diagnose ESLint config issues`);
2523
+ log.info(`Run ${import_chalk5.default.cyan("ai-guard doctor")} to diagnose ESLint config issues`);
2166
2524
  }
2167
2525
  log.blank();
2168
2526
  process.exit(getFailOnExitCode(result, opts.failOn, opts.maxWarnings));
@@ -2172,14 +2530,14 @@ function getFailOnExitCode(result, failOn, maxWarnings) {
2172
2530
  }
2173
2531
 
2174
2532
  // cli/commands/init.ts
2175
- var import_chalk5 = __toESM(require("chalk"));
2176
- var import_path6 = __toESM(require("path"));
2533
+ var import_chalk6 = __toESM(require("chalk"));
2534
+ var import_path7 = __toESM(require("path"));
2177
2535
  var import_fs7 = __toESM(require("fs"));
2178
2536
 
2179
2537
  // cli/utils/detector.ts
2180
2538
  var import_fs5 = __toESM(require("fs"));
2181
- var import_path4 = __toESM(require("path"));
2182
- var import_module = require("module");
2539
+ var import_path5 = __toESM(require("path"));
2540
+ var import_module2 = require("module");
2183
2541
  var FLAT_CONFIG_FILES = [
2184
2542
  { file: "eslint.config.js", type: "flat-js" },
2185
2543
  { file: "eslint.config.mjs", type: "flat-mjs" },
@@ -2195,11 +2553,11 @@ var LEGACY_CONFIG_FILES = [
2195
2553
  var ALL_CONFIG_FILES = [...FLAT_CONFIG_FILES, ...LEGACY_CONFIG_FILES];
2196
2554
  function isPackageInstalled(pkgName, cwd = process.cwd()) {
2197
2555
  try {
2198
- const pkgPath = import_path4.default.join(cwd, "node_modules", pkgName, "package.json");
2556
+ const pkgPath = import_path5.default.join(cwd, "node_modules", pkgName, "package.json");
2199
2557
  if (import_fs5.default.existsSync(pkgPath)) {
2200
2558
  return true;
2201
2559
  }
2202
- const req = (0, import_module.createRequire)(import_path4.default.join(cwd, "package.json"));
2560
+ const req = (0, import_module2.createRequire)(import_path5.default.join(cwd, "package.json"));
2203
2561
  req.resolve(`${pkgName}/package.json`);
2204
2562
  return true;
2205
2563
  } catch {
@@ -2208,8 +2566,8 @@ function isPackageInstalled(pkgName, cwd = process.cwd()) {
2208
2566
  }
2209
2567
  function getPackageVersion(pkgName, cwd = process.cwd()) {
2210
2568
  try {
2211
- const pkgPath = import_path4.default.join(cwd, "node_modules", pkgName, "package.json");
2212
- const resolvedPath = import_fs5.default.existsSync(pkgPath) ? pkgPath : (0, import_module.createRequire)(import_path4.default.join(cwd, "package.json")).resolve(`${pkgName}/package.json`);
2569
+ const pkgPath = import_path5.default.join(cwd, "node_modules", pkgName, "package.json");
2570
+ const resolvedPath = import_fs5.default.existsSync(pkgPath) ? pkgPath : (0, import_module2.createRequire)(import_path5.default.join(cwd, "package.json")).resolve(`${pkgName}/package.json`);
2213
2571
  const raw = import_fs5.default.readFileSync(resolvedPath, "utf-8");
2214
2572
  const json = JSON.parse(raw);
2215
2573
  return json.version ?? null;
@@ -2226,7 +2584,7 @@ function detectConfigType(cwd = process.cwd()) {
2226
2584
  const found = [];
2227
2585
  let first = null;
2228
2586
  for (const { file, type } of ALL_CONFIG_FILES) {
2229
- const fullPath = import_path4.default.join(cwd, file);
2587
+ const fullPath = import_path5.default.join(cwd, file);
2230
2588
  if (import_fs5.default.existsSync(fullPath)) {
2231
2589
  found.push(fullPath);
2232
2590
  if (!first) first = { type, path: fullPath };
@@ -2306,7 +2664,7 @@ async function verifyConfigLoads(configPath, cwd) {
2306
2664
  overrideConfigFile: configPath
2307
2665
  });
2308
2666
  await eslint.lintText("", {
2309
- filePath: import_path6.default.join(cwd, "_ai_guard_probe_.js")
2667
+ filePath: import_path7.default.join(cwd, "_ai_guard_probe_.js")
2310
2668
  });
2311
2669
  return null;
2312
2670
  } catch (err) {
@@ -2324,7 +2682,7 @@ function registerInitCommand(program2) {
2324
2682
  const isDryRun = opts.dryRun === true;
2325
2683
  log.banner("AI GUARD INIT");
2326
2684
  if (isDryRun) {
2327
- log.print(` ${import_chalk5.default.yellow("\u2691 DRY RUN \u2014 no files will be written")}`);
2685
+ log.print(` ${import_chalk6.default.yellow("\u2691 DRY RUN \u2014 no files will be written")}`);
2328
2686
  log.blank();
2329
2687
  }
2330
2688
  log.info("Detecting your project setup\u2026");
@@ -2342,7 +2700,7 @@ function registerInitCommand(program2) {
2342
2700
  log.warn("eslint-plugin-ai-guard not found");
2343
2701
  }
2344
2702
  if (env.configType !== "none") {
2345
- log.success(`ESLint config found: ${import_chalk5.default.white(import_path6.default.relative(cwd, env.configPath ?? env.configType))}`);
2703
+ log.success(`ESLint config found: ${import_chalk6.default.white(import_path7.default.relative(cwd, env.configPath ?? env.configType))}`);
2346
2704
  } else {
2347
2705
  log.info("No ESLint config found \u2014 will generate one");
2348
2706
  }
@@ -2351,9 +2709,9 @@ function registerInitCommand(program2) {
2351
2709
  log.blank();
2352
2710
  log.warn("Conflicting configs detected:");
2353
2711
  for (const p of env.allConfigPaths) {
2354
- log.print(` ${import_chalk5.default.yellow("\u2192")} ${import_chalk5.default.white(import_path6.default.relative(cwd, p))}`);
2712
+ log.print(` ${import_chalk6.default.yellow("\u2192")} ${import_chalk6.default.white(import_path7.default.relative(cwd, p))}`);
2355
2713
  }
2356
- log.print(` ${import_chalk5.default.gray("Multiple config formats found \u2014 this can cause unpredictable behavior.")}`);
2714
+ log.print(` ${import_chalk6.default.gray("Multiple config formats found \u2014 this can cause unpredictable behavior.")}`);
2357
2715
  }
2358
2716
  log.blank();
2359
2717
  const toInstall = [];
@@ -2364,22 +2722,22 @@ function registerInitCommand(program2) {
2364
2722
  log.warn("The following packages are not installed:");
2365
2723
  log.blank();
2366
2724
  for (const pkg of toInstall) {
2367
- log.print(` ${import_chalk5.default.yellow("\u2192")} ${import_chalk5.default.white(pkg)}`);
2725
+ log.print(` ${import_chalk6.default.yellow("\u2192")} ${import_chalk6.default.white(pkg)}`);
2368
2726
  }
2369
2727
  log.blank();
2370
- log.print(` ${import_chalk5.default.bold("Run this first:")}`);
2728
+ log.print(` ${import_chalk6.default.bold("Run this first:")}`);
2371
2729
  log.blank();
2372
- log.print(` ${import_chalk5.default.cyan(`npm install --save-dev ${toInstall.join(" ")}`)}`);
2730
+ log.print(` ${import_chalk6.default.cyan(`npm install --save-dev ${toInstall.join(" ")}`)}`);
2373
2731
  log.blank();
2374
- log.print(` Then re-run ${import_chalk5.default.cyan("ai-guard init")} to complete setup.`);
2732
+ log.print(` Then re-run ${import_chalk6.default.cyan("ai-guard init")} to complete setup.`);
2375
2733
  log.blank();
2376
2734
  process.exit(1);
2377
2735
  return;
2378
2736
  }
2379
2737
  try {
2380
- const { createRequire: createRequire2 } = await import("module");
2738
+ const { createRequire: createRequire3 } = await import("module");
2381
2739
  const { pathToFileURL: pathToFileURL2 } = await import("url");
2382
- const req = createRequire2(import_path6.default.join(cwd, "_probe.js"));
2740
+ const req = createRequire3(import_path7.default.join(cwd, "_probe.js"));
2383
2741
  const resolvedPath = req.resolve("eslint-plugin-ai-guard");
2384
2742
  const aiGuard = await import(pathToFileURL2(resolvedPath).href);
2385
2743
  const plugin = aiGuard.default || aiGuard;
@@ -2398,9 +2756,9 @@ function registerInitCommand(program2) {
2398
2756
  if (eslintNeedsFlat && existingIsLegacy) {
2399
2757
  log.section("Config Migration Required");
2400
2758
  log.warn(`ESLint v${env.eslintMajor} requires flat config, but a legacy config was found:`);
2401
- log.print(` ${import_chalk5.default.white(import_path6.default.relative(cwd, env.configPath))}`);
2759
+ log.print(` ${import_chalk6.default.white(import_path7.default.relative(cwd, env.configPath))}`);
2402
2760
  log.blank();
2403
- log.print(` ${import_chalk5.default.bold("ai-guard will create a new flat config.")}`);
2761
+ log.print(` ${import_chalk6.default.bold("ai-guard will create a new flat config.")}`);
2404
2762
  log.blank();
2405
2763
  }
2406
2764
  log.section(`Configuring ESLint${isDryRun ? " (dry run)" : ""}`);
@@ -2410,34 +2768,34 @@ function registerInitCommand(program2) {
2410
2768
  const raw = readConfig(env.configPath);
2411
2769
  const { content: fixed, changed } = removeNukeIgnore(raw);
2412
2770
  if (changed) {
2413
- log.warn(`Removed "**/*" ignore pattern from ${import_path6.default.relative(cwd, env.configPath)}`);
2771
+ log.warn(`Removed "**/*" ignore pattern from ${import_path7.default.relative(cwd, env.configPath)}`);
2414
2772
  if (!isDryRun) {
2415
2773
  backupConfig(env.configPath);
2416
2774
  writeConfig(env.configPath, fixed);
2417
2775
  log.success("Ignore pattern fixed");
2418
2776
  } else {
2419
- log.print(` ${import_chalk5.default.gray("[dry-run] would remove nuke-ignore from existing config")}`);
2777
+ log.print(` ${import_chalk6.default.gray("[dry-run] would remove nuke-ignore from existing config")}`);
2420
2778
  }
2421
2779
  }
2422
2780
  }
2423
2781
  if (env.configType === "none" || eslintNeedsFlat && existingIsLegacy) {
2424
2782
  const targetName = useFlat ? "eslint.config.mjs" : ".eslintrc.js";
2425
- finalConfigPath = import_path6.default.join(cwd, targetName);
2783
+ finalConfigPath = import_path7.default.join(cwd, targetName);
2426
2784
  const content2 = useFlat ? generateFlatConfig(preset) : generateLegacyConfig(preset);
2427
2785
  if (isDryRun) {
2428
- log.print(` ${import_chalk5.default.gray(`[dry-run] would create: ${targetName}`)}`);
2786
+ log.print(` ${import_chalk6.default.gray(`[dry-run] would create: ${targetName}`)}`);
2429
2787
  log.blank();
2430
- log.print(import_chalk5.default.gray("\u2500\u2500\u2500 Preview \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
2788
+ log.print(import_chalk6.default.gray("\u2500\u2500\u2500 Preview \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
2431
2789
  log.blank();
2432
2790
  for (const line of content2.split("\n")) {
2433
- log.print(import_chalk5.default.gray(` ${line}`));
2791
+ log.print(import_chalk6.default.gray(` ${line}`));
2434
2792
  }
2435
2793
  log.blank();
2436
2794
  } else {
2437
2795
  writeConfig(finalConfigPath, content2);
2438
- log.success(`Created ${import_chalk5.default.white(targetName)}`);
2439
- log.info(` Preset: ${import_chalk5.default.cyan(preset)}`);
2440
- log.info(` Format: ${import_chalk5.default.cyan(useFlat ? "ESLint v9 flat config (eslint.config.mjs)" : "ESLint v8 legacy config (.eslintrc.js)")}`);
2796
+ log.success(`Created ${import_chalk6.default.white(targetName)}`);
2797
+ log.info(` Preset: ${import_chalk6.default.cyan(preset)}`);
2798
+ log.info(` Format: ${import_chalk6.default.cyan(useFlat ? "ESLint v9 flat config (eslint.config.mjs)" : "ESLint v8 legacy config (.eslintrc.js)")}`);
2441
2799
  configWritten = true;
2442
2800
  }
2443
2801
  } else if (useFlat && existingIsFlat) {
@@ -2450,15 +2808,15 @@ function registerInitCommand(program2) {
2450
2808
  finalConfigPath = env.configPath;
2451
2809
  } else if (isDryRun) {
2452
2810
  finalConfigPath = env.configPath;
2453
- log.print(` ${import_chalk5.default.gray(`[dry-run] would patch: ${import_path6.default.relative(cwd, env.configPath)}`)}`);
2811
+ log.print(` ${import_chalk6.default.gray(`[dry-run] would patch: ${import_path7.default.relative(cwd, env.configPath)}`)}`);
2454
2812
  } else {
2455
2813
  const bak = backupConfig(env.configPath);
2456
- log.info(`Backed up \u2192 ${import_chalk5.default.gray(import_path6.default.relative(cwd, bak))}`);
2814
+ log.info(`Backed up \u2192 ${import_chalk6.default.gray(import_path7.default.relative(cwd, bak))}`);
2457
2815
  writeConfig(env.configPath, patched);
2458
2816
  if (isInvalid) {
2459
- log.success(`Detected invalid ai-guard config \u2014 repairing ${import_chalk5.default.white(import_path6.default.relative(cwd, env.configPath))}`);
2817
+ log.success(`Detected invalid ai-guard config \u2014 repairing ${import_chalk6.default.white(import_path7.default.relative(cwd, env.configPath))}`);
2460
2818
  } else {
2461
- log.success(`Patched ${import_chalk5.default.white(import_path6.default.relative(cwd, env.configPath))}`);
2819
+ log.success(`Patched ${import_chalk6.default.white(import_path7.default.relative(cwd, env.configPath))}`);
2462
2820
  }
2463
2821
  finalConfigPath = env.configPath;
2464
2822
  configWritten = true;
@@ -2471,12 +2829,12 @@ function registerInitCommand(program2) {
2471
2829
  finalConfigPath = env.configPath;
2472
2830
  } else if (isDryRun) {
2473
2831
  finalConfigPath = env.configPath;
2474
- log.print(` ${import_chalk5.default.gray(`[dry-run] would patch: ${import_path6.default.relative(cwd, env.configPath)}`)}`);
2832
+ log.print(` ${import_chalk6.default.gray(`[dry-run] would patch: ${import_path7.default.relative(cwd, env.configPath)}`)}`);
2475
2833
  } else {
2476
2834
  const bak = backupConfig(env.configPath);
2477
- log.info(`Backed up \u2192 ${import_chalk5.default.gray(import_path6.default.relative(cwd, bak))}`);
2835
+ log.info(`Backed up \u2192 ${import_chalk6.default.gray(import_path7.default.relative(cwd, bak))}`);
2478
2836
  writeConfig(env.configPath, patched);
2479
- log.success(`Patched ${import_chalk5.default.white(import_path6.default.relative(cwd, env.configPath))}`);
2837
+ log.success(`Patched ${import_chalk6.default.white(import_path7.default.relative(cwd, env.configPath))}`);
2480
2838
  finalConfigPath = env.configPath;
2481
2839
  configWritten = true;
2482
2840
  }
@@ -2492,11 +2850,11 @@ function registerInitCommand(program2) {
2492
2850
  cleanedUp = true;
2493
2851
  } catch (err) {
2494
2852
  const reason = err instanceof Error ? err.message : String(err);
2495
- log.warn(`Could not back up ${import_path6.default.relative(cwd, p)}: ${reason}`);
2853
+ log.warn(`Could not back up ${import_path7.default.relative(cwd, p)}: ${reason}`);
2496
2854
  }
2497
2855
  } else {
2498
2856
  cleanedUp = true;
2499
- log.print(` ${import_chalk5.default.gray(`[dry-run] would rename ${import_path6.default.relative(cwd, p)} to ${import_path6.default.basename(p)}.bak`)}`);
2857
+ log.print(` ${import_chalk6.default.gray(`[dry-run] would rename ${import_path7.default.relative(cwd, p)} to ${import_path7.default.basename(p)}.bak`)}`);
2500
2858
  }
2501
2859
  }
2502
2860
  }
@@ -2506,8 +2864,8 @@ function registerInitCommand(program2) {
2506
2864
  }
2507
2865
  if (isDryRun) {
2508
2866
  log.blank();
2509
- log.print(` ${import_chalk5.default.yellow("Dry run complete \u2014 no files written.")}`);
2510
- log.print(` Re-run without ${import_chalk5.default.cyan("--dry-run")} to apply.`);
2867
+ log.print(` ${import_chalk6.default.yellow("Dry run complete \u2014 no files written.")}`);
2868
+ log.print(` Re-run without ${import_chalk6.default.cyan("--dry-run")} to apply.`);
2511
2869
  log.blank();
2512
2870
  process.exit(0);
2513
2871
  return;
@@ -2515,10 +2873,10 @@ function registerInitCommand(program2) {
2515
2873
  log.blank();
2516
2874
  log.section("Validation");
2517
2875
  if (!import_fs7.default.existsSync(finalConfigPath)) {
2518
- log.error(`Config file not found after write: ${import_path6.default.relative(cwd, finalConfigPath)}`);
2876
+ log.error(`Config file not found after write: ${import_path7.default.relative(cwd, finalConfigPath)}`);
2519
2877
  log.blank();
2520
- log.print(` ${import_chalk5.default.bold("Problem:")} File write may have failed.`);
2521
- log.print(` ${import_chalk5.default.bold("Fix:")} Check disk space and file permissions, then re-run.`);
2878
+ log.print(` ${import_chalk6.default.bold("Problem:")} File write may have failed.`);
2879
+ log.print(` ${import_chalk6.default.bold("Fix:")} Check disk space and file permissions, then re-run.`);
2522
2880
  log.blank();
2523
2881
  process.exit(1);
2524
2882
  return;
@@ -2528,36 +2886,36 @@ function registerInitCommand(program2) {
2528
2886
  if (validationErrors.length > 0) {
2529
2887
  log.warn("Config validation found issues:");
2530
2888
  for (const e of validationErrors) {
2531
- log.print(` ${import_chalk5.default.red("\u2716")} ${e}`);
2889
+ log.print(` ${import_chalk6.default.red("\u2716")} ${e}`);
2532
2890
  }
2533
2891
  } else {
2534
- log.success(`Config structure valid: ${import_chalk5.default.white(import_path6.default.relative(cwd, finalConfigPath))}`);
2892
+ log.success(`Config structure valid: ${import_chalk6.default.white(import_path7.default.relative(cwd, finalConfigPath))}`);
2535
2893
  }
2536
2894
  log.info("Verifying ESLint can load the config\u2026");
2537
2895
  const loadError = await verifyConfigLoads(finalConfigPath, cwd);
2538
2896
  if (loadError !== null) {
2539
2897
  log.blank();
2540
2898
  if (loadError.kind === "module-not-found") {
2541
- log.warn(`Could not verify: module not found: ${import_chalk5.default.yellow(loadError.pkg)}`);
2899
+ log.warn(`Could not verify: module not found: ${import_chalk6.default.yellow(loadError.pkg)}`);
2542
2900
  log.blank();
2543
- log.print(` ${import_chalk5.default.bold("Install the missing package:")}`);
2544
- log.print(` ${import_chalk5.default.cyan(`npm install --save-dev ${loadError.pkg}`)}`);
2545
- log.print(` Then run ${import_chalk5.default.cyan("ai-guard doctor")} to confirm.`);
2901
+ log.print(` ${import_chalk6.default.bold("Install the missing package:")}`);
2902
+ log.print(` ${import_chalk6.default.cyan(`npm install --save-dev ${loadError.pkg}`)}`);
2903
+ log.print(` Then run ${import_chalk6.default.cyan("ai-guard doctor")} to confirm.`);
2546
2904
  log.blank();
2547
2905
  } else {
2548
2906
  log.error("ESLint failed to load the generated config.");
2549
2907
  log.blank();
2550
- log.print(` ${import_chalk5.default.bold("Problem:")}`);
2551
- log.print(` ${import_chalk5.default.red(loadError.message)}`);
2908
+ log.print(` ${import_chalk6.default.bold("Problem:")}`);
2909
+ log.print(` ${import_chalk6.default.red(loadError.message)}`);
2552
2910
  if (loadError.kind === "unknown") {
2553
2911
  log.blank();
2554
- log.print(` ${import_chalk5.default.yellow("Generated config may be using incorrect plugin structure.")}`);
2912
+ log.print(` ${import_chalk6.default.yellow("Generated config may be using incorrect plugin structure.")}`);
2555
2913
  }
2556
2914
  log.blank();
2557
- log.print(` ${import_chalk5.default.bold("Fix:")}`);
2558
- log.print(` 1. Check the syntax in ${import_chalk5.default.cyan(import_path6.default.relative(cwd, finalConfigPath))}`);
2559
- log.print(` 2. Make sure ${import_chalk5.default.cyan("eslint-plugin-ai-guard")} is installed`);
2560
- log.print(` 3. Run ${import_chalk5.default.cyan("ai-guard doctor")} for full diagnostics`);
2915
+ log.print(` ${import_chalk6.default.bold("Fix:")}`);
2916
+ log.print(` 1. Check the syntax in ${import_chalk6.default.cyan(import_path7.default.relative(cwd, finalConfigPath))}`);
2917
+ log.print(` 2. Make sure ${import_chalk6.default.cyan("eslint-plugin-ai-guard")} is installed`);
2918
+ log.print(` 3. Run ${import_chalk6.default.cyan("ai-guard doctor")} for full diagnostics`);
2561
2919
  log.blank();
2562
2920
  process.exit(1);
2563
2921
  return;
@@ -2575,30 +2933,30 @@ function registerInitCommand(program2) {
2575
2933
  }
2576
2934
  const lingeringConflicts = env.hasConflictingConfigs && !eslintNeedsFlat && !cleanedUpInfo;
2577
2935
  if (loadError === null && !lingeringConflicts) {
2578
- log.print(` ${import_chalk5.default.green("\u2714")} ${import_chalk5.default.bold.green("Configuration validated successfully")}`);
2936
+ log.print(` ${import_chalk6.default.green("\u2714")} ${import_chalk6.default.bold.green("Configuration validated successfully")}`);
2579
2937
  }
2580
- log.print(` ${import_chalk5.default.green("\u2714")} ${import_chalk5.default.bold("ESLint config:")} ${import_chalk5.default.cyan(import_path6.default.relative(cwd, finalConfigPath))}`);
2581
- log.print(` ${import_chalk5.default.green("\u2714")} ${import_chalk5.default.bold("Mode:")} ${import_chalk5.default.cyan(useFlat ? `Flat config (ESLint v${env.eslintMajor ?? 9})` : `Legacy config (ESLint v${env.eslintMajor ?? 8})`)}`);
2582
- log.print(` ${import_chalk5.default.green("\u2714")} ${import_chalk5.default.bold("Preset:")} ${import_chalk5.default.cyan(preset)}`);
2938
+ log.print(` ${import_chalk6.default.green("\u2714")} ${import_chalk6.default.bold("ESLint config:")} ${import_chalk6.default.cyan(import_path7.default.relative(cwd, finalConfigPath))}`);
2939
+ log.print(` ${import_chalk6.default.green("\u2714")} ${import_chalk6.default.bold("Mode:")} ${import_chalk6.default.cyan(useFlat ? `Flat config (ESLint v${env.eslintMajor ?? 9})` : `Legacy config (ESLint v${env.eslintMajor ?? 8})`)}`);
2940
+ log.print(` ${import_chalk6.default.green("\u2714")} ${import_chalk6.default.bold("Preset:")} ${import_chalk6.default.cyan(preset)}`);
2583
2941
  log.blank();
2584
- log.info(`Run ${import_chalk5.default.cyan("npx eslint .")} \u2192 lint with your editor integration`);
2585
- log.info(`Run ${import_chalk5.default.cyan("ai-guard run")} \u2192 zero-config scan`);
2586
- log.info(`Run ${import_chalk5.default.cyan("ai-guard doctor")} \u2192 verify the full setup`);
2587
- log.info(`Run ${import_chalk5.default.cyan("ai-guard baseline")} \u2192 save baseline, track only new issues`);
2942
+ log.info(`Run ${import_chalk6.default.cyan("npx eslint .")} \u2192 lint with your editor integration`);
2943
+ log.info(`Run ${import_chalk6.default.cyan("ai-guard run")} \u2192 zero-config scan`);
2944
+ log.info(`Run ${import_chalk6.default.cyan("ai-guard doctor")} \u2192 verify the full setup`);
2945
+ log.info(`Run ${import_chalk6.default.cyan("ai-guard baseline")} \u2192 save baseline, track only new issues`);
2588
2946
  log.blank();
2589
2947
  });
2590
2948
  }
2591
2949
 
2592
2950
  // cli/commands/doctor.ts
2593
- var import_chalk6 = __toESM(require("chalk"));
2594
- var import_path7 = __toESM(require("path"));
2951
+ var import_chalk7 = __toESM(require("chalk"));
2952
+ var import_path8 = __toESM(require("path"));
2595
2953
  init_config_manager();
2596
- var import_meta = {};
2954
+ var import_meta2 = {};
2597
2955
  async function probeConfigLoad(configPath, cwd) {
2598
2956
  try {
2599
2957
  const { ESLint } = await import("eslint");
2600
2958
  const eslint = new ESLint({ cwd, overrideConfigFile: configPath });
2601
- await eslint.lintText("", { filePath: import_path7.default.join(cwd, "_probe_.js") });
2959
+ await eslint.lintText("", { filePath: import_path8.default.join(cwd, "_probe_.js") });
2602
2960
  return { ok: true, error: null };
2603
2961
  } catch (err) {
2604
2962
  const msg = err instanceof Error ? err.message : String(err);
@@ -2633,7 +2991,7 @@ function registerDoctorCommand(program2) {
2633
2991
  checks.push({
2634
2992
  label: "ESLint config present",
2635
2993
  pass: hasConfig,
2636
- detail: hasConfig ? `${import_path7.default.relative(cwd, env.configPath ?? "")} (${env.configType})` : "No eslint.config.* or .eslintrc.* found",
2994
+ detail: hasConfig ? `${import_path8.default.relative(cwd, env.configPath ?? "")} (${env.configType})` : "No eslint.config.* or .eslintrc.* found",
2637
2995
  fix: hasConfig ? void 0 : "ai-guard init",
2638
2996
  note: hasConfig ? void 0 : "This will generate the correct config format for your ESLint version"
2639
2997
  });
@@ -2665,7 +3023,7 @@ function registerDoctorCommand(program2) {
2665
3023
  checks.push({
2666
3024
  label: "Plugin wired in config",
2667
3025
  pass: pluginWired && !isInvalidConfig,
2668
- detail: readError ? `Could not read config: ${readError}` : isInvalidConfig ? "Invalid ai-guard config detected (wrong export usage)" : pluginWired ? "eslint-plugin-ai-guard referenced in config" : `Config exists but ai-guard plugin not found in ${import_path7.default.relative(cwd, env.configPath)}`,
3026
+ detail: readError ? `Could not read config: ${readError}` : isInvalidConfig ? "Invalid ai-guard config detected (wrong export usage)" : pluginWired ? "eslint-plugin-ai-guard referenced in config" : `Config exists but ai-guard plugin not found in ${import_path8.default.relative(cwd, env.configPath)}`,
2669
3027
  fix: isInvalidConfig || !pluginWired && !readError ? "ai-guard init (will patch/repair your existing config)" : void 0
2670
3028
  });
2671
3029
  }
@@ -2673,7 +3031,7 @@ function registerDoctorCommand(program2) {
2673
3031
  label: "No conflicting config files",
2674
3032
  pass: !env.hasConflictingConfigs,
2675
3033
  detail: env.hasConflictingConfigs ? `Conflicting config detected:
2676
- ${env.allConfigPaths.map((p) => ` ${import_path7.default.relative(cwd, p)}`).join("\n")}` : "Only one config format detected",
3034
+ ${env.allConfigPaths.map((p) => ` ${import_path8.default.relative(cwd, p)}`).join("\n")}` : "Only one config format detected",
2677
3035
  fix: env.hasConflictingConfigs ? "Remove or backup legacy config" : void 0,
2678
3036
  note: env.hasConflictingConfigs ? "ESLint v9 silently ignores .eslintrc.* when a flat config exists. This can cause confusion." : void 0
2679
3037
  });
@@ -2700,7 +3058,7 @@ ${env.allConfigPaths.map((p) => ` ${import_path7.default.relative(cwd, p)}
2700
3058
  label: "ESLint config loads without errors",
2701
3059
  pass: probe.ok,
2702
3060
  detail: probe.ok ? "ESLint loaded config successfully" : probe.error ?? "Unknown error",
2703
- fix: probe.ok ? void 0 : `Check syntax in ${import_path7.default.relative(cwd, env.configPath)}`,
3061
+ fix: probe.ok ? void 0 : `Check syntax in ${import_path8.default.relative(cwd, env.configPath)}`,
2704
3062
  note: probe.ok ? void 0 : "Run: ai-guard init --dry-run to preview a fresh config"
2705
3063
  });
2706
3064
  }
@@ -2708,8 +3066,8 @@ ${env.allConfigPaths.map((p) => ` ${import_path7.default.relative(cwd, p)}
2708
3066
  let utilsOk = false;
2709
3067
  let utilsVersion = null;
2710
3068
  try {
2711
- const { createRequire: createRequire2 } = await import("module");
2712
- const req = createRequire2(import_path7.default.join(cwd, "package.json"));
3069
+ const { createRequire: createRequire3 } = await import("module");
3070
+ const req = createRequire3(import_path8.default.join(cwd, "package.json"));
2713
3071
  const pkgPath = req.resolve("@typescript-eslint/utils/package.json");
2714
3072
  const pkg = JSON.parse(
2715
3073
  (await import("fs")).readFileSync(pkgPath, "utf-8")
@@ -2720,10 +3078,10 @@ ${env.allConfigPaths.map((p) => ` ${import_path7.default.relative(cwd, p)}
2720
3078
  }
2721
3079
  if (!utilsOk) {
2722
3080
  try {
2723
- const selfDir = import_path7.default.dirname(
2724
- new URL(import_meta.url).pathname.replace(/^\/([A-Za-z]:)/, "$1")
3081
+ const selfDir = import_path8.default.dirname(
3082
+ new URL(import_meta2.url).pathname.replace(/^\/([A-Za-z]:)/, "$1")
2725
3083
  );
2726
- const pkgPath = import_path7.default.join(selfDir, "../../node_modules/@typescript-eslint/utils/package.json");
3084
+ const pkgPath = import_path8.default.join(selfDir, "../../node_modules/@typescript-eslint/utils/package.json");
2727
3085
  if ((await import("fs")).existsSync(pkgPath)) {
2728
3086
  utilsOk = true;
2729
3087
  }
@@ -2742,8 +3100,8 @@ ${env.allConfigPaths.map((p) => ` ${import_path7.default.relative(cwd, p)}
2742
3100
  let parserOk = false;
2743
3101
  let parserVersion = null;
2744
3102
  try {
2745
- const { createRequire: createRequire2 } = await import("module");
2746
- const req = createRequire2(import_path7.default.join(cwd, "package.json"));
3103
+ const { createRequire: createRequire3 } = await import("module");
3104
+ const req = createRequire3(import_path8.default.join(cwd, "package.json"));
2747
3105
  const pkgPath = req.resolve("@typescript-eslint/parser/package.json");
2748
3106
  const pkg = JSON.parse(
2749
3107
  (await import("fs")).readFileSync(pkgPath, "utf-8")
@@ -2774,17 +3132,17 @@ ${env.allConfigPaths.map((p) => ` ${import_path7.default.relative(cwd, p)}
2774
3132
  log.section("Diagnostics");
2775
3133
  let allPassed = true;
2776
3134
  for (const check of checks) {
2777
- const icon = check.pass ? import_chalk6.default.green("\u2714") : import_chalk6.default.red("\u2716");
2778
- const label = check.pass ? import_chalk6.default.white(check.label) : import_chalk6.default.red.bold(check.label);
3135
+ const icon = check.pass ? import_chalk7.default.green("\u2714") : import_chalk7.default.red("\u2716");
3136
+ const label = check.pass ? import_chalk7.default.white(check.label) : import_chalk7.default.red.bold(check.label);
2779
3137
  log.print(` ${icon} ${label}`);
2780
- log.print(` ${import_chalk6.default.gray(check.detail)}`);
3138
+ log.print(` ${import_chalk7.default.gray(check.detail)}`);
2781
3139
  if (!check.pass) {
2782
3140
  allPassed = false;
2783
3141
  if (check.fix) {
2784
- log.print(` ${import_chalk6.default.cyan("\u2192 Fix:")} ${import_chalk6.default.yellow(check.fix)}`);
3142
+ log.print(` ${import_chalk7.default.cyan("\u2192 Fix:")} ${import_chalk7.default.yellow(check.fix)}`);
2785
3143
  }
2786
3144
  if (check.note) {
2787
- log.print(` ${import_chalk6.default.gray(check.note)}`);
3145
+ log.print(` ${import_chalk7.default.gray(check.note)}`);
2788
3146
  }
2789
3147
  }
2790
3148
  log.blank();
@@ -2792,10 +3150,10 @@ ${env.allConfigPaths.map((p) => ` ${import_path7.default.relative(cwd, p)}
2792
3150
  log.divider();
2793
3151
  log.blank();
2794
3152
  if (allPassed) {
2795
- log.print(` ${import_chalk6.default.green("\u2714")} ${import_chalk6.default.bold.green("All checks passed! Your setup is correct.")}`);
3153
+ log.print(` ${import_chalk7.default.green("\u2714")} ${import_chalk7.default.bold.green("All checks passed! Your setup is correct.")}`);
2796
3154
  log.blank();
2797
- log.info(`Run ${import_chalk6.default.cyan("ai-guard run")} to start scanning.`);
2798
- log.info(`Run ${import_chalk6.default.cyan("npx eslint .")} to lint with ESLint directly.`);
3155
+ log.info(`Run ${import_chalk7.default.cyan("ai-guard run")} to start scanning.`);
3156
+ log.info(`Run ${import_chalk7.default.cyan("npx eslint .")} to lint with ESLint directly.`);
2799
3157
  } else {
2800
3158
  log.error("Some checks failed. Follow the fixes above.");
2801
3159
  log.blank();
@@ -2810,15 +3168,15 @@ ${env.allConfigPaths.map((p) => ` ${import_path7.default.relative(cwd, p)}
2810
3168
  );
2811
3169
  if (pluginMissing) {
2812
3170
  log.print(
2813
- ` Install missing packages first, then re-run ${import_chalk6.default.cyan("ai-guard doctor")}.`
3171
+ ` Install missing packages first, then re-run ${import_chalk7.default.cyan("ai-guard doctor")}.`
2814
3172
  );
2815
3173
  } else if (configMissing || configFormatMismatch) {
2816
3174
  log.print(
2817
- ` Run ${import_chalk6.default.cyan("ai-guard init")} to generate the correct config for your ESLint version.`
3175
+ ` Run ${import_chalk7.default.cyan("ai-guard init")} to generate the correct config for your ESLint version.`
2818
3176
  );
2819
3177
  } else {
2820
3178
  log.print(
2821
- ` Run ${import_chalk6.default.cyan("ai-guard init --dry-run")} to preview what would change.`
3179
+ ` Run ${import_chalk7.default.cyan("ai-guard init --dry-run")} to preview what would change.`
2822
3180
  );
2823
3181
  }
2824
3182
  }
@@ -2829,9 +3187,9 @@ ${env.allConfigPaths.map((p) => ` ${import_path7.default.relative(cwd, p)}
2829
3187
 
2830
3188
  // cli/commands/preset.ts
2831
3189
  var import_prompts = require("@inquirer/prompts");
2832
- var import_chalk7 = __toESM(require("chalk"));
3190
+ var import_chalk8 = __toESM(require("chalk"));
2833
3191
  init_config_manager();
2834
- var import_path8 = __toESM(require("path"));
3192
+ var import_path9 = __toESM(require("path"));
2835
3193
  function registerPresetCommand(program2) {
2836
3194
  program2.command("preset").description("Interactively select and apply an ai-guard preset to your ESLint config").action(async () => {
2837
3195
  const cwd = process.cwd();
@@ -2841,32 +3199,32 @@ function registerPresetCommand(program2) {
2841
3199
  message: "Choose a preset:",
2842
3200
  choices: [
2843
3201
  {
2844
- name: `${import_chalk7.default.green("recommended")} \u2014 balanced defaults, low noise. Best starting point.`,
3202
+ name: `${import_chalk8.default.green("recommended")} \u2014 balanced defaults, low noise. Best starting point.`,
2845
3203
  value: "recommended"
2846
3204
  },
2847
3205
  {
2848
- name: `${import_chalk7.default.yellow("strict")} \u2014 all rules at error. For mature codebases.`,
3206
+ name: `${import_chalk8.default.yellow("strict")} \u2014 all rules at error. For mature codebases.`,
2849
3207
  value: "strict"
2850
3208
  },
2851
3209
  {
2852
- name: `${import_chalk7.default.red("security")} \u2014 security rules only. For AppSec teams.`,
3210
+ name: `${import_chalk8.default.red("security")} \u2014 security rules only. For AppSec teams.`,
2853
3211
  value: "security"
2854
3212
  }
2855
3213
  ]
2856
3214
  });
2857
3215
  log.blank();
2858
- log.info(`Applying preset: ${import_chalk7.default.cyan(preset)}`);
3216
+ log.info(`Applying preset: ${import_chalk8.default.cyan(preset)}`);
2859
3217
  const env = detect(cwd);
2860
3218
  const useFlat = env.eslintMajor !== null && env.eslintMajor >= 9 || isFlat(env.configType);
2861
3219
  if (env.configType === "none") {
2862
- const configPath = useFlat ? import_path8.default.join(cwd, "eslint.config.mjs") : import_path8.default.join(cwd, ".eslintrc.js");
3220
+ const configPath = useFlat ? import_path9.default.join(cwd, "eslint.config.mjs") : import_path9.default.join(cwd, ".eslintrc.js");
2863
3221
  const content = useFlat ? generateFlatConfig(preset) : generateLegacyConfig(preset);
2864
3222
  writeConfig(configPath, content);
2865
- log.success(`Created ${import_chalk7.default.white(import_path8.default.relative(cwd, configPath))} with ${import_chalk7.default.cyan(preset)} preset`);
3223
+ log.success(`Created ${import_chalk8.default.white(import_path9.default.relative(cwd, configPath))} with ${import_chalk8.default.cyan(preset)} preset`);
2866
3224
  } else {
2867
3225
  const configPath = env.configPath;
2868
3226
  const backupPath = backupConfig(configPath);
2869
- log.info(`Backed up \u2192 ${import_chalk7.default.gray(import_path8.default.relative(cwd, backupPath))}`);
3227
+ log.info(`Backed up \u2192 ${import_chalk8.default.gray(import_path9.default.relative(cwd, backupPath))}`);
2870
3228
  const existing = readConfig(configPath);
2871
3229
  const withPlugin = isFlat(env.configType) ? patchFlatConfig(existing, preset) : patchLegacyConfig(existing, preset);
2872
3230
  const patched = isFlat(env.configType) ? switchFlatPreset(withPlugin, preset) : switchLegacyPreset(withPlugin, preset);
@@ -2874,47 +3232,47 @@ function registerPresetCommand(program2) {
2874
3232
  log.warn("No preset changes needed. Config already matches selected preset.");
2875
3233
  } else {
2876
3234
  writeConfig(configPath, patched);
2877
- log.success(`Updated ${import_chalk7.default.white(import_path8.default.relative(cwd, configPath))} to ${import_chalk7.default.cyan(preset)} preset`);
3235
+ log.success(`Updated ${import_chalk8.default.white(import_path9.default.relative(cwd, configPath))} to ${import_chalk8.default.cyan(preset)} preset`);
2878
3236
  }
2879
3237
  }
2880
3238
  log.blank();
2881
3239
  log.section("Preset Details");
2882
3240
  const presetDetails = {
2883
3241
  recommended: [
2884
- { rule: "no-empty-catch", level: import_chalk7.default.red("error") },
2885
- { rule: "no-floating-promise", level: import_chalk7.default.red("error") },
2886
- { rule: "no-hardcoded-secret", level: import_chalk7.default.red("error") },
2887
- { rule: "no-eval-dynamic", level: import_chalk7.default.red("error") },
2888
- { rule: "no-broad-exception", level: import_chalk7.default.yellow("warn") },
2889
- { rule: "no-async-array-callback", level: import_chalk7.default.yellow("warn") },
2890
- { rule: "no-await-in-loop", level: import_chalk7.default.yellow("warn") },
2891
- { rule: "+ 5 more\u2026", level: import_chalk7.default.gray("warn") }
3242
+ { rule: "no-empty-catch", level: import_chalk8.default.red("error") },
3243
+ { rule: "no-floating-promise", level: import_chalk8.default.red("error") },
3244
+ { rule: "no-hardcoded-secret", level: import_chalk8.default.red("error") },
3245
+ { rule: "no-eval-dynamic", level: import_chalk8.default.red("error") },
3246
+ { rule: "no-broad-exception", level: import_chalk8.default.yellow("warn") },
3247
+ { rule: "no-async-array-callback", level: import_chalk8.default.yellow("warn") },
3248
+ { rule: "no-await-in-loop", level: import_chalk8.default.yellow("warn") },
3249
+ { rule: "+ 5 more\u2026", level: import_chalk8.default.gray("warn") }
2892
3250
  ],
2893
3251
  strict: [
2894
- { rule: "All 17 rules", level: import_chalk7.default.red("error") }
3252
+ { rule: "All 17 rules", level: import_chalk8.default.red("error") }
2895
3253
  ],
2896
3254
  security: [
2897
- { rule: "no-hardcoded-secret", level: import_chalk7.default.red("error") },
2898
- { rule: "no-eval-dynamic", level: import_chalk7.default.red("error") },
2899
- { rule: "no-sql-string-concat", level: import_chalk7.default.red("error") },
2900
- { rule: "no-unsafe-deserialize", level: import_chalk7.default.yellow("warn") },
2901
- { rule: "require-auth-middleware", level: import_chalk7.default.yellow("warn") },
2902
- { rule: "require-authz-check", level: import_chalk7.default.yellow("warn") }
3255
+ { rule: "no-hardcoded-secret", level: import_chalk8.default.red("error") },
3256
+ { rule: "no-eval-dynamic", level: import_chalk8.default.red("error") },
3257
+ { rule: "no-sql-string-concat", level: import_chalk8.default.red("error") },
3258
+ { rule: "no-unsafe-deserialize", level: import_chalk8.default.yellow("warn") },
3259
+ { rule: "require-auth-middleware", level: import_chalk8.default.yellow("warn") },
3260
+ { rule: "require-authz-check", level: import_chalk8.default.yellow("warn") }
2903
3261
  ]
2904
3262
  };
2905
3263
  for (const { rule, level } of presetDetails[preset]) {
2906
- log.print(` ${import_chalk7.default.gray("\u2022")} ${import_chalk7.default.white(rule).padEnd(32)}${level}`);
3264
+ log.print(` ${import_chalk8.default.gray("\u2022")} ${import_chalk8.default.white(rule).padEnd(32)}${level}`);
2907
3265
  }
2908
3266
  log.blank();
2909
- log.info(`Run ${import_chalk7.default.cyan("ai-guard run")} to see results with the new preset.`);
3267
+ log.info(`Run ${import_chalk8.default.cyan("ai-guard run")} to see results with the new preset.`);
2910
3268
  log.blank();
2911
3269
  });
2912
3270
  }
2913
3271
 
2914
3272
  // cli/commands/ignore.ts
2915
- var import_chalk8 = __toESM(require("chalk"));
3273
+ var import_chalk9 = __toESM(require("chalk"));
2916
3274
  init_config_manager();
2917
- var import_path9 = __toESM(require("path"));
3275
+ var import_path10 = __toESM(require("path"));
2918
3276
  var DEFAULT_IGNORES = [
2919
3277
  ".next/",
2920
3278
  "dist/",
@@ -2930,40 +3288,40 @@ function registerIgnoreCommand(program2) {
2930
3288
  log.blank();
2931
3289
  log.section("Default Ignores");
2932
3290
  for (const p of DEFAULT_IGNORES) {
2933
- log.print(` ${import_chalk8.default.gray("\u2022")} ${import_chalk8.default.yellow(p)}`);
3291
+ log.print(` ${import_chalk9.default.gray("\u2022")} ${import_chalk9.default.yellow(p)}`);
2934
3292
  }
2935
3293
  log.blank();
2936
3294
  const env = detect(cwd);
2937
3295
  if (env.configType === "none") {
2938
3296
  const useFlat = env.eslintMajor !== null && env.eslintMajor >= 9;
2939
- const configPath = useFlat ? import_path9.default.join(cwd, "eslint.config.mjs") : import_path9.default.join(cwd, ".eslintrc.js");
3297
+ const configPath = useFlat ? import_path10.default.join(cwd, "eslint.config.mjs") : import_path10.default.join(cwd, ".eslintrc.js");
2940
3298
  const content = useFlat ? generateFlatConfig("recommended") : generateLegacyConfig("recommended");
2941
3299
  writeConfig(configPath, content);
2942
- log.success(`No config found \u2014 generated ${import_chalk8.default.white(import_path9.default.relative(cwd, configPath))} with ignores included`);
3300
+ log.success(`No config found \u2014 generated ${import_chalk9.default.white(import_path10.default.relative(cwd, configPath))} with ignores included`);
2943
3301
  } else {
2944
3302
  const configPath = env.configPath;
2945
3303
  const backupPath = backupConfig(configPath);
2946
- log.info(`Backed up \u2192 ${import_chalk8.default.gray(import_path9.default.relative(cwd, backupPath))}`);
3304
+ log.info(`Backed up \u2192 ${import_chalk9.default.gray(import_path10.default.relative(cwd, backupPath))}`);
2947
3305
  const existing = readConfig(configPath);
2948
3306
  const patched = isFlat(env.configType) ? addIgnoresToFlatConfig(existing) : addIgnoresToLegacyConfig(existing);
2949
3307
  if (patched === existing) {
2950
3308
  log.warn("Ignore patterns already present in config \u2014 no changes made.");
2951
3309
  } else {
2952
3310
  writeConfig(configPath, patched);
2953
- log.success(`Patched ${import_chalk8.default.white(import_path9.default.relative(cwd, configPath))} with ignore patterns`);
3311
+ log.success(`Patched ${import_chalk9.default.white(import_path10.default.relative(cwd, configPath))} with ignore patterns`);
2954
3312
  }
2955
3313
  }
2956
3314
  log.blank();
2957
3315
  log.info("Noisy directories will now be skipped in all future ESLint runs.");
2958
- log.info(`Run ${import_chalk8.default.cyan("ai-guard run")} to verify cleaner results.`);
3316
+ log.info(`Run ${import_chalk9.default.cyan("ai-guard run")} to verify cleaner results.`);
2959
3317
  log.blank();
2960
3318
  });
2961
3319
  }
2962
3320
 
2963
3321
  // cli/commands/baseline.ts
2964
3322
  var import_fs8 = __toESM(require("fs"));
2965
- var import_path10 = __toESM(require("path"));
2966
- var import_chalk9 = __toESM(require("chalk"));
3323
+ var import_path11 = __toESM(require("path"));
3324
+ var import_chalk10 = __toESM(require("chalk"));
2967
3325
  var import_ora3 = __toESM(require("ora"));
2968
3326
  var BASELINE_FILE = ".ai-guard-baseline.json";
2969
3327
  function saveBaseline(result, preset, mode, cwd) {
@@ -2983,12 +3341,12 @@ function saveBaseline(result, preset, mode, cwd) {
2983
3341
  totalIssues: result.totalIssues,
2984
3342
  entries
2985
3343
  };
2986
- const baselinePath = import_path10.default.join(cwd, BASELINE_FILE);
3344
+ const baselinePath = import_path11.default.join(cwd, BASELINE_FILE);
2987
3345
  import_fs8.default.writeFileSync(baselinePath, JSON.stringify(baseline, null, 2), "utf-8");
2988
3346
  return baselinePath;
2989
3347
  }
2990
3348
  function loadBaseline(cwd) {
2991
- const baselinePath = import_path10.default.join(cwd, BASELINE_FILE);
3349
+ const baselinePath = import_path11.default.join(cwd, BASELINE_FILE);
2992
3350
  if (!import_fs8.default.existsSync(baselinePath)) return null;
2993
3351
  try {
2994
3352
  const raw = import_fs8.default.readFileSync(baselinePath, "utf-8");
@@ -3075,28 +3433,28 @@ function registerBaselineCommand(program2) {
3075
3433
  }
3076
3434
  const baselinePath = saveBaseline(result, preset, mode, cwd);
3077
3435
  log.success(
3078
- `Baseline saved \u2192 ${import_chalk9.default.white(import_path10.default.relative(cwd, baselinePath))}`
3436
+ `Baseline saved \u2192 ${import_chalk10.default.white(import_path11.default.relative(cwd, baselinePath))}`
3079
3437
  );
3080
3438
  log.info(` ${result.totalIssues} issues recorded (${result.totalErrors} errors, ${result.totalWarnings} warnings)`);
3081
- log.info(` Preset: ${import_chalk9.default.cyan(preset)}`);
3082
- log.info(` Mode: ${import_chalk9.default.cyan(mode)}`);
3439
+ log.info(` Preset: ${import_chalk10.default.cyan(preset)}`);
3440
+ log.info(` Mode: ${import_chalk10.default.cyan(mode)}`);
3083
3441
  log.blank();
3084
- log.info("Future runs of " + import_chalk9.default.cyan("ai-guard baseline --check") + " will show only NEW issues.");
3085
- log.info("Add " + import_chalk9.default.white(BASELINE_FILE) + " to your git repository to share baseline with your team.");
3442
+ log.info("Future runs of " + import_chalk10.default.cyan("ai-guard baseline --check") + " will show only NEW issues.");
3443
+ log.info("Add " + import_chalk10.default.white(BASELINE_FILE) + " to your git repository to share baseline with your team.");
3086
3444
  log.blank();
3087
3445
  return;
3088
3446
  }
3089
3447
  if (doCheck) {
3090
3448
  if (!existingBaseline) {
3091
- log.error(`No baseline found at ${import_chalk9.default.white(BASELINE_FILE)}`);
3092
- log.info(`Run ${import_chalk9.default.cyan("ai-guard baseline --save")} first to create one.`);
3449
+ log.error(`No baseline found at ${import_chalk10.default.white(BASELINE_FILE)}`);
3450
+ log.info(`Run ${import_chalk10.default.cyan("ai-guard baseline --save")} first to create one.`);
3093
3451
  process.exit(1);
3094
3452
  }
3095
3453
  const baselineDate = new Date(existingBaseline.createdAt).toLocaleString();
3096
- log.info(`Baseline from: ${import_chalk9.default.gray(baselineDate)}`);
3097
- log.info(`Baseline preset: ${import_chalk9.default.cyan(existingBaseline.preset)}`);
3098
- log.info(`Baseline mode: ${import_chalk9.default.cyan(existingBaseline.mode ?? "strict")}`);
3099
- log.info(`Baseline issues: ${import_chalk9.default.gray(existingBaseline.totalIssues)}`);
3454
+ log.info(`Baseline from: ${import_chalk10.default.gray(baselineDate)}`);
3455
+ log.info(`Baseline preset: ${import_chalk10.default.cyan(existingBaseline.preset)}`);
3456
+ log.info(`Baseline mode: ${import_chalk10.default.cyan(existingBaseline.mode ?? "strict")}`);
3457
+ log.info(`Baseline issues: ${import_chalk10.default.gray(existingBaseline.totalIssues)}`);
3100
3458
  log.blank();
3101
3459
  const spinner = (0, import_ora3.default)({ text: "Scanning for new issues\u2026", color: "cyan" }).start();
3102
3460
  let result;
@@ -3121,7 +3479,7 @@ function registerBaselineCommand(program2) {
3121
3479
  return;
3122
3480
  }
3123
3481
  log.print(
3124
- import_chalk9.default.bold.red(` \u2716 ${newResult.totalIssues} new issue${newResult.totalIssues !== 1 ? "s" : ""} since baseline`)
3482
+ import_chalk10.default.bold.red(` \u2716 ${newResult.totalIssues} new issue${newResult.totalIssues !== 1 ? "s" : ""} since baseline`)
3125
3483
  );
3126
3484
  log.blank();
3127
3485
  if (newResult.ruleBreakdown.size > 0) {
@@ -3137,7 +3495,7 @@ function registerBaselineCommand(program2) {
3137
3495
  log.blank();
3138
3496
  for (const file of newResult.files) {
3139
3497
  log.print(
3140
- ` ${import_chalk9.default.bold.white(file.filePath)} ` + import_chalk9.default.gray(`(${file.issues.length} new)`)
3498
+ ` ${import_chalk10.default.bold.white(file.filePath)} ` + import_chalk10.default.gray(`(${file.issues.length} new)`)
3141
3499
  );
3142
3500
  for (const issue of file.issues) {
3143
3501
  log.issue(issue.message, issue.severity, issue.line, issue.column);
@@ -3150,7 +3508,7 @@ function registerBaselineCommand(program2) {
3150
3508
  log.error(
3151
3509
  `${newResult.totalIssues} new issue${newResult.totalIssues !== 1 ? "s" : ""} introduced since baseline.`
3152
3510
  );
3153
- log.info(`Run ${import_chalk9.default.cyan("ai-guard baseline --save")} to update the baseline after fixing them.`);
3511
+ log.info(`Run ${import_chalk10.default.cyan("ai-guard baseline --save")} to update the baseline after fixing them.`);
3154
3512
  log.blank();
3155
3513
  process.exit(1);
3156
3514
  }
@@ -3159,8 +3517,8 @@ function registerBaselineCommand(program2) {
3159
3517
 
3160
3518
  // cli/commands/init-context.ts
3161
3519
  var import_fs9 = __toESM(require("fs"));
3162
- var import_path11 = __toESM(require("path"));
3163
- var import_chalk10 = __toESM(require("chalk"));
3520
+ var import_path12 = __toESM(require("path"));
3521
+ var import_chalk11 = __toESM(require("chalk"));
3164
3522
  var import_prompts2 = require("@inquirer/prompts");
3165
3523
  var RULE_CATEGORIES = {
3166
3524
  "error-handling": [
@@ -3523,13 +3881,13 @@ var AGENTS = [
3523
3881
  {
3524
3882
  id: "copilot",
3525
3883
  label: "GitHub Copilot",
3526
- filePath: import_path11.default.join(".github", "copilot-instructions.md"),
3884
+ filePath: import_path12.default.join(".github", "copilot-instructions.md"),
3527
3885
  generate: generateCopilotFile
3528
3886
  }
3529
3887
  ];
3530
3888
  function getPackageVersion2(cwd) {
3531
3889
  try {
3532
- const pkgPath = import_path11.default.join(cwd, "node_modules", "eslint-plugin-ai-guard", "package.json");
3890
+ const pkgPath = import_path12.default.join(cwd, "node_modules", "eslint-plugin-ai-guard", "package.json");
3533
3891
  if (import_fs9.default.existsSync(pkgPath)) {
3534
3892
  const pkg = JSON.parse(import_fs9.default.readFileSync(pkgPath, "utf-8"));
3535
3893
  if (pkg.version) return pkg.version;
@@ -3537,7 +3895,7 @@ function getPackageVersion2(cwd) {
3537
3895
  } catch {
3538
3896
  }
3539
3897
  try {
3540
- const pkgPath = import_path11.default.join(cwd, "package.json");
3898
+ const pkgPath = import_path12.default.join(cwd, "package.json");
3541
3899
  if (import_fs9.default.existsSync(pkgPath)) {
3542
3900
  const pkg = JSON.parse(import_fs9.default.readFileSync(pkgPath, "utf-8"));
3543
3901
  if (pkg.version) return pkg.version;
@@ -3568,7 +3926,7 @@ function registerInitContextCommand(program2) {
3568
3926
  const isForce = opts.force === true;
3569
3927
  log.banner("AI GUARD INIT-CONTEXT");
3570
3928
  if (isDryRun) {
3571
- log.print(` ${import_chalk10.default.yellow("\u2691 DRY RUN \u2014 no files will be written")}`);
3929
+ log.print(` ${import_chalk11.default.yellow("\u2691 DRY RUN \u2014 no files will be written")}`);
3572
3930
  log.blank();
3573
3931
  }
3574
3932
  let selectedAgents;
@@ -3601,12 +3959,12 @@ function registerInitContextCommand(program2) {
3601
3959
  selectedAgents = AGENTS.filter((a) => selected.includes(a.id));
3602
3960
  }
3603
3961
  }
3604
- log.info(`Categories: ${import_chalk10.default.cyan(categories.join(", "))}`);
3605
- log.info(`Version: ${import_chalk10.default.cyan(version)}`);
3962
+ log.info(`Categories: ${import_chalk11.default.cyan(categories.join(", "))}`);
3963
+ log.info(`Version: ${import_chalk11.default.cyan(version)}`);
3606
3964
  log.blank();
3607
3965
  const results = [];
3608
3966
  for (const agent of selectedAgents) {
3609
- const fullPath = import_path11.default.join(cwd, agent.filePath);
3967
+ const fullPath = import_path12.default.join(cwd, agent.filePath);
3610
3968
  const exists = import_fs9.default.existsSync(fullPath);
3611
3969
  if (exists && !isForce && !isDryRun) {
3612
3970
  const overwrite = await (0, import_prompts2.confirm)({
@@ -3621,17 +3979,17 @@ function registerInitContextCommand(program2) {
3621
3979
  const content = agent.generate(version, categories);
3622
3980
  if (isDryRun) {
3623
3981
  log.section(`Preview: ${agent.filePath}`);
3624
- log.print(import_chalk10.default.gray("\u2500".repeat(60)));
3982
+ log.print(import_chalk11.default.gray("\u2500".repeat(60)));
3625
3983
  for (const line of content.split("\n").slice(0, 20)) {
3626
- log.print(import_chalk10.default.gray(` ${line}`));
3984
+ log.print(import_chalk11.default.gray(` ${line}`));
3627
3985
  }
3628
- log.print(import_chalk10.default.gray(" ... (truncated)"));
3629
- log.print(import_chalk10.default.gray("\u2500".repeat(60)));
3986
+ log.print(import_chalk11.default.gray(" ... (truncated)"));
3987
+ log.print(import_chalk11.default.gray("\u2500".repeat(60)));
3630
3988
  log.blank();
3631
3989
  results.push({ file: agent.filePath, status: "dry-run" });
3632
3990
  continue;
3633
3991
  }
3634
- const parentDir = import_path11.default.dirname(fullPath);
3992
+ const parentDir = import_path12.default.dirname(fullPath);
3635
3993
  if (!import_fs9.default.existsSync(parentDir)) {
3636
3994
  import_fs9.default.mkdirSync(parentDir, { recursive: true });
3637
3995
  }
@@ -3642,20 +4000,20 @@ function registerInitContextCommand(program2) {
3642
4000
  for (const result of results) {
3643
4001
  switch (result.status) {
3644
4002
  case "created":
3645
- log.print(` ${import_chalk10.default.green("\u2705")} Created ${import_chalk10.default.white(result.file)}`);
4003
+ log.print(` ${import_chalk11.default.green("\u2705")} Created ${import_chalk11.default.white(result.file)}`);
3646
4004
  break;
3647
4005
  case "skipped":
3648
- log.print(` ${import_chalk10.default.yellow("\u23ED")} Skipped ${import_chalk10.default.white(result.file)} ${import_chalk10.default.gray("(already exists \u2014 use --force to overwrite)")}`);
4006
+ log.print(` ${import_chalk11.default.yellow("\u23ED")} Skipped ${import_chalk11.default.white(result.file)} ${import_chalk11.default.gray("(already exists \u2014 use --force to overwrite)")}`);
3649
4007
  break;
3650
4008
  case "dry-run":
3651
- log.print(` ${import_chalk10.default.cyan("\u{1F4DD}")} Would create ${import_chalk10.default.white(result.file)}`);
4009
+ log.print(` ${import_chalk11.default.cyan("\u{1F4DD}")} Would create ${import_chalk11.default.white(result.file)}`);
3652
4010
  break;
3653
4011
  }
3654
4012
  }
3655
4013
  log.blank();
3656
4014
  if (isDryRun) {
3657
4015
  log.info("Dry run complete \u2014 no files were written.");
3658
- log.info(`Re-run without ${import_chalk10.default.cyan("--dry-run")} to apply.`);
4016
+ log.info(`Re-run without ${import_chalk11.default.cyan("--dry-run")} to apply.`);
3659
4017
  } else {
3660
4018
  const createdCount = results.filter((r) => r.status === "created").length;
3661
4019
  if (createdCount > 0) {
@@ -3670,7 +4028,7 @@ function registerInitContextCommand(program2) {
3670
4028
 
3671
4029
  // cli/commands/report.ts
3672
4030
  var import_fs10 = __toESM(require("fs"));
3673
- var import_path12 = __toESM(require("path"));
4031
+ var import_path13 = __toESM(require("path"));
3674
4032
  var import_ora4 = __toESM(require("ora"));
3675
4033
  var RULE_META = {
3676
4034
  "ai-guard/no-empty-catch": { description: "Empty catch blocks silently swallow errors", category: "Reliability" },
@@ -3694,18 +4052,18 @@ var RULE_META = {
3694
4052
  };
3695
4053
  function getProjectName(cwd) {
3696
4054
  try {
3697
- const pkgPath = import_path12.default.join(cwd, "package.json");
4055
+ const pkgPath = import_path13.default.join(cwd, "package.json");
3698
4056
  if (import_fs10.default.existsSync(pkgPath)) {
3699
4057
  const pkg = JSON.parse(import_fs10.default.readFileSync(pkgPath, "utf-8"));
3700
4058
  if (pkg.name) return pkg.name;
3701
4059
  }
3702
4060
  } catch {
3703
4061
  }
3704
- return import_path12.default.basename(cwd);
4062
+ return import_path13.default.basename(cwd);
3705
4063
  }
3706
4064
  function getPluginVersion(cwd) {
3707
4065
  try {
3708
- const pkgPath = import_path12.default.resolve(__dirname, "../../package.json");
4066
+ const pkgPath = import_path13.default.resolve(__dirname, "../../package.json");
3709
4067
  if (import_fs10.default.existsSync(pkgPath)) {
3710
4068
  const pkg = JSON.parse(import_fs10.default.readFileSync(pkgPath, "utf-8"));
3711
4069
  if (pkg.version) return pkg.version;
@@ -3713,7 +4071,7 @@ function getPluginVersion(cwd) {
3713
4071
  } catch {
3714
4072
  }
3715
4073
  try {
3716
- const pkgPath = import_path12.default.join(cwd, "node_modules", "eslint-plugin-ai-guard", "package.json");
4074
+ const pkgPath = import_path13.default.join(cwd, "node_modules", "eslint-plugin-ai-guard", "package.json");
3717
4075
  if (import_fs10.default.existsSync(pkgPath)) {
3718
4076
  const pkg = JSON.parse(import_fs10.default.readFileSync(pkgPath, "utf-8"));
3719
4077
  if (pkg.version) return pkg.version;
@@ -4092,7 +4450,7 @@ function registerReportCommand(program2) {
4092
4450
  log.banner("AI GUARD REPORT");
4093
4451
  log.blank();
4094
4452
  const html = generateHtml(reportData);
4095
- const outputPath = import_path12.default.resolve(cwd, opts.output);
4453
+ const outputPath = import_path13.default.resolve(cwd, opts.output);
4096
4454
  import_fs10.default.writeFileSync(outputPath, html, "utf-8");
4097
4455
  log.success(`Report saved: ${opts.output}`);
4098
4456
  log.info(
@@ -4126,7 +4484,7 @@ function registerReportCommand(program2) {
4126
4484
  // cli/index.ts
4127
4485
  function getVersion() {
4128
4486
  try {
4129
- const pkgPath = import_path13.default.resolve(__dirname, "../../package.json");
4487
+ const pkgPath = import_path14.default.resolve(__dirname, "../../package.json");
4130
4488
  const raw = import_fs11.default.readFileSync(pkgPath, "utf-8");
4131
4489
  const pkg = JSON.parse(raw);
4132
4490
  return typeof pkg.version === "string" ? pkg.version : "0.0.0";