@methiu/raigal 0.2.3 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{AgentApp-DJYdD1VH.js → AgentApp-CIiRfOun.js} +2 -4
- package/dist/adapters/vite.js +1 -2
- package/dist/cli.js +123 -197
- package/dist/index.js +84 -145
- package/dist/{json-BflWt4dX.js → json-B8XGYwMv.js} +1 -1
- package/dist/mcp.js +35 -56
- package/dist/{mount-CHGc3gB6.js → mount-DTc8WaIt.js} +1 -1
- package/dist/{sarif-CpuYM3aK.js → sarif-DqH4dGEo.js} +1 -1
- package/dist/{version-B4eYJn3o.js → version-BlgPglaO.js} +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as APP_VERSION } from "./version-
|
|
1
|
+
import { t as APP_VERSION } from "./version-BlgPglaO.js";
|
|
2
2
|
import { a as getEngineLabel, i as ENGINE_INFO, r as scoreImpactForRule, t as summarizeFindingAssessments } from "./finding-assessment-CGpt5YUR.js";
|
|
3
3
|
import { n as isSecretClassRule, r as maskSecrets, t as FIXED_SECRET_DIAGNOSTIC_MESSAGE } from "./mask-secrets-BXn-ZSEh.js";
|
|
4
4
|
import { createRequire, isBuiltin } from "node:module";
|
|
@@ -132,7 +132,7 @@ const DEFAULT_RULES_YAML = `# Architecture rules (BYO)
|
|
|
132
132
|
//#endregion
|
|
133
133
|
//#region src/config/extends.ts
|
|
134
134
|
const MAX_DEPTH$1 = 5;
|
|
135
|
-
const MAX_CONFIG_BYTES =
|
|
135
|
+
const MAX_CONFIG_BYTES = 1024 * 1024;
|
|
136
136
|
const isPlainObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
137
137
|
const deepMerge = (...sources) => {
|
|
138
138
|
const result = {};
|
|
@@ -611,8 +611,7 @@ const loadConfig = (directory) => {
|
|
|
611
611
|
const configPath = findConfigFile(directory);
|
|
612
612
|
if (!configPath) return DEFAULT_CONFIG;
|
|
613
613
|
try {
|
|
614
|
-
|
|
615
|
-
return validateConfig(merged, configPath);
|
|
614
|
+
return validateConfig(loadConfigChain(configPath), configPath);
|
|
616
615
|
} catch (error) {
|
|
617
616
|
if (error instanceof ConfigError) throw error;
|
|
618
617
|
throw new ConfigError(configPath, `Failed to parse ${configPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -708,8 +707,7 @@ const stringWidth = (s) => {
|
|
|
708
707
|
const bare = stripAnsi$1(s);
|
|
709
708
|
let total = 0;
|
|
710
709
|
for (const ch of bare) {
|
|
711
|
-
const
|
|
712
|
-
const w = wcwidth(cp);
|
|
710
|
+
const w = wcwidth(ch.codePointAt(0) ?? 0);
|
|
713
711
|
total += w > 0 ? w : 1;
|
|
714
712
|
}
|
|
715
713
|
return total;
|
|
@@ -725,8 +723,7 @@ const truncate = (s, max, ellipsis = "…") => {
|
|
|
725
723
|
let out = "";
|
|
726
724
|
let w = 0;
|
|
727
725
|
for (const ch of s) {
|
|
728
|
-
const
|
|
729
|
-
const cw = wcwidth(cp);
|
|
726
|
+
const cw = wcwidth(ch.codePointAt(0) ?? 0);
|
|
730
727
|
if (w + cw > limit) break;
|
|
731
728
|
out += ch;
|
|
732
729
|
w += cw;
|
|
@@ -736,8 +733,7 @@ const truncate = (s, max, ellipsis = "…") => {
|
|
|
736
733
|
//#endregion
|
|
737
734
|
//#region src/ui/display.ts
|
|
738
735
|
const renderDisplaySection = (label, deps = {}) => {
|
|
739
|
-
|
|
740
|
-
return style(t, "section", label);
|
|
736
|
+
return style(deps.theme ?? theme, "section", label);
|
|
741
737
|
};
|
|
742
738
|
const renderDisplayRows = (rows, options = {}) => {
|
|
743
739
|
if (rows.length === 0) return [];
|
|
@@ -884,10 +880,8 @@ const detectSourceLanguages = (sourceFiles) => {
|
|
|
884
880
|
const detectLanguages = (directory, sourceFiles) => {
|
|
885
881
|
const languages = new Set(detectSourceLanguages(sourceFiles));
|
|
886
882
|
for (const [file, lang] of Object.entries(LANGUAGE_SIGNALS)) if (fs.existsSync(path.join(directory, file))) languages.add(lang);
|
|
887
|
-
if (readPackageJson(path.join(directory, "package.json")))
|
|
888
|
-
|
|
889
|
-
else languages.add("javascript");
|
|
890
|
-
}
|
|
883
|
+
if (readPackageJson(path.join(directory, "package.json"))) if (fs.existsSync(path.join(directory, "tsconfig.json"))) languages.add("typescript");
|
|
884
|
+
else languages.add("javascript");
|
|
891
885
|
for (const signal of PYTHON_SIGNALS) if (fs.existsSync(path.join(directory, signal))) {
|
|
892
886
|
languages.add("python");
|
|
893
887
|
break;
|
|
@@ -1020,7 +1014,7 @@ const isAutoGenerated = (filePath) => {
|
|
|
1020
1014
|
};
|
|
1021
1015
|
//#endregion
|
|
1022
1016
|
//#region src/utils/git-ignore.ts
|
|
1023
|
-
const MAX_BUFFER$2 =
|
|
1017
|
+
const MAX_BUFFER$2 = 50 * 1024 * 1024;
|
|
1024
1018
|
const NOT_IGNORED_ARGUMENTS = [
|
|
1025
1019
|
"ls-files",
|
|
1026
1020
|
"--cached",
|
|
@@ -1131,7 +1125,7 @@ const dropGitIgnoredPaths = (rootDirectory, absolutePaths) => {
|
|
|
1131
1125
|
};
|
|
1132
1126
|
//#endregion
|
|
1133
1127
|
//#region src/utils/project-file-list.ts
|
|
1134
|
-
const MAX_BUFFER$1 =
|
|
1128
|
+
const MAX_BUFFER$1 = 50 * 1024 * 1024;
|
|
1135
1129
|
const normalizePruneDirectories = (directories) => new Set([...directories].map((directory) => directory.toLowerCase()));
|
|
1136
1130
|
const isInPrunedDirectory = (filePath, pruneDirectories) => {
|
|
1137
1131
|
const pathSegments = filePath.split("/");
|
|
@@ -1778,7 +1772,7 @@ const checkInstalledTools = async () => {
|
|
|
1778
1772
|
};
|
|
1779
1773
|
//#endregion
|
|
1780
1774
|
//#region src/utils/project-path-safety.ts
|
|
1781
|
-
const MAX_PROJECT_CONFIG_BYTES =
|
|
1775
|
+
const MAX_PROJECT_CONFIG_BYTES = 1024 * 1024;
|
|
1782
1776
|
const isWithinDirectory$2 = (rootDirectory, candidate) => {
|
|
1783
1777
|
const relative = path.relative(rootDirectory, candidate);
|
|
1784
1778
|
return relative === "" || !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
@@ -2103,8 +2097,7 @@ const resolveTrustedTscPath = () => {
|
|
|
2103
2097
|
};
|
|
2104
2098
|
const isReferenceOnlyConfig = (tsconfigPath) => {
|
|
2105
2099
|
try {
|
|
2106
|
-
const
|
|
2107
|
-
const parsed = parseJsonc(raw);
|
|
2100
|
+
const parsed = parseJsonc(fs.readFileSync(tsconfigPath, "utf-8"));
|
|
2108
2101
|
if (!parsed) return false;
|
|
2109
2102
|
return Array.isArray(parsed.references) && !parsed.files && !parsed.include && !parsed.extends;
|
|
2110
2103
|
} catch {
|
|
@@ -2423,7 +2416,7 @@ const changeContextOrder = (context) => {
|
|
|
2423
2416
|
};
|
|
2424
2417
|
//#endregion
|
|
2425
2418
|
//#region src/utils/git.ts
|
|
2426
|
-
const MAX_BUFFER =
|
|
2419
|
+
const MAX_BUFFER = 50 * 1024 * 1024;
|
|
2427
2420
|
const baseRefExists = (cwd, ref) => {
|
|
2428
2421
|
const result = spawnSync("git", [
|
|
2429
2422
|
"rev-parse",
|
|
@@ -6806,8 +6799,7 @@ const isJsRelativeOrAbsolute = (spec) => spec.startsWith(".") || spec.startsWith
|
|
|
6806
6799
|
const RUNTIME_BUILTINS = /* @__PURE__ */ new Set(["bun"]);
|
|
6807
6800
|
const isJsBuiltin = (spec) => {
|
|
6808
6801
|
if (RUNTIME_BUILTINS.has(spec)) return true;
|
|
6809
|
-
|
|
6810
|
-
return isBuiltin(stripped) || isBuiltin(spec);
|
|
6802
|
+
return isBuiltin(spec.startsWith("node:") ? spec.slice(5) : spec) || isBuiltin(spec);
|
|
6811
6803
|
};
|
|
6812
6804
|
const VIRTUAL_MODULE_PREFIXES = [
|
|
6813
6805
|
"astro:",
|
|
@@ -7019,8 +7011,7 @@ const isLocalAliasReplacement = (rawValue, configDirectory, rootDirectory) => {
|
|
|
7019
7011
|
if (!target) return false;
|
|
7020
7012
|
if (!target.startsWith(".") && !target.startsWith("/") && !target.startsWith("~/") && !target.startsWith("@/")) return false;
|
|
7021
7013
|
const normalized = target.startsWith("~/") || target.startsWith("@/") ? target.slice(2) : target;
|
|
7022
|
-
|
|
7023
|
-
return isRootBoundedTarget(candidate, rootDirectory);
|
|
7014
|
+
return isRootBoundedTarget(path.isAbsolute(normalized) ? normalized : path.resolve(configDirectory, normalized), rootDirectory);
|
|
7024
7015
|
};
|
|
7025
7016
|
const hasValidPackageImportTarget = (value, packageDirectory, rootDirectory) => {
|
|
7026
7017
|
if (!isRootBoundedTarget(packageDirectory, rootDirectory)) return false;
|
|
@@ -8214,9 +8205,7 @@ const isRustDocCommentLine = (line) => {
|
|
|
8214
8205
|
};
|
|
8215
8206
|
const collectBlocks = (sourceLines, syntax, content, ext) => {
|
|
8216
8207
|
const blocks = [];
|
|
8217
|
-
const
|
|
8218
|
-
const actualExt = ext ?? (syntax.linePrefixes.includes("//") ? ".ts" : ".py");
|
|
8219
|
-
const commentLines = getCommentLines(actualContent, actualExt);
|
|
8208
|
+
const commentLines = getCommentLines(content ?? sourceLines.join("\n"), ext ?? (syntax.linePrefixes.includes("//") ? ".ts" : ".py"));
|
|
8220
8209
|
let i = 0;
|
|
8221
8210
|
while (i < sourceLines.length) {
|
|
8222
8211
|
const line = sourceLines[i];
|
|
@@ -8544,8 +8533,7 @@ const detectNarrativeComments = async (context) => {
|
|
|
8544
8533
|
} catch {
|
|
8545
8534
|
continue;
|
|
8546
8535
|
}
|
|
8547
|
-
const
|
|
8548
|
-
const blocks = collectBlocks(lines, syntax, content, ext);
|
|
8536
|
+
const blocks = collectBlocks(content.split("\n"), syntax, content, ext);
|
|
8549
8537
|
for (const block of blocks) {
|
|
8550
8538
|
const { matched, reason } = detectNarrativeInBlock(block, ext);
|
|
8551
8539
|
if (!matched) continue;
|
|
@@ -10487,8 +10475,7 @@ const checkFunctionDiagnostics = (relativePath, fn, limits, ext) => {
|
|
|
10487
10475
|
const results = [];
|
|
10488
10476
|
const multiplier = functionLocMultiplier(fn, ext);
|
|
10489
10477
|
const fnMax = functionLocBudget(fn, ext, limits.maxFunctionLoc);
|
|
10490
|
-
|
|
10491
|
-
if (exceedsLimit(effectiveLineCount, limits.maxFunctionLoc, multiplier)) results.push({
|
|
10478
|
+
if (exceedsLimit(fn.lineCount - fn.templateLines, limits.maxFunctionLoc, multiplier)) results.push({
|
|
10492
10479
|
filePath: relativePath,
|
|
10493
10480
|
engine: "code-quality",
|
|
10494
10481
|
rule: "complexity/function-too-long",
|
|
@@ -10585,7 +10572,7 @@ const isLowSignalMarkupWindow = (lines) => {
|
|
|
10585
10572
|
return lines.filter((line) => SVG_MARKUP_RE.test(line)).length >= Math.ceil(WINDOW_SIZE / 2);
|
|
10586
10573
|
};
|
|
10587
10574
|
const isLowSignalDataWindow = (lines) => {
|
|
10588
|
-
return lines.filter((line) => DATA_LITERAL_RE.test(line)).length >=
|
|
10575
|
+
return lines.filter((line) => DATA_LITERAL_RE.test(line)).length >= WINDOW_SIZE - 1;
|
|
10589
10576
|
};
|
|
10590
10577
|
const findSuppressedLines = (lines) => {
|
|
10591
10578
|
const suppressed = /* @__PURE__ */ new Set();
|
|
@@ -10617,7 +10604,7 @@ const collectMeaningfulLines = (content) => {
|
|
|
10617
10604
|
if (isLowSignalDataWindow(window)) continue;
|
|
10618
10605
|
if (window.every(isTrivialLine)) continue;
|
|
10619
10606
|
const normalised = window.map(normaliseLine);
|
|
10620
|
-
if (normalised.filter((n) => n.length > 0 && n !== "}" && n !== "{").length <
|
|
10607
|
+
if (normalised.filter((n) => n.length > 0 && n !== "}" && n !== "{").length < WINDOW_SIZE - 1) continue;
|
|
10621
10608
|
if (new Set(normalised).size < MIN_DISTINCT_LINES) continue;
|
|
10622
10609
|
hits.push({
|
|
10623
10610
|
startLine: i + 1,
|
|
@@ -11392,7 +11379,7 @@ const fixClangFormat = async (context) => {
|
|
|
11392
11379
|
};
|
|
11393
11380
|
//#endregion
|
|
11394
11381
|
//#region src/engines/format/dotnet-format.ts
|
|
11395
|
-
const REPORT_FILENAME = ".
|
|
11382
|
+
const REPORT_FILENAME = ".raigal-dotnet-format.json";
|
|
11396
11383
|
const parseDotnetFormatReport = (json, rootDirectory) => {
|
|
11397
11384
|
if (!json) return [];
|
|
11398
11385
|
let report;
|
|
@@ -11763,8 +11750,7 @@ const parseRuffFormatOutput = (output, rootDir) => {
|
|
|
11763
11750
|
const fixRuffFormat = async (context) => {
|
|
11764
11751
|
const targets = context.files ? getPythonTargets(context) : [context.rootDirectory];
|
|
11765
11752
|
if (context.files && targets.length === 0) return;
|
|
11766
|
-
const
|
|
11767
|
-
const result = await runSubprocess(ruffBinary, ["format", ...targets], {
|
|
11753
|
+
const result = await runSubprocess(resolveToolBinary("ruff"), ["format", ...targets], {
|
|
11768
11754
|
cwd: context.rootDirectory,
|
|
11769
11755
|
timeout: 6e4
|
|
11770
11756
|
});
|
|
@@ -11834,8 +11820,7 @@ const parseClangTidyOutput = (output, rootDirectory) => {
|
|
|
11834
11820
|
const runClangTidy = async (context) => {
|
|
11835
11821
|
const compileCommandsDir = findCompileCommandsDir(context);
|
|
11836
11822
|
if (!compileCommandsDir) return [];
|
|
11837
|
-
const
|
|
11838
|
-
const sources = filterSourcesInDatabase(implSources, readCompileCommandsFiles(compileCommandsDir));
|
|
11823
|
+
const sources = filterSourcesInDatabase(findCppSources(context).filter((f) => CPP_IMPL_EXTENSIONS.has(path.extname(f).toLowerCase())), readCompileCommandsFiles(compileCommandsDir));
|
|
11839
11824
|
if (sources.length === 0) return [];
|
|
11840
11825
|
const diagnostics = [];
|
|
11841
11826
|
for (const chunk of chunkFilePaths(sources, CLANG_TIDY_CHUNK_MAX_FILES)) try {
|
|
@@ -12671,8 +12656,7 @@ const processFile = (filePath, fileTargets, result) => {
|
|
|
12671
12656
|
});
|
|
12672
12657
|
continue;
|
|
12673
12658
|
}
|
|
12674
|
-
const
|
|
12675
|
-
const { edit, skipReason } = computeEdit(sourceFile, shape);
|
|
12659
|
+
const { edit, skipReason } = computeEdit(sourceFile, classifyIdentifier(best));
|
|
12676
12660
|
if (!edit) {
|
|
12677
12661
|
pendingSkips.push({
|
|
12678
12662
|
target,
|
|
@@ -13487,8 +13471,7 @@ const ruffLintFixArgs = (context, unsafe) => {
|
|
|
13487
13471
|
};
|
|
13488
13472
|
const fixRuffLint = async (context) => {
|
|
13489
13473
|
if (context.files && getPythonTargets(context).length === 0) return;
|
|
13490
|
-
const
|
|
13491
|
-
const result = await runSubprocess(ruffBinary, ruffLintFixArgs(context, false), {
|
|
13474
|
+
const result = await runSubprocess(resolveToolBinary("ruff"), ruffLintFixArgs(context, false), {
|
|
13492
13475
|
cwd: context.rootDirectory,
|
|
13493
13476
|
timeout: 6e4
|
|
13494
13477
|
});
|
|
@@ -13496,8 +13479,7 @@ const fixRuffLint = async (context) => {
|
|
|
13496
13479
|
};
|
|
13497
13480
|
const fixRuffLintForce = async (context) => {
|
|
13498
13481
|
if (context.files && getPythonTargets(context).length === 0) return;
|
|
13499
|
-
const
|
|
13500
|
-
const result = await runSubprocess(ruffBinary, ruffLintFixArgs(context, true), {
|
|
13482
|
+
const result = await runSubprocess(resolveToolBinary("ruff"), ruffLintFixArgs(context, true), {
|
|
13501
13483
|
cwd: context.rootDirectory,
|
|
13502
13484
|
timeout: 6e4
|
|
13503
13485
|
});
|
|
@@ -14307,11 +14289,10 @@ const auditSkippedDiagnostic = (source, help) => ({
|
|
|
14307
14289
|
});
|
|
14308
14290
|
const runNpmAudit = async (rootDir, timeout) => {
|
|
14309
14291
|
try {
|
|
14310
|
-
|
|
14292
|
+
return parseJsAudit((await runSubprocess("npm", ["audit", "--json"], {
|
|
14311
14293
|
cwd: rootDir,
|
|
14312
14294
|
timeout
|
|
14313
|
-
});
|
|
14314
|
-
return parseJsAudit(result.stdout, "npm audit", readRuntimeDependencies(rootDir));
|
|
14295
|
+
})).stdout, "npm audit", readRuntimeDependencies(rootDir));
|
|
14315
14296
|
} catch (error) {
|
|
14316
14297
|
return [auditSkippedDiagnostic("npm audit", `Failed to run npm audit: ${errorMessageOf(error)}`)];
|
|
14317
14298
|
}
|
|
@@ -14332,11 +14313,10 @@ const runBunAudit = async (rootDir, timeout) => {
|
|
|
14332
14313
|
const runPnpmAuditWithFallback = async (rootDir, timeout) => {
|
|
14333
14314
|
const canFallbackToNpm = fs.existsSync(path.join(rootDir, "package-lock.json"));
|
|
14334
14315
|
try {
|
|
14335
|
-
const
|
|
14316
|
+
const diagnostics = parseJsAudit((await runSubprocess("pnpm", ["audit", "--json"], {
|
|
14336
14317
|
cwd: rootDir,
|
|
14337
14318
|
timeout
|
|
14338
|
-
});
|
|
14339
|
-
const diagnostics = parseJsAudit(result.stdout, "pnpm audit", readRuntimeDependencies(rootDir));
|
|
14319
|
+
})).stdout, "pnpm audit", readRuntimeDependencies(rootDir));
|
|
14340
14320
|
if (diagnostics.some((d) => d.rule === "security/dependency-audit-skipped")) {
|
|
14341
14321
|
if (canFallbackToNpm) return runNpmAudit(rootDir, timeout);
|
|
14342
14322
|
return diagnostics;
|
|
@@ -15070,10 +15050,7 @@ const runEngines = async (context, enabledEngines, onStart, onComplete) => {
|
|
|
15070
15050
|
failed: true,
|
|
15071
15051
|
skipReason: r.reason instanceof Error ? r.reason.message : String(r.reason)
|
|
15072
15052
|
});
|
|
15073
|
-
|
|
15074
|
-
const csharp = dedupeCSharpAsync(stripped);
|
|
15075
|
-
const comments = dedupeOverlappingComments(csharp);
|
|
15076
|
-
return dedupeEquivalenceDiagnostics(comments);
|
|
15053
|
+
return dedupeEquivalenceDiagnostics(dedupeOverlappingComments(dedupeCSharpAsync(stripSecretDiagnostics(finalResults))));
|
|
15077
15054
|
};
|
|
15078
15055
|
const stripSecretDiagnostics = (results) => {
|
|
15079
15056
|
for (const result of results) for (const d of result.diagnostics) if (d.redactSource || isSecretClassRule(d.rule)) {
|
|
@@ -15122,8 +15099,7 @@ const calculateScore = (diagnostics, weights, thresholds, sourceFileCount, smoot
|
|
|
15122
15099
|
const capScale = Math.max(1, fileCount.effectiveSourceFileCount / CAP_REFERENCE_FILES);
|
|
15123
15100
|
const defaultRuleCap = typeof maxPerRule === "number" && maxPerRule > 0 ? maxPerRule : null;
|
|
15124
15101
|
const capForRule = (key) => {
|
|
15125
|
-
const
|
|
15126
|
-
const ruleCap = scoreImpactForRule(rule).cap;
|
|
15102
|
+
const ruleCap = scoreImpactForRule(key.slice(key.indexOf(":") + 1)).cap;
|
|
15127
15103
|
if (typeof ruleCap === "number") return defaultRuleCap ? Math.min(defaultRuleCap, ruleCap) : ruleCap;
|
|
15128
15104
|
return defaultRuleCap;
|
|
15129
15105
|
};
|
|
@@ -15407,11 +15383,10 @@ const track = (input) => {
|
|
|
15407
15383
|
cachedInstallId = ensured.installId;
|
|
15408
15384
|
installCreated = ensured.created;
|
|
15409
15385
|
}
|
|
15410
|
-
const
|
|
15386
|
+
const { clean, dropped } = redactProperties({
|
|
15411
15387
|
...baseProperties(cachedInstallId),
|
|
15412
15388
|
...input.properties
|
|
15413
|
-
};
|
|
15414
|
-
const { clean, dropped } = redactProperties(merged);
|
|
15389
|
+
});
|
|
15415
15390
|
if (isDebug()) {
|
|
15416
15391
|
const compact = JSON.stringify({
|
|
15417
15392
|
event: input.event,
|
|
@@ -15691,17 +15666,14 @@ const renderRailStep = (step, deps = {}) => {
|
|
|
15691
15666
|
* between the last step and the footer.
|
|
15692
15667
|
*/
|
|
15693
15668
|
const renderRailConnector = (deps = {}) => {
|
|
15694
|
-
|
|
15695
|
-
const s = deps.symbols ?? symbols;
|
|
15696
|
-
return ` ${style(t, "accentDim", s.rail)}\n`;
|
|
15669
|
+
return ` ${style(deps.theme ?? theme, "accentDim", (deps.symbols ?? symbols).rail)}\n`;
|
|
15697
15670
|
};
|
|
15698
15671
|
/**
|
|
15699
15672
|
* Render the rail-end footer line ("└ <footer text>").
|
|
15700
15673
|
*/
|
|
15701
15674
|
const renderRailFooter = (footer, deps = {}) => {
|
|
15702
15675
|
const t = deps.theme ?? theme;
|
|
15703
|
-
|
|
15704
|
-
return ` ${style(t, "accentDim", s.railEnd)} ${highlightAislop(footer, t)}\n`;
|
|
15676
|
+
return ` ${style(t, "accentDim", (deps.symbols ?? symbols).railEnd)} ${highlightAislop(footer, t)}\n`;
|
|
15705
15677
|
};
|
|
15706
15678
|
const renderRail = (input, deps = {}) => {
|
|
15707
15679
|
const t = deps.theme ?? theme;
|
|
@@ -15828,8 +15800,7 @@ var LiveRail = class {
|
|
|
15828
15800
|
*/
|
|
15829
15801
|
const renderHintLine = (hint, deps = {}) => {
|
|
15830
15802
|
const t = deps.theme ?? theme;
|
|
15831
|
-
|
|
15832
|
-
return ` ${style(t, "accent", s.hint)} ${highlightAislop(maskSecrets(hint), t)}\n`;
|
|
15803
|
+
return ` ${style(t, "accent", (deps.symbols ?? symbols).hint)} ${highlightAislop(maskSecrets(hint), t)}\n`;
|
|
15833
15804
|
};
|
|
15834
15805
|
const createLogger = (deps = {}) => {
|
|
15835
15806
|
const t = deps.theme ?? theme;
|
|
@@ -15974,8 +15945,7 @@ const groupByFile = (diagnostics) => {
|
|
|
15974
15945
|
});
|
|
15975
15946
|
};
|
|
15976
15947
|
const isInstalled = (bin) => {
|
|
15977
|
-
|
|
15978
|
-
return spawnSync(cmd, [bin], { encoding: "utf-8" }).status === 0;
|
|
15948
|
+
return spawnSync(process.platform === "win32" ? "where" : "which", [bin], { encoding: "utf-8" }).status === 0;
|
|
15979
15949
|
};
|
|
15980
15950
|
const copyToClipboard = (text) => {
|
|
15981
15951
|
const args = {
|
|
@@ -16458,9 +16428,7 @@ const verifyEntitlementJwt = (jwt, options = {}) => {
|
|
|
16458
16428
|
if (!header.kid) throw new JwtVerificationError("JWT header missing 'kid'", "unknown_kid");
|
|
16459
16429
|
const publicKey = getPublicKey(header.kid);
|
|
16460
16430
|
if (!publicKey) throw new JwtVerificationError(`Unknown or untrusted signing key id (kid: ${header.kid})`, "unknown_kid");
|
|
16461
|
-
|
|
16462
|
-
const signature = Buffer.from(signatureB64, "base64url");
|
|
16463
|
-
if (!verify(null, signedData, publicKey, signature)) throw new JwtVerificationError("Invalid JWT cryptographic signature", "invalid_signature");
|
|
16431
|
+
if (!verify(null, Buffer.from(`${headerB64}.${payloadB64}`, "utf-8"), publicKey, Buffer.from(signatureB64, "base64url"))) throw new JwtVerificationError("Invalid JWT cryptographic signature", "invalid_signature");
|
|
16464
16432
|
let rawPayload;
|
|
16465
16433
|
try {
|
|
16466
16434
|
rawPayload = JSON.parse(Buffer.from(payloadB64, "base64url").toString("utf-8"));
|
|
@@ -16472,7 +16440,7 @@ const verifyEntitlementJwt = (jwt, options = {}) => {
|
|
|
16472
16440
|
const claims = parsed.data;
|
|
16473
16441
|
const expectedIssuer = process.env.RAIGAL_ISSUER?.trim() || "https://app.raigal.dev";
|
|
16474
16442
|
if (claims.iss !== expectedIssuer) throw new JwtVerificationError(`Untrusted issuer: ${claims.iss}`, "invalid_issuer");
|
|
16475
|
-
if (!isVersionAtLeast("0.2.
|
|
16443
|
+
if (!isVersionAtLeast("0.2.5", claims.min_cli_version)) throw new JwtVerificationError(`CLI version ${APP_VERSION} is below required minimum ${claims.min_cli_version}. Run "raigal update" or "npm install -g @methiu/raigal@latest".`, "cli_version_unsupported");
|
|
16476
16444
|
const now = options.nowSeconds ?? Math.floor(Date.now() / 1e3);
|
|
16477
16445
|
const grace = options.allowGraceSeconds ?? 0;
|
|
16478
16446
|
if (now > claims.exp + grace) {
|
|
@@ -16506,7 +16474,7 @@ const fetchGitHubOidcToken = async () => {
|
|
|
16506
16474
|
};
|
|
16507
16475
|
//#endregion
|
|
16508
16476
|
//#region src/cloud/entitlement.ts
|
|
16509
|
-
const GRACE_PERIOD_SECONDS =
|
|
16477
|
+
const GRACE_PERIOD_SECONDS = 4320 * 60;
|
|
16510
16478
|
var MissingCredentialError = class extends Error {
|
|
16511
16479
|
constructor(message = "No organization credential found") {
|
|
16512
16480
|
super(message);
|
|
@@ -16631,8 +16599,7 @@ const getEntitlement = async () => {
|
|
|
16631
16599
|
}
|
|
16632
16600
|
} else oidcToken = await fetchGitHubOidcToken();
|
|
16633
16601
|
try {
|
|
16634
|
-
const
|
|
16635
|
-
const response = await fetchEntitlementFromApi(tokenToPass, oidcToken);
|
|
16602
|
+
const response = await fetchEntitlementFromApi(activeToken?.token ?? "", oidcToken);
|
|
16636
16603
|
const claims = verifyEntitlementJwt(response.entitlement, { nowSeconds: now });
|
|
16637
16604
|
saveCachedEntitlement(response.entitlement, response.refresh_after);
|
|
16638
16605
|
return {
|
|
@@ -17175,8 +17142,7 @@ const fixNarrativeComments = async (context) => {
|
|
|
17175
17142
|
for (let i = 0; i < lines.length; i += 1) if (!toRemove.has(i + 1)) kept.push(lines[i]);
|
|
17176
17143
|
const newContent = kept.join("\n");
|
|
17177
17144
|
if (newContent !== content) {
|
|
17178
|
-
|
|
17179
|
-
if (!areLiteralMultisetsEqual(beforeLiterals, afterLiterals)) continue;
|
|
17145
|
+
if (!areLiteralMultisetsEqual(beforeLiterals, extractStringAndTemplateLiterals(newContent, ext))) continue;
|
|
17180
17146
|
fs.writeFileSync(filePath, newContent);
|
|
17181
17147
|
}
|
|
17182
17148
|
}
|
|
@@ -17670,7 +17636,7 @@ const removeUnusedDeclarations = (rootDirectory, declarations) => {
|
|
|
17670
17636
|
};
|
|
17671
17637
|
//#endregion
|
|
17672
17638
|
//#region src/commands/fix-expo.ts
|
|
17673
|
-
const INSTALL_TIMEOUT$1 =
|
|
17639
|
+
const INSTALL_TIMEOUT$1 = 1800 * 1e3;
|
|
17674
17640
|
const fixExpoDependencies = async (context, onProgress) => {
|
|
17675
17641
|
await removeDisallowedExpoPackages(context.rootDirectory, onProgress);
|
|
17676
17642
|
onProgress?.("Expo dependency alignment · running expo install --fix (can take a few minutes)");
|
|
@@ -17724,8 +17690,8 @@ const removeDisallowedExpoPackages = async (rootDir, onProgress) => {
|
|
|
17724
17690
|
};
|
|
17725
17691
|
//#endregion
|
|
17726
17692
|
//#region src/commands/fix-force.ts
|
|
17727
|
-
const INSTALL_TIMEOUT =
|
|
17728
|
-
const AUDIT_TIMEOUT =
|
|
17693
|
+
const INSTALL_TIMEOUT = 1800 * 1e3;
|
|
17694
|
+
const AUDIT_TIMEOUT = 60 * 1e3;
|
|
17729
17695
|
const detectPackageManager = (rootDirectory) => {
|
|
17730
17696
|
if (fs.existsSync(path.join(rootDirectory, "pnpm-lock.yaml"))) return "pnpm";
|
|
17731
17697
|
if (fs.existsSync(path.join(rootDirectory, "package-lock.json")) || fs.existsSync(path.join(rootDirectory, "package.json"))) return "npm";
|
|
@@ -18044,14 +18010,13 @@ const CANNOT_SCOPE_REASON = "cannot honour an explicit file list under --changes
|
|
|
18044
18010
|
const MISSING_MANIFEST_REASON = "no manifest or lockfile in the selected scope";
|
|
18045
18011
|
const fixScopeError = (resolvedDir, flags) => {
|
|
18046
18012
|
if (flags.changes && flags.staged) return "--changes and --staged cannot be used together.";
|
|
18047
|
-
|
|
18013
|
+
return scanTargetError(resolvedDir, {
|
|
18048
18014
|
changes: Boolean(flags.changes),
|
|
18049
18015
|
staged: Boolean(flags.staged),
|
|
18050
18016
|
base: flags.base,
|
|
18051
18017
|
verbose: false,
|
|
18052
18018
|
json: false
|
|
18053
|
-
};
|
|
18054
|
-
return scanTargetError(resolvedDir, options);
|
|
18019
|
+
});
|
|
18055
18020
|
};
|
|
18056
18021
|
const collectFixFileScope = (rootDirectory, excludePatterns, includePatterns, flags) => {
|
|
18057
18022
|
const mode = resolveScanScopeMode({
|
|
@@ -18110,10 +18075,9 @@ const runFormattingStep = async (deps) => {
|
|
|
18110
18075
|
else if (deps.projectInfo.languages.includes("python")) log.warn("Python detected but ruff is not installed; skipping Python formatting fixes.");
|
|
18111
18076
|
if (deps.projectInfo.languages.includes("go") && deps.projectInfo.installedTools.gofmt) await deps.runStep("Formatting (go)", () => runGofmt(deps.context), () => fixGofmt(deps.context));
|
|
18112
18077
|
else if (deps.projectInfo.languages.includes("go")) log.warn("Go detected but gofmt is not installed; skipping Go formatting fixes.");
|
|
18113
|
-
if (deps.projectInfo.languages.includes("rust") && deps.projectInfo.installedTools.rustfmt)
|
|
18114
|
-
|
|
18115
|
-
|
|
18116
|
-
} else if (deps.projectInfo.languages.includes("rust")) log.warn("Rust detected but rustfmt is not installed; skipping Rust formatting fixes.");
|
|
18078
|
+
if (deps.projectInfo.languages.includes("rust") && deps.projectInfo.installedTools.rustfmt) if (isScopedFix(deps.context)) deps.skipStep?.("Formatting (rust)", CANNOT_SCOPE_REASON);
|
|
18079
|
+
else await deps.runStep("Formatting (rust)", () => runGenericFormatter(deps.context, "rust"), () => fixGenericFormatter(deps.context, "rust"));
|
|
18080
|
+
else if (deps.projectInfo.languages.includes("rust")) log.warn("Rust detected but rustfmt is not installed; skipping Rust formatting fixes.");
|
|
18117
18081
|
if (deps.projectInfo.languages.includes("ruby") && deps.projectInfo.installedTools.rubocop) {
|
|
18118
18082
|
if (!skipUnsafeSafeFormatter(deps, "ruby")) await deps.runStep("Formatting (ruby)", () => runGenericFormatter(deps.context, "ruby"), () => fixGenericFormatter(deps.context, "ruby"));
|
|
18119
18083
|
} else if (deps.projectInfo.languages.includes("ruby")) log.warn("Ruby detected but rubocop is not installed; skipping Ruby formatting fixes.");
|
|
@@ -18162,8 +18126,7 @@ const runDeclarationStep = async (deps) => {
|
|
|
18162
18126
|
if (!deps.config.engines["code-quality"]) return;
|
|
18163
18127
|
if (!hasJsOrTs(deps.projectInfo)) return;
|
|
18164
18128
|
await deps.runStep("Unused declarations", () => detectUnusedDeclarations(deps.context), async () => {
|
|
18165
|
-
const
|
|
18166
|
-
const declarations = diagnosticsToDeclarations(diagnostics);
|
|
18129
|
+
const declarations = diagnosticsToDeclarations(await detectUnusedDeclarations(deps.context));
|
|
18167
18130
|
removeUnusedDeclarations(deps.resolvedDir, declarations);
|
|
18168
18131
|
});
|
|
18169
18132
|
};
|
|
@@ -18194,14 +18157,10 @@ const runForceSteps = async (deps) => {
|
|
|
18194
18157
|
return (await runKnipUnusedFiles(deps.resolvedDir)).filter((diagnostic) => isPathInFixScope(deps.context, diagnostic.filePath));
|
|
18195
18158
|
}, () => fixUnusedFiles(deps.resolvedDir, (filePath) => isPathInFixScope(deps.context, filePath)));
|
|
18196
18159
|
const railUpdate = (label) => deps.rail.setActiveLabel(label);
|
|
18197
|
-
if (deps.config.engines.security)
|
|
18198
|
-
|
|
18199
|
-
|
|
18200
|
-
|
|
18201
|
-
if (deps.projectInfo.frameworks.includes("expo") && deps.config.lint.expoDoctor) {
|
|
18202
|
-
if (!scopeIncludesManifestWrites(deps.context)) deps.skipStep?.("Expo dependency alignment", MISSING_MANIFEST_REASON);
|
|
18203
|
-
else await deps.runStep("Expo dependency alignment", () => runExpoDoctor(deps.context), () => fixExpoDependencies(deps.context, railUpdate));
|
|
18204
|
-
}
|
|
18160
|
+
if (deps.config.engines.security) if (!scopeIncludesManifestWrites(deps.context)) deps.skipStep?.("Dependency audit fixes", MISSING_MANIFEST_REASON);
|
|
18161
|
+
else await deps.runStep("Dependency audit fixes", () => runDependencyAudit(deps.context), () => fixDependencyAudit(deps.context, railUpdate));
|
|
18162
|
+
if (deps.projectInfo.frameworks.includes("expo") && deps.config.lint.expoDoctor) if (!scopeIncludesManifestWrites(deps.context)) deps.skipStep?.("Expo dependency alignment", MISSING_MANIFEST_REASON);
|
|
18163
|
+
else await deps.runStep("Expo dependency alignment", () => runExpoDoctor(deps.context), () => fixExpoDependencies(deps.context, railUpdate));
|
|
18205
18164
|
};
|
|
18206
18165
|
//#endregion
|
|
18207
18166
|
//#region src/commands/fix-plan.ts
|
|
@@ -18523,8 +18482,7 @@ const saveCachedPolicy = (repoSlug, policy) => {
|
|
|
18523
18482
|
};
|
|
18524
18483
|
const fetchRemotePolicy = async (repoSlug, token) => {
|
|
18525
18484
|
try {
|
|
18526
|
-
const
|
|
18527
|
-
const data = await requestApi(endpoint, {
|
|
18485
|
+
const data = await requestApi(`/v1/policy?repo=${encodeURIComponent(repoSlug.toLowerCase())}`, {
|
|
18528
18486
|
method: "GET",
|
|
18529
18487
|
token,
|
|
18530
18488
|
timeoutMs: 4e3
|
|
@@ -18714,8 +18672,8 @@ A PostToolUse hook runs \`raigal hook claude\` after every Edit, Write, or Multi
|
|
|
18714
18672
|
|
|
18715
18673
|
## Rules
|
|
18716
18674
|
|
|
18717
|
-
- \`.raigal/config.yaml\`
|
|
18718
|
-
- \`.raigal/rules.yaml\`
|
|
18675
|
+
- \`.raigal/config.yaml\` - thresholds and engine toggles. Treat as authoritative; don't edit without user consent.
|
|
18676
|
+
- \`.raigal/rules.yaml\` - project-specific architecture rules (may be absent). When a finding cites \`architecture/*\`, open this file and follow it.
|
|
18719
18677
|
- Custom rules can change between sessions. Trust what the scan returns, not a cached understanding of what the rules are.
|
|
18720
18678
|
|
|
18721
18679
|
## Principles
|
|
@@ -18730,7 +18688,7 @@ const atomicWrite = (targetPath, content) => {
|
|
|
18730
18688
|
const dir = path.dirname(targetPath);
|
|
18731
18689
|
fs.mkdirSync(dir, { recursive: true });
|
|
18732
18690
|
const rand = Math.random().toString(36).slice(2, 10);
|
|
18733
|
-
const tmp = path.join(dir, `.
|
|
18691
|
+
const tmp = path.join(dir, `.raigal-tmp-${process.pid}-${rand}`);
|
|
18734
18692
|
fs.writeFileSync(tmp, content, "utf-8");
|
|
18735
18693
|
try {
|
|
18736
18694
|
fs.renameSync(tmp, targetPath);
|
|
@@ -18824,9 +18782,7 @@ const applyRemoval = (result, opts, target, nextContent) => {
|
|
|
18824
18782
|
//#region src/hooks/install/rules-only.ts
|
|
18825
18783
|
const installRulesOnly = (opts, paths, summary) => {
|
|
18826
18784
|
const result = emptyResult();
|
|
18827
|
-
const
|
|
18828
|
-
const hash = sentinelHash(AISLOP_MD_BODY);
|
|
18829
|
-
const next = upsertMarkdownFence(existing, AISLOP_MD_BODY, hash).nextContent;
|
|
18785
|
+
const next = upsertMarkdownFence(readIfExists(paths.rules), AISLOP_MD_BODY, sentinelHash(AISLOP_MD_BODY)).nextContent;
|
|
18830
18786
|
applyContent(result, opts, paths.rules, next, summary);
|
|
18831
18787
|
if (paths.host && paths.marker) {
|
|
18832
18788
|
const host = readIfExists(paths.host) ?? "";
|
|
@@ -19002,8 +18958,7 @@ const installClaude = (opts) => {
|
|
|
19002
18958
|
const nextSettings = renderSettings$1(readIfExists(paths.settings), Boolean(opts.qualityGate));
|
|
19003
18959
|
applyContent(result, opts, paths.settings, nextSettings, "register PostToolUse + FileChanged hooks");
|
|
19004
18960
|
const mdHash = sentinelHash(AISLOP_MD_BODY);
|
|
19005
|
-
const
|
|
19006
|
-
const fenced = upsertMarkdownFence(existingMd, AISLOP_MD_BODY, mdHash);
|
|
18961
|
+
const fenced = upsertMarkdownFence(readIfExists(paths.aislopMd), AISLOP_MD_BODY, mdHash);
|
|
19007
18962
|
applyContent(result, opts, paths.aislopMd, fenced.nextContent, "write AISLOP.md rules");
|
|
19008
18963
|
const existingClaudeMd = readIfExists(paths.claudeMd) ?? "";
|
|
19009
18964
|
const marker = "@AISLOP.md";
|
|
@@ -19149,9 +19104,7 @@ const installCursor = (opts) => {
|
|
|
19149
19104
|
const nextHooks = renderHooksJson(readIfExists(paths.hooks));
|
|
19150
19105
|
applyContent(result, opts, paths.hooks, nextHooks, "register afterFileEdit hook");
|
|
19151
19106
|
if (opts.scope === "project") {
|
|
19152
|
-
const
|
|
19153
|
-
const hash = sentinelHash(AISLOP_MD_BODY);
|
|
19154
|
-
const rules = upsertMarkdownFence(existingRules, AISLOP_MD_BODY, hash).nextContent;
|
|
19107
|
+
const rules = upsertMarkdownFence(readIfExists(paths.rules), AISLOP_MD_BODY, sentinelHash(AISLOP_MD_BODY)).nextContent;
|
|
19155
19108
|
applyContent(result, opts, paths.rules, rules, "write .cursor/rules/aislop.mdc");
|
|
19156
19109
|
}
|
|
19157
19110
|
return result;
|
|
@@ -19224,9 +19177,7 @@ const installGemini = (opts) => {
|
|
|
19224
19177
|
const result = emptyResult();
|
|
19225
19178
|
const next = renderSettings(readIfExists(paths.settings));
|
|
19226
19179
|
applyContent(result, opts, paths.settings, next, "register AfterTool hook");
|
|
19227
|
-
const
|
|
19228
|
-
const hash = sentinelHash(AISLOP_MD_BODY);
|
|
19229
|
-
const fenced = upsertMarkdownFence(existingMd, AISLOP_MD_BODY, hash).nextContent;
|
|
19180
|
+
const fenced = upsertMarkdownFence(readIfExists(paths.aislopMd), AISLOP_MD_BODY, sentinelHash(AISLOP_MD_BODY)).nextContent;
|
|
19230
19181
|
applyContent(result, opts, paths.aislopMd, fenced, "write AISLOP.md rules");
|
|
19231
19182
|
const existingGeminiMd = readIfExists(paths.geminiMd) ?? "";
|
|
19232
19183
|
const marker = "@AISLOP.md";
|
|
@@ -20172,8 +20123,7 @@ const renderActionRows = (steps, t) => {
|
|
|
20172
20123
|
const renderTextSteps = (steps, t, s) => {
|
|
20173
20124
|
return steps.filter((step) => step.text).map((step) => {
|
|
20174
20125
|
const glyph = step.emphasis === "primary" ? s.hint : s.bullet;
|
|
20175
|
-
|
|
20176
|
-
return ` ${style(t, tokenFor, glyph)} ${highlightAislop(step.text ?? "", t)}`;
|
|
20126
|
+
return ` ${style(t, step.emphasis === "primary" ? "accent" : "muted", glyph)} ${highlightAislop(step.text ?? "", t)}`;
|
|
20177
20127
|
});
|
|
20178
20128
|
};
|
|
20179
20129
|
const renderSummary = (input, deps = {}) => {
|
|
@@ -20230,14 +20180,10 @@ const renderSummary = (input, deps = {}) => {
|
|
|
20230
20180
|
return lines.join("\n");
|
|
20231
20181
|
};
|
|
20232
20182
|
const renderStarCta = (deps = {}) => {
|
|
20233
|
-
|
|
20234
|
-
const repository = terminalLink("https://raigal.dev");
|
|
20235
|
-
return `\n ${style(t, "muted", `★ Found this useful? Consider purchasing this software at ${repository}`)}\n`;
|
|
20183
|
+
return `\n ${style(deps.theme ?? theme, "muted", `★ Found this useful? Consider purchasing this software at ${terminalLink("https://raigal.dev")}`)}\n`;
|
|
20236
20184
|
};
|
|
20237
20185
|
const renderTeamCta = (deps = {}) => {
|
|
20238
|
-
|
|
20239
|
-
const href = terminalLink("https://raigal.dev/contact?intent=team-baseline");
|
|
20240
|
-
return `\n ${style(t, "muted", `→ Using raigal with a team? Get a 14-day team baseline at ${href}`)}\n`;
|
|
20186
|
+
return `\n ${style(deps.theme ?? theme, "muted", `→ Using raigal with a team? Get a 14-day team baseline at ${terminalLink("https://raigal.dev/contact?intent=team-baseline")}`)}\n`;
|
|
20241
20187
|
};
|
|
20242
20188
|
const renderCleanRun = (input, deps = {}) => {
|
|
20243
20189
|
const t = deps.theme ?? theme;
|
|
@@ -20463,7 +20409,7 @@ const runScanBody = async (resolvedDir, config, options, projectInfo, scanScope,
|
|
|
20463
20409
|
architectureRulesPath: config.engines.architecture ? rulesPath : void 0,
|
|
20464
20410
|
engines: config.engines
|
|
20465
20411
|
};
|
|
20466
|
-
const
|
|
20412
|
+
const { results: unannotated, suppressedCount } = applySuppressions((await runEnginesWithProgress({
|
|
20467
20413
|
rootDirectory: resolvedDir,
|
|
20468
20414
|
languages: projectInfo.languages,
|
|
20469
20415
|
frameworks: projectInfo.frameworks,
|
|
@@ -20479,8 +20425,7 @@ const runScanBody = async (resolvedDir, config, options, projectInfo, scanScope,
|
|
|
20479
20425
|
}, config.engines, machineOutput)).map((result) => ({
|
|
20480
20426
|
...result,
|
|
20481
20427
|
diagnostics: config.overrides.length ? result.diagnostics : applyRuleSeverities(result.diagnostics, config.rules)
|
|
20482
|
-
}));
|
|
20483
|
-
const { results: unannotated, suppressedCount } = applySuppressions(severityAdjusted, resolvedDir);
|
|
20428
|
+
})), resolvedDir);
|
|
20484
20429
|
if (suppressedCount > 0 && !machineOutput) log.muted(`Suppressed ${suppressedCount} finding(s) via raigal-ignore directives`);
|
|
20485
20430
|
const changeMap = options.changes && !options.staged ? getChangedLineMap(resolvedDir, options.base) : null;
|
|
20486
20431
|
const results = changeMap ? unannotated.map((result) => ({
|
|
@@ -20541,12 +20486,12 @@ const runScanBody = async (resolvedDir, config, options, projectInfo, scanScope,
|
|
|
20541
20486
|
scoreFileCount
|
|
20542
20487
|
});
|
|
20543
20488
|
if (options.sarif) {
|
|
20544
|
-
const { buildSarifLog } = await import("./sarif-
|
|
20489
|
+
const { buildSarifLog } = await import("./sarif-DqH4dGEo.js");
|
|
20545
20490
|
console.log(JSON.stringify(buildSarifLog(results), null, 2));
|
|
20546
20491
|
return completion;
|
|
20547
20492
|
}
|
|
20548
20493
|
if (options.json) {
|
|
20549
|
-
const { buildJsonOutput } = await import("./json-
|
|
20494
|
+
const { buildJsonOutput } = await import("./json-B8XGYwMv.js");
|
|
20550
20495
|
const jsonOut = buildJsonOutput(results, scoreResult, scoreFileCount, elapsedMs, scanCoverage);
|
|
20551
20496
|
console.log(JSON.stringify(jsonOut, null, 2));
|
|
20552
20497
|
return completion;
|
|
@@ -20700,8 +20645,7 @@ const runFixBody = async (resolvedDir, config, options, projectInfo) => {
|
|
|
20700
20645
|
brand: options.printBrand !== false
|
|
20701
20646
|
}));
|
|
20702
20647
|
const safe = Boolean(options.safe);
|
|
20703
|
-
const
|
|
20704
|
-
const scope = collectFixFileScope(resolvedDir, excludePatterns, config.include, options);
|
|
20648
|
+
const scope = collectFixFileScope(resolvedDir, [...config.exclude, ...readAislopIgnorePatterns(resolvedDir)], config.include, options);
|
|
20705
20649
|
const scopedProjectInfo = scope ? {
|
|
20706
20650
|
...projectInfo,
|
|
20707
20651
|
languages: detectSourceLanguages([...scope.files, ...scope.testFiles])
|
|
@@ -21058,18 +21002,16 @@ const initCommand = async (directory, options = {}) => {
|
|
|
21058
21002
|
status: "done",
|
|
21059
21003
|
label: `Wrote ${CONFIG_DIR}/${CONFIG_FILE}`
|
|
21060
21004
|
}];
|
|
21061
|
-
if (choices.engines.includes("architecture")) {
|
|
21062
|
-
|
|
21063
|
-
|
|
21064
|
-
|
|
21065
|
-
|
|
21066
|
-
label: `Wrote ${CONFIG_DIR}/${RULES_FILE}`
|
|
21067
|
-
});
|
|
21068
|
-
} else steps.push({
|
|
21069
|
-
status: "skipped",
|
|
21070
|
-
label: `${CONFIG_DIR}/${RULES_FILE} already exists`
|
|
21005
|
+
if (choices.engines.includes("architecture")) if (!fs.existsSync(rulesPath)) {
|
|
21006
|
+
fs.writeFileSync(rulesPath, DEFAULT_RULES_YAML);
|
|
21007
|
+
steps.push({
|
|
21008
|
+
status: "done",
|
|
21009
|
+
label: `Wrote ${CONFIG_DIR}/${RULES_FILE}`
|
|
21071
21010
|
});
|
|
21072
|
-
}
|
|
21011
|
+
} else steps.push({
|
|
21012
|
+
status: "skipped",
|
|
21013
|
+
label: `${CONFIG_DIR}/${RULES_FILE} already exists`
|
|
21014
|
+
});
|
|
21073
21015
|
const workflowResult = writeGithubWorkflow(resolvedDir, choices.writeGithubWorkflow);
|
|
21074
21016
|
if (workflowResult.status === "written") steps.push({
|
|
21075
21017
|
status: "done",
|
|
@@ -21263,10 +21205,8 @@ const runSearchPrompt = async (options) => {
|
|
|
21263
21205
|
}
|
|
21264
21206
|
if (key.name === "space" && options.mode === "multi") {
|
|
21265
21207
|
const item = filtered[cursor];
|
|
21266
|
-
if (item)
|
|
21267
|
-
|
|
21268
|
-
else selected.add(item.value);
|
|
21269
|
-
}
|
|
21208
|
+
if (item) if (selected.has(item.value)) selected.delete(item.value);
|
|
21209
|
+
else selected.add(item.value);
|
|
21270
21210
|
render();
|
|
21271
21211
|
return;
|
|
21272
21212
|
}
|
|
@@ -21575,8 +21515,7 @@ const collectRuleEntries = (directory) => {
|
|
|
21575
21515
|
for (const { engine, rules } of BUILTIN_RULES) for (const rule of rules) entries.push(toRuleEntry(engine, rule));
|
|
21576
21516
|
const configDir = findConfigDir(resolvedDir);
|
|
21577
21517
|
if (configDir) {
|
|
21578
|
-
const
|
|
21579
|
-
const archRules = loadArchitectureRules(rulesPath);
|
|
21518
|
+
const archRules = loadArchitectureRules(path.join(configDir, RULES_FILE));
|
|
21580
21519
|
for (const rule of archRules) entries.push({
|
|
21581
21520
|
id: `arch/${rule.name}`,
|
|
21582
21521
|
engine: "architecture",
|