code-auditor-mcp 5.2.0 → 5.3.3
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/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +142 -0
- package/dist/analyzers/reactAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/reactAnalyzer.js +35 -9
- package/dist/analyzers/reactAnalyzer.js.map +1 -1
- package/dist/analyzers/universal/UniversalDRYAnalyzer.d.ts +0 -2
- package/dist/analyzers/universal/UniversalDRYAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/universal/UniversalDRYAnalyzer.js +4 -5
- package/dist/analyzers/universal/UniversalDRYAnalyzer.js.map +1 -1
- package/dist/analyzers/universal/schema/codeAnalysis.d.ts.map +1 -1
- package/dist/analyzers/universal/schema/codeAnalysis.js +51 -3
- package/dist/analyzers/universal/schema/codeAnalysis.js.map +1 -1
- package/dist/auditRunner.d.ts +9 -1
- package/dist/auditRunner.d.ts.map +1 -1
- package/dist/auditRunner.js +65 -7
- package/dist/auditRunner.js.map +1 -1
- package/dist/cacheGc.d.ts +88 -0
- package/dist/cacheGc.d.ts.map +1 -0
- package/dist/cacheGc.js +196 -0
- package/dist/cacheGc.js.map +1 -0
- package/dist/cli.js +65 -21
- package/dist/cli.js.map +1 -1
- package/dist/config/defaults.d.ts +60 -25
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +69 -58
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/effectiveConfig.d.ts +1 -1
- package/dist/config/effectiveConfig.d.ts.map +1 -1
- package/dist/config/effectiveConfig.js +4 -6
- package/dist/config/effectiveConfig.js.map +1 -1
- package/dist/config/pathProfiles.d.ts +4 -3
- package/dist/config/pathProfiles.d.ts.map +1 -1
- package/dist/config/pathProfiles.js +3 -2
- package/dist/config/pathProfiles.js.map +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/dataPaths.d.ts +17 -0
- package/dist/dataPaths.d.ts.map +1 -1
- package/dist/dataPaths.js +20 -2
- package/dist/dataPaths.js.map +1 -1
- package/dist/installer.d.ts.map +1 -1
- package/dist/installer.js +2 -1
- package/dist/installer.js.map +1 -1
- package/dist/languages/adapterBridge.d.ts +11 -0
- package/dist/languages/adapterBridge.d.ts.map +1 -1
- package/dist/languages/adapterBridge.js +11 -0
- package/dist/languages/adapterBridge.js.map +1 -1
- package/dist/languages/types.d.ts +8 -0
- package/dist/languages/types.d.ts.map +1 -1
- package/dist/languages/typescript/TreeSitterTypeScriptAdapter.d.ts +13 -0
- package/dist/languages/typescript/TreeSitterTypeScriptAdapter.d.ts.map +1 -1
- package/dist/languages/typescript/TreeSitterTypeScriptAdapter.js +117 -15
- package/dist/languages/typescript/TreeSitterTypeScriptAdapter.js.map +1 -1
- package/dist/ledger.d.ts +7 -0
- package/dist/ledger.d.ts.map +1 -1
- package/dist/ledger.js +7 -0
- package/dist/ledger.js.map +1 -1
- package/dist/mcpDiagnostics.d.ts +2 -0
- package/dist/mcpDiagnostics.d.ts.map +1 -1
- package/dist/mcpDiagnostics.js +2 -0
- package/dist/mcpDiagnostics.js.map +1 -1
- package/dist/phase/candidates.d.ts +53 -0
- package/dist/phase/candidates.d.ts.map +1 -0
- package/dist/phase/candidates.js +67 -0
- package/dist/phase/candidates.js.map +1 -0
- package/dist/phase/imports.d.ts.map +1 -1
- package/dist/phase/imports.js +1 -0
- package/dist/phase/imports.js.map +1 -1
- package/dist/phase/oracles.d.ts +28 -0
- package/dist/phase/oracles.d.ts.map +1 -1
- package/dist/phase/oracles.js +28 -0
- package/dist/phase/oracles.js.map +1 -1
- package/dist/phase/phaseModel.d.ts +11 -1
- package/dist/phase/phaseModel.d.ts.map +1 -1
- package/dist/phase/phaseModel.js +16 -5
- package/dist/phase/phaseModel.js.map +1 -1
- package/dist/phase/rules/conventions.d.ts.map +1 -1
- package/dist/phase/rules/conventions.js +6 -2
- package/dist/phase/rules/conventions.js.map +1 -1
- package/dist/phase/rules/dataAccess.d.ts.map +1 -1
- package/dist/phase/rules/dataAccess.js +13 -0
- package/dist/phase/rules/dataAccess.js.map +1 -1
- package/dist/phase/rules/documentation.d.ts.map +1 -1
- package/dist/phase/rules/documentation.js +11 -1
- package/dist/phase/rules/documentation.js.map +1 -1
- package/dist/phase/rules/dry.d.ts +16 -7
- package/dist/phase/rules/dry.d.ts.map +1 -1
- package/dist/phase/rules/dry.js +51 -31
- package/dist/phase/rules/dry.js.map +1 -1
- package/dist/phase/rules/secrets.d.ts.map +1 -1
- package/dist/phase/rules/secrets.js +29 -4
- package/dist/phase/rules/secrets.js.map +1 -1
- package/dist/phase/rules/styles.d.ts.map +1 -1
- package/dist/phase/rules/styles.js +14 -0
- package/dist/phase/rules/styles.js.map +1 -1
- package/dist/phase/rules/unreferencedModule.d.ts.map +1 -1
- package/dist/phase/rules/unreferencedModule.js +16 -5
- package/dist/phase/rules/unreferencedModule.js.map +1 -1
- package/dist/phase/stringLiterals.d.ts.map +1 -1
- package/dist/phase/stringLiterals.js +16 -7
- package/dist/phase/stringLiterals.js.map +1 -1
- package/dist/phase/types.d.ts +58 -0
- package/dist/phase/types.d.ts.map +1 -1
- package/dist/pipeline.d.ts +4 -0
- package/dist/pipeline.d.ts.map +1 -1
- package/dist/pipeline.js +4 -0
- package/dist/pipeline.js.map +1 -1
- package/dist/services/auditJobService.d.ts +15 -0
- package/dist/services/auditJobService.d.ts.map +1 -1
- package/dist/services/auditJobService.js +15 -0
- package/dist/services/auditJobService.js.map +1 -1
- package/dist/services/projectTaskHelpers.d.ts +7 -0
- package/dist/services/projectTaskHelpers.d.ts.map +1 -1
- package/dist/services/projectTaskHelpers.js +7 -0
- package/dist/services/projectTaskHelpers.js.map +1 -1
- package/dist/services/whitelistService.d.ts +28 -0
- package/dist/services/whitelistService.d.ts.map +1 -1
- package/dist/services/whitelistService.js +28 -0
- package/dist/services/whitelistService.js.map +1 -1
- package/dist/styles/tailwindUtilityExpander.d.ts +4 -0
- package/dist/styles/tailwindUtilityExpander.d.ts.map +1 -1
- package/dist/styles/tailwindUtilityExpander.js +4 -0
- package/dist/styles/tailwindUtilityExpander.js.map +1 -1
- package/dist/types.d.ts +50 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/version.generated.d.ts +1 -1
- package/dist/version.generated.js +1 -1
- package/package.json +4 -2
- package/plugin/.claude-plugin/manifest.json +7 -7
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/hooks/hooks.json +4 -4
- package/plugin/scripts/hook-audit.sh +16 -10
- package/plugin/scripts/hook-common.sh +4 -5
- package/plugin/scripts/hook-self-audit.sh +12 -6
- package/plugin/skills/code-auditor/SKILL.md +1 -1
- package/server.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -27,6 +27,8 @@ import { rankFilesByPriority, orderFindingsWithinFile } from './nextFile.js';
|
|
|
27
27
|
import { runNextFile } from './nextFileIncremental.js';
|
|
28
28
|
import { describeSqliteBackend } from './sqlite/driver.js';
|
|
29
29
|
import { isRuleTimingEnabled } from './analyzers/ruleTiming.js';
|
|
30
|
+
import { gateBudgetResolutions } from './config/defaults.js';
|
|
31
|
+
import { buildCandidatesArtifact } from './phase/candidates.js';
|
|
30
32
|
const program = new Command();
|
|
31
33
|
// Legacy severity names that were renamed off Spec-54's "advisory" back to "high"
|
|
32
34
|
// (Spec-54's third tier rendered as "advisory", which read as optional — the very
|
|
@@ -181,6 +183,27 @@ function printAuditDiagnostics(result) {
|
|
|
181
183
|
console.log(chalk.yellow(` ${file} — ${entry.lines.length} site(s)${loc}: ${shown}${more}`));
|
|
182
184
|
}
|
|
183
185
|
}
|
|
186
|
+
// ── Per-rule unproven breakdown (K9) ──────────────────────────
|
|
187
|
+
// The raw unproven-site total answers "which analyzer produced these?"
|
|
188
|
+
// (`schema`); this answers the question the finding actually asks — "which
|
|
189
|
+
// rule may have under-reported?" One unproven site blanks every rule in its
|
|
190
|
+
// `affectedRules` set, so a rule's `count` is the number of sites that could
|
|
191
|
+
// have produced a finding under it, with `causes` naming the emission path
|
|
192
|
+
// that drove each (parse-failure / dialect-undetermined / unresolved-import /
|
|
193
|
+
// unproven-receiver). This is the missing discriminant: it surfaces the 465
|
|
194
|
+
// sites as *per-rule under-report risk*, not a single opaque analyzer total.
|
|
195
|
+
const unprovenByRule = result.summary?.unprovenSitesByRule;
|
|
196
|
+
if (unprovenByRule && Object.keys(unprovenByRule).length > 0) {
|
|
197
|
+
console.log(chalk.yellow(`── Unproven sites by rule ──`));
|
|
198
|
+
const ruleRows = Object.entries(unprovenByRule).sort(([, a], [, b]) => b.count - a.count);
|
|
199
|
+
for (const [rule, entry] of ruleRows) {
|
|
200
|
+
const causes = Object.entries(entry.causes)
|
|
201
|
+
.sort(([, a], [, b]) => b - a)
|
|
202
|
+
.map(([cause, n]) => `${n} ${cause}`)
|
|
203
|
+
.join(' · ');
|
|
204
|
+
console.log(chalk.yellow(` ${rule} — ${entry.count} site(s): ${causes}`));
|
|
205
|
+
}
|
|
206
|
+
}
|
|
184
207
|
// ── Coverage gaps (Spec 58 follow-up) ─────────────────────────
|
|
185
208
|
const otherCoverageGaps = allDiagnostics.filter((d) => d.kind === 'unresolved-query' || d.kind === 'unresolved-dynamic-import' || d.kind === 'undefined-class-not-found');
|
|
186
209
|
if (otherCoverageGaps.length > 0) {
|
|
@@ -237,6 +260,19 @@ function printAuditDiagnostics(result) {
|
|
|
237
260
|
console.log(chalk.gray(` … and ${deadClusters.length - 10} more clusters`));
|
|
238
261
|
}
|
|
239
262
|
}
|
|
263
|
+
// ── Directive K10 — cache GC ─────────────────────────────────
|
|
264
|
+
// State what the GC collected so a silent delete of operator cache is visible.
|
|
265
|
+
const cacheGc = result.metadata?.cacheGc;
|
|
266
|
+
if (cacheGc && (cacheGc.removedCliVersions.length > 0 || cacheGc.removedProjects.length > 0)) {
|
|
267
|
+
const parts = [];
|
|
268
|
+
if (cacheGc.removedCliVersions.length > 0) {
|
|
269
|
+
parts.push(`${cacheGc.removedCliVersions.length} superseded CLI cop${cacheGc.removedCliVersions.length === 1 ? 'y' : 'ies'}`);
|
|
270
|
+
}
|
|
271
|
+
if (cacheGc.removedProjects.length > 0) {
|
|
272
|
+
parts.push(`${cacheGc.removedProjects.length} abandoned project index${cacheGc.removedProjects.length === 1 ? '' : 'es'}`);
|
|
273
|
+
}
|
|
274
|
+
console.log(chalk.gray(`── Cache GC ── collected ${parts.join(' and ')}`));
|
|
275
|
+
}
|
|
240
276
|
}
|
|
241
277
|
/**
|
|
242
278
|
* Print the findings summary: the delta view when a baseline exists, or the
|
|
@@ -552,6 +588,7 @@ program
|
|
|
552
588
|
.option('--preset <id>', 'Apply a shareable preset (repeatable)', (v, prev) => prev.concat([v]), [])
|
|
553
589
|
.option('--detach', 'Run the audit in a detached background process and print the job ID')
|
|
554
590
|
.option('--explain-skipped', 'Print a per-reason breakdown of files dropped from analysis')
|
|
591
|
+
.option('--emit-candidates <path>', 'Write the sampled-audit candidates artifact (rule dispositions + candidate sites) to this file')
|
|
555
592
|
.action(async (options) => {
|
|
556
593
|
console.log(chalk.blue('🔍 Code Quality Audit Tool'));
|
|
557
594
|
console.log(chalk.gray('══════════════════════════════════════════════════'));
|
|
@@ -604,16 +641,18 @@ program
|
|
|
604
641
|
printFileAccounting(result, !!options.explainSkipped);
|
|
605
642
|
printUnparsedAndSkipped(result);
|
|
606
643
|
printPipelineStages(result, options);
|
|
607
|
-
// Spec-20 R4: built-in profile visibility — silent behavior changes
|
|
608
|
-
// are never acceptable. Notify when scripts-and-tests excludes findings
|
|
609
|
-
// from the blocking gate.
|
|
610
|
-
const builtinCapped = Object.values(result.analyzerResults)
|
|
611
|
-
.reduce((count, ar) => count + ar.violations.filter(v => v.profile === 'scripts-and-tests').length, 0);
|
|
612
|
-
if (builtinCapped > 0) {
|
|
613
|
-
console.log(chalk.blue(`\nℹ️ ${builtinCapped.toLocaleString()} readings excluded from the blocking gate by built-in profile "scripts-and-tests" (scripts/tests/fixtures).`));
|
|
614
|
-
console.log(chalk.gray(` Set ${chalk.cyan('"builtin": false')} in .codeauditor.json to disable.`));
|
|
615
|
-
}
|
|
616
644
|
await writeReport(result, options);
|
|
645
|
+
// Directive H item 2 — emit the sampled-audit candidates artifact when
|
|
646
|
+
// `--emit-candidates` names a destination. The artifact is the audit's
|
|
647
|
+
// only dependency on app/: rule disposition vocabularies (read from the
|
|
648
|
+
// rules) + candidate sites with their source line text. Nothing here
|
|
649
|
+
// reaches a model; it only serializes what the deterministic matchers
|
|
650
|
+
// emitted.
|
|
651
|
+
if (options.emitCandidates) {
|
|
652
|
+
const artifact = await buildCandidatesArtifact(result);
|
|
653
|
+
await fs.writeFile(resolve(options.emitCandidates), JSON.stringify(artifact, null, 2), 'utf8');
|
|
654
|
+
console.log(chalk.gray(`Candidates artifact written to ${options.emitCandidates} (${artifact.rules.reduce((n, r) => n + r.sites.length, 0)} sites across ${artifact.rules.length} rules)`));
|
|
655
|
+
}
|
|
617
656
|
applyFailOnGates(result, violations, baseline, options, failOnSeverity);
|
|
618
657
|
}
|
|
619
658
|
catch (error) {
|
|
@@ -724,20 +763,29 @@ program
|
|
|
724
763
|
// blocks; there is no configurable gate.
|
|
725
764
|
const { blocking, resolutionGaps } = computeGatingDecision(violations, BLOCKING_SEVERITIES);
|
|
726
765
|
await emitChangedOutput(result, violations, blocking, dismissedCount, options);
|
|
727
|
-
// Spec 38 R2/R3 — per-rule timing + gate
|
|
766
|
+
// Spec 38 R2/R3 — per-rule timing + gate work count, opt-in by env var.
|
|
728
767
|
// Emitted to stderr so it never corrupts --json stdout. Slowest rule first.
|
|
729
|
-
//
|
|
730
|
-
//
|
|
768
|
+
// Directive J: the gate budget is now a deterministic-work count
|
|
769
|
+
// (receiverResolutions), not CPU time — the count moves only when the work
|
|
770
|
+
// does, where CPU time jitters with machine load. The wall/CPU times are
|
|
771
|
+
// still printed as a measurement for bench/gate-timing.ts, but they are no
|
|
772
|
+
// longer what the budget asserts on.
|
|
731
773
|
if (isRuleTimingEnabled()) {
|
|
732
774
|
const ruleTiming = result.metadata?.ruleTiming;
|
|
733
775
|
const gateMs = result.metadata?.auditCpuMs;
|
|
734
776
|
const gateWallMs = result.metadata?.auditDuration;
|
|
777
|
+
const gateWork = result.metadata?.receiverResolutions;
|
|
778
|
+
const budget = gateBudgetResolutions();
|
|
735
779
|
const lines = [];
|
|
736
780
|
lines.push('');
|
|
737
|
-
//
|
|
738
|
-
//
|
|
781
|
+
// Directive J — the asserted metric: deterministic receiver-resolution
|
|
782
|
+
// count vs the single-source budget (gateBudgetResolutions()). The
|
|
783
|
+
// verifier parses this line, so the CLI is the one source of the budget.
|
|
784
|
+
lines.push(`⏱ gate work: ${gateWork ?? 0} receiver resolutions (budget ${budget})`);
|
|
785
|
+
// Measurement, not assertion — wall-clock (what the hook's user feels)
|
|
786
|
+
// and CPU (what the rule actually burned); consumed by bench/gate-timing.ts.
|
|
739
787
|
lines.push(`⏱ gate wall-clock: ${(gateWallMs ?? 0).toFixed(1)} ms`);
|
|
740
|
-
lines.push(`⏱ gate cpu-time: ${(gateMs ?? 0).toFixed(1)} ms
|
|
788
|
+
lines.push(`⏱ gate cpu-time: ${(gateMs ?? 0).toFixed(1)} ms`);
|
|
741
789
|
lines.push('── per-rule timing (slowest first) ──');
|
|
742
790
|
if (ruleTiming && ruleTiming.length > 0) {
|
|
743
791
|
for (const t of ruleTiming) {
|
|
@@ -1883,9 +1931,7 @@ configCmd
|
|
|
1883
1931
|
else {
|
|
1884
1932
|
console.log(chalk.bold(`Profiles matching: ${options.file}`));
|
|
1885
1933
|
for (const name of resolved.matchedProfileNames) {
|
|
1886
|
-
|
|
1887
|
-
const builtinTag = profile?.builtin !== false && profiles.some(p => p.name === name) ? '' : '';
|
|
1888
|
-
console.log(` ${chalk.cyan(name)}${builtinTag ? chalk.gray(' (built-in)') : ''}`);
|
|
1934
|
+
console.log(` ${chalk.cyan(name)}`);
|
|
1889
1935
|
}
|
|
1890
1936
|
if (resolved.excludeFromGate) {
|
|
1891
1937
|
console.log(chalk.yellow(` excludeFromGate: true`));
|
|
@@ -1908,7 +1954,6 @@ configCmd
|
|
|
1908
1954
|
name: p.name,
|
|
1909
1955
|
paths: p.paths,
|
|
1910
1956
|
overrides: p.overrides,
|
|
1911
|
-
builtin: p.builtin !== false,
|
|
1912
1957
|
})),
|
|
1913
1958
|
}, null, 2) + '\n');
|
|
1914
1959
|
}
|
|
@@ -1919,8 +1964,7 @@ configCmd
|
|
|
1919
1964
|
else {
|
|
1920
1965
|
console.log(chalk.bold('Active path profiles:'));
|
|
1921
1966
|
for (const p of profiles) {
|
|
1922
|
-
|
|
1923
|
-
console.log(` ${chalk.cyan(p.name)}${tag}`);
|
|
1967
|
+
console.log(` ${chalk.cyan(p.name)}`);
|
|
1924
1968
|
console.log(chalk.gray(` paths: ${p.paths.join(', ')}`));
|
|
1925
1969
|
if (p.overrides && Object.keys(p.overrides).length > 0) {
|
|
1926
1970
|
for (const [key, value] of Object.entries(p.overrides)) {
|