claude-crap 0.2.0 → 0.3.0
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/CHANGELOG.md +33 -0
- package/README.md +4 -3
- package/dist/index.js +64 -1
- package/dist/index.js.map +1 -1
- package/dist/scanner/bootstrap.d.ts +89 -0
- package/dist/scanner/bootstrap.d.ts.map +1 -0
- package/dist/scanner/bootstrap.js +278 -0
- package/dist/scanner/bootstrap.js.map +1 -0
- package/dist/scanner/index.d.ts +1 -0
- package/dist/scanner/index.d.ts.map +1 -1
- package/dist/scanner/index.js +1 -0
- package/dist/scanner/index.js.map +1 -1
- package/dist/schemas/tool-schemas.d.ts +12 -0
- package/dist/schemas/tool-schemas.d.ts.map +1 -1
- package/dist/schemas/tool-schemas.js +12 -0
- package/dist/schemas/tool-schemas.js.map +1 -1
- package/package.json +1 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/bundle/mcp-server.mjs +280 -0
- package/plugin/bundle/mcp-server.mjs.map +4 -4
- package/plugin/package.json +1 -1
- package/src/index.ts +78 -0
- package/src/scanner/bootstrap.ts +383 -0
- package/src/scanner/index.ts +8 -0
- package/src/schemas/tool-schemas.ts +14 -0
- package/src/tests/integration/mcp-server.integration.test.ts +2 -1
- package/src/tests/scanner-bootstrap.test.ts +186 -0
package/dist/scanner/index.js
CHANGED
|
@@ -19,4 +19,5 @@
|
|
|
19
19
|
export { detectScanners } from "./detector.js";
|
|
20
20
|
export { runScanner } from "./runner.js";
|
|
21
21
|
export { autoScan } from "./auto-scan.js";
|
|
22
|
+
export { bootstrapScanner, detectProjectType, generateEslintConfig, } from "./bootstrap.js";
|
|
22
23
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/scanner/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,cAAc,EAAyB,MAAM,eAAe,CAAC;AACtE,OAAO,EAAE,UAAU,EAAyB,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,QAAQ,EAA2C,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/scanner/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,cAAc,EAAyB,MAAM,eAAe,CAAC;AACtE,OAAO,EAAE,UAAU,EAAyB,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,QAAQ,EAA2C,MAAM,gBAAgB,CAAC;AACnF,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,oBAAoB,GAIrB,MAAM,gBAAgB,CAAC"}
|
|
@@ -186,6 +186,18 @@ export declare const ingestScannerOutputSchema: {
|
|
|
186
186
|
* Schema for the `auto_scan` tool. Auto-detects available scanners
|
|
187
187
|
* in the workspace, runs them, and ingests findings into the SARIF store.
|
|
188
188
|
*/
|
|
189
|
+
/**
|
|
190
|
+
* Schema for the `bootstrap_scanner` tool. Detects project type,
|
|
191
|
+
* installs the appropriate scanner, creates config files, and runs
|
|
192
|
+
* auto_scan to verify.
|
|
193
|
+
*/
|
|
194
|
+
export declare const bootstrapScannerSchema: {
|
|
195
|
+
readonly type: "object";
|
|
196
|
+
readonly description: "Detect the project type (JavaScript, TypeScript, Python, Java, C#), install the appropriate scanner (ESLint for JS/TS, Bandit for Python, Semgrep for Java/C#), create a minimal config file, and run auto_scan to verify. Skips installation if a scanner is already configured. Use this when auto_scan finds no scanners and quality grades are vacuously A.";
|
|
197
|
+
readonly properties: {};
|
|
198
|
+
readonly required: readonly [];
|
|
199
|
+
readonly additionalProperties: false;
|
|
200
|
+
};
|
|
189
201
|
export declare const autoScanSchema: {
|
|
190
202
|
readonly type: "object";
|
|
191
203
|
readonly description: "Auto-detect available scanners (ESLint, Semgrep, Bandit, Stryker) in the workspace, execute them, and ingest findings into the SARIF store. Returns detection results, per-scanner execution stats, and total findings ingested. Call this to populate findings without manual scanner invocation.";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-schemas.d.ts","sourceRoot":"","sources":["../../src/schemas/tool-schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH;;;GAGG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiCpB,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;CAyBnB,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;CAuBvB,CAAC;AAEX;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;CAcrB,CAAC;AAEX;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;CAgB3B,CAAC;AAEX;;;;;;;;;;GAUG;AACH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;CAkB5B,CAAC;AAEX;;;;GAIG;AACH;;;GAGG;AACH,eAAO,MAAM,cAAc;;;;;;CAOjB,CAAC;AAEX,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuBpB,CAAC"}
|
|
1
|
+
{"version":3,"file":"tool-schemas.d.ts","sourceRoot":"","sources":["../../src/schemas/tool-schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH;;;GAGG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiCpB,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;CAyBnB,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;CAuBvB,CAAC;AAEX;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;CAcrB,CAAC;AAEX;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;CAgB3B,CAAC;AAEX;;;;;;;;;;GAUG;AACH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;CAkB5B,CAAC;AAEX;;;;GAIG;AACH;;;GAGG;AACH;;;;GAIG;AACH,eAAO,MAAM,sBAAsB;;;;;;CAOzB,CAAC;AAEX,eAAO,MAAM,cAAc;;;;;;CAOjB,CAAC;AAEX,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuBpB,CAAC"}
|
|
@@ -186,6 +186,18 @@ export const ingestScannerOutputSchema = {
|
|
|
186
186
|
* Schema for the `auto_scan` tool. Auto-detects available scanners
|
|
187
187
|
* in the workspace, runs them, and ingests findings into the SARIF store.
|
|
188
188
|
*/
|
|
189
|
+
/**
|
|
190
|
+
* Schema for the `bootstrap_scanner` tool. Detects project type,
|
|
191
|
+
* installs the appropriate scanner, creates config files, and runs
|
|
192
|
+
* auto_scan to verify.
|
|
193
|
+
*/
|
|
194
|
+
export const bootstrapScannerSchema = {
|
|
195
|
+
type: "object",
|
|
196
|
+
description: "Detect the project type (JavaScript, TypeScript, Python, Java, C#), install the appropriate scanner (ESLint for JS/TS, Bandit for Python, Semgrep for Java/C#), create a minimal config file, and run auto_scan to verify. Skips installation if a scanner is already configured. Use this when auto_scan finds no scanners and quality grades are vacuously A.",
|
|
197
|
+
properties: {},
|
|
198
|
+
required: [],
|
|
199
|
+
additionalProperties: false,
|
|
200
|
+
};
|
|
189
201
|
export const autoScanSchema = {
|
|
190
202
|
type: "object",
|
|
191
203
|
description: "Auto-detect available scanners (ESLint, Semgrep, Bandit, Stryker) in the workspace, execute them, and ingest findings into the SARIF store. Returns detection results, per-scanner execution stats, and total findings ingested. Call this to populate findings without manual scanner invocation.",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-schemas.js","sourceRoot":"","sources":["../../src/schemas/tool-schemas.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tool-schemas.js","sourceRoot":"","sources":["../../src/schemas/tool-schemas.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://code.claude.com/schemas/plugin.json",
|
|
3
3
|
"name": "claude-crap",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.3.0",
|
|
5
5
|
"description": "Deterministic Quality Assurance plugin for Claude Code. Wraps every Write / Edit / Bash tool call with a PreToolUse gatekeeper, a PostToolUse verifier, and a Stop quality gate backed by CRAP index, Technical Debt Ratio, tree-sitter AST metrics, and SARIF 2.1.0 reports. Forbids the agent from writing functional code before a test safety net exists.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Alan Hernandez",
|
|
@@ -8454,6 +8454,215 @@ async function autoScan(workspaceRoot, sarifStore, logger2) {
|
|
|
8454
8454
|
};
|
|
8455
8455
|
}
|
|
8456
8456
|
|
|
8457
|
+
// src/scanner/bootstrap.ts
|
|
8458
|
+
import { existsSync as existsSync3, writeFileSync, readdirSync } from "node:fs";
|
|
8459
|
+
import { join as join8 } from "node:path";
|
|
8460
|
+
import { execFile as execFile3 } from "node:child_process";
|
|
8461
|
+
function detectProjectType(workspaceRoot) {
|
|
8462
|
+
const has = (file) => existsSync3(join8(workspaceRoot, file));
|
|
8463
|
+
if (has("package.json")) {
|
|
8464
|
+
if (has("tsconfig.json")) return "typescript";
|
|
8465
|
+
return "javascript";
|
|
8466
|
+
}
|
|
8467
|
+
if (has("pyproject.toml") || has("setup.py") || has("requirements.txt")) {
|
|
8468
|
+
return "python";
|
|
8469
|
+
}
|
|
8470
|
+
if (has("pom.xml") || has("build.gradle") || has("build.gradle.kts")) {
|
|
8471
|
+
return "java";
|
|
8472
|
+
}
|
|
8473
|
+
if (has("Directory.Build.props")) return "csharp";
|
|
8474
|
+
try {
|
|
8475
|
+
const entries = readdirSync(workspaceRoot);
|
|
8476
|
+
if (entries.some((e) => e.endsWith(".csproj") || e.endsWith(".sln"))) {
|
|
8477
|
+
return "csharp";
|
|
8478
|
+
}
|
|
8479
|
+
} catch {
|
|
8480
|
+
}
|
|
8481
|
+
return "unknown";
|
|
8482
|
+
}
|
|
8483
|
+
function generateEslintConfig(isTypeScript) {
|
|
8484
|
+
if (isTypeScript) {
|
|
8485
|
+
return `import js from "@eslint/js";
|
|
8486
|
+
import tseslint from "typescript-eslint";
|
|
8487
|
+
|
|
8488
|
+
export default tseslint.config(
|
|
8489
|
+
js.configs.recommended,
|
|
8490
|
+
...tseslint.configs.recommended,
|
|
8491
|
+
{
|
|
8492
|
+
ignores: ["dist/", "node_modules/", "coverage/"],
|
|
8493
|
+
},
|
|
8494
|
+
);
|
|
8495
|
+
`;
|
|
8496
|
+
}
|
|
8497
|
+
return `import js from "@eslint/js";
|
|
8498
|
+
|
|
8499
|
+
export default [
|
|
8500
|
+
js.configs.recommended,
|
|
8501
|
+
{
|
|
8502
|
+
ignores: ["dist/", "node_modules/", "coverage/"],
|
|
8503
|
+
},
|
|
8504
|
+
];
|
|
8505
|
+
`;
|
|
8506
|
+
}
|
|
8507
|
+
function npmInstall(workspaceRoot, packages) {
|
|
8508
|
+
return new Promise((resolve6) => {
|
|
8509
|
+
execFile3(
|
|
8510
|
+
"npm",
|
|
8511
|
+
["install", "--save-dev", ...packages],
|
|
8512
|
+
{
|
|
8513
|
+
cwd: workspaceRoot,
|
|
8514
|
+
timeout: 12e4,
|
|
8515
|
+
env: { ...process.env, FORCE_COLOR: "0" }
|
|
8516
|
+
},
|
|
8517
|
+
(err, stdout, stderr) => {
|
|
8518
|
+
if (err) {
|
|
8519
|
+
resolve6({
|
|
8520
|
+
action: `npm install --save-dev ${packages.join(" ")}`,
|
|
8521
|
+
success: false,
|
|
8522
|
+
detail: stderr || err.message
|
|
8523
|
+
});
|
|
8524
|
+
return;
|
|
8525
|
+
}
|
|
8526
|
+
resolve6({
|
|
8527
|
+
action: `npm install --save-dev ${packages.join(" ")}`,
|
|
8528
|
+
success: true,
|
|
8529
|
+
detail: `installed ${packages.join(", ")}`
|
|
8530
|
+
});
|
|
8531
|
+
}
|
|
8532
|
+
);
|
|
8533
|
+
});
|
|
8534
|
+
}
|
|
8535
|
+
function writeEslintConfigFile(workspaceRoot, isTypeScript) {
|
|
8536
|
+
const configPath = join8(workspaceRoot, "eslint.config.mjs");
|
|
8537
|
+
if (existsSync3(configPath)) {
|
|
8538
|
+
return {
|
|
8539
|
+
action: "create eslint.config.mjs",
|
|
8540
|
+
success: true,
|
|
8541
|
+
detail: "eslint.config.mjs already exists \u2014 skipped"
|
|
8542
|
+
};
|
|
8543
|
+
}
|
|
8544
|
+
try {
|
|
8545
|
+
writeFileSync(configPath, generateEslintConfig(isTypeScript), "utf-8");
|
|
8546
|
+
return {
|
|
8547
|
+
action: "create eslint.config.mjs",
|
|
8548
|
+
success: true,
|
|
8549
|
+
detail: `created eslint.config.mjs (${isTypeScript ? "TypeScript" : "JavaScript"} template)`
|
|
8550
|
+
};
|
|
8551
|
+
} catch (err) {
|
|
8552
|
+
return {
|
|
8553
|
+
action: "create eslint.config.mjs",
|
|
8554
|
+
success: false,
|
|
8555
|
+
detail: err.message
|
|
8556
|
+
};
|
|
8557
|
+
}
|
|
8558
|
+
}
|
|
8559
|
+
function getRecommendation(projectType) {
|
|
8560
|
+
switch (projectType) {
|
|
8561
|
+
case "javascript":
|
|
8562
|
+
case "typescript":
|
|
8563
|
+
return {
|
|
8564
|
+
scanner: "eslint",
|
|
8565
|
+
canAutoInstall: true,
|
|
8566
|
+
installInstructions: "npm install --save-dev eslint @eslint/js"
|
|
8567
|
+
};
|
|
8568
|
+
case "python":
|
|
8569
|
+
return {
|
|
8570
|
+
scanner: "bandit",
|
|
8571
|
+
canAutoInstall: false,
|
|
8572
|
+
installInstructions: "pip install bandit (or: pipx install bandit, poetry add --group dev bandit)"
|
|
8573
|
+
};
|
|
8574
|
+
case "java":
|
|
8575
|
+
case "csharp":
|
|
8576
|
+
return {
|
|
8577
|
+
scanner: "semgrep",
|
|
8578
|
+
canAutoInstall: false,
|
|
8579
|
+
installInstructions: "brew install semgrep (or: pip install semgrep, pipx install semgrep)"
|
|
8580
|
+
};
|
|
8581
|
+
case "unknown":
|
|
8582
|
+
return {
|
|
8583
|
+
scanner: "semgrep",
|
|
8584
|
+
canAutoInstall: false,
|
|
8585
|
+
installInstructions: "brew install semgrep (or: pip install semgrep, pipx install semgrep)"
|
|
8586
|
+
};
|
|
8587
|
+
}
|
|
8588
|
+
}
|
|
8589
|
+
async function bootstrapScanner(workspaceRoot, sarifStore, logger2) {
|
|
8590
|
+
const detections = await detectScanners(workspaceRoot);
|
|
8591
|
+
const available = detections.filter((d) => d.available);
|
|
8592
|
+
if (available.length > 0) {
|
|
8593
|
+
const existingScanners = available.map((d) => d.scanner);
|
|
8594
|
+
logger2.info(
|
|
8595
|
+
{ existingScanners },
|
|
8596
|
+
"bootstrap: scanner(s) already configured \u2014 skipping"
|
|
8597
|
+
);
|
|
8598
|
+
return {
|
|
8599
|
+
projectType: detectProjectType(workspaceRoot),
|
|
8600
|
+
alreadyConfigured: true,
|
|
8601
|
+
existingScanners,
|
|
8602
|
+
steps: [],
|
|
8603
|
+
autoScanResult: null,
|
|
8604
|
+
success: true,
|
|
8605
|
+
summary: `Scanner(s) already configured: ${existingScanners.join(", ")}. Run auto_scan to ingest findings.`
|
|
8606
|
+
};
|
|
8607
|
+
}
|
|
8608
|
+
const projectType = detectProjectType(workspaceRoot);
|
|
8609
|
+
const recommendation = getRecommendation(projectType);
|
|
8610
|
+
const steps = [];
|
|
8611
|
+
logger2.info(
|
|
8612
|
+
{ projectType, scanner: recommendation.scanner },
|
|
8613
|
+
"bootstrap: detected project type"
|
|
8614
|
+
);
|
|
8615
|
+
if (recommendation.canAutoInstall) {
|
|
8616
|
+
const isTypeScript = projectType === "typescript";
|
|
8617
|
+
const packages = isTypeScript ? ["eslint", "@eslint/js", "typescript-eslint"] : ["eslint", "@eslint/js"];
|
|
8618
|
+
const installStep = await npmInstall(workspaceRoot, packages);
|
|
8619
|
+
steps.push(installStep);
|
|
8620
|
+
if (installStep.success) {
|
|
8621
|
+
const configStep = writeEslintConfigFile(workspaceRoot, isTypeScript);
|
|
8622
|
+
steps.push(configStep);
|
|
8623
|
+
}
|
|
8624
|
+
} else {
|
|
8625
|
+
steps.push({
|
|
8626
|
+
action: `suggest ${recommendation.scanner} install`,
|
|
8627
|
+
success: true,
|
|
8628
|
+
detail: recommendation.installInstructions
|
|
8629
|
+
});
|
|
8630
|
+
}
|
|
8631
|
+
const installSucceeded = steps.every((s) => s.success);
|
|
8632
|
+
let autoScanResult = null;
|
|
8633
|
+
if (installSucceeded && recommendation.canAutoInstall) {
|
|
8634
|
+
try {
|
|
8635
|
+
autoScanResult = await autoScan(workspaceRoot, sarifStore, logger2);
|
|
8636
|
+
} catch (err) {
|
|
8637
|
+
logger2.warn(
|
|
8638
|
+
{ err: err.message },
|
|
8639
|
+
"bootstrap: auto_scan after install failed"
|
|
8640
|
+
);
|
|
8641
|
+
}
|
|
8642
|
+
}
|
|
8643
|
+
const findings = autoScanResult?.totalFindings ?? 0;
|
|
8644
|
+
const scannerInstalled = recommendation.canAutoInstall && installSucceeded;
|
|
8645
|
+
let summary;
|
|
8646
|
+
if (scannerInstalled && autoScanResult) {
|
|
8647
|
+
summary = `Installed ${recommendation.scanner} for ${projectType} project. Auto-scan found ${findings} finding(s).`;
|
|
8648
|
+
} else if (scannerInstalled) {
|
|
8649
|
+
summary = `Installed ${recommendation.scanner} for ${projectType} project. Auto-scan did not run.`;
|
|
8650
|
+
} else if (!recommendation.canAutoInstall) {
|
|
8651
|
+
summary = `Detected ${projectType} project. Install ${recommendation.scanner} manually: ${recommendation.installInstructions}`;
|
|
8652
|
+
} else {
|
|
8653
|
+
summary = `Failed to install ${recommendation.scanner}. Check the error details in the steps.`;
|
|
8654
|
+
}
|
|
8655
|
+
return {
|
|
8656
|
+
projectType,
|
|
8657
|
+
alreadyConfigured: false,
|
|
8658
|
+
existingScanners: [],
|
|
8659
|
+
steps,
|
|
8660
|
+
autoScanResult,
|
|
8661
|
+
success: installSucceeded,
|
|
8662
|
+
summary
|
|
8663
|
+
};
|
|
8664
|
+
}
|
|
8665
|
+
|
|
8457
8666
|
// src/schemas/tool-schemas.ts
|
|
8458
8667
|
var computeCrapSchema = {
|
|
8459
8668
|
type: "object",
|
|
@@ -8581,6 +8790,13 @@ var ingestScannerOutputSchema = {
|
|
|
8581
8790
|
required: ["scanner", "rawOutput"],
|
|
8582
8791
|
additionalProperties: false
|
|
8583
8792
|
};
|
|
8793
|
+
var bootstrapScannerSchema = {
|
|
8794
|
+
type: "object",
|
|
8795
|
+
description: "Detect the project type (JavaScript, TypeScript, Python, Java, C#), install the appropriate scanner (ESLint for JS/TS, Bandit for Python, Semgrep for Java/C#), create a minimal config file, and run auto_scan to verify. Skips installation if a scanner is already configured. Use this when auto_scan finds no scanners and quality grades are vacuously A.",
|
|
8796
|
+
properties: {},
|
|
8797
|
+
required: [],
|
|
8798
|
+
additionalProperties: false
|
|
8799
|
+
};
|
|
8584
8800
|
var autoScanSchema = {
|
|
8585
8801
|
type: "object",
|
|
8586
8802
|
description: "Auto-detect available scanners (ESLint, Semgrep, Bandit, Stryker) in the workspace, execute them, and ingest findings into the SARIF store. Returns detection results, per-scanner execution stats, and total findings ingested. Call this to populate findings without manual scanner invocation.",
|
|
@@ -8712,6 +8928,11 @@ async function main() {
|
|
|
8712
8928
|
name: "auto_scan",
|
|
8713
8929
|
description: "Auto-detect available scanners (ESLint, Semgrep, Bandit, Stryker) in the workspace, run them, and ingest findings into the SARIF store.",
|
|
8714
8930
|
inputSchema: autoScanSchema
|
|
8931
|
+
},
|
|
8932
|
+
{
|
|
8933
|
+
name: "bootstrap_scanner",
|
|
8934
|
+
description: "Detect project type, install the right scanner (ESLint for JS/TS, Bandit for Python, Semgrep for Java/C#), create minimal config, and run auto_scan to verify.",
|
|
8935
|
+
inputSchema: bootstrapScannerSchema
|
|
8715
8936
|
}
|
|
8716
8937
|
]
|
|
8717
8938
|
}));
|
|
@@ -8993,6 +9214,35 @@ async function main() {
|
|
|
8993
9214
|
};
|
|
8994
9215
|
}
|
|
8995
9216
|
}
|
|
9217
|
+
case "bootstrap_scanner": {
|
|
9218
|
+
logger.info({ tool: "bootstrap_scanner" }, "Tool call received");
|
|
9219
|
+
try {
|
|
9220
|
+
const result = await bootstrapScanner(config.pluginRoot, sarifStore, logger);
|
|
9221
|
+
const markdown = renderBootstrapMarkdown(result);
|
|
9222
|
+
return {
|
|
9223
|
+
content: [
|
|
9224
|
+
{ type: "text", text: markdown },
|
|
9225
|
+
{ type: "text", text: JSON.stringify(result, null, 2) }
|
|
9226
|
+
],
|
|
9227
|
+
isError: !result.success
|
|
9228
|
+
};
|
|
9229
|
+
} catch (err) {
|
|
9230
|
+
logger.error({ err }, "bootstrap_scanner failed");
|
|
9231
|
+
return {
|
|
9232
|
+
content: [
|
|
9233
|
+
{
|
|
9234
|
+
type: "text",
|
|
9235
|
+
text: JSON.stringify(
|
|
9236
|
+
{ tool: "bootstrap_scanner", status: "error", message: err.message },
|
|
9237
|
+
null,
|
|
9238
|
+
2
|
|
9239
|
+
)
|
|
9240
|
+
}
|
|
9241
|
+
],
|
|
9242
|
+
isError: true
|
|
9243
|
+
};
|
|
9244
|
+
}
|
|
9245
|
+
}
|
|
8996
9246
|
case "auto_scan": {
|
|
8997
9247
|
logger.info({ tool: "auto_scan" }, "Tool call received");
|
|
8998
9248
|
try {
|
|
@@ -9089,6 +9339,36 @@ async function main() {
|
|
|
9089
9339
|
);
|
|
9090
9340
|
});
|
|
9091
9341
|
}
|
|
9342
|
+
function renderBootstrapMarkdown(result) {
|
|
9343
|
+
const lines = ["## claude-crap :: bootstrap scanner\n"];
|
|
9344
|
+
lines.push(`**Project type:** ${result.projectType}`);
|
|
9345
|
+
if (result.alreadyConfigured) {
|
|
9346
|
+
lines.push(`**Status:** Scanner(s) already configured: ${result.existingScanners.join(", ")}`);
|
|
9347
|
+
lines.push("\nNo installation needed. Run `auto_scan` to ingest findings.");
|
|
9348
|
+
return lines.join("\n");
|
|
9349
|
+
}
|
|
9350
|
+
lines.push("");
|
|
9351
|
+
if (result.steps.length > 0) {
|
|
9352
|
+
lines.push("### Steps\n");
|
|
9353
|
+
lines.push("| Action | Status | Detail |");
|
|
9354
|
+
lines.push("| ------ | :----: | ------ |");
|
|
9355
|
+
for (const s of result.steps) {
|
|
9356
|
+
const status = s.success ? "ok" : "failed";
|
|
9357
|
+
lines.push(`| ${s.action} | ${status} | ${s.detail} |`);
|
|
9358
|
+
}
|
|
9359
|
+
lines.push("");
|
|
9360
|
+
}
|
|
9361
|
+
if (result.autoScanResult) {
|
|
9362
|
+
const r = result.autoScanResult;
|
|
9363
|
+
const scanners = r.results.filter((s) => s.success).map((s) => s.scanner);
|
|
9364
|
+
lines.push(
|
|
9365
|
+
`**Auto-scan:** ${r.totalFindings} finding(s) ingested from ${scanners.join(", ") || "no scanners"} in ${(r.totalDurationMs / 1e3).toFixed(1)}s`
|
|
9366
|
+
);
|
|
9367
|
+
lines.push("");
|
|
9368
|
+
}
|
|
9369
|
+
lines.push(`**Summary:** ${result.summary}`);
|
|
9370
|
+
return lines.join("\n");
|
|
9371
|
+
}
|
|
9092
9372
|
function renderAutoScanMarkdown(result) {
|
|
9093
9373
|
const lines = ["## claude-crap :: auto-scan results\n"];
|
|
9094
9374
|
lines.push("### Detected scanners\n");
|