@methiu/raigal 0.2.3 → 0.2.4
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-BBZKvm0E.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-Lt31Ld5t.js} +1 -1
- package/dist/{version-B4eYJn3o.js → version-CukuIVX4.js} +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -13,7 +13,8 @@ import { z } from "zod/v4";
|
|
|
13
13
|
import crypto, { createHash, createPublicKey, randomUUID, verify } from "node:crypto";
|
|
14
14
|
import YAML, { parse } from "yaml";
|
|
15
15
|
import { confirm, isCancel, multiselect, select, text } from "@clack/prompts";
|
|
16
|
-
import
|
|
16
|
+
import * as readline$1 from "node:readline";
|
|
17
|
+
import readline from "node:readline";
|
|
17
18
|
import picomatch from "picomatch";
|
|
18
19
|
import ts from "typescript";
|
|
19
20
|
import { parse as parse$1 } from "smol-toml";
|
|
@@ -112,8 +113,7 @@ const commandExists = (bin) => {
|
|
|
112
113
|
}
|
|
113
114
|
}
|
|
114
115
|
}
|
|
115
|
-
const
|
|
116
|
-
const result = spawnSync(command, [bin], {
|
|
116
|
+
const result = spawnSync(process.platform === "win32" ? "where.exe" : "which", [bin], {
|
|
117
117
|
encoding: "utf-8",
|
|
118
118
|
timeout: PROVIDER_PROBE_TIMEOUT_MS
|
|
119
119
|
});
|
|
@@ -711,8 +711,7 @@ const stringWidth = (s) => {
|
|
|
711
711
|
const bare = stripAnsi$1(s);
|
|
712
712
|
let total = 0;
|
|
713
713
|
for (const ch of bare) {
|
|
714
|
-
const
|
|
715
|
-
const w = wcwidth(cp);
|
|
714
|
+
const w = wcwidth(ch.codePointAt(0) ?? 0);
|
|
716
715
|
total += w > 0 ? w : 1;
|
|
717
716
|
}
|
|
718
717
|
return total;
|
|
@@ -728,8 +727,7 @@ const truncate = (s, max, ellipsis = "…") => {
|
|
|
728
727
|
let out = "";
|
|
729
728
|
let w = 0;
|
|
730
729
|
for (const ch of s) {
|
|
731
|
-
const
|
|
732
|
-
const cw = wcwidth(cp);
|
|
730
|
+
const cw = wcwidth(ch.codePointAt(0) ?? 0);
|
|
733
731
|
if (w + cw > limit) break;
|
|
734
732
|
out += ch;
|
|
735
733
|
w += cw;
|
|
@@ -739,8 +737,7 @@ const truncate = (s, max, ellipsis = "…") => {
|
|
|
739
737
|
//#endregion
|
|
740
738
|
//#region src/ui/display.ts
|
|
741
739
|
const renderDisplaySection = (label, deps = {}) => {
|
|
742
|
-
|
|
743
|
-
return style$1(t, "section", label);
|
|
740
|
+
return style$1(deps.theme ?? theme, "section", label);
|
|
744
741
|
};
|
|
745
742
|
const renderDisplayRows = (rows, options = {}) => {
|
|
746
743
|
if (rows.length === 0) return [];
|
|
@@ -901,8 +898,7 @@ const symbols = createSymbols({ plain: isPlain() });
|
|
|
901
898
|
*/
|
|
902
899
|
const renderHintLine = (hint, deps = {}) => {
|
|
903
900
|
const t = deps.theme ?? theme;
|
|
904
|
-
|
|
905
|
-
return ` ${style$1(t, "accent", s.hint)} ${highlightAislop(maskSecrets(hint), t)}\n`;
|
|
901
|
+
return ` ${style$1(t, "accent", (deps.symbols ?? symbols).hint)} ${highlightAislop(maskSecrets(hint), t)}\n`;
|
|
906
902
|
};
|
|
907
903
|
const createLogger = (deps = {}) => {
|
|
908
904
|
const t = deps.theme ?? theme;
|
|
@@ -927,7 +923,7 @@ const createLogger = (deps = {}) => {
|
|
|
927
923
|
const log = createLogger();
|
|
928
924
|
//#endregion
|
|
929
925
|
//#region src/version.ts
|
|
930
|
-
const APP_VERSION = "0.2.
|
|
926
|
+
const APP_VERSION = "0.2.4";
|
|
931
927
|
//#endregion
|
|
932
928
|
//#region src/commands/agent-connect.ts
|
|
933
929
|
const commandText = (status) => [status.provider.loginCommand.command, ...status.provider.loginCommand.args].join(" ");
|
|
@@ -1414,9 +1410,7 @@ const verifyEntitlementJwt = (jwt, options = {}) => {
|
|
|
1414
1410
|
if (!header.kid) throw new JwtVerificationError("JWT header missing 'kid'", "unknown_kid");
|
|
1415
1411
|
const publicKey = getPublicKey(header.kid);
|
|
1416
1412
|
if (!publicKey) throw new JwtVerificationError(`Unknown or untrusted signing key id (kid: ${header.kid})`, "unknown_kid");
|
|
1417
|
-
|
|
1418
|
-
const signature = Buffer.from(signatureB64, "base64url");
|
|
1419
|
-
if (!verify(null, signedData, publicKey, signature)) throw new JwtVerificationError("Invalid JWT cryptographic signature", "invalid_signature");
|
|
1413
|
+
if (!verify(null, Buffer.from(`${headerB64}.${payloadB64}`, "utf-8"), publicKey, Buffer.from(signatureB64, "base64url"))) throw new JwtVerificationError("Invalid JWT cryptographic signature", "invalid_signature");
|
|
1420
1414
|
let rawPayload;
|
|
1421
1415
|
try {
|
|
1422
1416
|
rawPayload = JSON.parse(Buffer.from(payloadB64, "base64url").toString("utf-8"));
|
|
@@ -1428,7 +1422,7 @@ const verifyEntitlementJwt = (jwt, options = {}) => {
|
|
|
1428
1422
|
const claims = parsed.data;
|
|
1429
1423
|
const expectedIssuer = process.env.RAIGAL_ISSUER?.trim() || "https://app.raigal.dev";
|
|
1430
1424
|
if (claims.iss !== expectedIssuer) throw new JwtVerificationError(`Untrusted issuer: ${claims.iss}`, "invalid_issuer");
|
|
1431
|
-
if (!isVersionAtLeast("0.2.
|
|
1425
|
+
if (!isVersionAtLeast("0.2.4", 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");
|
|
1432
1426
|
const now = options.nowSeconds ?? Math.floor(Date.now() / 1e3);
|
|
1433
1427
|
const grace = options.allowGraceSeconds ?? 0;
|
|
1434
1428
|
if (now > claims.exp + grace) {
|
|
@@ -1462,7 +1456,7 @@ const fetchGitHubOidcToken = async () => {
|
|
|
1462
1456
|
};
|
|
1463
1457
|
//#endregion
|
|
1464
1458
|
//#region src/cloud/entitlement.ts
|
|
1465
|
-
const GRACE_PERIOD_SECONDS =
|
|
1459
|
+
const GRACE_PERIOD_SECONDS = 4320 * 60;
|
|
1466
1460
|
var MissingCredentialError = class extends Error {
|
|
1467
1461
|
constructor(message = "No organization credential found") {
|
|
1468
1462
|
super(message);
|
|
@@ -1587,8 +1581,7 @@ const getEntitlement = async () => {
|
|
|
1587
1581
|
}
|
|
1588
1582
|
} else oidcToken = await fetchGitHubOidcToken();
|
|
1589
1583
|
try {
|
|
1590
|
-
const
|
|
1591
|
-
const response = await fetchEntitlementFromApi(tokenToPass, oidcToken);
|
|
1584
|
+
const response = await fetchEntitlementFromApi(activeToken?.token ?? "", oidcToken);
|
|
1592
1585
|
const claims = verifyEntitlementJwt(response.entitlement, { nowSeconds: now });
|
|
1593
1586
|
saveCachedEntitlement(response.entitlement, response.refresh_after);
|
|
1594
1587
|
return {
|
|
@@ -2383,7 +2376,7 @@ var AgentTui = class {
|
|
|
2383
2376
|
}
|
|
2384
2377
|
ensureMounted() {
|
|
2385
2378
|
if (!this.tty || this.handle) return;
|
|
2386
|
-
this.handle = import("./mount-
|
|
2379
|
+
this.handle = import("./mount-DTc8WaIt.js").then((m) => m.mountAgentTui(this.store));
|
|
2387
2380
|
}
|
|
2388
2381
|
setActions(actions) {
|
|
2389
2382
|
this.store.update({ actions: actions.filter((action) => action.trim().length > 0) });
|
|
@@ -2478,7 +2471,7 @@ const runSelf = (args, cwd) => {
|
|
|
2478
2471
|
AISLOP_NO_UPDATE_NOTIFIER: "1",
|
|
2479
2472
|
NO_COLOR: "1"
|
|
2480
2473
|
},
|
|
2481
|
-
maxBuffer:
|
|
2474
|
+
maxBuffer: 50 * 1024 * 1024
|
|
2482
2475
|
});
|
|
2483
2476
|
return {
|
|
2484
2477
|
exitCode: result.status,
|
|
@@ -2517,7 +2510,7 @@ const applyDiff = async (root, patch) => {
|
|
|
2517
2510
|
cwd: root,
|
|
2518
2511
|
input: patch,
|
|
2519
2512
|
encoding: "utf-8",
|
|
2520
|
-
maxBuffer:
|
|
2513
|
+
maxBuffer: 50 * 1024 * 1024
|
|
2521
2514
|
});
|
|
2522
2515
|
if (child.status !== 0) throw new Error(child.stderr || child.stdout || "Failed to apply agent diff.");
|
|
2523
2516
|
};
|
|
@@ -2890,7 +2883,7 @@ const detectCiContext = () => {
|
|
|
2890
2883
|
};
|
|
2891
2884
|
//#endregion
|
|
2892
2885
|
//#region src/cloud/outbox.ts
|
|
2893
|
-
const MAX_OUTBOX_BYTES =
|
|
2886
|
+
const MAX_OUTBOX_BYTES = 5 * 1024 * 1024;
|
|
2894
2887
|
const getMaxOutboxBytes = () => {
|
|
2895
2888
|
const override = process.env.RAIGAL_MAX_OUTBOX_BYTES;
|
|
2896
2889
|
if (override) {
|
|
@@ -3085,8 +3078,7 @@ var CloudRunRecorder = class {
|
|
|
3085
3078
|
if (this.finished) return;
|
|
3086
3079
|
this.finished = true;
|
|
3087
3080
|
try {
|
|
3088
|
-
|
|
3089
|
-
enqueueRun(run);
|
|
3081
|
+
enqueueRun(this.buildRunPayload(exitCode));
|
|
3090
3082
|
const activeToken = getActiveToken();
|
|
3091
3083
|
let oidcToken;
|
|
3092
3084
|
if (!activeToken) oidcToken = await fetchGitHubOidcToken();
|
|
@@ -3789,8 +3781,7 @@ const runSafeFixStep = (tui, cwd, options) => {
|
|
|
3789
3781
|
};
|
|
3790
3782
|
const selectFindings = (tui, cwd, limit, pass) => {
|
|
3791
3783
|
tui.start(`Pass ${pass}: selecting findings`);
|
|
3792
|
-
const
|
|
3793
|
-
const findings = selectAgentFindings(scan.diagnostics, limit);
|
|
3784
|
+
const findings = selectAgentFindings(scanJson(cwd).diagnostics, limit);
|
|
3794
3785
|
tui.setMetric("Selected", findings.length);
|
|
3795
3786
|
tui.complete({
|
|
3796
3787
|
status: findings.length > 0 ? "done" : "skipped",
|
|
@@ -4823,7 +4814,7 @@ const DEFAULT_RULES_YAML = `# Architecture rules (BYO)
|
|
|
4823
4814
|
//#endregion
|
|
4824
4815
|
//#region src/config/extends.ts
|
|
4825
4816
|
const MAX_DEPTH$1 = 5;
|
|
4826
|
-
const MAX_CONFIG_BYTES =
|
|
4817
|
+
const MAX_CONFIG_BYTES = 1024 * 1024;
|
|
4827
4818
|
const isPlainObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
4828
4819
|
const deepMerge = (...sources) => {
|
|
4829
4820
|
const result = {};
|
|
@@ -5301,8 +5292,7 @@ const loadConfig = (directory) => {
|
|
|
5301
5292
|
const configPath = findConfigFile(directory);
|
|
5302
5293
|
if (!configPath) return DEFAULT_CONFIG;
|
|
5303
5294
|
try {
|
|
5304
|
-
|
|
5305
|
-
return validateConfig(merged, configPath);
|
|
5295
|
+
return validateConfig(loadConfigChain(configPath), configPath);
|
|
5306
5296
|
} catch (error) {
|
|
5307
5297
|
if (error instanceof ConfigError) throw error;
|
|
5308
5298
|
throw new ConfigError(configPath, `Failed to parse ${configPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -5577,11 +5567,10 @@ const track = (input) => {
|
|
|
5577
5567
|
cachedInstallId = ensured.installId;
|
|
5578
5568
|
installCreated = ensured.created;
|
|
5579
5569
|
}
|
|
5580
|
-
const
|
|
5570
|
+
const { clean, dropped } = redactProperties({
|
|
5581
5571
|
...baseProperties(cachedInstallId),
|
|
5582
5572
|
...input.properties
|
|
5583
|
-
};
|
|
5584
|
-
const { clean, dropped } = redactProperties(merged);
|
|
5573
|
+
});
|
|
5585
5574
|
if (isDebug()) {
|
|
5586
5575
|
const compact = JSON.stringify({
|
|
5587
5576
|
event: input.event,
|
|
@@ -6421,17 +6410,14 @@ const renderRailStep = (step, deps = {}) => {
|
|
|
6421
6410
|
* between the last step and the footer.
|
|
6422
6411
|
*/
|
|
6423
6412
|
const renderRailConnector = (deps = {}) => {
|
|
6424
|
-
|
|
6425
|
-
const s = deps.symbols ?? symbols;
|
|
6426
|
-
return ` ${style$1(t, "accentDim", s.rail)}\n`;
|
|
6413
|
+
return ` ${style$1(deps.theme ?? theme, "accentDim", (deps.symbols ?? symbols).rail)}\n`;
|
|
6427
6414
|
};
|
|
6428
6415
|
/**
|
|
6429
6416
|
* Render the rail-end footer line ("└ <footer text>").
|
|
6430
6417
|
*/
|
|
6431
6418
|
const renderRailFooter = (footer, deps = {}) => {
|
|
6432
6419
|
const t = deps.theme ?? theme;
|
|
6433
|
-
|
|
6434
|
-
return ` ${style$1(t, "accentDim", s.railEnd)} ${highlightAislop(footer, t)}\n`;
|
|
6420
|
+
return ` ${style$1(t, "accentDim", (deps.symbols ?? symbols).railEnd)} ${highlightAislop(footer, t)}\n`;
|
|
6435
6421
|
};
|
|
6436
6422
|
const renderRail = (input, deps = {}) => {
|
|
6437
6423
|
const t = deps.theme ?? theme;
|
|
@@ -6588,7 +6574,7 @@ const launchMonitorInBackground = async (directory, options) => {
|
|
|
6588
6574
|
fs.mkdirSync(logDir, { recursive: true });
|
|
6589
6575
|
const logPath = path.join(logDir, `${monitorId}.log`);
|
|
6590
6576
|
const logFd = fs.openSync(logPath, "a");
|
|
6591
|
-
|
|
6577
|
+
writeAgentMonitorRecord(root, {
|
|
6592
6578
|
id: monitorId,
|
|
6593
6579
|
root,
|
|
6594
6580
|
requestedDirectory: path.resolve(directory),
|
|
@@ -6606,8 +6592,7 @@ const launchMonitorInBackground = async (directory, options) => {
|
|
|
6606
6592
|
noFix: options.noFix,
|
|
6607
6593
|
logPath,
|
|
6608
6594
|
recentCycles: []
|
|
6609
|
-
};
|
|
6610
|
-
writeAgentMonitorRecord(root, record);
|
|
6595
|
+
});
|
|
6611
6596
|
const child = spawn(process.execPath, [cliPath(), ...buildBackgroundMonitorArgs(directory, options)], {
|
|
6612
6597
|
cwd: root,
|
|
6613
6598
|
detached: true,
|
|
@@ -7856,8 +7841,7 @@ const registerPlanSubcommand = (agent) => {
|
|
|
7856
7841
|
const plan = agent.command("plan [directory]").description("Preview provider, worktree, findings, and publish actions without editing");
|
|
7857
7842
|
addAgentOptions(plan);
|
|
7858
7843
|
plan.action(async (directory = ".", _flags, command) => {
|
|
7859
|
-
const
|
|
7860
|
-
const options = agentOptionsFromFlags(flags, command);
|
|
7844
|
+
const options = agentOptionsFromFlags(command.optsWithGlobals(), command);
|
|
7861
7845
|
await withAgentLifecycle("agent_plan", directory, agentTelemetryProperties(options), async () => {
|
|
7862
7846
|
await agentPlanCommand(directory, options);
|
|
7863
7847
|
});
|
|
@@ -7867,8 +7851,7 @@ const registerAgentCommand = (program) => {
|
|
|
7867
7851
|
const agent = program.command("agent [directory]").description("Run a local AI slop repair session with Codex, Claude Code, or OpenCode");
|
|
7868
7852
|
addAgentOptions(agent);
|
|
7869
7853
|
agent.action(async (directory = ".", _flags, command) => {
|
|
7870
|
-
const
|
|
7871
|
-
const options = agentOptionsFromFlags(flags, command);
|
|
7854
|
+
const options = agentOptionsFromFlags(command.optsWithGlobals(), command);
|
|
7872
7855
|
await withAgentLifecycle("agent", directory, agentTelemetryProperties(options), async () => {
|
|
7873
7856
|
return await agentCommand(directory, options);
|
|
7874
7857
|
});
|
|
@@ -8468,7 +8451,7 @@ const filterExcludedDiagnostics = (diagnostics, rootDirectory, excludePatterns)
|
|
|
8468
8451
|
};
|
|
8469
8452
|
//#endregion
|
|
8470
8453
|
//#region src/utils/project-path-safety.ts
|
|
8471
|
-
const MAX_PROJECT_CONFIG_BYTES =
|
|
8454
|
+
const MAX_PROJECT_CONFIG_BYTES = 1024 * 1024;
|
|
8472
8455
|
const isWithinDirectory$3 = (rootDirectory, candidate) => {
|
|
8473
8456
|
const relative = path.relative(rootDirectory, candidate);
|
|
8474
8457
|
return relative === "" || !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
@@ -8568,7 +8551,7 @@ const isAutoGenerated = (filePath) => {
|
|
|
8568
8551
|
};
|
|
8569
8552
|
//#endregion
|
|
8570
8553
|
//#region src/utils/git-ignore.ts
|
|
8571
|
-
const MAX_BUFFER$2 =
|
|
8554
|
+
const MAX_BUFFER$2 = 50 * 1024 * 1024;
|
|
8572
8555
|
const NOT_IGNORED_ARGUMENTS = [
|
|
8573
8556
|
"ls-files",
|
|
8574
8557
|
"--cached",
|
|
@@ -8679,7 +8662,7 @@ const dropGitIgnoredPaths = (rootDirectory, absolutePaths) => {
|
|
|
8679
8662
|
};
|
|
8680
8663
|
//#endregion
|
|
8681
8664
|
//#region src/utils/project-file-list.ts
|
|
8682
|
-
const MAX_BUFFER$1 =
|
|
8665
|
+
const MAX_BUFFER$1 = 50 * 1024 * 1024;
|
|
8683
8666
|
const normalizePruneDirectories = (directories) => new Set([...directories].map((directory) => directory.toLowerCase()));
|
|
8684
8667
|
const isInPrunedDirectory = (filePath, pruneDirectories) => {
|
|
8685
8668
|
const pathSegments = filePath.split("/");
|
|
@@ -13098,8 +13081,7 @@ const isJsRelativeOrAbsolute = (spec) => spec.startsWith(".") || spec.startsWith
|
|
|
13098
13081
|
const RUNTIME_BUILTINS = /* @__PURE__ */ new Set(["bun"]);
|
|
13099
13082
|
const isJsBuiltin = (spec) => {
|
|
13100
13083
|
if (RUNTIME_BUILTINS.has(spec)) return true;
|
|
13101
|
-
|
|
13102
|
-
return isBuiltin(stripped) || isBuiltin(spec);
|
|
13084
|
+
return isBuiltin(spec.startsWith("node:") ? spec.slice(5) : spec) || isBuiltin(spec);
|
|
13103
13085
|
};
|
|
13104
13086
|
const VIRTUAL_MODULE_PREFIXES = [
|
|
13105
13087
|
"astro:",
|
|
@@ -13311,8 +13293,7 @@ const isLocalAliasReplacement = (rawValue, configDirectory, rootDirectory) => {
|
|
|
13311
13293
|
if (!target) return false;
|
|
13312
13294
|
if (!target.startsWith(".") && !target.startsWith("/") && !target.startsWith("~/") && !target.startsWith("@/")) return false;
|
|
13313
13295
|
const normalized = target.startsWith("~/") || target.startsWith("@/") ? target.slice(2) : target;
|
|
13314
|
-
|
|
13315
|
-
return isRootBoundedTarget(candidate, rootDirectory);
|
|
13296
|
+
return isRootBoundedTarget(path.isAbsolute(normalized) ? normalized : path.resolve(configDirectory, normalized), rootDirectory);
|
|
13316
13297
|
};
|
|
13317
13298
|
const hasValidPackageImportTarget = (value, packageDirectory, rootDirectory) => {
|
|
13318
13299
|
if (!isRootBoundedTarget(packageDirectory, rootDirectory)) return false;
|
|
@@ -14506,9 +14487,7 @@ const isRustDocCommentLine = (line) => {
|
|
|
14506
14487
|
};
|
|
14507
14488
|
const collectBlocks = (sourceLines, syntax, content, ext) => {
|
|
14508
14489
|
const blocks = [];
|
|
14509
|
-
const
|
|
14510
|
-
const actualExt = ext ?? (syntax.linePrefixes.includes("//") ? ".ts" : ".py");
|
|
14511
|
-
const commentLines = getCommentLines(actualContent, actualExt);
|
|
14490
|
+
const commentLines = getCommentLines(content ?? sourceLines.join("\n"), ext ?? (syntax.linePrefixes.includes("//") ? ".ts" : ".py"));
|
|
14512
14491
|
let i = 0;
|
|
14513
14492
|
while (i < sourceLines.length) {
|
|
14514
14493
|
const line = sourceLines[i];
|
|
@@ -14836,8 +14815,7 @@ const detectNarrativeComments = async (context) => {
|
|
|
14836
14815
|
} catch {
|
|
14837
14816
|
continue;
|
|
14838
14817
|
}
|
|
14839
|
-
const
|
|
14840
|
-
const blocks = collectBlocks(lines, syntax, content, ext);
|
|
14818
|
+
const blocks = collectBlocks(content.split("\n"), syntax, content, ext);
|
|
14841
14819
|
for (const block of blocks) {
|
|
14842
14820
|
const { matched, reason } = detectNarrativeInBlock(block, ext);
|
|
14843
14821
|
if (!matched) continue;
|
|
@@ -16790,8 +16768,7 @@ const checkFunctionDiagnostics = (relativePath, fn, limits, ext) => {
|
|
|
16790
16768
|
const results = [];
|
|
16791
16769
|
const multiplier = functionLocMultiplier(fn, ext);
|
|
16792
16770
|
const fnMax = functionLocBudget(fn, ext, limits.maxFunctionLoc);
|
|
16793
|
-
|
|
16794
|
-
if (exceedsLimit(effectiveLineCount, limits.maxFunctionLoc, multiplier)) results.push({
|
|
16771
|
+
if (exceedsLimit(fn.lineCount - fn.templateLines, limits.maxFunctionLoc, multiplier)) results.push({
|
|
16795
16772
|
filePath: relativePath,
|
|
16796
16773
|
engine: "code-quality",
|
|
16797
16774
|
rule: "complexity/function-too-long",
|
|
@@ -16888,7 +16865,7 @@ const isLowSignalMarkupWindow = (lines) => {
|
|
|
16888
16865
|
return lines.filter((line) => SVG_MARKUP_RE.test(line)).length >= Math.ceil(WINDOW_SIZE / 2);
|
|
16889
16866
|
};
|
|
16890
16867
|
const isLowSignalDataWindow = (lines) => {
|
|
16891
|
-
return lines.filter((line) => DATA_LITERAL_RE.test(line)).length >=
|
|
16868
|
+
return lines.filter((line) => DATA_LITERAL_RE.test(line)).length >= WINDOW_SIZE - 1;
|
|
16892
16869
|
};
|
|
16893
16870
|
const findSuppressedLines = (lines) => {
|
|
16894
16871
|
const suppressed = /* @__PURE__ */ new Set();
|
|
@@ -16920,7 +16897,7 @@ const collectMeaningfulLines = (content) => {
|
|
|
16920
16897
|
if (isLowSignalDataWindow(window)) continue;
|
|
16921
16898
|
if (window.every(isTrivialLine)) continue;
|
|
16922
16899
|
const normalised = window.map(normaliseLine);
|
|
16923
|
-
if (normalised.filter((n) => n.length > 0 && n !== "}" && n !== "{").length <
|
|
16900
|
+
if (normalised.filter((n) => n.length > 0 && n !== "}" && n !== "{").length < WINDOW_SIZE - 1) continue;
|
|
16924
16901
|
if (new Set(normalised).size < MIN_DISTINCT_LINES) continue;
|
|
16925
16902
|
hits.push({
|
|
16926
16903
|
startLine: i + 1,
|
|
@@ -17695,7 +17672,7 @@ const fixClangFormat = async (context) => {
|
|
|
17695
17672
|
};
|
|
17696
17673
|
//#endregion
|
|
17697
17674
|
//#region src/engines/format/dotnet-format.ts
|
|
17698
|
-
const REPORT_FILENAME = ".
|
|
17675
|
+
const REPORT_FILENAME = ".raigal-dotnet-format.json";
|
|
17699
17676
|
const parseDotnetFormatReport = (json, rootDirectory) => {
|
|
17700
17677
|
if (!json) return [];
|
|
17701
17678
|
let report;
|
|
@@ -18136,8 +18113,7 @@ const parseRuffFormatOutput = (output, rootDir) => {
|
|
|
18136
18113
|
const fixRuffFormat = async (context) => {
|
|
18137
18114
|
const targets = context.files ? getPythonTargets(context) : [context.rootDirectory];
|
|
18138
18115
|
if (context.files && targets.length === 0) return;
|
|
18139
|
-
const
|
|
18140
|
-
const result = await runSubprocess(ruffBinary, ["format", ...targets], {
|
|
18116
|
+
const result = await runSubprocess(resolveToolBinary("ruff"), ["format", ...targets], {
|
|
18141
18117
|
cwd: context.rootDirectory,
|
|
18142
18118
|
timeout: 6e4
|
|
18143
18119
|
});
|
|
@@ -18207,8 +18183,7 @@ const parseClangTidyOutput = (output, rootDirectory) => {
|
|
|
18207
18183
|
const runClangTidy = async (context) => {
|
|
18208
18184
|
const compileCommandsDir = findCompileCommandsDir(context);
|
|
18209
18185
|
if (!compileCommandsDir) return [];
|
|
18210
|
-
const
|
|
18211
|
-
const sources = filterSourcesInDatabase(implSources, readCompileCommandsFiles(compileCommandsDir));
|
|
18186
|
+
const sources = filterSourcesInDatabase(findCppSources(context).filter((f) => CPP_IMPL_EXTENSIONS.has(path.extname(f).toLowerCase())), readCompileCommandsFiles(compileCommandsDir));
|
|
18212
18187
|
if (sources.length === 0) return [];
|
|
18213
18188
|
const diagnostics = [];
|
|
18214
18189
|
for (const chunk of chunkFilePaths(sources, CLANG_TIDY_CHUNK_MAX_FILES)) try {
|
|
@@ -19044,8 +19019,7 @@ const processFile = (filePath, fileTargets, result) => {
|
|
|
19044
19019
|
});
|
|
19045
19020
|
continue;
|
|
19046
19021
|
}
|
|
19047
|
-
const
|
|
19048
|
-
const { edit, skipReason } = computeEdit(sourceFile, shape);
|
|
19022
|
+
const { edit, skipReason } = computeEdit(sourceFile, classifyIdentifier(best));
|
|
19049
19023
|
if (!edit) {
|
|
19050
19024
|
pendingSkips.push({
|
|
19051
19025
|
target,
|
|
@@ -19860,8 +19834,7 @@ const ruffLintFixArgs = (context, unsafe) => {
|
|
|
19860
19834
|
};
|
|
19861
19835
|
const fixRuffLint = async (context) => {
|
|
19862
19836
|
if (context.files && getPythonTargets(context).length === 0) return;
|
|
19863
|
-
const
|
|
19864
|
-
const result = await runSubprocess(ruffBinary, ruffLintFixArgs(context, false), {
|
|
19837
|
+
const result = await runSubprocess(resolveToolBinary("ruff"), ruffLintFixArgs(context, false), {
|
|
19865
19838
|
cwd: context.rootDirectory,
|
|
19866
19839
|
timeout: 6e4
|
|
19867
19840
|
});
|
|
@@ -19869,8 +19842,7 @@ const fixRuffLint = async (context) => {
|
|
|
19869
19842
|
};
|
|
19870
19843
|
const fixRuffLintForce = async (context) => {
|
|
19871
19844
|
if (context.files && getPythonTargets(context).length === 0) return;
|
|
19872
|
-
const
|
|
19873
|
-
const result = await runSubprocess(ruffBinary, ruffLintFixArgs(context, true), {
|
|
19845
|
+
const result = await runSubprocess(resolveToolBinary("ruff"), ruffLintFixArgs(context, true), {
|
|
19874
19846
|
cwd: context.rootDirectory,
|
|
19875
19847
|
timeout: 6e4
|
|
19876
19848
|
});
|
|
@@ -19911,8 +19883,7 @@ const resolveTrustedTscPath = () => {
|
|
|
19911
19883
|
};
|
|
19912
19884
|
const isReferenceOnlyConfig = (tsconfigPath) => {
|
|
19913
19885
|
try {
|
|
19914
|
-
const
|
|
19915
|
-
const parsed = parseJsonc(raw);
|
|
19886
|
+
const parsed = parseJsonc(fs.readFileSync(tsconfigPath, "utf-8"));
|
|
19916
19887
|
if (!parsed) return false;
|
|
19917
19888
|
return Array.isArray(parsed.references) && !parsed.files && !parsed.include && !parsed.extends;
|
|
19918
19889
|
} catch {
|
|
@@ -20779,11 +20750,10 @@ const auditSkippedDiagnostic = (source, help) => ({
|
|
|
20779
20750
|
});
|
|
20780
20751
|
const runNpmAudit = async (rootDir, timeout) => {
|
|
20781
20752
|
try {
|
|
20782
|
-
|
|
20753
|
+
return parseJsAudit((await runSubprocess("npm", ["audit", "--json"], {
|
|
20783
20754
|
cwd: rootDir,
|
|
20784
20755
|
timeout
|
|
20785
|
-
});
|
|
20786
|
-
return parseJsAudit(result.stdout, "npm audit", readRuntimeDependencies(rootDir));
|
|
20756
|
+
})).stdout, "npm audit", readRuntimeDependencies(rootDir));
|
|
20787
20757
|
} catch (error) {
|
|
20788
20758
|
return [auditSkippedDiagnostic("npm audit", `Failed to run npm audit: ${errorMessageOf(error)}`)];
|
|
20789
20759
|
}
|
|
@@ -20804,11 +20774,10 @@ const runBunAudit = async (rootDir, timeout) => {
|
|
|
20804
20774
|
const runPnpmAuditWithFallback = async (rootDir, timeout) => {
|
|
20805
20775
|
const canFallbackToNpm = fs.existsSync(path.join(rootDir, "package-lock.json"));
|
|
20806
20776
|
try {
|
|
20807
|
-
const
|
|
20777
|
+
const diagnostics = parseJsAudit((await runSubprocess("pnpm", ["audit", "--json"], {
|
|
20808
20778
|
cwd: rootDir,
|
|
20809
20779
|
timeout
|
|
20810
|
-
});
|
|
20811
|
-
const diagnostics = parseJsAudit(result.stdout, "pnpm audit", readRuntimeDependencies(rootDir));
|
|
20780
|
+
})).stdout, "pnpm audit", readRuntimeDependencies(rootDir));
|
|
20812
20781
|
if (diagnostics.some((d) => d.rule === "security/dependency-audit-skipped")) {
|
|
20813
20782
|
if (canFallbackToNpm) return runNpmAudit(rootDir, timeout);
|
|
20814
20783
|
return diagnostics;
|
|
@@ -21542,10 +21511,7 @@ const runEngines = async (context, enabledEngines, onStart, onComplete) => {
|
|
|
21542
21511
|
failed: true,
|
|
21543
21512
|
skipReason: r.reason instanceof Error ? r.reason.message : String(r.reason)
|
|
21544
21513
|
});
|
|
21545
|
-
|
|
21546
|
-
const csharp = dedupeCSharpAsync(stripped);
|
|
21547
|
-
const comments = dedupeOverlappingComments(csharp);
|
|
21548
|
-
return dedupeEquivalenceDiagnostics(comments);
|
|
21514
|
+
return dedupeEquivalenceDiagnostics(dedupeOverlappingComments(dedupeCSharpAsync(stripSecretDiagnostics(finalResults))));
|
|
21549
21515
|
};
|
|
21550
21516
|
const stripSecretDiagnostics = (results) => {
|
|
21551
21517
|
for (const result of results) for (const d of result.diagnostics) if (d.redactSource || isSecretClassRule(d.rule)) {
|
|
@@ -21770,8 +21736,7 @@ const calculateScore = (diagnostics, weights, thresholds, sourceFileCount, smoot
|
|
|
21770
21736
|
const capScale = Math.max(1, fileCount.effectiveSourceFileCount / CAP_REFERENCE_FILES);
|
|
21771
21737
|
const defaultRuleCap = typeof maxPerRule === "number" && maxPerRule > 0 ? maxPerRule : null;
|
|
21772
21738
|
const capForRule = (key) => {
|
|
21773
|
-
const
|
|
21774
|
-
const ruleCap = scoreImpactForRule(rule).cap;
|
|
21739
|
+
const ruleCap = scoreImpactForRule(key.slice(key.indexOf(":") + 1)).cap;
|
|
21775
21740
|
if (typeof ruleCap === "number") return defaultRuleCap ? Math.min(defaultRuleCap, ruleCap) : ruleCap;
|
|
21776
21741
|
return defaultRuleCap;
|
|
21777
21742
|
};
|
|
@@ -21884,10 +21849,8 @@ const detectSourceLanguages = (sourceFiles) => {
|
|
|
21884
21849
|
const detectLanguages = (directory, sourceFiles) => {
|
|
21885
21850
|
const languages = new Set(detectSourceLanguages(sourceFiles));
|
|
21886
21851
|
for (const [file, lang] of Object.entries(LANGUAGE_SIGNALS)) if (fs.existsSync(path.join(directory, file))) languages.add(lang);
|
|
21887
|
-
if (readPackageJson(path.join(directory, "package.json")))
|
|
21888
|
-
|
|
21889
|
-
else languages.add("javascript");
|
|
21890
|
-
}
|
|
21852
|
+
if (readPackageJson(path.join(directory, "package.json"))) if (fs.existsSync(path.join(directory, "tsconfig.json"))) languages.add("typescript");
|
|
21853
|
+
else languages.add("javascript");
|
|
21891
21854
|
for (const signal of PYTHON_SIGNALS) if (fs.existsSync(path.join(directory, signal))) {
|
|
21892
21855
|
languages.add("python");
|
|
21893
21856
|
break;
|
|
@@ -22114,7 +22077,7 @@ const runScopedScan = async (cwd, filePaths) => {
|
|
|
22114
22077
|
const rulesPath = configDir ? path.join(configDir, RULES_FILE) : void 0;
|
|
22115
22078
|
const enumeratedPaths = new Set(projectCandidates.map((filePath) => path.resolve(rootDirectory, filePath)));
|
|
22116
22079
|
const scopedCandidates = filePaths.filter((filePath) => enumeratedPaths.has(path.resolve(rootDirectory, filePath)));
|
|
22117
|
-
const
|
|
22080
|
+
const diagnostics = applyRuleSeverities((await runEngines({
|
|
22118
22081
|
rootDirectory: project.rootDirectory,
|
|
22119
22082
|
languages: project.languages,
|
|
22120
22083
|
frameworks: project.frameworks,
|
|
@@ -22137,17 +22100,14 @@ const runScopedScan = async (cwd, filePaths) => {
|
|
|
22137
22100
|
allowProjectLocalTools: false,
|
|
22138
22101
|
architectureRulesPath: config.engines.architecture ? rulesPath : void 0
|
|
22139
22102
|
}
|
|
22140
|
-
}
|
|
22141
|
-
const enabled = {
|
|
22103
|
+
}, {
|
|
22142
22104
|
format: false,
|
|
22143
22105
|
lint: false,
|
|
22144
22106
|
"code-quality": config.engines["code-quality"],
|
|
22145
22107
|
"ai-slop": config.engines["ai-slop"],
|
|
22146
22108
|
architecture: config.engines.architecture,
|
|
22147
22109
|
security: false
|
|
22148
|
-
};
|
|
22149
|
-
const results = await runEngines(context, enabled);
|
|
22150
|
-
const diagnostics = applyRuleSeverities(results.flatMap((result) => result.diagnostics), config.overrides.length ? {} : config.rules);
|
|
22110
|
+
})).flatMap((result) => result.diagnostics), config.overrides.length ? {} : config.rules);
|
|
22151
22111
|
const { score } = calculateScore(diagnostics, config.scoring.weights, config.scoring.thresholds, projectSourceFiles.length + projectTestFiles.length, config.scoring.smoothing, config.scoring.maxPerRule);
|
|
22152
22112
|
return {
|
|
22153
22113
|
diagnostics,
|
|
@@ -22161,7 +22121,7 @@ const atomicWrite = (targetPath, content) => {
|
|
|
22161
22121
|
const dir = path.dirname(targetPath);
|
|
22162
22122
|
fs.mkdirSync(dir, { recursive: true });
|
|
22163
22123
|
const rand = Math.random().toString(36).slice(2, 10);
|
|
22164
|
-
const tmp = path.join(dir, `.
|
|
22124
|
+
const tmp = path.join(dir, `.raigal-tmp-${process.pid}-${rand}`);
|
|
22165
22125
|
fs.writeFileSync(tmp, content, "utf-8");
|
|
22166
22126
|
try {
|
|
22167
22127
|
fs.renameSync(tmp, targetPath);
|
|
@@ -22210,14 +22170,18 @@ const baselinePath = (cwd) => {
|
|
|
22210
22170
|
if (fs.existsSync(raigalCandidate)) return raigalCandidate;
|
|
22211
22171
|
const raigalDir = path.join(cwd, ".raigal");
|
|
22212
22172
|
if (fs.existsSync(raigalDir)) return raigalCandidate;
|
|
22213
|
-
|
|
22173
|
+
const legacyCandidate = path.join(cwd, ".aislop", "baseline.json");
|
|
22174
|
+
if (fs.existsSync(legacyCandidate)) return legacyCandidate;
|
|
22175
|
+
return raigalCandidate;
|
|
22214
22176
|
};
|
|
22215
22177
|
const sessionPath = (cwd) => {
|
|
22216
22178
|
const raigalCandidate = path.join(cwd, ".raigal", "session.jsonl");
|
|
22217
22179
|
if (fs.existsSync(raigalCandidate)) return raigalCandidate;
|
|
22218
22180
|
const raigalDir = path.join(cwd, ".raigal");
|
|
22219
22181
|
if (fs.existsSync(raigalDir)) return raigalCandidate;
|
|
22220
|
-
|
|
22182
|
+
const legacyCandidate = path.join(cwd, ".aislop", "session.jsonl");
|
|
22183
|
+
if (fs.existsSync(legacyCandidate)) return legacyCandidate;
|
|
22184
|
+
return raigalCandidate;
|
|
22221
22185
|
};
|
|
22222
22186
|
const readBaseline = (cwd) => {
|
|
22223
22187
|
const raw = readIfExists(baselinePath(cwd));
|
|
@@ -22228,7 +22192,7 @@ const readBaseline = (cwd) => {
|
|
|
22228
22192
|
const findingFingerprints = parsed.findingFingerprints ?? [];
|
|
22229
22193
|
const needsWindowsMigration = parsed.pathFormat !== "posix";
|
|
22230
22194
|
return {
|
|
22231
|
-
schema: "
|
|
22195
|
+
schema: "raigal.baseline.v2",
|
|
22232
22196
|
pathFormat: "posix",
|
|
22233
22197
|
updatedAt: parsed.updatedAt ?? "",
|
|
22234
22198
|
score: parsed.score ?? 0,
|
|
@@ -22242,7 +22206,7 @@ const readBaseline = (cwd) => {
|
|
|
22242
22206
|
}
|
|
22243
22207
|
};
|
|
22244
22208
|
const writeBaseline = (cwd, baseline) => {
|
|
22245
|
-
const target =
|
|
22209
|
+
const target = path.join(cwd, ".raigal", "baseline.json");
|
|
22246
22210
|
atomicWrite(target, `${JSON.stringify({
|
|
22247
22211
|
...baseline,
|
|
22248
22212
|
pathFormat: "posix"
|
|
@@ -22256,7 +22220,7 @@ const captureBaseline = async (cwd) => {
|
|
|
22256
22220
|
});
|
|
22257
22221
|
const project = await discoverProject(cwd);
|
|
22258
22222
|
const config = loadConfig(cwd);
|
|
22259
|
-
const
|
|
22223
|
+
const results = await runEngines({
|
|
22260
22224
|
rootDirectory: project.rootDirectory,
|
|
22261
22225
|
languages: project.languages,
|
|
22262
22226
|
frameworks: project.frameworks,
|
|
@@ -22275,27 +22239,24 @@ const captureBaseline = async (cwd) => {
|
|
|
22275
22239
|
},
|
|
22276
22240
|
allowProjectLocalTools: false
|
|
22277
22241
|
}
|
|
22278
|
-
}
|
|
22279
|
-
const enabled = {
|
|
22242
|
+
}, {
|
|
22280
22243
|
format: false,
|
|
22281
22244
|
lint: false,
|
|
22282
22245
|
"code-quality": config.engines["code-quality"],
|
|
22283
22246
|
"ai-slop": config.engines["ai-slop"],
|
|
22284
22247
|
architecture: config.engines.architecture,
|
|
22285
22248
|
security: false
|
|
22286
|
-
};
|
|
22287
|
-
const results = await runEngines(context, enabled);
|
|
22249
|
+
});
|
|
22288
22250
|
const diagnostics = applyRuleSeverities(results.flatMap((r) => r.diagnostics), config.overrides.length ? {} : config.rules);
|
|
22289
22251
|
const { score } = calculateScore(diagnostics, config.scoring.weights, config.scoring.thresholds, project.sourceFileCount, config.scoring.smoothing, config.scoring.maxPerRule);
|
|
22290
22252
|
const byEngine = {};
|
|
22291
22253
|
for (const r of results) {
|
|
22292
|
-
const
|
|
22293
|
-
const { score: engineScore } = calculateScore(engineDiags, config.scoring.weights, config.scoring.thresholds, project.sourceFileCount, config.scoring.smoothing, config.scoring.maxPerRule);
|
|
22254
|
+
const { score: engineScore } = calculateScore(diagnostics.filter((d) => d.engine === r.engine), config.scoring.weights, config.scoring.thresholds, project.sourceFileCount, config.scoring.smoothing, config.scoring.maxPerRule);
|
|
22294
22255
|
byEngine[r.engine] = engineScore;
|
|
22295
22256
|
}
|
|
22296
22257
|
const findingFingerprints = diagnostics.filter((d) => d.severity === "error" || d.severity === "warning").map((d) => fingerprintDiagnostic(d, project.rootDirectory));
|
|
22297
22258
|
const baseline = {
|
|
22298
|
-
schema: "
|
|
22259
|
+
schema: "raigal.baseline.v2",
|
|
22299
22260
|
pathFormat: "posix",
|
|
22300
22261
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
22301
22262
|
score,
|
|
@@ -22323,8 +22284,7 @@ const appendSessionFiles = (cwd, files) => {
|
|
|
22323
22284
|
} catch {}
|
|
22324
22285
|
};
|
|
22325
22286
|
const readSessionFiles = (cwd) => {
|
|
22326
|
-
const
|
|
22327
|
-
const raw = readIfExists(target);
|
|
22287
|
+
const raw = readIfExists(sessionPath(cwd));
|
|
22328
22288
|
if (!raw) return [];
|
|
22329
22289
|
const files = /* @__PURE__ */ new Set();
|
|
22330
22290
|
for (const line of raw.split("\n")) {
|
|
@@ -22714,8 +22674,8 @@ A PostToolUse hook runs \`raigal hook claude\` after every Edit, Write, or Multi
|
|
|
22714
22674
|
|
|
22715
22675
|
## Rules
|
|
22716
22676
|
|
|
22717
|
-
- \`.raigal/config.yaml\`
|
|
22718
|
-
- \`.raigal/rules.yaml\`
|
|
22677
|
+
- \`.raigal/config.yaml\` - thresholds and engine toggles. Treat as authoritative; don't edit without user consent.
|
|
22678
|
+
- \`.raigal/rules.yaml\` - project-specific architecture rules (may be absent). When a finding cites \`architecture/*\`, open this file and follow it.
|
|
22719
22679
|
- Custom rules can change between sessions. Trust what the scan returns, not a cached understanding of what the rules are.
|
|
22720
22680
|
|
|
22721
22681
|
## Principles
|
|
@@ -22797,9 +22757,7 @@ const applyRemoval = (result, opts, target, nextContent) => {
|
|
|
22797
22757
|
//#region src/hooks/install/rules-only.ts
|
|
22798
22758
|
const installRulesOnly = (opts, paths, summary) => {
|
|
22799
22759
|
const result = emptyResult();
|
|
22800
|
-
const
|
|
22801
|
-
const hash = sentinelHash(AISLOP_MD_BODY);
|
|
22802
|
-
const next = upsertMarkdownFence(existing, AISLOP_MD_BODY, hash).nextContent;
|
|
22760
|
+
const next = upsertMarkdownFence(readIfExists(paths.rules), AISLOP_MD_BODY, sentinelHash(AISLOP_MD_BODY)).nextContent;
|
|
22803
22761
|
applyContent(result, opts, paths.rules, next, summary);
|
|
22804
22762
|
if (paths.host && paths.marker) {
|
|
22805
22763
|
const host = readIfExists(paths.host) ?? "";
|
|
@@ -22975,8 +22933,7 @@ const installClaude = (opts) => {
|
|
|
22975
22933
|
const nextSettings = renderSettings$1(readIfExists(paths.settings), Boolean(opts.qualityGate));
|
|
22976
22934
|
applyContent(result, opts, paths.settings, nextSettings, "register PostToolUse + FileChanged hooks");
|
|
22977
22935
|
const mdHash = sentinelHash(AISLOP_MD_BODY);
|
|
22978
|
-
const
|
|
22979
|
-
const fenced = upsertMarkdownFence(existingMd, AISLOP_MD_BODY, mdHash);
|
|
22936
|
+
const fenced = upsertMarkdownFence(readIfExists(paths.aislopMd), AISLOP_MD_BODY, mdHash);
|
|
22980
22937
|
applyContent(result, opts, paths.aislopMd, fenced.nextContent, "write AISLOP.md rules");
|
|
22981
22938
|
const existingClaudeMd = readIfExists(paths.claudeMd) ?? "";
|
|
22982
22939
|
const marker = "@AISLOP.md";
|
|
@@ -23122,9 +23079,7 @@ const installCursor = (opts) => {
|
|
|
23122
23079
|
const nextHooks = renderHooksJson(readIfExists(paths.hooks));
|
|
23123
23080
|
applyContent(result, opts, paths.hooks, nextHooks, "register afterFileEdit hook");
|
|
23124
23081
|
if (opts.scope === "project") {
|
|
23125
|
-
const
|
|
23126
|
-
const hash = sentinelHash(AISLOP_MD_BODY);
|
|
23127
|
-
const rules = upsertMarkdownFence(existingRules, AISLOP_MD_BODY, hash).nextContent;
|
|
23082
|
+
const rules = upsertMarkdownFence(readIfExists(paths.rules), AISLOP_MD_BODY, sentinelHash(AISLOP_MD_BODY)).nextContent;
|
|
23128
23083
|
applyContent(result, opts, paths.rules, rules, "write .cursor/rules/aislop.mdc");
|
|
23129
23084
|
}
|
|
23130
23085
|
return result;
|
|
@@ -23197,9 +23152,7 @@ const installGemini = (opts) => {
|
|
|
23197
23152
|
const result = emptyResult();
|
|
23198
23153
|
const next = renderSettings(readIfExists(paths.settings));
|
|
23199
23154
|
applyContent(result, opts, paths.settings, next, "register AfterTool hook");
|
|
23200
|
-
const
|
|
23201
|
-
const hash = sentinelHash(AISLOP_MD_BODY);
|
|
23202
|
-
const fenced = upsertMarkdownFence(existingMd, AISLOP_MD_BODY, hash).nextContent;
|
|
23155
|
+
const fenced = upsertMarkdownFence(readIfExists(paths.aislopMd), AISLOP_MD_BODY, sentinelHash(AISLOP_MD_BODY)).nextContent;
|
|
23203
23156
|
applyContent(result, opts, paths.aislopMd, fenced, "write AISLOP.md rules");
|
|
23204
23157
|
const existingGeminiMd = readIfExists(paths.geminiMd) ?? "";
|
|
23205
23158
|
const marker = "@AISLOP.md";
|
|
@@ -23697,10 +23650,8 @@ const runSearchPrompt = async (options) => {
|
|
|
23697
23650
|
}
|
|
23698
23651
|
if (key.name === "space" && options.mode === "multi") {
|
|
23699
23652
|
const item = filtered[cursor];
|
|
23700
|
-
if (item)
|
|
23701
|
-
|
|
23702
|
-
else selected.add(item.value);
|
|
23703
|
-
}
|
|
23653
|
+
if (item) if (selected.has(item.value)) selected.delete(item.value);
|
|
23654
|
+
else selected.add(item.value);
|
|
23704
23655
|
render();
|
|
23705
23656
|
return;
|
|
23706
23657
|
}
|
|
@@ -23964,11 +23915,10 @@ const hookRun = async (agent, flags) => {
|
|
|
23964
23915
|
process.exit(0);
|
|
23965
23916
|
}
|
|
23966
23917
|
let exitCode = 0;
|
|
23967
|
-
if (agent === "claude")
|
|
23968
|
-
|
|
23969
|
-
|
|
23970
|
-
|
|
23971
|
-
} else if (agent === "cursor") exitCode = await runCursorHook();
|
|
23918
|
+
if (agent === "claude") if (flags?.onFileChanged) exitCode = await runClaudeFileChangedHook();
|
|
23919
|
+
else if (flags?.stop) exitCode = await runClaudeStopHook();
|
|
23920
|
+
else exitCode = await runClaudeHook();
|
|
23921
|
+
else if (agent === "cursor") exitCode = await runCursorHook();
|
|
23972
23922
|
else if (agent === "gemini") exitCode = await runGeminiHook();
|
|
23973
23923
|
else if (agent === "pi") exitCode = await runPiHook();
|
|
23974
23924
|
else {
|
|
@@ -23979,8 +23929,7 @@ const hookRun = async (agent, flags) => {
|
|
|
23979
23929
|
process.exit(exitCode);
|
|
23980
23930
|
};
|
|
23981
23931
|
const hookBaseline = async () => {
|
|
23982
|
-
const
|
|
23983
|
-
const result = await captureBaseline(cwd);
|
|
23932
|
+
const result = await captureBaseline(process.cwd());
|
|
23984
23933
|
process.stdout.write(renderHookBaseline({
|
|
23985
23934
|
score: result.score,
|
|
23986
23935
|
fileCount: result.fileCount,
|
|
@@ -24810,8 +24759,7 @@ const collectRuleEntries = (directory) => {
|
|
|
24810
24759
|
for (const { engine, rules } of BUILTIN_RULES) for (const rule of rules) entries.push(toRuleEntry(engine, rule));
|
|
24811
24760
|
const configDir = findConfigDir(resolvedDir);
|
|
24812
24761
|
if (configDir) {
|
|
24813
|
-
const
|
|
24814
|
-
const archRules = loadArchitectureRules(rulesPath);
|
|
24762
|
+
const archRules = loadArchitectureRules(path.join(configDir, RULES_FILE));
|
|
24815
24763
|
for (const rule of archRules) entries.push({
|
|
24816
24764
|
id: `arch/${rule.name}`,
|
|
24817
24765
|
engine: "architecture",
|
|
@@ -25009,7 +24957,7 @@ const trendCommand = async (directory, limit) => {
|
|
|
25009
24957
|
//#endregion
|
|
25010
24958
|
//#region src/update-notifier.ts
|
|
25011
24959
|
const REGISTRY_URL = "https://registry.npmjs.org/@methiu/raigal/latest";
|
|
25012
|
-
const CHECK_INTERVAL_MS =
|
|
24960
|
+
const CHECK_INTERVAL_MS = 1440 * 60 * 1e3;
|
|
25013
24961
|
const REQUEST_TIMEOUT_MS = 2e3;
|
|
25014
24962
|
const CACHE_BASENAME = "update_check.json";
|
|
25015
24963
|
const isUpdateNotifierDisabled = (env = process.env) => {
|
|
@@ -25082,7 +25030,7 @@ const maybeNotifyUpdate = async (now = Date.now()) => {
|
|
|
25082
25030
|
if (!process.stderr.isTTY) return;
|
|
25083
25031
|
const cachePath = resolveUpdateCachePath();
|
|
25084
25032
|
const cache = readCache(cachePath);
|
|
25085
|
-
if (cache && isOutdated("0.2.
|
|
25033
|
+
if (cache && isOutdated("0.2.4", cache.latest)) process.stderr.write(formatUpdateNotice(APP_VERSION, cache.latest));
|
|
25086
25034
|
if (!cache || now - cache.checkedAt > CHECK_INTERVAL_MS) {
|
|
25087
25035
|
const latest = await fetchLatestVersion$1();
|
|
25088
25036
|
if (latest) writeCache(cachePath, {
|
|
@@ -25602,7 +25550,7 @@ const renderCommandGroup = (group, commandWidth) => {
|
|
|
25602
25550
|
return lines;
|
|
25603
25551
|
};
|
|
25604
25552
|
const renderCommandReference = (input = {}) => {
|
|
25605
|
-
const version = input.version ?? "0.2.
|
|
25553
|
+
const version = input.version ?? "0.2.4";
|
|
25606
25554
|
const commandWidth = Math.max(...COMMAND_REFERENCE.map((item) => item.command.length));
|
|
25607
25555
|
const lines = [renderHeader({
|
|
25608
25556
|
version,
|
|
@@ -25824,9 +25772,8 @@ const renderHelpDetails = () => [
|
|
|
25824
25772
|
""
|
|
25825
25773
|
].map((line) => highlightRaigal(line, theme)).join("\n");
|
|
25826
25774
|
const renderHome = (input = {}) => {
|
|
25827
|
-
const version = input.version ?? "0.2.3";
|
|
25828
25775
|
let out = renderHeader({
|
|
25829
|
-
version,
|
|
25776
|
+
version: input.version ?? "0.2.4",
|
|
25830
25777
|
command: "--bare",
|
|
25831
25778
|
context: []
|
|
25832
25779
|
});
|
|
@@ -26077,8 +26024,7 @@ const saveCachedPolicy = (repoSlug, policy) => {
|
|
|
26077
26024
|
};
|
|
26078
26025
|
const fetchRemotePolicy = async (repoSlug, token) => {
|
|
26079
26026
|
try {
|
|
26080
|
-
const
|
|
26081
|
-
const data = await requestApi(endpoint, {
|
|
26027
|
+
const data = await requestApi(`/v1/policy?repo=${encodeURIComponent(repoSlug.toLowerCase())}`, {
|
|
26082
26028
|
method: "GET",
|
|
26083
26029
|
token,
|
|
26084
26030
|
timeoutMs: 4e3
|
|
@@ -26483,7 +26429,7 @@ const printEngineStatus = (result) => {
|
|
|
26483
26429
|
};
|
|
26484
26430
|
//#endregion
|
|
26485
26431
|
//#region src/utils/git.ts
|
|
26486
|
-
const MAX_BUFFER =
|
|
26432
|
+
const MAX_BUFFER = 50 * 1024 * 1024;
|
|
26487
26433
|
const baseRefExists = (cwd, ref) => {
|
|
26488
26434
|
const result = spawnSync("git", [
|
|
26489
26435
|
"rev-parse",
|
|
@@ -27006,8 +26952,7 @@ const renderActionRows = (steps, t) => {
|
|
|
27006
26952
|
const renderTextSteps = (steps, t, s) => {
|
|
27007
26953
|
return steps.filter((step) => step.text).map((step) => {
|
|
27008
26954
|
const glyph = step.emphasis === "primary" ? s.hint : s.bullet;
|
|
27009
|
-
|
|
27010
|
-
return ` ${style$1(t, tokenFor, glyph)} ${highlightAislop(step.text ?? "", t)}`;
|
|
26955
|
+
return ` ${style$1(t, step.emphasis === "primary" ? "accent" : "muted", glyph)} ${highlightAislop(step.text ?? "", t)}`;
|
|
27011
26956
|
});
|
|
27012
26957
|
};
|
|
27013
26958
|
const renderSummary = (input, deps = {}) => {
|
|
@@ -27064,14 +27009,10 @@ const renderSummary = (input, deps = {}) => {
|
|
|
27064
27009
|
return lines.join("\n");
|
|
27065
27010
|
};
|
|
27066
27011
|
const renderStarCta = (deps = {}) => {
|
|
27067
|
-
|
|
27068
|
-
const repository = terminalLink("https://raigal.dev");
|
|
27069
|
-
return `\n ${style$1(t, "muted", `★ Found this useful? Consider purchasing this software at ${repository}`)}\n`;
|
|
27012
|
+
return `\n ${style$1(deps.theme ?? theme, "muted", `★ Found this useful? Consider purchasing this software at ${terminalLink("https://raigal.dev")}`)}\n`;
|
|
27070
27013
|
};
|
|
27071
27014
|
const renderTeamCta = (deps = {}) => {
|
|
27072
|
-
|
|
27073
|
-
const href = terminalLink("https://raigal.dev/contact?intent=team-baseline");
|
|
27074
|
-
return `\n ${style$1(t, "muted", `→ Using raigal with a team? Get a 14-day team baseline at ${href}`)}\n`;
|
|
27015
|
+
return `\n ${style$1(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`;
|
|
27075
27016
|
};
|
|
27076
27017
|
const renderCleanRun = (input, deps = {}) => {
|
|
27077
27018
|
const t = deps.theme ?? theme;
|
|
@@ -27305,7 +27246,7 @@ const runScanBody = async (resolvedDir, config, options, projectInfo, scanScope,
|
|
|
27305
27246
|
architectureRulesPath: config.engines.architecture ? rulesPath : void 0,
|
|
27306
27247
|
engines: config.engines
|
|
27307
27248
|
};
|
|
27308
|
-
const
|
|
27249
|
+
const { results: unannotated, suppressedCount } = applySuppressions((await runEnginesWithProgress({
|
|
27309
27250
|
rootDirectory: resolvedDir,
|
|
27310
27251
|
languages: projectInfo.languages,
|
|
27311
27252
|
frameworks: projectInfo.frameworks,
|
|
@@ -27321,8 +27262,7 @@ const runScanBody = async (resolvedDir, config, options, projectInfo, scanScope,
|
|
|
27321
27262
|
}, config.engines, machineOutput)).map((result) => ({
|
|
27322
27263
|
...result,
|
|
27323
27264
|
diagnostics: config.overrides.length ? result.diagnostics : applyRuleSeverities(result.diagnostics, config.rules)
|
|
27324
|
-
}));
|
|
27325
|
-
const { results: unannotated, suppressedCount } = applySuppressions(severityAdjusted, resolvedDir);
|
|
27265
|
+
})), resolvedDir);
|
|
27326
27266
|
if (suppressedCount > 0 && !machineOutput) log.muted(`Suppressed ${suppressedCount} finding(s) via raigal-ignore directives`);
|
|
27327
27267
|
const changeMap = options.changes && !options.staged ? getChangedLineMap(resolvedDir, options.base) : null;
|
|
27328
27268
|
const results = changeMap ? unannotated.map((result) => ({
|
|
@@ -28033,8 +27973,7 @@ const groupByFile = (diagnostics) => {
|
|
|
28033
27973
|
});
|
|
28034
27974
|
};
|
|
28035
27975
|
const isInstalled = (bin) => {
|
|
28036
|
-
|
|
28037
|
-
return spawnSync(cmd, [bin], { encoding: "utf-8" }).status === 0;
|
|
27976
|
+
return spawnSync(process.platform === "win32" ? "where" : "which", [bin], { encoding: "utf-8" }).status === 0;
|
|
28038
27977
|
};
|
|
28039
27978
|
const copyToClipboard = (text) => {
|
|
28040
27979
|
const args = {
|
|
@@ -28510,8 +28449,7 @@ const fixNarrativeComments = async (context) => {
|
|
|
28510
28449
|
for (let i = 0; i < lines.length; i += 1) if (!toRemove.has(i + 1)) kept.push(lines[i]);
|
|
28511
28450
|
const newContent = kept.join("\n");
|
|
28512
28451
|
if (newContent !== content) {
|
|
28513
|
-
|
|
28514
|
-
if (!areLiteralMultisetsEqual(beforeLiterals, afterLiterals)) continue;
|
|
28452
|
+
if (!areLiteralMultisetsEqual(beforeLiterals, extractStringAndTemplateLiterals(newContent, ext))) continue;
|
|
28515
28453
|
fs.writeFileSync(filePath, newContent);
|
|
28516
28454
|
}
|
|
28517
28455
|
}
|
|
@@ -29005,7 +28943,7 @@ const removeUnusedDeclarations = (rootDirectory, declarations) => {
|
|
|
29005
28943
|
};
|
|
29006
28944
|
//#endregion
|
|
29007
28945
|
//#region src/commands/fix-expo.ts
|
|
29008
|
-
const INSTALL_TIMEOUT$1 =
|
|
28946
|
+
const INSTALL_TIMEOUT$1 = 1800 * 1e3;
|
|
29009
28947
|
const fixExpoDependencies = async (context, onProgress) => {
|
|
29010
28948
|
await removeDisallowedExpoPackages(context.rootDirectory, onProgress);
|
|
29011
28949
|
onProgress?.("Expo dependency alignment · running expo install --fix (can take a few minutes)");
|
|
@@ -29059,8 +28997,8 @@ const removeDisallowedExpoPackages = async (rootDir, onProgress) => {
|
|
|
29059
28997
|
};
|
|
29060
28998
|
//#endregion
|
|
29061
28999
|
//#region src/commands/fix-force.ts
|
|
29062
|
-
const INSTALL_TIMEOUT =
|
|
29063
|
-
const AUDIT_TIMEOUT =
|
|
29000
|
+
const INSTALL_TIMEOUT = 1800 * 1e3;
|
|
29001
|
+
const AUDIT_TIMEOUT = 60 * 1e3;
|
|
29064
29002
|
const detectPackageManager = (rootDirectory) => {
|
|
29065
29003
|
if (fs.existsSync(path.join(rootDirectory, "pnpm-lock.yaml"))) return "pnpm";
|
|
29066
29004
|
if (fs.existsSync(path.join(rootDirectory, "package-lock.json")) || fs.existsSync(path.join(rootDirectory, "package.json"))) return "npm";
|
|
@@ -29358,14 +29296,13 @@ const CANNOT_SCOPE_REASON = "cannot honour an explicit file list under --changes
|
|
|
29358
29296
|
const MISSING_MANIFEST_REASON = "no manifest or lockfile in the selected scope";
|
|
29359
29297
|
const fixScopeError = (resolvedDir, flags) => {
|
|
29360
29298
|
if (flags.changes && flags.staged) return "--changes and --staged cannot be used together.";
|
|
29361
|
-
|
|
29299
|
+
return scanTargetError(resolvedDir, {
|
|
29362
29300
|
changes: Boolean(flags.changes),
|
|
29363
29301
|
staged: Boolean(flags.staged),
|
|
29364
29302
|
base: flags.base,
|
|
29365
29303
|
verbose: false,
|
|
29366
29304
|
json: false
|
|
29367
|
-
};
|
|
29368
|
-
return scanTargetError(resolvedDir, options);
|
|
29305
|
+
});
|
|
29369
29306
|
};
|
|
29370
29307
|
const collectFixFileScope = (rootDirectory, excludePatterns, includePatterns, flags) => {
|
|
29371
29308
|
const mode = resolveScanScopeMode({
|
|
@@ -29424,10 +29361,9 @@ const runFormattingStep = async (deps) => {
|
|
|
29424
29361
|
else if (deps.projectInfo.languages.includes("python")) log.warn("Python detected but ruff is not installed; skipping Python formatting fixes.");
|
|
29425
29362
|
if (deps.projectInfo.languages.includes("go") && deps.projectInfo.installedTools.gofmt) await deps.runStep("Formatting (go)", () => runGofmt(deps.context), () => fixGofmt(deps.context));
|
|
29426
29363
|
else if (deps.projectInfo.languages.includes("go")) log.warn("Go detected but gofmt is not installed; skipping Go formatting fixes.");
|
|
29427
|
-
if (deps.projectInfo.languages.includes("rust") && deps.projectInfo.installedTools.rustfmt)
|
|
29428
|
-
|
|
29429
|
-
|
|
29430
|
-
} else if (deps.projectInfo.languages.includes("rust")) log.warn("Rust detected but rustfmt is not installed; skipping Rust formatting fixes.");
|
|
29364
|
+
if (deps.projectInfo.languages.includes("rust") && deps.projectInfo.installedTools.rustfmt) if (isScopedFix(deps.context)) deps.skipStep?.("Formatting (rust)", CANNOT_SCOPE_REASON);
|
|
29365
|
+
else await deps.runStep("Formatting (rust)", () => runGenericFormatter(deps.context, "rust"), () => fixGenericFormatter(deps.context, "rust"));
|
|
29366
|
+
else if (deps.projectInfo.languages.includes("rust")) log.warn("Rust detected but rustfmt is not installed; skipping Rust formatting fixes.");
|
|
29431
29367
|
if (deps.projectInfo.languages.includes("ruby") && deps.projectInfo.installedTools.rubocop) {
|
|
29432
29368
|
if (!skipUnsafeSafeFormatter(deps, "ruby")) await deps.runStep("Formatting (ruby)", () => runGenericFormatter(deps.context, "ruby"), () => fixGenericFormatter(deps.context, "ruby"));
|
|
29433
29369
|
} else if (deps.projectInfo.languages.includes("ruby")) log.warn("Ruby detected but rubocop is not installed; skipping Ruby formatting fixes.");
|
|
@@ -29476,8 +29412,7 @@ const runDeclarationStep = async (deps) => {
|
|
|
29476
29412
|
if (!deps.config.engines["code-quality"]) return;
|
|
29477
29413
|
if (!hasJsOrTs(deps.projectInfo)) return;
|
|
29478
29414
|
await deps.runStep("Unused declarations", () => detectUnusedDeclarations(deps.context), async () => {
|
|
29479
|
-
const
|
|
29480
|
-
const declarations = diagnosticsToDeclarations(diagnostics);
|
|
29415
|
+
const declarations = diagnosticsToDeclarations(await detectUnusedDeclarations(deps.context));
|
|
29481
29416
|
removeUnusedDeclarations(deps.resolvedDir, declarations);
|
|
29482
29417
|
});
|
|
29483
29418
|
};
|
|
@@ -29508,14 +29443,10 @@ const runForceSteps = async (deps) => {
|
|
|
29508
29443
|
return (await runKnipUnusedFiles(deps.resolvedDir)).filter((diagnostic) => isPathInFixScope(deps.context, diagnostic.filePath));
|
|
29509
29444
|
}, () => fixUnusedFiles(deps.resolvedDir, (filePath) => isPathInFixScope(deps.context, filePath)));
|
|
29510
29445
|
const railUpdate = (label) => deps.rail.setActiveLabel(label);
|
|
29511
|
-
if (deps.config.engines.security)
|
|
29512
|
-
|
|
29513
|
-
|
|
29514
|
-
|
|
29515
|
-
if (deps.projectInfo.frameworks.includes("expo") && deps.config.lint.expoDoctor) {
|
|
29516
|
-
if (!scopeIncludesManifestWrites(deps.context)) deps.skipStep?.("Expo dependency alignment", MISSING_MANIFEST_REASON);
|
|
29517
|
-
else await deps.runStep("Expo dependency alignment", () => runExpoDoctor(deps.context), () => fixExpoDependencies(deps.context, railUpdate));
|
|
29518
|
-
}
|
|
29446
|
+
if (deps.config.engines.security) if (!scopeIncludesManifestWrites(deps.context)) deps.skipStep?.("Dependency audit fixes", MISSING_MANIFEST_REASON);
|
|
29447
|
+
else await deps.runStep("Dependency audit fixes", () => runDependencyAudit(deps.context), () => fixDependencyAudit(deps.context, railUpdate));
|
|
29448
|
+
if (deps.projectInfo.frameworks.includes("expo") && deps.config.lint.expoDoctor) if (!scopeIncludesManifestWrites(deps.context)) deps.skipStep?.("Expo dependency alignment", MISSING_MANIFEST_REASON);
|
|
29449
|
+
else await deps.runStep("Expo dependency alignment", () => runExpoDoctor(deps.context), () => fixExpoDependencies(deps.context, railUpdate));
|
|
29519
29450
|
};
|
|
29520
29451
|
//#endregion
|
|
29521
29452
|
//#region src/commands/fix-plan.ts
|
|
@@ -29811,8 +29742,7 @@ const runFixBody = async (resolvedDir, config, options, projectInfo) => {
|
|
|
29811
29742
|
brand: options.printBrand !== false
|
|
29812
29743
|
}));
|
|
29813
29744
|
const safe = Boolean(options.safe);
|
|
29814
|
-
const
|
|
29815
|
-
const scope = collectFixFileScope(resolvedDir, excludePatterns, config.include, options);
|
|
29745
|
+
const scope = collectFixFileScope(resolvedDir, [...config.exclude, ...readAislopIgnorePatterns(resolvedDir)], config.include, options);
|
|
29816
29746
|
const scopedProjectInfo = scope ? {
|
|
29817
29747
|
...projectInfo,
|
|
29818
29748
|
languages: detectSourceLanguages([...scope.files, ...scope.testFiles])
|
|
@@ -30162,18 +30092,16 @@ const initCommand = async (directory, options = {}) => {
|
|
|
30162
30092
|
status: "done",
|
|
30163
30093
|
label: `Wrote ${CONFIG_DIR}/${CONFIG_FILE}`
|
|
30164
30094
|
}];
|
|
30165
|
-
if (choices.engines.includes("architecture")) {
|
|
30166
|
-
|
|
30167
|
-
|
|
30168
|
-
|
|
30169
|
-
|
|
30170
|
-
label: `Wrote ${CONFIG_DIR}/${RULES_FILE}`
|
|
30171
|
-
});
|
|
30172
|
-
} else steps.push({
|
|
30173
|
-
status: "skipped",
|
|
30174
|
-
label: `${CONFIG_DIR}/${RULES_FILE} already exists`
|
|
30095
|
+
if (choices.engines.includes("architecture")) if (!fs.existsSync(rulesPath)) {
|
|
30096
|
+
fs.writeFileSync(rulesPath, DEFAULT_RULES_YAML);
|
|
30097
|
+
steps.push({
|
|
30098
|
+
status: "done",
|
|
30099
|
+
label: `Wrote ${CONFIG_DIR}/${RULES_FILE}`
|
|
30175
30100
|
});
|
|
30176
|
-
}
|
|
30101
|
+
} else steps.push({
|
|
30102
|
+
status: "skipped",
|
|
30103
|
+
label: `${CONFIG_DIR}/${RULES_FILE} already exists`
|
|
30104
|
+
});
|
|
30177
30105
|
const workflowResult = writeGithubWorkflow(resolvedDir, choices.writeGithubWorkflow);
|
|
30178
30106
|
if (workflowResult.status === "written") steps.push({
|
|
30179
30107
|
status: "done",
|
|
@@ -30565,13 +30493,11 @@ program.hook("preAction", (_thisCommand, actionCommand) => {
|
|
|
30565
30493
|
"hook"
|
|
30566
30494
|
].includes(cmdName)) {
|
|
30567
30495
|
const flagNames = process.argv.slice(2).filter((arg) => arg.startsWith("-")).map((arg) => arg.replace(/^--?/, "").split("=")[0] ?? "");
|
|
30568
|
-
|
|
30569
|
-
startRunRecorder(cmdName, dir, flagNames);
|
|
30496
|
+
startRunRecorder(cmdName, actionCommand.args?.[0] || process.cwd(), flagNames);
|
|
30570
30497
|
}
|
|
30571
30498
|
});
|
|
30572
30499
|
program.hook("postAction", async () => {
|
|
30573
|
-
|
|
30574
|
-
await finishActiveRecorder(code);
|
|
30500
|
+
await finishActiveRecorder(typeof process.exitCode === "number" ? process.exitCode : 0);
|
|
30575
30501
|
});
|
|
30576
30502
|
const main = async () => {
|
|
30577
30503
|
fireInstalledOnce();
|