eslint-plugin-ai-guard 1.2.4 → 1.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +288 -94
- package/dist/cli/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -414,19 +414,19 @@ function addIgnoresToLegacyConfig(existing) {
|
|
|
414
414
|
function getConfigFilePath(configType, cwd = process.cwd()) {
|
|
415
415
|
switch (configType) {
|
|
416
416
|
case "flat-js":
|
|
417
|
-
return
|
|
417
|
+
return import_path7.default.join(cwd, "eslint.config.js");
|
|
418
418
|
case "flat-mjs":
|
|
419
|
-
return
|
|
419
|
+
return import_path7.default.join(cwd, "eslint.config.mjs");
|
|
420
420
|
case "flat-cjs":
|
|
421
|
-
return
|
|
421
|
+
return import_path7.default.join(cwd, "eslint.config.cjs");
|
|
422
422
|
case "eslintrc-js":
|
|
423
|
-
return
|
|
423
|
+
return import_path7.default.join(cwd, ".eslintrc.js");
|
|
424
424
|
case "eslintrc-cjs":
|
|
425
|
-
return
|
|
425
|
+
return import_path7.default.join(cwd, ".eslintrc.cjs");
|
|
426
426
|
case "eslintrc-json":
|
|
427
|
-
return
|
|
427
|
+
return import_path7.default.join(cwd, ".eslintrc.json");
|
|
428
428
|
default:
|
|
429
|
-
return
|
|
429
|
+
return import_path7.default.join(cwd, ".eslintrc.js");
|
|
430
430
|
}
|
|
431
431
|
}
|
|
432
432
|
function validateFlatConfigText(content) {
|
|
@@ -461,12 +461,12 @@ function validateLegacyConfigText(content) {
|
|
|
461
461
|
}
|
|
462
462
|
return problems;
|
|
463
463
|
}
|
|
464
|
-
var import_fs7,
|
|
464
|
+
var import_fs7, import_path7, AI_GUARD_MARKER, DEFAULT_FLAT_IGNORES, DEFAULT_LEGACY_IGNORES;
|
|
465
465
|
var init_config_manager = __esm({
|
|
466
466
|
"cli/utils/config-manager.ts"() {
|
|
467
467
|
"use strict";
|
|
468
468
|
import_fs7 = __toESM(require("fs"));
|
|
469
|
-
|
|
469
|
+
import_path7 = __toESM(require("path"));
|
|
470
470
|
AI_GUARD_MARKER = "eslint-plugin-ai-guard";
|
|
471
471
|
DEFAULT_FLAT_IGNORES = [
|
|
472
472
|
"node_modules/**",
|
|
@@ -490,7 +490,7 @@ var init_config_manager = __esm({
|
|
|
490
490
|
// cli/index.ts
|
|
491
491
|
var import_commander = require("commander");
|
|
492
492
|
var import_fs12 = __toESM(require("fs"));
|
|
493
|
-
var
|
|
493
|
+
var import_path15 = __toESM(require("path"));
|
|
494
494
|
|
|
495
495
|
// cli/commands/run.ts
|
|
496
496
|
var import_fs4 = __toESM(require("fs"));
|
|
@@ -1205,6 +1205,10 @@ async function runEslint(options) {
|
|
|
1205
1205
|
};
|
|
1206
1206
|
}
|
|
1207
1207
|
|
|
1208
|
+
// cli/utils/sarif.ts
|
|
1209
|
+
var import_crypto = require("crypto");
|
|
1210
|
+
var import_path3 = __toESM(require("path"));
|
|
1211
|
+
|
|
1208
1212
|
// cli/utils/version.ts
|
|
1209
1213
|
var import_module = require("module");
|
|
1210
1214
|
var import_url2 = require("url");
|
|
@@ -1230,6 +1234,8 @@ function readVersion() {
|
|
|
1230
1234
|
var PKG_VERSION = _version ?? (_version = readVersion());
|
|
1231
1235
|
|
|
1232
1236
|
// cli/utils/sarif.ts
|
|
1237
|
+
var SARIF_AUTOMATION_ID = "ai-guard";
|
|
1238
|
+
var FINGERPRINT_KEY = "ai-guard/v1";
|
|
1233
1239
|
var RULE_DOCS = {
|
|
1234
1240
|
"ai-guard/no-empty-catch": { shortDesc: "Empty catch block silently swallows errors", tags: ["reliability"] },
|
|
1235
1241
|
"ai-guard/no-broad-exception": { shortDesc: "Catching broad Exception/Error masks specific failures", tags: ["reliability"] },
|
|
@@ -1353,8 +1359,34 @@ function confidenceToRank(confidence) {
|
|
|
1353
1359
|
return 30;
|
|
1354
1360
|
}
|
|
1355
1361
|
}
|
|
1356
|
-
function
|
|
1357
|
-
|
|
1362
|
+
function normalizeSarifPath(filePath, repoRoot) {
|
|
1363
|
+
let normalized = filePath;
|
|
1364
|
+
normalized = normalized.replace(/\\/g, "/");
|
|
1365
|
+
normalized = normalized.replace(/^[A-Za-z]:\//, "/");
|
|
1366
|
+
if (repoRoot && import_path3.default.isAbsolute(filePath)) {
|
|
1367
|
+
const posixRoot = repoRoot.replace(/\\/g, "/").replace(/^[A-Za-z]:\//, "/").replace(/\/$/, "");
|
|
1368
|
+
if (normalized.startsWith(posixRoot + "/")) {
|
|
1369
|
+
normalized = normalized.slice(posixRoot.length + 1);
|
|
1370
|
+
} else if (normalized.startsWith(posixRoot)) {
|
|
1371
|
+
normalized = normalized.slice(posixRoot.length);
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
normalized = normalized.replace(/^\/+/, "");
|
|
1375
|
+
normalized = normalized.replace(/^\.\//, "");
|
|
1376
|
+
if (!normalized || normalized === ".") {
|
|
1377
|
+
normalized = filePath.replace(/\\/g, "/");
|
|
1378
|
+
}
|
|
1379
|
+
return normalized;
|
|
1380
|
+
}
|
|
1381
|
+
function generateStableFingerprint(normalizedUri, ruleId, startLine, message) {
|
|
1382
|
+
const normalizedMessage = message.trim().toLowerCase().replace(/\s+/g, " ");
|
|
1383
|
+
const input = [
|
|
1384
|
+
ruleId,
|
|
1385
|
+
normalizedUri.toLowerCase(),
|
|
1386
|
+
String(startLine),
|
|
1387
|
+
normalizedMessage
|
|
1388
|
+
].join(":");
|
|
1389
|
+
return (0, import_crypto.createHash)("sha256").update(input, "utf8").digest("hex");
|
|
1358
1390
|
}
|
|
1359
1391
|
function collectUsedRuleIds(result) {
|
|
1360
1392
|
const ids = /* @__PURE__ */ new Set();
|
|
@@ -1405,22 +1437,34 @@ function buildRuleDescriptors(ruleIds) {
|
|
|
1405
1437
|
});
|
|
1406
1438
|
});
|
|
1407
1439
|
}
|
|
1408
|
-
function buildSarifResult(issue, file) {
|
|
1440
|
+
function buildSarifResult(issue, file, repoRoot) {
|
|
1409
1441
|
const confidence = ISSUE_CONFIDENCE[issue.ruleId];
|
|
1410
1442
|
const asyncRiskType = ISSUE_ASYNC_RISK_TYPE[issue.ruleId];
|
|
1411
1443
|
const category = ISSUE_CATEGORY[issue.ruleId];
|
|
1444
|
+
const sarifUri = normalizeSarifPath(file.filePath, repoRoot);
|
|
1445
|
+
const fingerprint = generateStableFingerprint(
|
|
1446
|
+
sarifUri,
|
|
1447
|
+
issue.ruleId,
|
|
1448
|
+
Math.max(1, issue.line),
|
|
1449
|
+
issue.message
|
|
1450
|
+
);
|
|
1412
1451
|
return {
|
|
1413
1452
|
ruleId: issue.ruleId,
|
|
1414
1453
|
level: confidenceToSarifLevel(confidence),
|
|
1415
1454
|
kind: confidence === "informational" ? "informational" : "fail",
|
|
1416
1455
|
rank: confidenceToRank(confidence),
|
|
1417
1456
|
message: { text: issue.message },
|
|
1457
|
+
// partialFingerprints: per-result hash for GitHub alert deduplication.
|
|
1458
|
+
// Without this, GitHub closes and reopens every alert on every scan run.
|
|
1459
|
+
partialFingerprints: {
|
|
1460
|
+
[FINGERPRINT_KEY]: fingerprint
|
|
1461
|
+
},
|
|
1418
1462
|
locations: [
|
|
1419
1463
|
{
|
|
1420
1464
|
physicalLocation: {
|
|
1421
1465
|
artifactLocation: {
|
|
1422
|
-
|
|
1423
|
-
|
|
1466
|
+
// Repository-relative POSIX path — no uriBaseId
|
|
1467
|
+
uri: sarifUri
|
|
1424
1468
|
},
|
|
1425
1469
|
region: {
|
|
1426
1470
|
startLine: Math.max(1, issue.line),
|
|
@@ -1515,13 +1559,13 @@ function normalizeSarifForGitHub(log2) {
|
|
|
1515
1559
|
runs: normalizedRuns
|
|
1516
1560
|
};
|
|
1517
1561
|
}
|
|
1518
|
-
function buildSarifLog(result, version = PKG_VERSION) {
|
|
1562
|
+
function buildSarifLog(result, version = PKG_VERSION, repoRoot) {
|
|
1519
1563
|
const usedRuleIds = collectUsedRuleIds(result);
|
|
1520
1564
|
const rules = buildRuleDescriptors(usedRuleIds);
|
|
1521
1565
|
const sarifResults = [];
|
|
1522
1566
|
for (const file of result.files) {
|
|
1523
1567
|
for (const issue of file.issues) {
|
|
1524
|
-
sarifResults.push(buildSarifResult(issue, file));
|
|
1568
|
+
sarifResults.push(buildSarifResult(issue, file, repoRoot));
|
|
1525
1569
|
}
|
|
1526
1570
|
}
|
|
1527
1571
|
const log2 = {
|
|
@@ -1537,6 +1581,12 @@ function buildSarifLog(result, version = PKG_VERSION) {
|
|
|
1537
1581
|
rules
|
|
1538
1582
|
}
|
|
1539
1583
|
},
|
|
1584
|
+
// automationDetails.id: stable tool identifier for GitHub Code Scanning.
|
|
1585
|
+
// Groups all ai-guard scan runs into one persistent analysis slot.
|
|
1586
|
+
// MUST remain "ai-guard" forever — changing this orphans all existing alerts.
|
|
1587
|
+
automationDetails: {
|
|
1588
|
+
id: SARIF_AUTOMATION_ID
|
|
1589
|
+
},
|
|
1540
1590
|
results: sarifResults,
|
|
1541
1591
|
properties: {
|
|
1542
1592
|
preset: "recommended",
|
|
@@ -1553,7 +1603,19 @@ function buildSarifLog(result, version = PKG_VERSION) {
|
|
|
1553
1603
|
function sarifToJson(log2) {
|
|
1554
1604
|
return JSON.stringify(log2, null, 2);
|
|
1555
1605
|
}
|
|
1556
|
-
function
|
|
1606
|
+
function debugSarifPath(filePath, repoRoot) {
|
|
1607
|
+
const normalizedUri = normalizeSarifPath(filePath, repoRoot);
|
|
1608
|
+
return {
|
|
1609
|
+
originalPath: filePath,
|
|
1610
|
+
normalizedUri,
|
|
1611
|
+
isRepositoryRelative: !import_path3.default.isAbsolute(normalizedUri) && !normalizedUri.startsWith("/"),
|
|
1612
|
+
hasLeadingSlash: normalizedUri.startsWith("/"),
|
|
1613
|
+
hasDriveLetter: /^[A-Za-z]:/.test(normalizedUri),
|
|
1614
|
+
hasBackslashes: normalizedUri.includes("\\"),
|
|
1615
|
+
hasLeadingDotSlash: normalizedUri.startsWith("./")
|
|
1616
|
+
};
|
|
1617
|
+
}
|
|
1618
|
+
function buildSarifDebugInfo(result, repoRoot) {
|
|
1557
1619
|
const usedRuleIds = collectUsedRuleIds(result);
|
|
1558
1620
|
const rulesEmitted = usedRuleIds.map((id) => {
|
|
1559
1621
|
const meta = RULE_DOCS[id];
|
|
@@ -1575,9 +1637,22 @@ function buildSarifDebugInfo(result) {
|
|
|
1575
1637
|
};
|
|
1576
1638
|
});
|
|
1577
1639
|
const resultsEmitted = [];
|
|
1640
|
+
const pathsDebug = [];
|
|
1641
|
+
const seenPaths = /* @__PURE__ */ new Set();
|
|
1578
1642
|
for (const file of result.files) {
|
|
1643
|
+
if (!seenPaths.has(file.filePath)) {
|
|
1644
|
+
seenPaths.add(file.filePath);
|
|
1645
|
+
pathsDebug.push(debugSarifPath(file.filePath, repoRoot));
|
|
1646
|
+
}
|
|
1579
1647
|
for (const issue of file.issues) {
|
|
1580
1648
|
const confidence = ISSUE_CONFIDENCE[issue.ruleId];
|
|
1649
|
+
const normalizedUri = normalizeSarifPath(file.filePath, repoRoot);
|
|
1650
|
+
const fingerprint = generateStableFingerprint(
|
|
1651
|
+
normalizedUri,
|
|
1652
|
+
issue.ruleId,
|
|
1653
|
+
Math.max(1, issue.line),
|
|
1654
|
+
issue.message
|
|
1655
|
+
);
|
|
1581
1656
|
resultsEmitted.push({
|
|
1582
1657
|
ruleId: issue.ruleId,
|
|
1583
1658
|
level: confidenceToSarifLevel(confidence),
|
|
@@ -1585,13 +1660,18 @@ function buildSarifDebugInfo(result) {
|
|
|
1585
1660
|
securitySeverity: confidenceToSecuritySeverity(confidence),
|
|
1586
1661
|
precision: confidenceToPrecision(confidence),
|
|
1587
1662
|
filePath: file.filePath,
|
|
1588
|
-
|
|
1663
|
+
normalizedUri,
|
|
1664
|
+
line: issue.line,
|
|
1665
|
+
fingerprint
|
|
1589
1666
|
});
|
|
1590
1667
|
}
|
|
1591
1668
|
}
|
|
1592
1669
|
return {
|
|
1670
|
+
automationId: SARIF_AUTOMATION_ID,
|
|
1671
|
+
fingerprintKey: FINGERPRINT_KEY,
|
|
1593
1672
|
rulesEmitted,
|
|
1594
1673
|
resultsEmitted,
|
|
1674
|
+
pathsDebug,
|
|
1595
1675
|
totalResults: result.files.reduce((n, f) => n + f.issues.length, 0),
|
|
1596
1676
|
version: PKG_VERSION
|
|
1597
1677
|
};
|
|
@@ -1824,7 +1904,7 @@ function writeGitHubOutputs(result, sarifPath) {
|
|
|
1824
1904
|
|
|
1825
1905
|
// cli/utils/git-diff.ts
|
|
1826
1906
|
var import_child_process = require("child_process");
|
|
1827
|
-
var
|
|
1907
|
+
var import_path4 = __toESM(require("path"));
|
|
1828
1908
|
var import_fs3 = __toESM(require("fs"));
|
|
1829
1909
|
var DEFAULT_EXTENSIONS = [".js", ".jsx", ".ts", ".tsx", ".mjs", ".cjs", ".mts", ".cts"];
|
|
1830
1910
|
var IGNORE_PREFIXES = [
|
|
@@ -1934,7 +2014,7 @@ function filterFiles(rawFiles, extensions, workingDirectory, cwd, debugInfo) {
|
|
|
1934
2014
|
for (const rel of rawFiles) {
|
|
1935
2015
|
const normalized = rel.replace(/\\/g, "/").trim();
|
|
1936
2016
|
if (!normalized) continue;
|
|
1937
|
-
const ext =
|
|
2017
|
+
const ext = import_path4.default.extname(normalized).toLowerCase();
|
|
1938
2018
|
if (!extensions.includes(ext)) {
|
|
1939
2019
|
debugInfo.droppedByExtension++;
|
|
1940
2020
|
continue;
|
|
@@ -1950,7 +2030,7 @@ function filterFiles(rawFiles, extensions, workingDirectory, cwd, debugInfo) {
|
|
|
1950
2030
|
continue;
|
|
1951
2031
|
}
|
|
1952
2032
|
}
|
|
1953
|
-
const abs =
|
|
2033
|
+
const abs = import_path4.default.resolve(cwd, normalized);
|
|
1954
2034
|
if (!import_fs3.default.existsSync(abs)) {
|
|
1955
2035
|
debugInfo.droppedMissing++;
|
|
1956
2036
|
continue;
|
|
@@ -2073,7 +2153,7 @@ function registerRunCommand(program2) {
|
|
|
2073
2153
|
"--max-warnings <n>",
|
|
2074
2154
|
"Fail with exit code 1 if warnings exceed this count",
|
|
2075
2155
|
(value) => Number.parseInt(value, 10)
|
|
2076
|
-
).option("--verbose", "Show all issues \u2014 disable grouping of repeated warnings").option("--quiet", "Only show errors \u2014 suppress warnings and informational hints").option("--debug-timing", "Print per-phase timing diagnostics").option("--debug-sarif", "Print SARIF tag normalization trace \u2014 diagnose
|
|
2156
|
+
).option("--verbose", "Show all issues \u2014 disable grouping of repeated warnings").option("--quiet", "Only show errors \u2014 suppress warnings and informational hints").option("--debug-timing", "Print per-phase timing diagnostics").option("--debug-sarif", "Print SARIF tag/level normalization trace \u2014 diagnose schema issues").option("--debug-sarif-paths", "Print path normalization trace \u2014 diagnose GitHub Code Scanning path resolution").option("--debug-sarif-persistence", "Print persistence identity trace \u2014 fingerprints, automationDetails, category").option("--sarif-output <file>", "Write SARIF to this file instead of stdout").action(async (opts) => {
|
|
2077
2157
|
if (opts.maxWarnings !== void 0 && (!Number.isInteger(opts.maxWarnings) || opts.maxWarnings < 0)) {
|
|
2078
2158
|
log.blank();
|
|
2079
2159
|
log.error("--max-warnings must be a non-negative integer.");
|
|
@@ -2126,10 +2206,11 @@ function registerRunCommand(program2) {
|
|
|
2126
2206
|
writeGitHubOutputs(result);
|
|
2127
2207
|
}
|
|
2128
2208
|
if (opts.sarif || opts.sarifOutput) {
|
|
2129
|
-
const
|
|
2209
|
+
const repoRoot = process.env.GITHUB_WORKSPACE ?? void 0;
|
|
2210
|
+
const sarifLog = buildSarifLog(result, void 0, repoRoot);
|
|
2130
2211
|
const sarifJson = sarifToJson(sarifLog);
|
|
2131
2212
|
if (opts.debugSarif) {
|
|
2132
|
-
const debugInfo = buildSarifDebugInfo(result);
|
|
2213
|
+
const debugInfo = buildSarifDebugInfo(result, repoRoot);
|
|
2133
2214
|
process.stderr.write("\n[debug-sarif] SARIF GitHub Compatibility Trace\n");
|
|
2134
2215
|
process.stderr.write("[debug-sarif] \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\n");
|
|
2135
2216
|
process.stderr.write("[debug-sarif] Rules Emitted:\n");
|
|
@@ -2167,11 +2248,67 @@ function registerRunCommand(program2) {
|
|
|
2167
2248
|
process.stderr.write(`[debug-sarif] security-severity: ${res.securitySeverity}
|
|
2168
2249
|
`);
|
|
2169
2250
|
process.stderr.write(`[debug-sarif] precision: ${res.precision}
|
|
2251
|
+
`);
|
|
2252
|
+
process.stderr.write(`[debug-sarif] artifact uri: ${res.normalizedUri}
|
|
2170
2253
|
`);
|
|
2171
2254
|
}
|
|
2172
2255
|
}
|
|
2173
2256
|
process.stderr.write("[debug-sarif] \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\n\n");
|
|
2174
2257
|
}
|
|
2258
|
+
if (opts.debugSarifPaths) {
|
|
2259
|
+
const debugInfo = buildSarifDebugInfo(result, repoRoot);
|
|
2260
|
+
process.stderr.write("\n[debug-sarif-paths] Path Normalization Trace\n");
|
|
2261
|
+
process.stderr.write("[debug-sarif-paths] \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\n");
|
|
2262
|
+
process.stderr.write(`[debug-sarif-paths] GITHUB_WORKSPACE: ${repoRoot ?? "(not set \u2014 local run)"}
|
|
2263
|
+
|
|
2264
|
+
`);
|
|
2265
|
+
if (debugInfo.pathsDebug.length === 0) {
|
|
2266
|
+
process.stderr.write("[debug-sarif-paths] (no files in results)\n");
|
|
2267
|
+
} else {
|
|
2268
|
+
for (const p of debugInfo.pathsDebug) {
|
|
2269
|
+
process.stderr.write(`[debug-sarif-paths] original path: ${p.originalPath}
|
|
2270
|
+
`);
|
|
2271
|
+
process.stderr.write(`[debug-sarif-paths] artifact uri: ${p.normalizedUri}
|
|
2272
|
+
`);
|
|
2273
|
+
process.stderr.write(`[debug-sarif-paths] repo-relative: ${p.isRepositoryRelative ? "\u2705 yes" : "\u274C NO (GitHub may miss this)"}
|
|
2274
|
+
`);
|
|
2275
|
+
if (p.hasBackslashes) process.stderr.write("[debug-sarif-paths] \u26A0 had backslashes \u2014 converted\n");
|
|
2276
|
+
if (p.hasDriveLetter) process.stderr.write("[debug-sarif-paths] \u26A0 had drive letter \u2014 stripped\n");
|
|
2277
|
+
if (p.hasLeadingSlash) process.stderr.write("[debug-sarif-paths] \u26A0 had leading slash \u2014 stripped\n");
|
|
2278
|
+
if (p.hasLeadingDotSlash) process.stderr.write("[debug-sarif-paths] \u26A0 had leading ./ \u2014 stripped\n");
|
|
2279
|
+
process.stderr.write("\n");
|
|
2280
|
+
}
|
|
2281
|
+
}
|
|
2282
|
+
process.stderr.write("[debug-sarif-paths] \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\n\n");
|
|
2283
|
+
}
|
|
2284
|
+
if (opts.debugSarifPersistence) {
|
|
2285
|
+
const debugInfo = buildSarifDebugInfo(result, repoRoot);
|
|
2286
|
+
process.stderr.write("\n[debug-sarif-persistence] GitHub Persistence Identity Trace\n");
|
|
2287
|
+
process.stderr.write("[debug-sarif-persistence] \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\n");
|
|
2288
|
+
process.stderr.write(`[debug-sarif-persistence] automationDetails.id: ${debugInfo.automationId}
|
|
2289
|
+
`);
|
|
2290
|
+
process.stderr.write(`[debug-sarif-persistence] fingerprintKey: ${debugInfo.fingerprintKey}
|
|
2291
|
+
`);
|
|
2292
|
+
process.stderr.write(`[debug-sarif-persistence] GITHUB_WORKSPACE: ${repoRoot ?? "(not set)"}
|
|
2293
|
+
`);
|
|
2294
|
+
process.stderr.write(`[debug-sarif-persistence] totalResults: ${debugInfo.totalResults}
|
|
2295
|
+
|
|
2296
|
+
`);
|
|
2297
|
+
if (debugInfo.resultsEmitted.length === 0) {
|
|
2298
|
+
process.stderr.write("[debug-sarif-persistence] (no findings \u2014 no fingerprints to show)\n");
|
|
2299
|
+
} else {
|
|
2300
|
+
process.stderr.write("[debug-sarif-persistence] Fingerprints (stable identity per finding):\n");
|
|
2301
|
+
for (const res of debugInfo.resultsEmitted) {
|
|
2302
|
+
process.stderr.write(`[debug-sarif-persistence] \u2500 ${res.ruleId}
|
|
2303
|
+
`);
|
|
2304
|
+
process.stderr.write(`[debug-sarif-persistence] file: ${res.normalizedUri}:${res.line}
|
|
2305
|
+
`);
|
|
2306
|
+
process.stderr.write(`[debug-sarif-persistence] fingerprint: ${res.fingerprint}
|
|
2307
|
+
`);
|
|
2308
|
+
}
|
|
2309
|
+
}
|
|
2310
|
+
process.stderr.write("[debug-sarif-persistence] \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\n\n");
|
|
2311
|
+
}
|
|
2175
2312
|
if (opts.sarifOutput) {
|
|
2176
2313
|
import_fs4.default.writeFileSync(opts.sarifOutput, sarifJson, "utf-8");
|
|
2177
2314
|
if (opts.debugSarif) {
|
|
@@ -2514,7 +2651,7 @@ function resolveExitCode(result, failOn, maxWarnings) {
|
|
|
2514
2651
|
}
|
|
2515
2652
|
|
|
2516
2653
|
// cli/commands/changed.ts
|
|
2517
|
-
var
|
|
2654
|
+
var import_path5 = __toESM(require("path"));
|
|
2518
2655
|
var import_fs5 = __toESM(require("fs"));
|
|
2519
2656
|
var import_ora2 = __toESM(require("ora"));
|
|
2520
2657
|
var import_chalk5 = __toESM(require("chalk"));
|
|
@@ -2523,7 +2660,7 @@ function registerChangedCommand(program2) {
|
|
|
2523
2660
|
"--max-warnings <n>",
|
|
2524
2661
|
"Fail if warnings exceed this count",
|
|
2525
2662
|
(v) => Number.parseInt(v, 10)
|
|
2526
|
-
).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)").option("--debug-sarif", "Print SARIF tag normalization trace \u2014 diagnose
|
|
2663
|
+
).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)").option("--debug-sarif", "Print SARIF tag/level normalization trace \u2014 diagnose schema issues").option("--debug-sarif-paths", "Print path normalization trace \u2014 diagnose GitHub Code Scanning path resolution").option("--debug-sarif-persistence", "Print persistence identity trace \u2014 fingerprints, automationDetails, category").action(async (opts) => {
|
|
2527
2664
|
const preset = opts.strict ? "strict" : opts.security ? "security" : "recommended";
|
|
2528
2665
|
const inCI = isGitHubActions();
|
|
2529
2666
|
const baseRef = opts.base ?? (opts.pr || inCI ? getGitHubBaseRef() : void 0);
|
|
@@ -2552,7 +2689,7 @@ function registerChangedCommand(program2) {
|
|
|
2552
2689
|
});
|
|
2553
2690
|
}
|
|
2554
2691
|
const cwd = process.cwd();
|
|
2555
|
-
const resolvedPath =
|
|
2692
|
+
const resolvedPath = import_path5.default.resolve(opts.path);
|
|
2556
2693
|
const workingDirectory = opts.path !== "." ? opts.path : void 0;
|
|
2557
2694
|
const spinner = opts.json || opts.sarif ? null : (0, import_ora2.default)({ text: import_chalk5.default.dim("Detecting changed files\u2026"), color: "cyan" }).start();
|
|
2558
2695
|
const changedResult = getChangedFiles({
|
|
@@ -2633,10 +2770,11 @@ function handleResults(result, opts, preset, scanMode, changedFilesCount, inCI,
|
|
|
2633
2770
|
emitGitHubAnnotations(result);
|
|
2634
2771
|
}
|
|
2635
2772
|
if (opts.sarif) {
|
|
2636
|
-
const
|
|
2773
|
+
const repoRoot = process.env.GITHUB_WORKSPACE ?? void 0;
|
|
2774
|
+
const sarifLog = buildSarifLog(result, void 0, repoRoot);
|
|
2637
2775
|
const sarifJson = sarifToJson(sarifLog);
|
|
2638
2776
|
if (opts.debugSarif) {
|
|
2639
|
-
const debugInfo = buildSarifDebugInfo(result);
|
|
2777
|
+
const debugInfo = buildSarifDebugInfo(result, repoRoot);
|
|
2640
2778
|
process.stderr.write("\n[debug-sarif] SARIF GitHub Compatibility Trace\n");
|
|
2641
2779
|
process.stderr.write("[debug-sarif] \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\n");
|
|
2642
2780
|
process.stderr.write("[debug-sarif] Rules Emitted:\n");
|
|
@@ -2674,11 +2812,67 @@ function handleResults(result, opts, preset, scanMode, changedFilesCount, inCI,
|
|
|
2674
2812
|
process.stderr.write(`[debug-sarif] security-severity: ${res.securitySeverity}
|
|
2675
2813
|
`);
|
|
2676
2814
|
process.stderr.write(`[debug-sarif] precision: ${res.precision}
|
|
2815
|
+
`);
|
|
2816
|
+
process.stderr.write(`[debug-sarif] artifact uri: ${res.normalizedUri}
|
|
2677
2817
|
`);
|
|
2678
2818
|
}
|
|
2679
2819
|
}
|
|
2680
2820
|
process.stderr.write("[debug-sarif] \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\n\n");
|
|
2681
2821
|
}
|
|
2822
|
+
if (opts.debugSarifPaths) {
|
|
2823
|
+
const debugInfo = buildSarifDebugInfo(result, repoRoot);
|
|
2824
|
+
process.stderr.write("\n[debug-sarif-paths] Path Normalization Trace\n");
|
|
2825
|
+
process.stderr.write("[debug-sarif-paths] \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\n");
|
|
2826
|
+
process.stderr.write(`[debug-sarif-paths] GITHUB_WORKSPACE: ${repoRoot ?? "(not set \u2014 local run)"}
|
|
2827
|
+
|
|
2828
|
+
`);
|
|
2829
|
+
if (debugInfo.pathsDebug.length === 0) {
|
|
2830
|
+
process.stderr.write("[debug-sarif-paths] (no files in results)\n");
|
|
2831
|
+
} else {
|
|
2832
|
+
for (const p of debugInfo.pathsDebug) {
|
|
2833
|
+
process.stderr.write(`[debug-sarif-paths] original path: ${p.originalPath}
|
|
2834
|
+
`);
|
|
2835
|
+
process.stderr.write(`[debug-sarif-paths] artifact uri: ${p.normalizedUri}
|
|
2836
|
+
`);
|
|
2837
|
+
process.stderr.write(`[debug-sarif-paths] repo-relative: ${p.isRepositoryRelative ? "\u2705 yes" : "\u274C NO (GitHub may miss this)"}
|
|
2838
|
+
`);
|
|
2839
|
+
if (p.hasBackslashes) process.stderr.write("[debug-sarif-paths] \u26A0 had backslashes \u2014 converted\n");
|
|
2840
|
+
if (p.hasDriveLetter) process.stderr.write("[debug-sarif-paths] \u26A0 had drive letter \u2014 stripped\n");
|
|
2841
|
+
if (p.hasLeadingSlash) process.stderr.write("[debug-sarif-paths] \u26A0 had leading slash \u2014 stripped\n");
|
|
2842
|
+
if (p.hasLeadingDotSlash) process.stderr.write("[debug-sarif-paths] \u26A0 had leading ./ \u2014 stripped\n");
|
|
2843
|
+
process.stderr.write("\n");
|
|
2844
|
+
}
|
|
2845
|
+
}
|
|
2846
|
+
process.stderr.write("[debug-sarif-paths] \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\n\n");
|
|
2847
|
+
}
|
|
2848
|
+
if (opts.debugSarifPersistence) {
|
|
2849
|
+
const debugInfo = buildSarifDebugInfo(result, repoRoot);
|
|
2850
|
+
process.stderr.write("\n[debug-sarif-persistence] GitHub Persistence Identity Trace\n");
|
|
2851
|
+
process.stderr.write("[debug-sarif-persistence] \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\n");
|
|
2852
|
+
process.stderr.write(`[debug-sarif-persistence] automationDetails.id: ${debugInfo.automationId}
|
|
2853
|
+
`);
|
|
2854
|
+
process.stderr.write(`[debug-sarif-persistence] fingerprintKey: ${debugInfo.fingerprintKey}
|
|
2855
|
+
`);
|
|
2856
|
+
process.stderr.write(`[debug-sarif-persistence] GITHUB_WORKSPACE: ${repoRoot ?? "(not set)"}
|
|
2857
|
+
`);
|
|
2858
|
+
process.stderr.write(`[debug-sarif-persistence] totalResults: ${debugInfo.totalResults}
|
|
2859
|
+
|
|
2860
|
+
`);
|
|
2861
|
+
if (debugInfo.resultsEmitted.length === 0) {
|
|
2862
|
+
process.stderr.write("[debug-sarif-persistence] (no findings \u2014 no fingerprints to show)\n");
|
|
2863
|
+
} else {
|
|
2864
|
+
process.stderr.write("[debug-sarif-persistence] Fingerprints (stable identity per finding):\n");
|
|
2865
|
+
for (const res of debugInfo.resultsEmitted) {
|
|
2866
|
+
process.stderr.write(`[debug-sarif-persistence] \u2500 ${res.ruleId}
|
|
2867
|
+
`);
|
|
2868
|
+
process.stderr.write(`[debug-sarif-persistence] file: ${res.normalizedUri}:${res.line}
|
|
2869
|
+
`);
|
|
2870
|
+
process.stderr.write(`[debug-sarif-persistence] fingerprint: ${res.fingerprint}
|
|
2871
|
+
`);
|
|
2872
|
+
}
|
|
2873
|
+
}
|
|
2874
|
+
process.stderr.write("[debug-sarif-persistence] \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\n\n");
|
|
2875
|
+
}
|
|
2682
2876
|
if (resolvedSarifPath) {
|
|
2683
2877
|
import_fs5.default.writeFileSync(resolvedSarifPath, sarifJson, "utf-8");
|
|
2684
2878
|
if (opts.debugSarif) {
|
|
@@ -2814,12 +3008,12 @@ function getFailOnExitCode(result, failOn, maxWarnings) {
|
|
|
2814
3008
|
|
|
2815
3009
|
// cli/commands/init.ts
|
|
2816
3010
|
var import_chalk6 = __toESM(require("chalk"));
|
|
2817
|
-
var
|
|
3011
|
+
var import_path8 = __toESM(require("path"));
|
|
2818
3012
|
var import_fs8 = __toESM(require("fs"));
|
|
2819
3013
|
|
|
2820
3014
|
// cli/utils/detector.ts
|
|
2821
3015
|
var import_fs6 = __toESM(require("fs"));
|
|
2822
|
-
var
|
|
3016
|
+
var import_path6 = __toESM(require("path"));
|
|
2823
3017
|
var import_module2 = require("module");
|
|
2824
3018
|
var FLAT_CONFIG_FILES = [
|
|
2825
3019
|
{ file: "eslint.config.js", type: "flat-js" },
|
|
@@ -2836,11 +3030,11 @@ var LEGACY_CONFIG_FILES = [
|
|
|
2836
3030
|
var ALL_CONFIG_FILES = [...FLAT_CONFIG_FILES, ...LEGACY_CONFIG_FILES];
|
|
2837
3031
|
function isPackageInstalled(pkgName, cwd = process.cwd()) {
|
|
2838
3032
|
try {
|
|
2839
|
-
const pkgPath =
|
|
3033
|
+
const pkgPath = import_path6.default.join(cwd, "node_modules", pkgName, "package.json");
|
|
2840
3034
|
if (import_fs6.default.existsSync(pkgPath)) {
|
|
2841
3035
|
return true;
|
|
2842
3036
|
}
|
|
2843
|
-
const req = (0, import_module2.createRequire)(
|
|
3037
|
+
const req = (0, import_module2.createRequire)(import_path6.default.join(cwd, "package.json"));
|
|
2844
3038
|
req.resolve(`${pkgName}/package.json`);
|
|
2845
3039
|
return true;
|
|
2846
3040
|
} catch {
|
|
@@ -2849,8 +3043,8 @@ function isPackageInstalled(pkgName, cwd = process.cwd()) {
|
|
|
2849
3043
|
}
|
|
2850
3044
|
function getPackageVersion(pkgName, cwd = process.cwd()) {
|
|
2851
3045
|
try {
|
|
2852
|
-
const pkgPath =
|
|
2853
|
-
const resolvedPath = import_fs6.default.existsSync(pkgPath) ? pkgPath : (0, import_module2.createRequire)(
|
|
3046
|
+
const pkgPath = import_path6.default.join(cwd, "node_modules", pkgName, "package.json");
|
|
3047
|
+
const resolvedPath = import_fs6.default.existsSync(pkgPath) ? pkgPath : (0, import_module2.createRequire)(import_path6.default.join(cwd, "package.json")).resolve(`${pkgName}/package.json`);
|
|
2854
3048
|
const raw = import_fs6.default.readFileSync(resolvedPath, "utf-8");
|
|
2855
3049
|
const json = JSON.parse(raw);
|
|
2856
3050
|
return json.version ?? null;
|
|
@@ -2867,7 +3061,7 @@ function detectConfigType(cwd = process.cwd()) {
|
|
|
2867
3061
|
const found = [];
|
|
2868
3062
|
let first = null;
|
|
2869
3063
|
for (const { file, type } of ALL_CONFIG_FILES) {
|
|
2870
|
-
const fullPath =
|
|
3064
|
+
const fullPath = import_path6.default.join(cwd, file);
|
|
2871
3065
|
if (import_fs6.default.existsSync(fullPath)) {
|
|
2872
3066
|
found.push(fullPath);
|
|
2873
3067
|
if (!first) first = { type, path: fullPath };
|
|
@@ -2947,7 +3141,7 @@ async function verifyConfigLoads(configPath, cwd) {
|
|
|
2947
3141
|
overrideConfigFile: configPath
|
|
2948
3142
|
});
|
|
2949
3143
|
await eslint.lintText("", {
|
|
2950
|
-
filePath:
|
|
3144
|
+
filePath: import_path8.default.join(cwd, "_ai_guard_probe_.js")
|
|
2951
3145
|
});
|
|
2952
3146
|
return null;
|
|
2953
3147
|
} catch (err) {
|
|
@@ -2983,7 +3177,7 @@ function registerInitCommand(program2) {
|
|
|
2983
3177
|
log.warn("eslint-plugin-ai-guard not found");
|
|
2984
3178
|
}
|
|
2985
3179
|
if (env.configType !== "none") {
|
|
2986
|
-
log.success(`ESLint config found: ${import_chalk6.default.white(
|
|
3180
|
+
log.success(`ESLint config found: ${import_chalk6.default.white(import_path8.default.relative(cwd, env.configPath ?? env.configType))}`);
|
|
2987
3181
|
} else {
|
|
2988
3182
|
log.info("No ESLint config found \u2014 will generate one");
|
|
2989
3183
|
}
|
|
@@ -2992,7 +3186,7 @@ function registerInitCommand(program2) {
|
|
|
2992
3186
|
log.blank();
|
|
2993
3187
|
log.warn("Conflicting configs detected:");
|
|
2994
3188
|
for (const p of env.allConfigPaths) {
|
|
2995
|
-
log.print(` ${import_chalk6.default.yellow("\u2192")} ${import_chalk6.default.white(
|
|
3189
|
+
log.print(` ${import_chalk6.default.yellow("\u2192")} ${import_chalk6.default.white(import_path8.default.relative(cwd, p))}`);
|
|
2996
3190
|
}
|
|
2997
3191
|
log.print(` ${import_chalk6.default.gray("Multiple config formats found \u2014 this can cause unpredictable behavior.")}`);
|
|
2998
3192
|
}
|
|
@@ -3020,7 +3214,7 @@ function registerInitCommand(program2) {
|
|
|
3020
3214
|
try {
|
|
3021
3215
|
const { createRequire: createRequire3 } = await import("module");
|
|
3022
3216
|
const { pathToFileURL: pathToFileURL2 } = await import("url");
|
|
3023
|
-
const req = createRequire3(
|
|
3217
|
+
const req = createRequire3(import_path8.default.join(cwd, "_probe.js"));
|
|
3024
3218
|
const resolvedPath = req.resolve("eslint-plugin-ai-guard");
|
|
3025
3219
|
const aiGuard = await import(pathToFileURL2(resolvedPath).href);
|
|
3026
3220
|
const plugin = aiGuard.default || aiGuard;
|
|
@@ -3039,7 +3233,7 @@ function registerInitCommand(program2) {
|
|
|
3039
3233
|
if (eslintNeedsFlat && existingIsLegacy) {
|
|
3040
3234
|
log.section("Config Migration Required");
|
|
3041
3235
|
log.warn(`ESLint v${env.eslintMajor} requires flat config, but a legacy config was found:`);
|
|
3042
|
-
log.print(` ${import_chalk6.default.white(
|
|
3236
|
+
log.print(` ${import_chalk6.default.white(import_path8.default.relative(cwd, env.configPath))}`);
|
|
3043
3237
|
log.blank();
|
|
3044
3238
|
log.print(` ${import_chalk6.default.bold("ai-guard will create a new flat config.")}`);
|
|
3045
3239
|
log.blank();
|
|
@@ -3051,7 +3245,7 @@ function registerInitCommand(program2) {
|
|
|
3051
3245
|
const raw = readConfig(env.configPath);
|
|
3052
3246
|
const { content: fixed, changed } = removeNukeIgnore(raw);
|
|
3053
3247
|
if (changed) {
|
|
3054
|
-
log.warn(`Removed "**/*" ignore pattern from ${
|
|
3248
|
+
log.warn(`Removed "**/*" ignore pattern from ${import_path8.default.relative(cwd, env.configPath)}`);
|
|
3055
3249
|
if (!isDryRun) {
|
|
3056
3250
|
backupConfig(env.configPath);
|
|
3057
3251
|
writeConfig(env.configPath, fixed);
|
|
@@ -3063,7 +3257,7 @@ function registerInitCommand(program2) {
|
|
|
3063
3257
|
}
|
|
3064
3258
|
if (env.configType === "none" || eslintNeedsFlat && existingIsLegacy) {
|
|
3065
3259
|
const targetName = useFlat ? "eslint.config.mjs" : ".eslintrc.js";
|
|
3066
|
-
finalConfigPath =
|
|
3260
|
+
finalConfigPath = import_path8.default.join(cwd, targetName);
|
|
3067
3261
|
const content2 = useFlat ? generateFlatConfig(preset) : generateLegacyConfig(preset);
|
|
3068
3262
|
if (isDryRun) {
|
|
3069
3263
|
log.print(` ${import_chalk6.default.gray(`[dry-run] would create: ${targetName}`)}`);
|
|
@@ -3091,15 +3285,15 @@ function registerInitCommand(program2) {
|
|
|
3091
3285
|
finalConfigPath = env.configPath;
|
|
3092
3286
|
} else if (isDryRun) {
|
|
3093
3287
|
finalConfigPath = env.configPath;
|
|
3094
|
-
log.print(` ${import_chalk6.default.gray(`[dry-run] would patch: ${
|
|
3288
|
+
log.print(` ${import_chalk6.default.gray(`[dry-run] would patch: ${import_path8.default.relative(cwd, env.configPath)}`)}`);
|
|
3095
3289
|
} else {
|
|
3096
3290
|
const bak = backupConfig(env.configPath);
|
|
3097
|
-
log.info(`Backed up \u2192 ${import_chalk6.default.gray(
|
|
3291
|
+
log.info(`Backed up \u2192 ${import_chalk6.default.gray(import_path8.default.relative(cwd, bak))}`);
|
|
3098
3292
|
writeConfig(env.configPath, patched);
|
|
3099
3293
|
if (isInvalid) {
|
|
3100
|
-
log.success(`Detected invalid ai-guard config \u2014 repairing ${import_chalk6.default.white(
|
|
3294
|
+
log.success(`Detected invalid ai-guard config \u2014 repairing ${import_chalk6.default.white(import_path8.default.relative(cwd, env.configPath))}`);
|
|
3101
3295
|
} else {
|
|
3102
|
-
log.success(`Patched ${import_chalk6.default.white(
|
|
3296
|
+
log.success(`Patched ${import_chalk6.default.white(import_path8.default.relative(cwd, env.configPath))}`);
|
|
3103
3297
|
}
|
|
3104
3298
|
finalConfigPath = env.configPath;
|
|
3105
3299
|
configWritten = true;
|
|
@@ -3112,12 +3306,12 @@ function registerInitCommand(program2) {
|
|
|
3112
3306
|
finalConfigPath = env.configPath;
|
|
3113
3307
|
} else if (isDryRun) {
|
|
3114
3308
|
finalConfigPath = env.configPath;
|
|
3115
|
-
log.print(` ${import_chalk6.default.gray(`[dry-run] would patch: ${
|
|
3309
|
+
log.print(` ${import_chalk6.default.gray(`[dry-run] would patch: ${import_path8.default.relative(cwd, env.configPath)}`)}`);
|
|
3116
3310
|
} else {
|
|
3117
3311
|
const bak = backupConfig(env.configPath);
|
|
3118
|
-
log.info(`Backed up \u2192 ${import_chalk6.default.gray(
|
|
3312
|
+
log.info(`Backed up \u2192 ${import_chalk6.default.gray(import_path8.default.relative(cwd, bak))}`);
|
|
3119
3313
|
writeConfig(env.configPath, patched);
|
|
3120
|
-
log.success(`Patched ${import_chalk6.default.white(
|
|
3314
|
+
log.success(`Patched ${import_chalk6.default.white(import_path8.default.relative(cwd, env.configPath))}`);
|
|
3121
3315
|
finalConfigPath = env.configPath;
|
|
3122
3316
|
configWritten = true;
|
|
3123
3317
|
}
|
|
@@ -3133,11 +3327,11 @@ function registerInitCommand(program2) {
|
|
|
3133
3327
|
cleanedUp = true;
|
|
3134
3328
|
} catch (err) {
|
|
3135
3329
|
const reason = err instanceof Error ? err.message : String(err);
|
|
3136
|
-
log.warn(`Could not back up ${
|
|
3330
|
+
log.warn(`Could not back up ${import_path8.default.relative(cwd, p)}: ${reason}`);
|
|
3137
3331
|
}
|
|
3138
3332
|
} else {
|
|
3139
3333
|
cleanedUp = true;
|
|
3140
|
-
log.print(` ${import_chalk6.default.gray(`[dry-run] would rename ${
|
|
3334
|
+
log.print(` ${import_chalk6.default.gray(`[dry-run] would rename ${import_path8.default.relative(cwd, p)} to ${import_path8.default.basename(p)}.bak`)}`);
|
|
3141
3335
|
}
|
|
3142
3336
|
}
|
|
3143
3337
|
}
|
|
@@ -3156,7 +3350,7 @@ function registerInitCommand(program2) {
|
|
|
3156
3350
|
log.blank();
|
|
3157
3351
|
log.section("Validation");
|
|
3158
3352
|
if (!import_fs8.default.existsSync(finalConfigPath)) {
|
|
3159
|
-
log.error(`Config file not found after write: ${
|
|
3353
|
+
log.error(`Config file not found after write: ${import_path8.default.relative(cwd, finalConfigPath)}`);
|
|
3160
3354
|
log.blank();
|
|
3161
3355
|
log.print(` ${import_chalk6.default.bold("Problem:")} File write may have failed.`);
|
|
3162
3356
|
log.print(` ${import_chalk6.default.bold("Fix:")} Check disk space and file permissions, then re-run.`);
|
|
@@ -3172,7 +3366,7 @@ function registerInitCommand(program2) {
|
|
|
3172
3366
|
log.print(` ${import_chalk6.default.red("\u2716")} ${e}`);
|
|
3173
3367
|
}
|
|
3174
3368
|
} else {
|
|
3175
|
-
log.success(`Config structure valid: ${import_chalk6.default.white(
|
|
3369
|
+
log.success(`Config structure valid: ${import_chalk6.default.white(import_path8.default.relative(cwd, finalConfigPath))}`);
|
|
3176
3370
|
}
|
|
3177
3371
|
log.info("Verifying ESLint can load the config\u2026");
|
|
3178
3372
|
const loadError = await verifyConfigLoads(finalConfigPath, cwd);
|
|
@@ -3196,7 +3390,7 @@ function registerInitCommand(program2) {
|
|
|
3196
3390
|
}
|
|
3197
3391
|
log.blank();
|
|
3198
3392
|
log.print(` ${import_chalk6.default.bold("Fix:")}`);
|
|
3199
|
-
log.print(` 1. Check the syntax in ${import_chalk6.default.cyan(
|
|
3393
|
+
log.print(` 1. Check the syntax in ${import_chalk6.default.cyan(import_path8.default.relative(cwd, finalConfigPath))}`);
|
|
3200
3394
|
log.print(` 2. Make sure ${import_chalk6.default.cyan("eslint-plugin-ai-guard")} is installed`);
|
|
3201
3395
|
log.print(` 3. Run ${import_chalk6.default.cyan("ai-guard doctor")} for full diagnostics`);
|
|
3202
3396
|
log.blank();
|
|
@@ -3218,7 +3412,7 @@ function registerInitCommand(program2) {
|
|
|
3218
3412
|
if (loadError === null && !lingeringConflicts) {
|
|
3219
3413
|
log.print(` ${import_chalk6.default.green("\u2714")} ${import_chalk6.default.bold.green("Configuration validated successfully")}`);
|
|
3220
3414
|
}
|
|
3221
|
-
log.print(` ${import_chalk6.default.green("\u2714")} ${import_chalk6.default.bold("ESLint config:")} ${import_chalk6.default.cyan(
|
|
3415
|
+
log.print(` ${import_chalk6.default.green("\u2714")} ${import_chalk6.default.bold("ESLint config:")} ${import_chalk6.default.cyan(import_path8.default.relative(cwd, finalConfigPath))}`);
|
|
3222
3416
|
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})`)}`);
|
|
3223
3417
|
log.print(` ${import_chalk6.default.green("\u2714")} ${import_chalk6.default.bold("Preset:")} ${import_chalk6.default.cyan(preset)}`);
|
|
3224
3418
|
log.blank();
|
|
@@ -3232,14 +3426,14 @@ function registerInitCommand(program2) {
|
|
|
3232
3426
|
|
|
3233
3427
|
// cli/commands/doctor.ts
|
|
3234
3428
|
var import_chalk7 = __toESM(require("chalk"));
|
|
3235
|
-
var
|
|
3429
|
+
var import_path9 = __toESM(require("path"));
|
|
3236
3430
|
init_config_manager();
|
|
3237
3431
|
var import_meta2 = {};
|
|
3238
3432
|
async function probeConfigLoad(configPath, cwd) {
|
|
3239
3433
|
try {
|
|
3240
3434
|
const { ESLint } = await import("eslint");
|
|
3241
3435
|
const eslint = new ESLint({ cwd, overrideConfigFile: configPath });
|
|
3242
|
-
await eslint.lintText("", { filePath:
|
|
3436
|
+
await eslint.lintText("", { filePath: import_path9.default.join(cwd, "_probe_.js") });
|
|
3243
3437
|
return { ok: true, error: null };
|
|
3244
3438
|
} catch (err) {
|
|
3245
3439
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -3274,7 +3468,7 @@ function registerDoctorCommand(program2) {
|
|
|
3274
3468
|
checks.push({
|
|
3275
3469
|
label: "ESLint config present",
|
|
3276
3470
|
pass: hasConfig,
|
|
3277
|
-
detail: hasConfig ? `${
|
|
3471
|
+
detail: hasConfig ? `${import_path9.default.relative(cwd, env.configPath ?? "")} (${env.configType})` : "No eslint.config.* or .eslintrc.* found",
|
|
3278
3472
|
fix: hasConfig ? void 0 : "ai-guard init",
|
|
3279
3473
|
note: hasConfig ? void 0 : "This will generate the correct config format for your ESLint version"
|
|
3280
3474
|
});
|
|
@@ -3306,7 +3500,7 @@ function registerDoctorCommand(program2) {
|
|
|
3306
3500
|
checks.push({
|
|
3307
3501
|
label: "Plugin wired in config",
|
|
3308
3502
|
pass: pluginWired && !isInvalidConfig,
|
|
3309
|
-
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 ${
|
|
3503
|
+
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_path9.default.relative(cwd, env.configPath)}`,
|
|
3310
3504
|
fix: isInvalidConfig || !pluginWired && !readError ? "ai-guard init (will patch/repair your existing config)" : void 0
|
|
3311
3505
|
});
|
|
3312
3506
|
}
|
|
@@ -3314,7 +3508,7 @@ function registerDoctorCommand(program2) {
|
|
|
3314
3508
|
label: "No conflicting config files",
|
|
3315
3509
|
pass: !env.hasConflictingConfigs,
|
|
3316
3510
|
detail: env.hasConflictingConfigs ? `Conflicting config detected:
|
|
3317
|
-
${env.allConfigPaths.map((p) => ` ${
|
|
3511
|
+
${env.allConfigPaths.map((p) => ` ${import_path9.default.relative(cwd, p)}`).join("\n")}` : "Only one config format detected",
|
|
3318
3512
|
fix: env.hasConflictingConfigs ? "Remove or backup legacy config" : void 0,
|
|
3319
3513
|
note: env.hasConflictingConfigs ? "ESLint v9 silently ignores .eslintrc.* when a flat config exists. This can cause confusion." : void 0
|
|
3320
3514
|
});
|
|
@@ -3341,7 +3535,7 @@ ${env.allConfigPaths.map((p) => ` ${import_path8.default.relative(cwd, p)}
|
|
|
3341
3535
|
label: "ESLint config loads without errors",
|
|
3342
3536
|
pass: probe.ok,
|
|
3343
3537
|
detail: probe.ok ? "ESLint loaded config successfully" : probe.error ?? "Unknown error",
|
|
3344
|
-
fix: probe.ok ? void 0 : `Check syntax in ${
|
|
3538
|
+
fix: probe.ok ? void 0 : `Check syntax in ${import_path9.default.relative(cwd, env.configPath)}`,
|
|
3345
3539
|
note: probe.ok ? void 0 : "Run: ai-guard init --dry-run to preview a fresh config"
|
|
3346
3540
|
});
|
|
3347
3541
|
}
|
|
@@ -3350,7 +3544,7 @@ ${env.allConfigPaths.map((p) => ` ${import_path8.default.relative(cwd, p)}
|
|
|
3350
3544
|
let utilsVersion = null;
|
|
3351
3545
|
try {
|
|
3352
3546
|
const { createRequire: createRequire3 } = await import("module");
|
|
3353
|
-
const req = createRequire3(
|
|
3547
|
+
const req = createRequire3(import_path9.default.join(cwd, "package.json"));
|
|
3354
3548
|
const pkgPath = req.resolve("@typescript-eslint/utils/package.json");
|
|
3355
3549
|
const pkg = JSON.parse(
|
|
3356
3550
|
(await import("fs")).readFileSync(pkgPath, "utf-8")
|
|
@@ -3361,10 +3555,10 @@ ${env.allConfigPaths.map((p) => ` ${import_path8.default.relative(cwd, p)}
|
|
|
3361
3555
|
}
|
|
3362
3556
|
if (!utilsOk) {
|
|
3363
3557
|
try {
|
|
3364
|
-
const selfDir =
|
|
3558
|
+
const selfDir = import_path9.default.dirname(
|
|
3365
3559
|
new URL(import_meta2.url).pathname.replace(/^\/([A-Za-z]:)/, "$1")
|
|
3366
3560
|
);
|
|
3367
|
-
const pkgPath =
|
|
3561
|
+
const pkgPath = import_path9.default.join(selfDir, "../../node_modules/@typescript-eslint/utils/package.json");
|
|
3368
3562
|
if ((await import("fs")).existsSync(pkgPath)) {
|
|
3369
3563
|
utilsOk = true;
|
|
3370
3564
|
}
|
|
@@ -3384,7 +3578,7 @@ ${env.allConfigPaths.map((p) => ` ${import_path8.default.relative(cwd, p)}
|
|
|
3384
3578
|
let parserVersion = null;
|
|
3385
3579
|
try {
|
|
3386
3580
|
const { createRequire: createRequire3 } = await import("module");
|
|
3387
|
-
const req = createRequire3(
|
|
3581
|
+
const req = createRequire3(import_path9.default.join(cwd, "package.json"));
|
|
3388
3582
|
const pkgPath = req.resolve("@typescript-eslint/parser/package.json");
|
|
3389
3583
|
const pkg = JSON.parse(
|
|
3390
3584
|
(await import("fs")).readFileSync(pkgPath, "utf-8")
|
|
@@ -3472,7 +3666,7 @@ ${env.allConfigPaths.map((p) => ` ${import_path8.default.relative(cwd, p)}
|
|
|
3472
3666
|
var import_prompts = require("@inquirer/prompts");
|
|
3473
3667
|
var import_chalk8 = __toESM(require("chalk"));
|
|
3474
3668
|
init_config_manager();
|
|
3475
|
-
var
|
|
3669
|
+
var import_path10 = __toESM(require("path"));
|
|
3476
3670
|
function registerPresetCommand(program2) {
|
|
3477
3671
|
program2.command("preset").description("Interactively select and apply an ai-guard preset to your ESLint config").action(async () => {
|
|
3478
3672
|
const cwd = process.cwd();
|
|
@@ -3500,14 +3694,14 @@ function registerPresetCommand(program2) {
|
|
|
3500
3694
|
const env = detect(cwd);
|
|
3501
3695
|
const useFlat = env.eslintMajor !== null && env.eslintMajor >= 9 || isFlat(env.configType);
|
|
3502
3696
|
if (env.configType === "none") {
|
|
3503
|
-
const configPath = useFlat ?
|
|
3697
|
+
const configPath = useFlat ? import_path10.default.join(cwd, "eslint.config.mjs") : import_path10.default.join(cwd, ".eslintrc.js");
|
|
3504
3698
|
const content = useFlat ? generateFlatConfig(preset) : generateLegacyConfig(preset);
|
|
3505
3699
|
writeConfig(configPath, content);
|
|
3506
|
-
log.success(`Created ${import_chalk8.default.white(
|
|
3700
|
+
log.success(`Created ${import_chalk8.default.white(import_path10.default.relative(cwd, configPath))} with ${import_chalk8.default.cyan(preset)} preset`);
|
|
3507
3701
|
} else {
|
|
3508
3702
|
const configPath = env.configPath;
|
|
3509
3703
|
const backupPath = backupConfig(configPath);
|
|
3510
|
-
log.info(`Backed up \u2192 ${import_chalk8.default.gray(
|
|
3704
|
+
log.info(`Backed up \u2192 ${import_chalk8.default.gray(import_path10.default.relative(cwd, backupPath))}`);
|
|
3511
3705
|
const existing = readConfig(configPath);
|
|
3512
3706
|
const withPlugin = isFlat(env.configType) ? patchFlatConfig(existing, preset) : patchLegacyConfig(existing, preset);
|
|
3513
3707
|
const patched = isFlat(env.configType) ? switchFlatPreset(withPlugin, preset) : switchLegacyPreset(withPlugin, preset);
|
|
@@ -3515,7 +3709,7 @@ function registerPresetCommand(program2) {
|
|
|
3515
3709
|
log.warn("No preset changes needed. Config already matches selected preset.");
|
|
3516
3710
|
} else {
|
|
3517
3711
|
writeConfig(configPath, patched);
|
|
3518
|
-
log.success(`Updated ${import_chalk8.default.white(
|
|
3712
|
+
log.success(`Updated ${import_chalk8.default.white(import_path10.default.relative(cwd, configPath))} to ${import_chalk8.default.cyan(preset)} preset`);
|
|
3519
3713
|
}
|
|
3520
3714
|
}
|
|
3521
3715
|
log.blank();
|
|
@@ -3555,7 +3749,7 @@ function registerPresetCommand(program2) {
|
|
|
3555
3749
|
// cli/commands/ignore.ts
|
|
3556
3750
|
var import_chalk9 = __toESM(require("chalk"));
|
|
3557
3751
|
init_config_manager();
|
|
3558
|
-
var
|
|
3752
|
+
var import_path11 = __toESM(require("path"));
|
|
3559
3753
|
var DEFAULT_IGNORES = [
|
|
3560
3754
|
".next/",
|
|
3561
3755
|
"dist/",
|
|
@@ -3577,21 +3771,21 @@ function registerIgnoreCommand(program2) {
|
|
|
3577
3771
|
const env = detect(cwd);
|
|
3578
3772
|
if (env.configType === "none") {
|
|
3579
3773
|
const useFlat = env.eslintMajor !== null && env.eslintMajor >= 9;
|
|
3580
|
-
const configPath = useFlat ?
|
|
3774
|
+
const configPath = useFlat ? import_path11.default.join(cwd, "eslint.config.mjs") : import_path11.default.join(cwd, ".eslintrc.js");
|
|
3581
3775
|
const content = useFlat ? generateFlatConfig("recommended") : generateLegacyConfig("recommended");
|
|
3582
3776
|
writeConfig(configPath, content);
|
|
3583
|
-
log.success(`No config found \u2014 generated ${import_chalk9.default.white(
|
|
3777
|
+
log.success(`No config found \u2014 generated ${import_chalk9.default.white(import_path11.default.relative(cwd, configPath))} with ignores included`);
|
|
3584
3778
|
} else {
|
|
3585
3779
|
const configPath = env.configPath;
|
|
3586
3780
|
const backupPath = backupConfig(configPath);
|
|
3587
|
-
log.info(`Backed up \u2192 ${import_chalk9.default.gray(
|
|
3781
|
+
log.info(`Backed up \u2192 ${import_chalk9.default.gray(import_path11.default.relative(cwd, backupPath))}`);
|
|
3588
3782
|
const existing = readConfig(configPath);
|
|
3589
3783
|
const patched = isFlat(env.configType) ? addIgnoresToFlatConfig(existing) : addIgnoresToLegacyConfig(existing);
|
|
3590
3784
|
if (patched === existing) {
|
|
3591
3785
|
log.warn("Ignore patterns already present in config \u2014 no changes made.");
|
|
3592
3786
|
} else {
|
|
3593
3787
|
writeConfig(configPath, patched);
|
|
3594
|
-
log.success(`Patched ${import_chalk9.default.white(
|
|
3788
|
+
log.success(`Patched ${import_chalk9.default.white(import_path11.default.relative(cwd, configPath))} with ignore patterns`);
|
|
3595
3789
|
}
|
|
3596
3790
|
}
|
|
3597
3791
|
log.blank();
|
|
@@ -3603,7 +3797,7 @@ function registerIgnoreCommand(program2) {
|
|
|
3603
3797
|
|
|
3604
3798
|
// cli/commands/baseline.ts
|
|
3605
3799
|
var import_fs9 = __toESM(require("fs"));
|
|
3606
|
-
var
|
|
3800
|
+
var import_path12 = __toESM(require("path"));
|
|
3607
3801
|
var import_chalk10 = __toESM(require("chalk"));
|
|
3608
3802
|
var import_ora3 = __toESM(require("ora"));
|
|
3609
3803
|
var BASELINE_FILE = ".ai-guard-baseline.json";
|
|
@@ -3624,12 +3818,12 @@ function saveBaseline(result, preset, mode, cwd) {
|
|
|
3624
3818
|
totalIssues: result.totalIssues,
|
|
3625
3819
|
entries
|
|
3626
3820
|
};
|
|
3627
|
-
const baselinePath =
|
|
3821
|
+
const baselinePath = import_path12.default.join(cwd, BASELINE_FILE);
|
|
3628
3822
|
import_fs9.default.writeFileSync(baselinePath, JSON.stringify(baseline, null, 2), "utf-8");
|
|
3629
3823
|
return baselinePath;
|
|
3630
3824
|
}
|
|
3631
3825
|
function loadBaseline(cwd) {
|
|
3632
|
-
const baselinePath =
|
|
3826
|
+
const baselinePath = import_path12.default.join(cwd, BASELINE_FILE);
|
|
3633
3827
|
if (!import_fs9.default.existsSync(baselinePath)) return null;
|
|
3634
3828
|
try {
|
|
3635
3829
|
const raw = import_fs9.default.readFileSync(baselinePath, "utf-8");
|
|
@@ -3716,7 +3910,7 @@ function registerBaselineCommand(program2) {
|
|
|
3716
3910
|
}
|
|
3717
3911
|
const baselinePath = saveBaseline(result, preset, mode, cwd);
|
|
3718
3912
|
log.success(
|
|
3719
|
-
`Baseline saved \u2192 ${import_chalk10.default.white(
|
|
3913
|
+
`Baseline saved \u2192 ${import_chalk10.default.white(import_path12.default.relative(cwd, baselinePath))}`
|
|
3720
3914
|
);
|
|
3721
3915
|
log.info(` ${result.totalIssues} issues recorded (${result.totalErrors} errors, ${result.totalWarnings} warnings)`);
|
|
3722
3916
|
log.info(` Preset: ${import_chalk10.default.cyan(preset)}`);
|
|
@@ -3800,7 +3994,7 @@ function registerBaselineCommand(program2) {
|
|
|
3800
3994
|
|
|
3801
3995
|
// cli/commands/init-context.ts
|
|
3802
3996
|
var import_fs10 = __toESM(require("fs"));
|
|
3803
|
-
var
|
|
3997
|
+
var import_path13 = __toESM(require("path"));
|
|
3804
3998
|
var import_chalk11 = __toESM(require("chalk"));
|
|
3805
3999
|
var import_prompts2 = require("@inquirer/prompts");
|
|
3806
4000
|
var RULE_CATEGORIES = {
|
|
@@ -4164,13 +4358,13 @@ var AGENTS = [
|
|
|
4164
4358
|
{
|
|
4165
4359
|
id: "copilot",
|
|
4166
4360
|
label: "GitHub Copilot",
|
|
4167
|
-
filePath:
|
|
4361
|
+
filePath: import_path13.default.join(".github", "copilot-instructions.md"),
|
|
4168
4362
|
generate: generateCopilotFile
|
|
4169
4363
|
}
|
|
4170
4364
|
];
|
|
4171
4365
|
function getPackageVersion2(cwd) {
|
|
4172
4366
|
try {
|
|
4173
|
-
const pkgPath =
|
|
4367
|
+
const pkgPath = import_path13.default.join(cwd, "node_modules", "eslint-plugin-ai-guard", "package.json");
|
|
4174
4368
|
if (import_fs10.default.existsSync(pkgPath)) {
|
|
4175
4369
|
const pkg = JSON.parse(import_fs10.default.readFileSync(pkgPath, "utf-8"));
|
|
4176
4370
|
if (pkg.version) return pkg.version;
|
|
@@ -4178,7 +4372,7 @@ function getPackageVersion2(cwd) {
|
|
|
4178
4372
|
} catch {
|
|
4179
4373
|
}
|
|
4180
4374
|
try {
|
|
4181
|
-
const pkgPath =
|
|
4375
|
+
const pkgPath = import_path13.default.join(cwd, "package.json");
|
|
4182
4376
|
if (import_fs10.default.existsSync(pkgPath)) {
|
|
4183
4377
|
const pkg = JSON.parse(import_fs10.default.readFileSync(pkgPath, "utf-8"));
|
|
4184
4378
|
if (pkg.version) return pkg.version;
|
|
@@ -4247,7 +4441,7 @@ function registerInitContextCommand(program2) {
|
|
|
4247
4441
|
log.blank();
|
|
4248
4442
|
const results = [];
|
|
4249
4443
|
for (const agent of selectedAgents) {
|
|
4250
|
-
const fullPath =
|
|
4444
|
+
const fullPath = import_path13.default.join(cwd, agent.filePath);
|
|
4251
4445
|
const exists = import_fs10.default.existsSync(fullPath);
|
|
4252
4446
|
if (exists && !isForce && !isDryRun) {
|
|
4253
4447
|
const overwrite = await (0, import_prompts2.confirm)({
|
|
@@ -4272,7 +4466,7 @@ function registerInitContextCommand(program2) {
|
|
|
4272
4466
|
results.push({ file: agent.filePath, status: "dry-run" });
|
|
4273
4467
|
continue;
|
|
4274
4468
|
}
|
|
4275
|
-
const parentDir =
|
|
4469
|
+
const parentDir = import_path13.default.dirname(fullPath);
|
|
4276
4470
|
if (!import_fs10.default.existsSync(parentDir)) {
|
|
4277
4471
|
import_fs10.default.mkdirSync(parentDir, { recursive: true });
|
|
4278
4472
|
}
|
|
@@ -4311,7 +4505,7 @@ function registerInitContextCommand(program2) {
|
|
|
4311
4505
|
|
|
4312
4506
|
// cli/commands/report.ts
|
|
4313
4507
|
var import_fs11 = __toESM(require("fs"));
|
|
4314
|
-
var
|
|
4508
|
+
var import_path14 = __toESM(require("path"));
|
|
4315
4509
|
var import_ora4 = __toESM(require("ora"));
|
|
4316
4510
|
var RULE_META = {
|
|
4317
4511
|
"ai-guard/no-empty-catch": { description: "Empty catch blocks silently swallow errors", category: "Reliability" },
|
|
@@ -4335,18 +4529,18 @@ var RULE_META = {
|
|
|
4335
4529
|
};
|
|
4336
4530
|
function getProjectName(cwd) {
|
|
4337
4531
|
try {
|
|
4338
|
-
const pkgPath =
|
|
4532
|
+
const pkgPath = import_path14.default.join(cwd, "package.json");
|
|
4339
4533
|
if (import_fs11.default.existsSync(pkgPath)) {
|
|
4340
4534
|
const pkg = JSON.parse(import_fs11.default.readFileSync(pkgPath, "utf-8"));
|
|
4341
4535
|
if (pkg.name) return pkg.name;
|
|
4342
4536
|
}
|
|
4343
4537
|
} catch {
|
|
4344
4538
|
}
|
|
4345
|
-
return
|
|
4539
|
+
return import_path14.default.basename(cwd);
|
|
4346
4540
|
}
|
|
4347
4541
|
function getPluginVersion(cwd) {
|
|
4348
4542
|
try {
|
|
4349
|
-
const pkgPath =
|
|
4543
|
+
const pkgPath = import_path14.default.resolve(__dirname, "../../package.json");
|
|
4350
4544
|
if (import_fs11.default.existsSync(pkgPath)) {
|
|
4351
4545
|
const pkg = JSON.parse(import_fs11.default.readFileSync(pkgPath, "utf-8"));
|
|
4352
4546
|
if (pkg.version) return pkg.version;
|
|
@@ -4354,7 +4548,7 @@ function getPluginVersion(cwd) {
|
|
|
4354
4548
|
} catch {
|
|
4355
4549
|
}
|
|
4356
4550
|
try {
|
|
4357
|
-
const pkgPath =
|
|
4551
|
+
const pkgPath = import_path14.default.join(cwd, "node_modules", "eslint-plugin-ai-guard", "package.json");
|
|
4358
4552
|
if (import_fs11.default.existsSync(pkgPath)) {
|
|
4359
4553
|
const pkg = JSON.parse(import_fs11.default.readFileSync(pkgPath, "utf-8"));
|
|
4360
4554
|
if (pkg.version) return pkg.version;
|
|
@@ -4733,7 +4927,7 @@ function registerReportCommand(program2) {
|
|
|
4733
4927
|
log.banner("AI GUARD REPORT");
|
|
4734
4928
|
log.blank();
|
|
4735
4929
|
const html = generateHtml(reportData);
|
|
4736
|
-
const outputPath =
|
|
4930
|
+
const outputPath = import_path14.default.resolve(cwd, opts.output);
|
|
4737
4931
|
import_fs11.default.writeFileSync(outputPath, html, "utf-8");
|
|
4738
4932
|
log.success(`Report saved: ${opts.output}`);
|
|
4739
4933
|
log.info(
|
|
@@ -4767,7 +4961,7 @@ function registerReportCommand(program2) {
|
|
|
4767
4961
|
// cli/index.ts
|
|
4768
4962
|
function getVersion() {
|
|
4769
4963
|
try {
|
|
4770
|
-
const pkgPath =
|
|
4964
|
+
const pkgPath = import_path15.default.resolve(__dirname, "../../package.json");
|
|
4771
4965
|
const raw = import_fs12.default.readFileSync(pkgPath, "utf-8");
|
|
4772
4966
|
const pkg = JSON.parse(raw);
|
|
4773
4967
|
return typeof pkg.version === "string" ? pkg.version : "0.0.0";
|