code-auditor-mcp 4.0.2 → 4.0.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.
Files changed (43) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +79 -4
  3. package/dist/cli.js +28 -3
  4. package/dist/cli.js.map +1 -1
  5. package/dist/constants.d.ts +1 -1
  6. package/dist/dataPaths.d.ts +11 -0
  7. package/dist/dataPaths.d.ts.map +1 -1
  8. package/dist/dataPaths.js +13 -0
  9. package/dist/dataPaths.js.map +1 -1
  10. package/dist/languages/RuntimeManager.d.ts +4 -2
  11. package/dist/languages/RuntimeManager.d.ts.map +1 -1
  12. package/dist/languages/RuntimeManager.js +65 -35
  13. package/dist/languages/RuntimeManager.js.map +1 -1
  14. package/dist/languages/go/{analyzer → analyzer-darwin-amd64} +0 -0
  15. package/dist/languages/go/analyzer-darwin-arm64 +0 -0
  16. package/dist/languages/go/analyzer-linux-amd64 +0 -0
  17. package/dist/languages/go/analyzer-linux-arm64 +0 -0
  18. package/dist/languages/go/analyzer-windows-amd64.exe +0 -0
  19. package/dist/languages/goBinary.d.ts +8 -7
  20. package/dist/languages/goBinary.d.ts.map +1 -1
  21. package/dist/languages/goBinary.js +8 -7
  22. package/dist/languages/goBinary.js.map +1 -1
  23. package/dist/languages/typescript/TreeSitterTypeScriptAdapter.d.ts +17 -0
  24. package/dist/languages/typescript/TreeSitterTypeScriptAdapter.d.ts.map +1 -1
  25. package/dist/languages/typescript/TreeSitterTypeScriptAdapter.js +123 -15
  26. package/dist/languages/typescript/TreeSitterTypeScriptAdapter.js.map +1 -1
  27. package/dist/mcpAuditJobs.d.ts.map +1 -1
  28. package/dist/mcpAuditJobs.js +6 -2
  29. package/dist/mcpAuditJobs.js.map +1 -1
  30. package/dist/reporting/reportGenerator.d.ts +2 -1
  31. package/dist/reporting/reportGenerator.d.ts.map +1 -1
  32. package/dist/reporting/reportGenerator.js +2 -2
  33. package/dist/reporting/reportGenerator.js.map +1 -1
  34. package/dist/reporting/sarifReportGenerator.d.ts +15 -0
  35. package/dist/reporting/sarifReportGenerator.d.ts.map +1 -1
  36. package/dist/reporting/sarifReportGenerator.js +75 -15
  37. package/dist/reporting/sarifReportGenerator.js.map +1 -1
  38. package/dist/version.generated.d.ts +1 -1
  39. package/dist/version.generated.js +1 -1
  40. package/package.json +1 -1
  41. package/plugin/.claude-plugin/plugin.json +1 -1
  42. package/plugin/skills/code-auditor/SKILL.md +1 -1
  43. package/server.json +2 -2
@@ -10,7 +10,7 @@
10
10
  "name": "code-auditor",
11
11
  "source": "./plugin",
12
12
  "description": "Diff-scoped code quality auditing on every edit. Indexes your codebase, enforces invariants, and feeds violations back to the agent so fixes happen inline.",
13
- "version": "4.0.2",
13
+ "version": "4.0.4",
14
14
  "author": {
15
15
  "name": "Ben Hammond"
16
16
  },
package/CHANGELOG.md CHANGED
@@ -2,7 +2,81 @@
2
2
 
3
3
  All notable changes to the Code Auditor MCP project.
4
4
 
5
- ## [4.0.2] — 2026-09-19
5
+ ## [4.0.4] — 2026-09-20
6
+
7
+ ### Go analysis now works everywhere, not just Intel Macs
8
+
9
+ Go analysis silently returned zero findings on every platform but Intel Macs.
10
+ The shipped Go analyzer was a single `darwin/amd64` binary, so Apple Silicon,
11
+ Linux, and Windows (including all Linux/Windows CI) skipped Go entirely and
12
+ reported a clean tree. That silent-skip is fixed:
13
+
14
+ - **Per-platform binaries** — five static `CGO_ENABLED=0` binaries ship in the
15
+ package (`analyzer-darwin-arm64`, `analyzer-darwin-amd64`,
16
+ `analyzer-linux-amd64`, `analyzer-linux-arm64`, `analyzer-windows-amd64.exe`),
17
+ cross-compiled from one machine. The runtime picks the binary from **Node's**
18
+ platform/arch (Node spawns the process), not the Go toolchain's — a subtlety
19
+ that matters under Rosetta, where `go env` reports `amd64` while Node reports
20
+ `arm64`.
21
+ - **Cache-dir rebuild fallback** — when no native binary is present, the
22
+ analyzer now builds into the OS cache dir (`~/Library/Caches/code-auditor`,
23
+ `~/.cache/code-auditor`, `%LOCALAPPDATA%\code-auditor`) instead of writing into
24
+ the read-only shipped tree and overwriting the artifact.
25
+ - **Silent failure now says so** — a missing toolchain, wrong-arch binary, or
26
+ failed build surfaces as a named `Skipped analyzers` diagnostic in the text
27
+ CLI (`go-toolchain-missing`, `go-analyzer-wrong-arch`,
28
+ `go-analyzer-build-failed`) instead of a silent zero.
29
+ - **Guard 8** now asserts all five shipped binaries are present *and* that the
30
+ running platform's binary executes — a build where one cross-compile failed
31
+ can no longer pass on one machine and ship broken for another.
32
+
33
+ ## [4.0.3] — 2026-09-20
34
+
35
+ ### SQL injection: parameterized-query false positives fixed
36
+
37
+ Two parameterized-query idioms were misread as `sql-injection-risk` at every
38
+ prior count. The safety analysis now proves them safe instead of flagging them:
39
+
40
+ - **Placeholder list** — `filePaths.map(() => '?').join(', ')` is a constant
41
+ list of `?` placeholders regardless of the source array's contents; the values
42
+ are bound out-of-band, so the interpolated text is never raw data.
43
+ - **Literal clause template** — `['run_id = ?', 'rule = ?'].join(' AND ')` is a
44
+ join over literal `col = ?` fragments with values bound out-of-band. A new
45
+ `isSafeJoin` proves the receiver and every `.push()`ed element are safe, so a
46
+ `.push(userInput)` before the join is still flagged.
47
+
48
+ The two patterns were clearing real findings in `codeIndexDB`, `blastRadius`,
49
+ and `ledger`. Both are now correctly recognized as safe; the remaining
50
+ `sql-injection-risk` findings are genuine dynamic SQL (table/column identifier
51
+ interpolation, escaped name lists, reassigned `let` clauses) rather than
52
+ parameterized queries. Guard coverage is pinned by new fixtures
53
+ (`placeholder-list.ts`, `clause-template.ts`) asserting exact zero counts.
54
+
55
+ This also fixed a latent scope-resolution bug: `findEnclosingScope` fell back to
56
+ file-level first-match when a wrapped node was detached from its parent chain,
57
+ so `const where: string[] = [...]` in one function could resolve against a
58
+ different function's `let where` of the same name. The enclosing scope is now
59
+ resolved through the raw parent chain.
60
+
61
+ ### SARIF: version-control provenance and schema validity
62
+
63
+ SARIF 2.1.0 output now carries GitHub Code Scanning metadata and emits only
64
+ schema-valid fields:
65
+
66
+ - `versionControlProvenance` (`repositoryUri` + `revisionId`) is read
67
+ best-effort from the project's git remote and HEAD, so uploaded alerts are
68
+ tied to a commit.
69
+ - `automationDetails.id` is set to `<tool>/<version>`, giving this tool's
70
+ uploads a distinct analysis category alongside CodeQL and others.
71
+ - Suggestions are emitted as `properties.resolution` (and a `help` string per
72
+ rule) instead of a bare `fixes` array — a SARIF fix requires `artifactChanges`,
73
+ which this tool does not produce, so the old output was schema-invalid.
74
+ - `startColumn` is omitted rather than clamped for 0-based/unknown columns
75
+ (SARIF requires a minimum of 1).
76
+ - Partial fingerprints are computed from the repo-relative path so GitHub alert
77
+ identity is stable across checkouts and machines.
78
+
79
+
6
80
 
7
81
  ### Severity vocabulary restored: `advisory` → `high`
8
82
 
@@ -14,15 +88,16 @@ tool results. The three non-severity meanings of "advisory" are unchanged: hook
14
88
  mode (`hookType: 'blocking' | 'advisory' | 'none'`), the non-invariant
15
89
  "advisory findings" report channel, and consultative "advisory" (= non-fatal).
16
90
 
17
- ### Fifteen rules restored from `severe` to `high`
91
+ ### Sixteen rules restored from `severe` to `high`
18
92
 
19
- The same recalibration escalated fifteen rules to `severe` that Spec 54 had
93
+ The same recalibration escalated sixteen rules to `severe` that Spec 54 had
20
94
  deliberately placed at `high`. They return to `high`:
21
95
 
22
96
  `solid/class-size`, `solid/method-complexity`, `solid/dependency-inversion`,
23
97
  `interface-size`, `parameter-count`, `function-length`, `function-size`,
24
98
  `struct-size`, `switch-size`, `dry/duplicate`, `complex-query`,
25
- `unfiltered-query`, `imports/import-style`, `tight-coupling`, `hub-nodes`.
99
+ `unfiltered-query`, `react/performance`, `imports/import-style`, `tight-coupling`,
100
+ `hub-nodes`.
26
101
 
27
102
  ### Severity-ledger conformance guard
28
103
 
package/dist/cli.js CHANGED
@@ -175,6 +175,25 @@ program
175
175
  `${covUnassessed} unassessed · ${covNotApplicable} not-applicable · ` +
176
176
  `${covCannotFire} cannot-fire`));
177
177
  }
178
+ // ── Skipped analyzers (Spec 61) ──────────────────────────────
179
+ // A language present on disk but never analyzed is a stated gap, not a
180
+ // silent zero. The Go path surfaces a named runtime failure (missing
181
+ // toolchain, wrong-arch prebuilt binary, failed rebuild) as a
182
+ // metadata.diagnostics entry; before this section those kinds were
183
+ // invisible outside --json, so a polyglot repo with .go files and no Go
184
+ // toolchain printed zero Go findings and exited clean — the silent-zero
185
+ // failure mode. These lead above coverage gaps: a skipped analyzer is a
186
+ // whole language unmeasured, more severe than a per-file visibility gap.
187
+ const skippedAnalyzers = (result.metadata?.diagnostics ?? []).filter((d) => d.kind === 'go-toolchain-missing' ||
188
+ d.kind === 'go-analyzer-wrong-arch' ||
189
+ d.kind === 'go-analyzer-build-failed');
190
+ if (skippedAnalyzers.length > 0) {
191
+ console.log(chalk.yellow(`── Skipped analyzers ── ${skippedAnalyzers.length}`));
192
+ for (const d of skippedAnalyzers) {
193
+ const name = d.analyzerName || 'go';
194
+ console.log(chalk.yellow(` ${name} [${d.kind}] — ${d.message}`));
195
+ }
196
+ }
178
197
  // ── Coverage gaps (Spec 58 follow-up) ─────────────────────────
179
198
  // Coverage diagnostics are the analyzer saying "my visibility ends here",
180
199
  // not "the code is wrong". They lead with counts, then per-occurrence
@@ -419,7 +438,12 @@ program
419
438
  process.exit(1);
420
439
  }
421
440
  const { generateReport } = await import('./reporting/reportGenerator.js');
422
- const report = generateReport(result, options.format);
441
+ const { readVersionControlProvenance } = await import('./reporting/sarifReportGenerator.js');
442
+ const rootDir = resolve(options.path || process.cwd());
443
+ const config = options.format === 'sarif'
444
+ ? { rootDir, ...readVersionControlProvenance(rootDir) }
445
+ : { rootDir };
446
+ const report = generateReport(result, options.format, config);
423
447
  const outputDir = options.output || process.cwd();
424
448
  const ext = options.format === 'sarif' ? 'sarif' : options.format;
425
449
  const reportPath = join(outputDir, `audit-report.${ext}`);
@@ -573,8 +597,9 @@ program
573
597
  const { blocking, resolutionGaps } = computeGatingDecision(violations, BLOCKING_SEVERITIES);
574
598
  // JSON output
575
599
  if (options.format === 'sarif') {
576
- const { generateSARIFReport } = await import('./reporting/sarifReportGenerator.js');
577
- const sarifOutput = generateSARIFReport(result);
600
+ const { generateSARIFReport, readVersionControlProvenance } = await import('./reporting/sarifReportGenerator.js');
601
+ const projectDir = resolve(options.path || process.cwd());
602
+ const sarifOutput = generateSARIFReport(result, { rootDir: projectDir, ...readVersionControlProvenance(projectDir) });
578
603
  process.stdout.write(sarifOutput + '\n');
579
604
  }
580
605
  else if (options.json) {