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.
@@ -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,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-crap",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Deterministic QA plugin for Claude Code — CRAP index, Technical Debt Ratio, tree-sitter AST, SARIF 2.1.0, hooks, and a local Vue dashboard.",
5
5
  "keywords": [
6
6
  "claude-code",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://code.claude.com/schemas/plugin.json",
3
3
  "name": "claude-crap",
4
- "version": "0.2.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");