@methiu/raigal 0.2.2 → 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.
@@ -1,5 +1,5 @@
1
- import { t as APP_VERSION } from "./version-9Cnt1TiK.js";
2
- import { i as ENGINE_INFO, n as withFindingAssessments, t as summarizeFindingAssessments } from "./finding-assessment-M5fUTE-C.js";
1
+ import { t as APP_VERSION } from "./version-CukuIVX4.js";
2
+ import { i as ENGINE_INFO, n as withFindingAssessments, t as summarizeFindingAssessments } from "./finding-assessment-CGpt5YUR.js";
3
3
  //#region src/output/json.ts
4
4
  const buildJsonOutput = (results, scoreResult, fileCount, elapsedMs, coverage) => {
5
5
  const allDiagnostics = results.flatMap((r) => r.diagnostics);
package/dist/mcp.js CHANGED
@@ -84,7 +84,7 @@ const getActiveToken = () => {
84
84
  };
85
85
  //#endregion
86
86
  //#region src/version.ts
87
- const APP_VERSION = "0.2.2";
87
+ const APP_VERSION = "0.2.4";
88
88
  //#endregion
89
89
  //#region src/cloud/contract.ts
90
90
  const Severity = z.enum(["error", "warning"]);
@@ -359,7 +359,7 @@ const verifyEntitlementJwt = (jwt, options = {}) => {
359
359
  const claims = parsed.data;
360
360
  const expectedIssuer = process.env.RAIGAL_ISSUER?.trim() || "https://app.raigal.dev";
361
361
  if (claims.iss !== expectedIssuer) throw new JwtVerificationError(`Untrusted issuer: ${claims.iss}`, "invalid_issuer");
362
- if (!isVersionAtLeast("0.2.2", 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");
362
+ 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");
363
363
  const now = options.nowSeconds ?? Math.floor(Date.now() / 1e3);
364
364
  const grace = options.allowGraceSeconds ?? 0;
365
365
  if (now > claims.exp + grace) {
@@ -532,7 +532,7 @@ const getEntitlement = async () => {
532
532
  };
533
533
  //#endregion
534
534
  //#region src/cloud/owner.ts
535
- const GITHUB_REMOTE_RE = /^(?:(?:git@|ssh:\/\/(?:git@)?)github\.com(?::(?:\d+\/)?|[:/])|https:\/\/(?:[^@]+@)?github\.com\/)([^/]+)\/([^/.\s]+?)(?:\.git)?\s*$/;
535
+ const GITHUB_REMOTE_RE = /^(?:(?:git@|ssh:\/\/(?:git@)?)github\.com(?::(?:\d+\/)?|[:/])|https:\/\/(?:[^@]+@)?github\.com\/)([^/]+)\/([^/\s]+?)(?:\.git)?\s*$/;
536
536
  const parseGitRemote = (rawUrl) => {
537
537
  if (!rawUrl) return {
538
538
  owner: null,
@@ -994,6 +994,9 @@ const CiSchema = z.object({
994
994
  format: z.enum(["json"]).default("json")
995
995
  }).strict();
996
996
  const TelemetrySchema = z.object({ enabled: z.boolean().default(true) }).strict();
997
+ const BaselineConfigSchema = z.object({ mode: z.enum(["strict", "relaxed"]).default("relaxed") }).strict();
998
+ const LicensingConfigSchema = z.object({ onLapse: z.enum(["fail-open", "fail-closed"]).default("fail-open") }).strict();
999
+ const WorkspaceConfigSchema = z.object({ minimumFloor: z.number().min(0).max(100).default(50) }).strict();
997
1000
  const RuleSeverityOverride = z.enum([
998
1001
  "error",
999
1002
  "warning",
@@ -1064,6 +1067,9 @@ const AislopConfigSchema = z.object({
1064
1067
  format: "json"
1065
1068
  })),
1066
1069
  telemetry: TelemetrySchema.default(() => ({ enabled: true })),
1070
+ baseline: BaselineConfigSchema.optional(),
1071
+ licensing: LicensingConfigSchema.optional(),
1072
+ workspace: WorkspaceConfigSchema.optional(),
1067
1073
  rules: RulesSchema,
1068
1074
  overrides: z.array(FileOverrideSchema).default(() => []),
1069
1075
  exclude: z.array(z.string()).default(() => [
@@ -1097,6 +1103,9 @@ const KNOWN_KEYS_BY_PATH = {
1097
1103
  "scoring",
1098
1104
  "ci",
1099
1105
  "telemetry",
1106
+ "baseline",
1107
+ "licensing",
1108
+ "workspace",
1100
1109
  "rules",
1101
1110
  "exclude",
1102
1111
  "include"
@@ -1147,7 +1156,10 @@ const KNOWN_KEYS_BY_PATH = {
1147
1156
  ],
1148
1157
  "scoring.thresholds": ["good", "ok"],
1149
1158
  ci: ["failBelow", "format"],
1150
- telemetry: ["enabled"]
1159
+ telemetry: ["enabled"],
1160
+ baseline: ["mode"],
1161
+ licensing: ["onLapse"],
1162
+ workspace: ["minimumFloor"]
1151
1163
  };
1152
1164
  const levenshtein = (a, b) => {
1153
1165
  const m = a.length;
@@ -2567,7 +2579,7 @@ const tokenizeJs = (content, ext = ".ts") => {
2567
2579
  };
2568
2580
  //#endregion
2569
2581
  //#region src/utils/source-masker.ts
2570
- const JS_EXTS$2 = /* @__PURE__ */ new Set([
2582
+ const JS_EXTS$3 = /* @__PURE__ */ new Set([
2571
2583
  ".ts",
2572
2584
  ".tsx",
2573
2585
  ".js",
@@ -2575,7 +2587,7 @@ const JS_EXTS$2 = /* @__PURE__ */ new Set([
2575
2587
  ".mjs",
2576
2588
  ".cjs"
2577
2589
  ]);
2578
- const PY_EXTS = /* @__PURE__ */ new Set([".py"]);
2590
+ const PY_EXTS$1 = /* @__PURE__ */ new Set([".py"]);
2579
2591
  const RB_EXTS = /* @__PURE__ */ new Set([".rb"]);
2580
2592
  const PHP_EXTS = /* @__PURE__ */ new Set([".php"]);
2581
2593
  const CSHARP_EXTS = /* @__PURE__ */ new Set([".cs"]);
@@ -2599,8 +2611,8 @@ const C_STYLE_COMMENT_EXTS = /* @__PURE__ */ new Set([
2599
2611
  ".zig"
2600
2612
  ]);
2601
2613
  const familyForExt = (ext) => {
2602
- if (JS_EXTS$2.has(ext)) return "js";
2603
- if (PY_EXTS.has(ext)) return "py";
2614
+ if (JS_EXTS$3.has(ext)) return "js";
2615
+ if (PY_EXTS$1.has(ext)) return "py";
2604
2616
  if (RB_EXTS.has(ext)) return "rb";
2605
2617
  if (PHP_EXTS.has(ext)) return "php";
2606
2618
  if (CSHARP_EXTS.has(ext)) return "csharp";
@@ -2832,7 +2844,7 @@ const getCommentLines = (content, ext) => {
2832
2844
  };
2833
2845
  //#endregion
2834
2846
  //#region src/engines/ai-slop/abstractions.ts
2835
- const JS_EXTS$1 = /* @__PURE__ */ new Set([
2847
+ const JS_EXTS$2 = /* @__PURE__ */ new Set([
2836
2848
  ".ts",
2837
2849
  ".tsx",
2838
2850
  ".js",
@@ -2843,11 +2855,11 @@ const JS_EXTS$1 = /* @__PURE__ */ new Set([
2843
2855
  const THIN_WRAPPER_PATTERNS = [
2844
2856
  {
2845
2857
  pattern: /(?:export\s+)?(?:async\s+)?function\s+(\w+)\s*\([^)]*\)\s*(?::\s*\w[^{]*)?\{\s*\n?\s*return\s+\w+\([^)]*\);\s*\n?\s*\}/g,
2846
- extensions: JS_EXTS$1
2858
+ extensions: JS_EXTS$2
2847
2859
  },
2848
2860
  {
2849
2861
  pattern: /(?:export\s+)?const\s+(\w+)\s*=\s*(?:async\s+)?\([^)]*\)\s*(?::\s*\w[^=]*)?\s*=>\s*\w+\([^)]*\);/g,
2850
- extensions: JS_EXTS$1
2862
+ extensions: JS_EXTS$2
2851
2863
  },
2852
2864
  {
2853
2865
  pattern: /def\s+(\w+)\s*\([^)]*\)(?:\s*->[^:]*)?:\s*\n\s+return\s+\w+\([^)]*\)\s*$/gm,
@@ -4095,7 +4107,7 @@ const scriptKindFor$1 = (ext) => {
4095
4107
  }
4096
4108
  };
4097
4109
  const lineFor$1 = (sourceFile, node) => sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line + 1;
4098
- const makeDiagnostic = (filePath, line, rule, message, help) => ({
4110
+ const makeDiagnostic$1 = (filePath, line, rule, message, help) => ({
4099
4111
  filePath,
4100
4112
  engine: "ai-slop",
4101
4113
  rule,
@@ -4145,7 +4157,7 @@ const detectRedundantTryCatch = (sourceFile, relativePath) => {
4145
4157
  if (ts.isTryStatement(node) && node.catchClause && !node.finallyBlock) {
4146
4158
  const catchNameNode = node.catchClause.variableDeclaration?.name;
4147
4159
  const [onlyStatement] = node.catchClause.block.statements;
4148
- if (catchNameNode && ts.isIdentifier(catchNameNode) && node.catchClause.block.statements.length === 1 && onlyStatement && (isRethrowStatement(onlyStatement, catchNameNode.text) || isPromiseRejectRethrow(onlyStatement, catchNameNode.text))) diagnostics.push(makeDiagnostic(relativePath, lineFor$1(sourceFile, node.catchClause), "ai-slop/redundant-try-catch", "Catch block only rethrows the same error", "Remove the try/catch or add useful context, cleanup, or recovery. Rethrowing unchanged errors is usually defensive agent noise."));
4160
+ if (catchNameNode && ts.isIdentifier(catchNameNode) && node.catchClause.block.statements.length === 1 && onlyStatement && (isRethrowStatement(onlyStatement, catchNameNode.text) || isPromiseRejectRethrow(onlyStatement, catchNameNode.text))) diagnostics.push(makeDiagnostic$1(relativePath, lineFor$1(sourceFile, node.catchClause), "ai-slop/redundant-try-catch", "Catch block only rethrows the same error", "Remove the try/catch or add useful context, cleanup, or recovery. Rethrowing unchanged errors is usually defensive agent noise."));
4149
4161
  }
4150
4162
  ts.forEachChild(node, visit);
4151
4163
  };
@@ -4163,7 +4175,7 @@ const detectPrimitiveCoercions = (sourceFile, relativePath) => {
4163
4175
  const [arg] = child.arguments;
4164
4176
  if (arg && ts.isIdentifier(arg)) {
4165
4177
  const primitive = params.get(arg.text);
4166
- if (primitive && child.expression.text === COERCION_CTORS[primitive]) diagnostics.push(makeDiagnostic(relativePath, lineFor$1(sourceFile, child), "ai-slop/redundant-type-coercion", `Parameter '${arg.text}' is already typed as ${primitive} but is coerced again`, "Trust the typed boundary or validate unknown input before this function. Re-coercing already typed parameters is usually defensive agent noise."));
4178
+ if (primitive && child.expression.text === COERCION_CTORS[primitive]) diagnostics.push(makeDiagnostic$1(relativePath, lineFor$1(sourceFile, child), "ai-slop/redundant-type-coercion", `Parameter '${arg.text}' is already typed as ${primitive} but is coerced again`, "Trust the typed boundary or validate unknown input before this function. Re-coercing already typed parameters is usually defensive agent noise."));
4167
4179
  }
4168
4180
  }
4169
4181
  ts.forEachChild(child, visitBody);
@@ -4206,7 +4218,7 @@ const detectDuplicateExportedTypes = (parsedSources) => {
4206
4218
  continue;
4207
4219
  }
4208
4220
  if (previous.filePath === declaration.filePath) continue;
4209
- diagnostics.push(makeDiagnostic(declaration.filePath, declaration.line, "ai-slop/duplicate-type-declaration", `Exported type '${declaration.name}' duplicates an existing declaration`, `Reuse or import the existing type from ${previous.filePath} instead of re-declaring the same shape in another file.`));
4221
+ diagnostics.push(makeDiagnostic$1(declaration.filePath, declaration.line, "ai-slop/duplicate-type-declaration", `Exported type '${declaration.name}' duplicates an existing declaration`, `Reuse or import the existing type from ${previous.filePath} instead of re-declaring the same shape in another file.`));
4210
4222
  }
4211
4223
  }
4212
4224
  return diagnostics;
@@ -4308,7 +4320,7 @@ const detectDuplicateImports = async (context) => {
4308
4320
  rule: "ai-slop/duplicate-import",
4309
4321
  severity: "warning",
4310
4322
  message: `"${spec}" is also imported on line ${firstLine}. Merge into a single import statement.`,
4311
- help: "Two imports from the same module split readers' attention and grow the import block. Run aislop fix to merge them automatically.",
4323
+ help: "Two imports from the same module split readers' attention and grow the import block. Run raigal fix to merge them automatically.",
4312
4324
  line: dup.line,
4313
4325
  column: 1,
4314
4326
  category: "AI Slop",
@@ -8148,7 +8160,7 @@ const detectRustPatterns = async (context) => {
8148
8160
  };
8149
8161
  //#endregion
8150
8162
  //#region src/engines/ai-slop/silent-recovery.ts
8151
- const JS_EXTS = /* @__PURE__ */ new Set([
8163
+ const JS_EXTS$1 = /* @__PURE__ */ new Set([
8152
8164
  ".ts",
8153
8165
  ".tsx",
8154
8166
  ".js",
@@ -8343,7 +8355,7 @@ const detectSilentRecovery = async (context) => {
8343
8355
  for (const filePath of files) {
8344
8356
  if (isAutoGenerated(filePath)) continue;
8345
8357
  const ext = path.extname(filePath);
8346
- const isJs = JS_EXTS.has(ext);
8358
+ const isJs = JS_EXTS$1.has(ext);
8347
8359
  if (!isJs && !(ext === ".py")) continue;
8348
8360
  const relPath = relativePosix(context.rootDirectory, filePath);
8349
8361
  if (isNonProductionPath(relPath)) continue;
@@ -8628,7 +8640,7 @@ const detectUnusedCss = async (context) => {
8628
8640
  rule: "ai-slop/unused-css",
8629
8641
  severity: "warning",
8630
8642
  message: `CSS class '.${def.name}' is defined but never referenced in the codebase`,
8631
- help: "Remove the dead CSS rule, or confirm the class is used dynamically (and add an aislop-ignore comment if so)",
8643
+ help: "Remove the dead CSS rule, or confirm the class is used dynamically (and add a raigal-ignore comment if so)",
8632
8644
  line: def.line,
8633
8645
  column: 0,
8634
8646
  category: "AI Slop",
@@ -9718,8 +9730,8 @@ const isTrivialLine = (line) => {
9718
9730
  };
9719
9731
  const SVG_MARKUP_RE = /<\/?(?:svg|path|polyline|line|circle|rect|g)\b|(?:xmlns|viewBox|stroke(?:-width|-linecap|-linejoin)?|fill|fill-opacity|d|points|x1|x2|y1|y2)=/;
9720
9732
  const DATA_LITERAL_RE = /^\s*(?:[A-Za-z_$][\w$-]*:\s*(?:["'`[{]|\d|true\b|false\b|null\b)|["'`][^"'`]*["'`],?\s*$|[{}\]],?\s*$|\),?\s*$)/;
9721
- const SUPPRESS_RE = /aislop[- ]ignore(?:-next-block|-file)?\b.*\b(?:duplicate-block|code-quality\/duplicate-block)\b/;
9722
- const FILE_SUPPRESS_RE = /aislop[- ]ignore-file\b.*\b(?:duplicate-block|code-quality\/duplicate-block)\b/;
9733
+ const SUPPRESS_RE = /(?:raigal|aislop)[- ]ignore(?:-next-block|-file)?\b.*\b(?:duplicate-block|code-quality\/duplicate-block)\b/;
9734
+ const FILE_SUPPRESS_RE = /(?:raigal|aislop)[- ]ignore-file\b.*\b(?:duplicate-block|code-quality\/duplicate-block)\b/;
9723
9735
  const fileHasSuppression = (content) => FILE_SUPPRESS_RE.test(content);
9724
9736
  const isLowSignalMarkupWindow = (lines) => {
9725
9737
  return lines.filter((line) => SVG_MARKUP_RE.test(line)).length >= Math.ceil(WINDOW_SIZE / 2);
@@ -10045,8 +10057,8 @@ const shouldIncludeIssue = (issueType, filePath) => {
10045
10057
  return !filePath.replace(/\\/g, "/").includes(".github/workflows/");
10046
10058
  };
10047
10059
  const DEPENDENCY_HELP = {
10048
- dependencies: "This package is listed in package.json but not imported anywhere. Remove it with `npm uninstall` or `aislop fix`.",
10049
- devDependencies: "This package is listed in package.json but not imported anywhere. Remove it with `npm uninstall` or `aislop fix`.",
10060
+ dependencies: "This package is listed in package.json but not imported anywhere. Remove it with `npm uninstall` or `raigal fix`.",
10061
+ devDependencies: "This package is listed in package.json but not imported anywhere. Remove it with `npm uninstall` or `raigal fix`.",
10050
10062
  unlisted: "This package is imported in code but not declared in package.json. Run `npm install` to add it.",
10051
10063
  unresolved: "This import cannot be resolved. Check for typos or missing packages.",
10052
10064
  binaries: "This binary is used but its package is not in package.json."
@@ -10630,7 +10642,7 @@ const runClangFormat = async (context) => {
10630
10642
  };
10631
10643
  //#endregion
10632
10644
  //#region src/engines/format/dotnet-format.ts
10633
- const REPORT_FILENAME = ".aislop-dotnet-format.json";
10645
+ const REPORT_FILENAME = ".raigal-dotnet-format.json";
10634
10646
  const parseDotnetFormatReport = (json, rootDirectory) => {
10635
10647
  if (!json) return [];
10636
10648
  let report;
@@ -10888,7 +10900,7 @@ const runGofmt = async (context) => {
10888
10900
  rule: "go-formatting",
10889
10901
  severity: "warning",
10890
10902
  message: "Go file is not formatted correctly",
10891
- help: "Run `aislop fix` to auto-format with gofmt",
10903
+ help: "Run `raigal fix` to auto-format with gofmt",
10892
10904
  line: 0,
10893
10905
  column: 0,
10894
10906
  category: "Format",
@@ -10907,7 +10919,8 @@ const resolvePackageRoot = (startFile) => {
10907
10919
  while (true) {
10908
10920
  const packageJsonPath = path.join(current, "package.json");
10909
10921
  if (fs.existsSync(packageJsonPath)) try {
10910
- if (JSON.parse(fs.readFileSync(packageJsonPath, "utf-8")).name === "aislop") return current;
10922
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
10923
+ if (packageJson.name === "aislop" || packageJson.name === "@methiu/raigal" || packageJson.name === "raigal") return current;
10911
10924
  } catch {}
10912
10925
  const parent = path.dirname(current);
10913
10926
  if (parent === current) break;
@@ -11018,7 +11031,7 @@ const parseRuffFormatOutput = (output, rootDir) => {
11018
11031
  rule: "python-formatting",
11019
11032
  severity: "warning",
11020
11033
  message: "Python file is not formatted correctly",
11021
- help: "Run `aislop fix` to auto-format with ruff",
11034
+ help: "Run `raigal fix` to auto-format with ruff",
11022
11035
  line: 0,
11023
11036
  column: 0,
11024
11037
  category: "Format",
@@ -11461,7 +11474,7 @@ const runExpoDoctor = async (context) => {
11461
11474
  rule: "expo-doctor/config-error",
11462
11475
  severity: "warning",
11463
11476
  message: configError,
11464
- help: "Install project dependencies, then re-run `aislop scan`.",
11477
+ help: "Install project dependencies, then re-run `raigal scan`.",
11465
11478
  line: 0,
11466
11479
  column: 0,
11467
11480
  category: "Expo",
@@ -12568,6 +12581,174 @@ const lintEngine = {
12568
12581
  }
12569
12582
  };
12570
12583
  //#endregion
12584
+ //#region src/engines/security/ai-security.ts
12585
+ const JS_EXTS = /* @__PURE__ */ new Set([
12586
+ ".ts",
12587
+ ".tsx",
12588
+ ".js",
12589
+ ".jsx",
12590
+ ".mjs",
12591
+ ".cjs"
12592
+ ]);
12593
+ const PY_EXTS = /* @__PURE__ */ new Set([".py"]);
12594
+ const UNICODE_TAG_RE = /[\u{E0000}-\u{E007F}]/gu;
12595
+ const hasRuleIgnore = (lines, lineIndex, ruleSuffix) => {
12596
+ const start = Math.max(0, lineIndex - 2);
12597
+ const re = new RegExp(`(?:raigal|aislop)[- ]ignore(?:-file)?\\b.*(?:${ruleSuffix}|security\\/${ruleSuffix})`, "i");
12598
+ return lines.slice(start, lineIndex + 1).some((line) => re.test(line));
12599
+ };
12600
+ const hasFileIgnore = (lines, ruleSuffix) => {
12601
+ const re = new RegExp(`(?:raigal|aislop)[- ]ignore-file\\b.*(?:${ruleSuffix}|security\\/${ruleSuffix})`, "i");
12602
+ return lines.slice(0, 10).some((line) => re.test(line));
12603
+ };
12604
+ const makeDiagnostic = (filePath, rule, message, help, line, column) => ({
12605
+ filePath,
12606
+ engine: "security",
12607
+ rule,
12608
+ severity: "error",
12609
+ message,
12610
+ help,
12611
+ line,
12612
+ column,
12613
+ category: "Security",
12614
+ fixable: false
12615
+ });
12616
+ const P_BYPASS = "bypassPermissions";
12617
+ const P_EXEC_TYPE = "executor_type";
12618
+ const P_LOCAL = "local";
12619
+ const P_USE_DOCKER = "use_docker";
12620
+ const P_AUTO_RUN = "auto_run";
12621
+ const P_UNSAFE_MODE = "unsafe_mode";
12622
+ const P_PYTHON_REPL = "PythonREPLTool";
12623
+ const UNSANDBOXED_TOOL_PATTERNS = [
12624
+ {
12625
+ pattern: new RegExp(`\\bpermission_?mode["']?\\s*[:=]\\s*["']${P_BYPASS}["']`, "i"),
12626
+ message: `permission_mode '${P_BYPASS}' bypasses agent sandboxing and human confirmation`,
12627
+ help: `Do not use ${P_BYPASS} mode in production; use standard interactive approval`
12628
+ },
12629
+ {
12630
+ pattern: new RegExp(`\\b${P_EXEC_TYPE}["']?\\s*[:=]\\s*["']${P_LOCAL}["']`, "i"),
12631
+ message: `${P_EXEC_TYPE}='${P_LOCAL}' executes LLM-generated code directly on host machine without container isolation`,
12632
+ help: "Configure agent to use DockerCommandLineCodeExecutor or a containerized sandbox environment"
12633
+ },
12634
+ {
12635
+ pattern: new RegExp(`\\b(?:LocalCommandLineCodeExecutor|LocalCodeExecutor)\\s*\\(`),
12636
+ message: "Local code executor executes LLM-generated code on host machine without container isolation",
12637
+ help: "Use DockerCommandLineCodeExecutor or an isolated execution sandbox"
12638
+ },
12639
+ {
12640
+ pattern: new RegExp(`\\b${P_USE_DOCKER}\\s*[:=]\\s*(?:False|false)\\b|["']${P_USE_DOCKER}["']\\s*:\\s*(?:False|false)\\b`),
12641
+ message: `${P_USE_DOCKER}=False disables container sandboxing for agent code execution`,
12642
+ help: `Set ${P_USE_DOCKER}=True to isolate agent execution inside Docker containers`
12643
+ },
12644
+ {
12645
+ pattern: new RegExp(`\\b(?:interpreter\\.)?${P_AUTO_RUN}\\s*[:=]\\s*(?:True|true)\\b`),
12646
+ message: `${P_AUTO_RUN}=True allows autonomous shell execution without human confirmation`,
12647
+ help: `Keep ${P_AUTO_RUN}=False so dangerous commands require explicit human review`
12648
+ },
12649
+ {
12650
+ pattern: new RegExp(`\\bCodeInterpreterTool\\s*\\([^)]*${P_UNSAFE_MODE}\\s*=\\s*(?:True|true)\\b|\\b${P_UNSAFE_MODE}\\s*[:=]\\s*(?:True|true)\\b`),
12651
+ message: `${P_UNSAFE_MODE}=True allows code interpreter tool to execute without Docker isolation`,
12652
+ help: `Disable ${P_UNSAFE_MODE} and isolate code execution in containerized environments`
12653
+ },
12654
+ {
12655
+ pattern: new RegExp(`\\b(?:${P_PYTHON_REPL}|PythonAstREPLTool)\\s*\\(`),
12656
+ message: `${P_PYTHON_REPL} executes arbitrary Python code in host process without container isolation`,
12657
+ help: `Use containerized sandbox execution rather than unconfined ${P_PYTHON_REPL} in production`
12658
+ }
12659
+ ];
12660
+ const P_SYS = "system";
12661
+ const P_DEV = "developer";
12662
+ const P_SM = "SystemMessage";
12663
+ const PROMPT_INJECTION_JS_PATTERNS = [
12664
+ new RegExp(`(?:role\\s*:\\s*["'](?:${P_SYS}|${P_DEV})["'][^}{;]{0,120}?content\\s*:\\s*\`[^\`]*\\$\\{[^}]+\\}[^\`]*\`)`, "g"),
12665
+ new RegExp(`(?:content\\s*:\\s*\`[^\`]*\\$\\{[^}]+\\}[^\`]*\`[^}{;]{0,120}?role\\s*:\\s*["'](?:${P_SYS}|${P_DEV})["'])`, "g"),
12666
+ new RegExp(`(?:role\\s*:\\s*["'](?:${P_SYS}|${P_DEV})["'][^}{;]{0,120}?content\\s*:\\s*(?:["'][^"'\\n]*["']\\s*\\+\\s*[a-zA-Z_$]|[a-zA-Z_$][\\w$]*\\s*\\+\\s*["']))`, "g"),
12667
+ new RegExp(`(?:content\\s*:\\s*(?:["'][^"'\\n]*["']\\s*\\+\\s*[a-zA-Z_$]|[a-zA-Z_$][\\w$]*\\s*\\+\\s*["'])[^}{;]{0,120}?role\\s*:\\s*["'](?:${P_SYS}|${P_DEV})["'])`, "g"),
12668
+ new RegExp(`\\b(?:${P_SYS}|systemPrompt|system_prompt|system_instruction)\\s*:\\s*\`[^\`]*\\$\\{[^}]+\\}[^\`]*\``, "g"),
12669
+ new RegExp(`\\b(?:${P_SYS}|systemPrompt|system_prompt|system_instruction)\\s*:\\s*(?:["'][^"'\\n]*["']\\s*\\+\\s*[a-zA-Z_$]|[a-zA-Z_$][\\w$]*\\s*\\+\\s*["'])`, "g"),
12670
+ new RegExp(`\\b(?:new\\s+)?${P_SM}\\s*\\(\\s*(?:\`[^\`]*\\$\\{[^}]+\\}[^\`]*\`|["'][^"'\\n]*["']\\s*\\+\\s*[a-zA-Z_$]|[a-zA-Z_$][\\w$]*\\s*\\+\\s*["']|\\{\\s*content\\s*:\\s*\`[^\`]*\\$\\{[^}]+\\}[^\`]*\`)`, "g"),
12671
+ new RegExp(`\\[\\s*["']${P_SYS}["']\\s*,\\s*\`[^\`]*\\$\\{[^}]+\\}[^\`]*\`\\s*\\]`, "g")
12672
+ ];
12673
+ const PROMPT_INJECTION_PY_PATTERNS = [
12674
+ new RegExp(`(?:["']role["']\\s*:\\s*["'](?:${P_SYS}|${P_DEV})["'][^}{;]{0,120}?["']content["']\\s*:\\s*f(?:"""[\\s\\S]*?\\{[^}]+\\}[\\s\\S]*?"""|\'\'\'[\\s\\S]*?\\{[^}]+\\}[\\s\\S]*?\'\'\'|["'][^"'\\n]*?\\{[^}]+\\}[^"'\\n]*?["']))`, "g"),
12675
+ new RegExp(`(?:["']content["']\\s*:\\s*f(?:"""[\\s\\S]*?\\{[^}]+\\}[\\s\\S]*?"""|\'\'\'[\\s\\S]*?\\{[^}]+\\}[\\s\\S]*?\'\'\'|["'][^"'\\n]*?\\{[^}]+\\}[^"'\\n]*?["'])[^}{;]{0,120}?["']role["']\\s*:\\s*["'](?:${P_SYS}|${P_DEV})["'])`, "g"),
12676
+ new RegExp(`(?:["']role["']\\s*:\\s*["'](?:${P_SYS}|${P_DEV})["'][^}{;]{0,120}?["']content["']\\s*:\\s*(?:["'][^"'\\n]*["']\\s*\\+\\s*[a-zA-Z_]|[a-zA-Z_]\\w*\\s*\\+\\s*["']|["'][^"'\\n]*["']\\.format\\())`, "g"),
12677
+ new RegExp(`(?:["']content["']\\s*:\\s*(?:["'][^"'\\n]*["']\\s*\\+\\s*[a-zA-Z_]|[a-zA-Z_]\\w*\\s*\\+\\s*["']|["'][^"'\\n]*["']\\.format\\()[^}{;]{0,120}?["']role["']\\s*:\\s*["'](?:${P_SYS}|${P_DEV})["'])`, "g"),
12678
+ new RegExp(`\\b(?:${P_SYS}|system_prompt|system_message|system_instruction)\\s*=\\s*f(?:"""[\\s\\S]*?\\{[^}]+\\}[\\s\\S]*?"""|\'\'\'[\\s\\S]*?\\{[^}]+\\}[\\s\\S]*?\'\'\'|["'][^"'\\n]*?\\{[^}]+\\}[^"'\\n]*?["'])`, "g"),
12679
+ new RegExp(`\\b(?:${P_SYS}|system_prompt|system_message|system_instruction)\\s*=\\s*(?:["'][^"'\\n]*["']\\s*\\+\\s*[a-zA-Z_]|[a-zA-Z_]\\w*\\s*\\+\\s*["']|["'][^"'\\n]*["']\\.format\\()`, "g"),
12680
+ new RegExp(`\\b${P_SM}\\s*\\(\\s*(?:content\\s*=\\s*)?f(?:"""[\\s\\S]*?\\{[^}]+\\}[\\s\\S]*?"""|\'\'\'[\\s\\S]*?\\{[^}]+\\}[\\s\\S]*?\'\'\'|["'][^"'\\n]*?\\{[^}]+\\}[^"'\\n]*?["'])`, "g"),
12681
+ new RegExp(`\\b${P_SM}\\s*\\(\\s*(?:content\\s*=\\s*)?(?:["'][^"'\\n]*["']\\s*\\+\\s*[a-zA-Z_]|[a-zA-Z_]\\w*\\s*\\+\\s*["']|["'][^"'\\n]*["']\\.format\\()`, "g"),
12682
+ new RegExp(`\\(\\s*["']${P_SYS}["']\\s*,\\s*f(?:"""[\\s\\S]*?\\{[^}]+\\}[\\s\\S]*?"""|\'\'\'[\\s\\S]*?\\{[^}]+\\}[\\s\\S]*?\'\'\'|["'][^"'\\n]*?\\{[^}]+\\}[^"'\\n]*?["'])\\s*\\)`, "g")
12683
+ ];
12684
+ const checkInvisibleUnicode = (relPath, content, lines) => {
12685
+ if (hasFileIgnore(lines, "invisible-unicode-tags")) return [];
12686
+ const results = [];
12687
+ const tagRegex = new RegExp(UNICODE_TAG_RE.source, UNICODE_TAG_RE.flags);
12688
+ for (const match of content.matchAll(tagRegex)) {
12689
+ const matchIndex = match.index ?? 0;
12690
+ const line = content.slice(0, matchIndex).split("\n").length;
12691
+ const col = matchIndex - content.lastIndexOf("\n", matchIndex - 1);
12692
+ if (hasRuleIgnore(lines, line - 1, "invisible-unicode-tags")) continue;
12693
+ results.push(makeDiagnostic(relPath, "security/invisible-unicode-tags", "Invisible Unicode Tag character (U+E0000-U+E007F) detected: potential stealth prompt injection or ASCII smuggling", "Remove invisible Unicode tag characters. Unicode Tag block (U+E0000-U+E007F) has no legitimate printable presentation in source code", line, col));
12694
+ }
12695
+ return results;
12696
+ };
12697
+ const checkUnsandboxedTools = (relPath, content, lines) => {
12698
+ if (hasFileIgnore(lines, "unsandboxed-agent-tool")) return [];
12699
+ const results = [];
12700
+ for (const { pattern, message, help } of UNSANDBOXED_TOOL_PATTERNS) {
12701
+ const regex = new RegExp(pattern.source, pattern.flags.includes("g") ? pattern.flags : `${pattern.flags}g`);
12702
+ for (const match of content.matchAll(regex)) {
12703
+ const matchIndex = match.index ?? 0;
12704
+ const line = content.slice(0, matchIndex).split("\n").length;
12705
+ const col = matchIndex - content.lastIndexOf("\n", matchIndex - 1);
12706
+ if (hasRuleIgnore(lines, line - 1, "unsandboxed-agent-tool")) continue;
12707
+ results.push(makeDiagnostic(relPath, "security/unsandboxed-agent-tool", message, help, line, col));
12708
+ }
12709
+ }
12710
+ return results;
12711
+ };
12712
+ const checkPromptInjection = (relPath, content, lines, isJs) => {
12713
+ if (hasFileIgnore(lines, "prompt-injection")) return [];
12714
+ const results = [];
12715
+ const patterns = isJs ? PROMPT_INJECTION_JS_PATTERNS : PROMPT_INJECTION_PY_PATTERNS;
12716
+ for (const pattern of patterns) {
12717
+ const regex = new RegExp(pattern.source, pattern.flags);
12718
+ for (const match of content.matchAll(regex)) {
12719
+ const matchIndex = match.index ?? 0;
12720
+ const line = content.slice(0, matchIndex).split("\n").length;
12721
+ const col = matchIndex - content.lastIndexOf("\n", matchIndex - 1);
12722
+ if (hasRuleIgnore(lines, line - 1, "prompt-injection")) continue;
12723
+ results.push(makeDiagnostic(relPath, "security/prompt-injection", "Untrusted variable interpolation into system prompt creates prompt injection vulnerability", "Keep system prompts static. Pass dynamic user inputs via user messages or input parameters with strict delimiters", line, col));
12724
+ }
12725
+ }
12726
+ return results;
12727
+ };
12728
+ const scanAiSecurity = async (context) => {
12729
+ const files = getSourceFiles(context);
12730
+ const diagnostics = [];
12731
+ for (const filePath of files) {
12732
+ const ext = path.extname(filePath);
12733
+ let content;
12734
+ try {
12735
+ content = fs.readFileSync(filePath, "utf-8");
12736
+ } catch {
12737
+ continue;
12738
+ }
12739
+ const relativePath = relativePosix(context.rootDirectory, filePath);
12740
+ const lines = content.split("\n");
12741
+ diagnostics.push(...checkInvisibleUnicode(relativePath, content, lines));
12742
+ const isJs = JS_EXTS.has(ext);
12743
+ const isPy = PY_EXTS.has(ext);
12744
+ if (isJs || isPy) {
12745
+ diagnostics.push(...checkUnsandboxedTools(relativePath, content, lines));
12746
+ diagnostics.push(...checkPromptInjection(relativePath, content, lines, isJs));
12747
+ }
12748
+ }
12749
+ return diagnostics;
12750
+ };
12751
+ //#endregion
12571
12752
  //#region src/ui/invocation.ts
12572
12753
  const detectInvocation = () => "raigal";
12573
12754
  //#endregion
@@ -12950,7 +13131,7 @@ const parseJsAudit = (output, source, manifest) => {
12950
13131
  rule: "security/dependency-audit-skipped",
12951
13132
  severity: "info",
12952
13133
  message: `Dependency audit skipped (${source}): lockfile is missing`,
12953
- help: errorDetail ?? "Generate a lockfile, then re-run `aislop scan` for dependency vulnerability checks.",
13134
+ help: errorDetail ?? "Generate a lockfile, then re-run `raigal scan` for dependency vulnerability checks.",
12954
13135
  line: 0,
12955
13136
  column: 0,
12956
13137
  category: "Security",
@@ -13508,7 +13689,7 @@ const RISKY_PATTERNS = [
13508
13689
  //#region src/engines/security/risky.ts
13509
13690
  const hasDangerouslySetInnerHtmlIgnore = (lines, lineIndex) => {
13510
13691
  const start = Math.max(0, lineIndex - 2);
13511
- return lines.slice(start, lineIndex + 1).some((line) => /(?:biome-ignore|eslint-disable|aislop-ignore).*(?:noDangerouslySetInnerHtml|dangerouslySetInnerHTML|dangerously-set-innerhtml)/i.test(line));
13692
+ return lines.slice(start, lineIndex + 1).some((line) => /(?:biome-ignore|eslint-disable|raigal-ignore|aislop-ignore).*(?:noDangerouslySetInnerHtml|dangerouslySetInnerHTML|dangerously-set-innerhtml)/i.test(line));
13512
13693
  };
13513
13694
  const isStructuredDataScript = (content, matchIndex) => {
13514
13695
  const before = content.slice(Math.max(0, matchIndex - 300), matchIndex);
@@ -13830,7 +14011,11 @@ const securityEngine = {
13830
14011
  name: "security",
13831
14012
  async run(context) {
13832
14013
  const diagnostics = [];
13833
- const promises = [scanSecrets(context), detectRiskyConstructs(context)];
14014
+ const promises = [
14015
+ scanSecrets(context),
14016
+ detectRiskyConstructs(context),
14017
+ scanAiSecurity(context)
14018
+ ];
13834
14019
  if (context.config.security.audit) promises.push(runDependencyAudit(context));
13835
14020
  const results = await Promise.allSettled(promises);
13836
14021
  for (const result of results) if (result.status === "fulfilled") diagnostics.push(...result.value);
@@ -14100,6 +14285,9 @@ const RULE_SCORE_IMPACTS = {
14100
14285
  "security/shell-injection": strict("Interpolated shell commands can become command execution."),
14101
14286
  "security/unsafe-deserialization": strict("Deserializing untrusted data with a legacy .NET formatter can become remote code execution."),
14102
14287
  "security/unsafe-c-call": strict("Unbounded C string and process calls can become buffer overflows or command execution."),
14288
+ "security/prompt-injection": strict("Dynamic user interpolation in system/developer prompts enables prompt injection attacks."),
14289
+ "security/unsandboxed-agent-tool": strict("Unsandboxed agent code execution or tool permission bypass allows arbitrary host commands."),
14290
+ "security/invisible-unicode-tags": strict("Invisible Unicode Tag characters (U+E0000-U+E007F) hide stealth prompt injection payloads."),
14103
14291
  "security/dependency-audit-skipped": advisory("An unavailable audit is visibility loss, not evidence of a vulnerability."),
14104
14292
  "dotnet/projects-skipped": advisory("Skipping unrestored C# projects is visibility loss, not evidence of a defect."),
14105
14293
  "cppcheck/chunks-skipped": advisory("A skipped cppcheck chunk is visibility loss, not evidence that the skipped files have a defect."),
@@ -14481,18 +14669,25 @@ const hasExistingLiteralBackslashPath = (cwd, fingerprint) => {
14481
14669
  }
14482
14670
  };
14483
14671
  const migrateMarkerlessFingerprint = (cwd, fingerprint) => hasExistingLiteralBackslashPath(cwd, fingerprint) ? fingerprint : normalizeLegacyFingerprint(fingerprint);
14484
- const BASELINE_REL = path.join(".aislop", "baseline.json");
14485
- const baselinePath = (cwd) => path.join(cwd, BASELINE_REL);
14672
+ const baselinePath = (cwd) => {
14673
+ const raigalCandidate = path.join(cwd, ".raigal", "baseline.json");
14674
+ if (fs.existsSync(raigalCandidate)) return raigalCandidate;
14675
+ const raigalDir = path.join(cwd, ".raigal");
14676
+ if (fs.existsSync(raigalDir)) return raigalCandidate;
14677
+ const legacyCandidate = path.join(cwd, ".aislop", "baseline.json");
14678
+ if (fs.existsSync(legacyCandidate)) return legacyCandidate;
14679
+ return raigalCandidate;
14680
+ };
14486
14681
  const readBaseline = (cwd) => {
14487
14682
  const raw = readIfExists(baselinePath(cwd));
14488
14683
  if (!raw) return null;
14489
14684
  try {
14490
14685
  const parsed = JSON.parse(raw);
14491
- if (parsed.schema !== "aislop.baseline.v2" && parsed.schema !== "aislop.baseline.v1") return null;
14686
+ if (parsed.schema !== "aislop.baseline.v2" && parsed.schema !== "aislop.baseline.v1" && parsed.schema !== "raigal.baseline.v2" && parsed.schema !== "raigal.baseline.v1") return null;
14492
14687
  const findingFingerprints = parsed.findingFingerprints ?? [];
14493
14688
  const needsWindowsMigration = parsed.pathFormat !== "posix";
14494
14689
  return {
14495
- schema: "aislop.baseline.v2",
14690
+ schema: "raigal.baseline.v2",
14496
14691
  pathFormat: "posix",
14497
14692
  updatedAt: parsed.updatedAt ?? "",
14498
14693
  score: parsed.score ?? 0,
@@ -14688,12 +14883,11 @@ const runScan = async (cwd) => {
14688
14883
  }
14689
14884
  };
14690
14885
  };
14691
- const aislopScanInputSchema = z$1.object({ path: z$1.string().optional().describe("Project directory to scan, confined to the MCP server's cwd. Defaults to that cwd.") });
14692
- const aislopScanTool = {
14886
+ const raigalScanInputSchema = z$1.object({ path: z$1.string().optional().describe("Project directory to scan, confined to the MCP server's cwd. Defaults to that cwd.") });
14887
+ const raigalScanTool = {
14693
14888
  name: "raigal_scan",
14694
14889
  description: "Scan a project with Raigal. Runs the deterministic engines (format, lint, code-quality, ai-slop, security, architecture), returns a 0–100 score and the top findings. Use this before deciding whether the agent's recent changes are ready to ship.",
14695
- inputSchema: aislopScanInputSchema,
14696
- name: "aislop_scan"
14890
+ inputSchema: raigalScanInputSchema
14697
14891
  };
14698
14892
  const handleRaigalScan = async (input) => {
14699
14893
  const cwd = resolveCwd(input.path);
@@ -14708,7 +14902,7 @@ const handleRaigalScan = async (input) => {
14708
14902
  ...summary
14709
14903
  };
14710
14904
  };
14711
- const aislopFixInputSchema = z$1.object({
14905
+ const raigalFixInputSchema = z$1.object({
14712
14906
  path: z$1.string().optional().describe("Project directory to fix, confined to the MCP server's cwd. Defaults to that cwd."),
14713
14907
  force: z$1.boolean().optional().describe("Run aggressive fixes (dependency audit overrides, unused-file removal, framework alignment). Off by default; on means writes to package.json and may delete files.")
14714
14908
  });
@@ -14738,11 +14932,10 @@ const runRaigalFix = (cwd, force) => {
14738
14932
  }));
14739
14933
  });
14740
14934
  };
14741
- const aislopFixTool = {
14935
+ const raigalFixTool = {
14742
14936
  name: "raigal_fix",
14743
14937
  description: "Apply mechanical fixes (formatting, unused imports, narrative comments, duplicate imports, etc.). Returns counts before/after so the agent can see how many issues remain. Use BEFORE handing off to the agent — saves tokens by clearing what the CLI handles deterministically.",
14744
- inputSchema: aislopFixInputSchema,
14745
- name: "aislop_fix"
14938
+ inputSchema: raigalFixInputSchema
14746
14939
  };
14747
14940
  const handleRaigalFix = async (input) => {
14748
14941
  const cwd = resolveCwd(input.path);
@@ -14764,12 +14957,11 @@ const handleRaigalFix = async (input) => {
14764
14957
  elided: summary.elided
14765
14958
  };
14766
14959
  };
14767
- const aislopWhyInputSchema = z$1.object({ rule_id: z$1.string().describe("Full rule id (e.g. `ai-slop/narrative-comment`, `complexity/function-too-long`, `security/sql-injection`).") });
14768
- const aislopWhyTool = {
14960
+ const raigalWhyInputSchema = z$1.object({ rule_id: z$1.string().describe("Full rule id (e.g. `ai-slop/narrative-comment`, `complexity/function-too-long`, `security/sql-injection`).") });
14961
+ const raigalWhyTool = {
14769
14962
  name: "raigal_why",
14770
14963
  description: "Explain a Raigal rule: what it catches, why an AI agent typically produces it, severity, and whether it's auto-fixable. Use when a finding's message alone isn't enough to act on.",
14771
- inputSchema: aislopWhyInputSchema,
14772
- name: "aislop_why"
14964
+ inputSchema: raigalWhyInputSchema
14773
14965
  };
14774
14966
  const handleRaigalWhy = (input) => {
14775
14967
  const ruleId = input.rule_id.trim();
@@ -14782,12 +14974,11 @@ const handleRaigalWhy = (input) => {
14782
14974
  hint: "Run `raigal rules` for the full list of rules and their auto-fix status. The /patterns page has bad/good code examples for every named ai-slop pattern."
14783
14975
  };
14784
14976
  };
14785
- const aislopBaselineInputSchema = z$1.object({ path: z$1.string().optional().describe("Project directory, confined to the MCP server's cwd. Defaults to that cwd.") });
14786
- const aislopBaselineTool = {
14977
+ const raigalBaselineInputSchema = z$1.object({ path: z$1.string().optional().describe("Project directory, confined to the MCP server's cwd. Defaults to that cwd.") });
14978
+ const raigalBaselineTool = {
14787
14979
  name: "raigal_baseline",
14788
14980
  description: "Read the project's baseline (the last captured score the per-edit hook compares against). Returns score / lastScanAt / fileCount, or null if no baseline exists yet (run `raigal hook baseline` to capture).",
14789
- inputSchema: aislopBaselineInputSchema,
14790
- name: "aislop_baseline"
14981
+ inputSchema: raigalBaselineInputSchema
14791
14982
  };
14792
14983
  const handleRaigalBaseline = (input) => {
14793
14984
  const baseline = readBaseline(resolveCwd(input.path));
@@ -15164,37 +15355,21 @@ const buildServer = () => {
15164
15355
  name: "raigal",
15165
15356
  version: APP_VERSION
15166
15357
  });
15167
- server.registerTool(aislopScanTool.name, {
15168
- description: aislopScanTool.description,
15169
- inputSchema: aislopScanInputSchema.shape
15170
- }, (input) => instrument("aislop_scan", () => handleRaigalScan(input)));
15171
- server.registerTool(aislopFixTool.name, {
15172
- description: aislopFixTool.description,
15173
- inputSchema: aislopFixInputSchema.shape
15174
- }, (input) => instrument("aislop_fix", () => handleRaigalFix(input)));
15175
- server.registerTool(aislopWhyTool.name, {
15176
- description: aislopWhyTool.description,
15177
- inputSchema: aislopWhyInputSchema.shape
15178
- }, (input) => instrument("aislop_why", () => handleRaigalWhy(input)));
15179
- server.registerTool(aislopBaselineTool.name, {
15180
- description: aislopBaselineTool.description,
15181
- inputSchema: aislopBaselineInputSchema.shape
15182
- }, (input) => instrument("aislop_baseline", () => handleRaigalBaseline(input)));
15183
- server.registerTool("raigal_scan", {
15184
- description: aislopScanTool.description,
15185
- inputSchema: aislopScanInputSchema.shape
15358
+ server.registerTool(raigalScanTool.name, {
15359
+ description: raigalScanTool.description,
15360
+ inputSchema: raigalScanInputSchema.shape
15186
15361
  }, (input) => instrument("raigal_scan", () => handleRaigalScan(input)));
15187
- server.registerTool("raigal_fix", {
15188
- description: aislopFixTool.description,
15189
- inputSchema: aislopFixInputSchema.shape
15362
+ server.registerTool(raigalFixTool.name, {
15363
+ description: raigalFixTool.description,
15364
+ inputSchema: raigalFixInputSchema.shape
15190
15365
  }, (input) => instrument("raigal_fix", () => handleRaigalFix(input)));
15191
- server.registerTool("raigal_why", {
15192
- description: aislopWhyTool.description,
15193
- inputSchema: aislopWhyInputSchema.shape
15366
+ server.registerTool(raigalWhyTool.name, {
15367
+ description: raigalWhyTool.description,
15368
+ inputSchema: raigalWhyInputSchema.shape
15194
15369
  }, (input) => instrument("raigal_why", () => handleRaigalWhy(input)));
15195
- server.registerTool("raigal_baseline", {
15196
- description: aislopBaselineTool.description,
15197
- inputSchema: aislopBaselineInputSchema.shape
15370
+ server.registerTool(raigalBaselineTool.name, {
15371
+ description: raigalBaselineTool.description,
15372
+ inputSchema: raigalBaselineInputSchema.shape
15198
15373
  }, (input) => instrument("raigal_baseline", () => handleRaigalBaseline(input)));
15199
15374
  return server;
15200
15375
  };
@@ -53,7 +53,7 @@ const buildSarifLog = (results) => {
53
53
  version: SARIF_VERSION,
54
54
  runs: [{
55
55
  tool: { driver: {
56
- name: "aislop",
56
+ name: "raigal",
57
57
  version: APP_VERSION,
58
58
  informationUri: "https://github.com/meethiu/raigal",
59
59
  rules