code-auditor-mcp 4.0.1 → 4.0.2
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 +54 -0
- package/dist/analyzers/analyzerUtils.js +2 -2
- package/dist/analyzers/analyzerUtils.js.map +1 -1
- package/dist/analyzers/applicability.d.ts +13 -0
- package/dist/analyzers/applicability.d.ts.map +1 -1
- package/dist/analyzers/applicability.js +1 -1
- package/dist/analyzers/applicability.js.map +1 -1
- package/dist/analyzers/cross-language/DependencyGraphBuilder.d.ts +1 -1
- package/dist/analyzers/cross-language/DependencyGraphBuilder.d.ts.map +1 -1
- package/dist/analyzers/cross-language/DependencyGraphBuilder.js +3 -3
- package/dist/analyzers/cross-language/DependencyGraphBuilder.js.map +1 -1
- package/dist/analyzers/crossDomain/CrossDomainAnalyzer.d.ts +1 -1
- package/dist/analyzers/crossDomain/CrossDomainAnalyzer.js +5 -5
- package/dist/analyzers/crossDomain/CrossDomainAnalyzer.js.map +1 -1
- package/dist/analyzers/documentationAnalyzer.js +5 -5
- package/dist/analyzers/documentationAnalyzer.js.map +1 -1
- package/dist/analyzers/reactAnalyzer.js +8 -8
- package/dist/analyzers/reactAnalyzer.js.map +1 -1
- package/dist/analyzers/universal/UniversalConventionsAnalyzer.d.ts +2 -2
- package/dist/analyzers/universal/UniversalConventionsAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/universal/UniversalConventionsAnalyzer.js +7 -7
- package/dist/analyzers/universal/UniversalConventionsAnalyzer.js.map +1 -1
- package/dist/analyzers/universal/UniversalDRYAnalyzer.d.ts +4 -4
- package/dist/analyzers/universal/UniversalDRYAnalyzer.js +10 -10
- package/dist/analyzers/universal/UniversalDRYAnalyzer.js.map +1 -1
- package/dist/analyzers/universal/UniversalDataAccessAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/universal/UniversalDataAccessAnalyzer.js +42 -5
- package/dist/analyzers/universal/UniversalDataAccessAnalyzer.js.map +1 -1
- package/dist/analyzers/universal/UniversalDocumentationAnalyzer.d.ts +1 -1
- package/dist/analyzers/universal/UniversalDocumentationAnalyzer.js +7 -7
- package/dist/analyzers/universal/UniversalDocumentationAnalyzer.js.map +1 -1
- package/dist/analyzers/universal/UniversalSOLIDAnalyzer.d.ts +18 -0
- package/dist/analyzers/universal/UniversalSOLIDAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/universal/UniversalSOLIDAnalyzer.js +57 -11
- package/dist/analyzers/universal/UniversalSOLIDAnalyzer.js.map +1 -1
- package/dist/analyzers/universal/UniversalStylesAnalyzer.d.ts +1 -1
- package/dist/analyzers/universal/UniversalStylesAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/universal/UniversalStylesAnalyzer.js +9 -9
- package/dist/analyzers/universal/UniversalStylesAnalyzer.js.map +1 -1
- package/dist/analyzers/universal/schema/codeAnalysis.js +2 -2
- package/dist/analyzers/universal/schema/codeAnalysis.js.map +1 -1
- package/dist/analyzers/universal/schema/jsonSchema.js +1 -1
- package/dist/analyzers/universal/schema/jsonSchema.js.map +1 -1
- package/dist/analyzers/universal/schema/violations.d.ts +1 -1
- package/dist/analyzers/universal/schema/violations.d.ts.map +1 -1
- package/dist/auditRouter.js +2 -2
- package/dist/auditRouter.js.map +1 -1
- package/dist/auditRunner.d.ts.map +1 -1
- package/dist/auditRunner.js +25 -7
- package/dist/auditRunner.js.map +1 -1
- package/dist/cli.js +64 -21
- package/dist/cli.js.map +1 -1
- package/dist/config/configLoader.js +1 -1
- package/dist/config/configLoader.js.map +1 -1
- package/dist/config/defaults.js +3 -3
- package/dist/config/defaults.js.map +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/daemon/lspServer.js +1 -1
- package/dist/daemon/lspServer.js.map +1 -1
- package/dist/enforcement/gate.js +2 -2
- package/dist/hooks/codex.d.ts.map +1 -1
- package/dist/hooks/codex.js +1 -1
- package/dist/hooks/codex.js.map +1 -1
- package/dist/hooks/core.d.ts +1 -1
- package/dist/hooks/core.d.ts.map +1 -1
- package/dist/hooks/core.js +4 -4
- package/dist/hooks/core.js.map +1 -1
- package/dist/hooks/cursor.d.ts.map +1 -1
- package/dist/hooks/cursor.js +2 -2
- package/dist/hooks/cursor.js.map +1 -1
- package/dist/invariants/invariant-rules.schema.json +1 -1
- package/dist/invariants/ruleValidator.js +1 -1
- package/dist/invariants/ruleValidator.js.map +1 -1
- package/dist/invariants/types.d.ts +1 -1
- package/dist/invariants/types.d.ts.map +1 -1
- package/dist/languages/LanguageOrchestrator.d.ts +2 -2
- package/dist/languages/LanguageOrchestrator.d.ts.map +1 -1
- package/dist/languages/RuntimeManager.js +2 -2
- package/dist/languages/RuntimeManager.js.map +1 -1
- package/dist/languages/go/analyzer +0 -0
- package/dist/languages/go/analyzer-src/analyzer.go +3 -3
- package/dist/languages/go/analyzer-src/solid.go +5 -5
- package/dist/languages/types.d.ts +1 -1
- package/dist/languages/typescript/TreeSitterTypeScriptAdapter.d.ts +1 -1
- package/dist/languages/typescript/TreeSitterTypeScriptAdapter.js +1 -1
- package/dist/ledger.js +1 -1
- package/dist/ledger.js.map +1 -1
- package/dist/mcp-tools/projectTasks.js +2 -2
- package/dist/mcp-tools/projectTasks.js.map +1 -1
- package/dist/mcp-tools/workflowGuide.js +3 -3
- package/dist/mcp-tools/workflowGuide.js.map +1 -1
- package/dist/mcp-tools-shared.js +13 -13
- package/dist/mcp-tools-shared.js.map +1 -1
- package/dist/mcp-ui-simple.js +6 -6
- package/dist/mcp-ui-simple.js.map +1 -1
- package/dist/mcp.js +14 -14
- package/dist/mcp.js.map +1 -1
- package/dist/mcpAuditJobs.js +7 -7
- package/dist/mcpAuditJobs.js.map +1 -1
- package/dist/mcpAutoIndex.js +1 -1
- package/dist/mcpAutoIndex.js.map +1 -1
- package/dist/nextFile.d.ts +2 -2
- package/dist/nextFile.d.ts.map +1 -1
- package/dist/nextFile.js +3 -3
- package/dist/nextFile.js.map +1 -1
- package/dist/nextFileIncremental.d.ts +2 -2
- package/dist/nextFileIncremental.d.ts.map +1 -1
- package/dist/nextFileIncremental.js +16 -14
- package/dist/nextFileIncremental.js.map +1 -1
- package/dist/pipeline.d.ts.map +1 -1
- package/dist/pipeline.js +10 -0
- package/dist/pipeline.js.map +1 -1
- package/dist/pipelineAdapters.d.ts +39 -2
- package/dist/pipelineAdapters.d.ts.map +1 -1
- package/dist/pipelineAdapters.js +150 -7
- package/dist/pipelineAdapters.js.map +1 -1
- package/dist/reporting/csvReportGenerator.js +6 -6
- package/dist/reporting/csvReportGenerator.js.map +1 -1
- package/dist/reporting/htmlReportGenerator.js +11 -11
- package/dist/reporting/htmlReportGenerator.js.map +1 -1
- package/dist/reporting/jsonReportGenerator.js +1 -1
- package/dist/reporting/jsonReportGenerator.js.map +1 -1
- package/dist/reporting/sarifReportGenerator.js +1 -1
- package/dist/reporting/sarifReportGenerator.js.map +1 -1
- package/dist/reporting/sizeDistribution.d.ts +17 -0
- package/dist/reporting/sizeDistribution.d.ts.map +1 -0
- package/dist/reporting/sizeDistribution.js +93 -0
- package/dist/reporting/sizeDistribution.js.map +1 -0
- package/dist/scripts/benchmarkWorkers.js +1 -1
- package/dist/scripts/benchmarkWorkers.js.map +1 -1
- package/dist/telemetry.d.ts +1 -1
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/types/crossLanguage.d.ts +1 -1
- package/dist/types/crossLanguage.d.ts.map +1 -1
- package/dist/types.d.ts +90 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +3 -3
- 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 +1 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/skills/code-auditor/SKILL-RULE-KINDS.md +7 -7
- package/plugin/skills/code-auditor/SKILL.md +9 -9
- package/server.json +2 -2
package/dist/pipelineAdapters.js
CHANGED
|
@@ -49,10 +49,9 @@ function lazySingleton(loader) {
|
|
|
49
49
|
return promise;
|
|
50
50
|
};
|
|
51
51
|
}
|
|
52
|
-
// ── SOLID visitor ────────────────────────────────────────────────────────────
|
|
53
52
|
export function createSolidVisitor() {
|
|
54
53
|
const getAnalyzer = lazySingleton(() => import('./analyzers/universal/UniversalSOLIDAnalyzer.js').then((m) => new m.UniversalSOLIDAnalyzer()));
|
|
55
|
-
|
|
54
|
+
const visitor = {
|
|
56
55
|
name: 'solid',
|
|
57
56
|
stage: 'visitor',
|
|
58
57
|
getRuleIds: () => getRuleIdsFor('solid'),
|
|
@@ -68,6 +67,18 @@ export function createSolidVisitor() {
|
|
|
68
67
|
description: 'Detects violations of SOLID principles',
|
|
69
68
|
category: 'architecture',
|
|
70
69
|
};
|
|
70
|
+
return {
|
|
71
|
+
visitor,
|
|
72
|
+
getSizeSamples: async () => {
|
|
73
|
+
try {
|
|
74
|
+
const a = await getAnalyzer();
|
|
75
|
+
return a.sizeSamples ?? [];
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return [];
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
};
|
|
71
82
|
}
|
|
72
83
|
export function createDryVisitor(fullFunctionIndex) {
|
|
73
84
|
const getAnalyzer = lazySingleton(() => import('./analyzers/universal/UniversalDRYAnalyzer.js').then((m) => new m.UniversalDRYAnalyzer()));
|
|
@@ -544,7 +555,7 @@ export function createReactVisitor() {
|
|
|
544
555
|
}
|
|
545
556
|
}
|
|
546
557
|
catch {
|
|
547
|
-
// Cross-component checks are
|
|
558
|
+
// Cross-component checks are high
|
|
548
559
|
}
|
|
549
560
|
return violations;
|
|
550
561
|
},
|
|
@@ -1560,6 +1571,100 @@ function clComputeReachability(fileFacts, options) {
|
|
|
1560
1571
|
}
|
|
1561
1572
|
return { reachability, importersOf };
|
|
1562
1573
|
}
|
|
1574
|
+
/**
|
|
1575
|
+
* Spec 60 R1 — classify every non-test source module as `tested`,
|
|
1576
|
+
* `untested-live`, or `untested-dead` off the file-level import edges
|
|
1577
|
+
* (`importersOf`), not `function_dependencies`.
|
|
1578
|
+
*
|
|
1579
|
+
* A module is `tested` when a test file imports it *directly* (the edge set is
|
|
1580
|
+
* alias-aware — built by `clResolveImport` through `classifyImportSpecifier`).
|
|
1581
|
+
* `untested-dead` is the *post*-exception dead bucket: a file imported by
|
|
1582
|
+
* nothing *and* not a framework entry point. `deadPreException` is the
|
|
1583
|
+
* empty-importers count before the entry-point exception, so the drop
|
|
1584
|
+
* (`deadPreException - untestedDead`) attributes the entry points exempted.
|
|
1585
|
+
*/
|
|
1586
|
+
export function classifyTestCoverage(fileFacts, importersOf, packageEntrySet) {
|
|
1587
|
+
const result = {
|
|
1588
|
+
tested: 0,
|
|
1589
|
+
untestedLive: 0,
|
|
1590
|
+
untestedDead: 0,
|
|
1591
|
+
total: 0,
|
|
1592
|
+
deadPreException: 0,
|
|
1593
|
+
deadPostException: 0,
|
|
1594
|
+
deadDrop: 0,
|
|
1595
|
+
entryPointExemptions: [],
|
|
1596
|
+
testedFiles: [],
|
|
1597
|
+
untestedLiveFiles: [],
|
|
1598
|
+
untestedDeadFiles: [],
|
|
1599
|
+
};
|
|
1600
|
+
for (const fp of fileFacts.keys()) {
|
|
1601
|
+
if (clIsTestFile(fp))
|
|
1602
|
+
continue;
|
|
1603
|
+
result.total++;
|
|
1604
|
+
const importers = importersOf.get(fp);
|
|
1605
|
+
if (!importers || importers.size === 0) {
|
|
1606
|
+
// Imported by nothing — dead *unless* it is a framework entry point.
|
|
1607
|
+
result.deadPreException++;
|
|
1608
|
+
const isPackageEntry = packageEntrySet.has(fp);
|
|
1609
|
+
const isEntry = isPackageEntry || clIsEntryPointFile(fp);
|
|
1610
|
+
if (isEntry) {
|
|
1611
|
+
result.untestedLive++;
|
|
1612
|
+
result.untestedLiveFiles.push(fp);
|
|
1613
|
+
result.entryPointExemptions.push({
|
|
1614
|
+
file: fp,
|
|
1615
|
+
kind: isPackageEntry ? 'package-entry' : 'entry-point',
|
|
1616
|
+
});
|
|
1617
|
+
}
|
|
1618
|
+
else {
|
|
1619
|
+
result.untestedDead++;
|
|
1620
|
+
result.untestedDeadFiles.push(fp);
|
|
1621
|
+
}
|
|
1622
|
+
continue;
|
|
1623
|
+
}
|
|
1624
|
+
let hasTestImporter = false;
|
|
1625
|
+
for (const importer of importers) {
|
|
1626
|
+
if (clIsTestFile(importer)) {
|
|
1627
|
+
hasTestImporter = true;
|
|
1628
|
+
break;
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1631
|
+
if (hasTestImporter) {
|
|
1632
|
+
result.tested++;
|
|
1633
|
+
result.testedFiles.push(fp);
|
|
1634
|
+
}
|
|
1635
|
+
else {
|
|
1636
|
+
result.untestedLive++;
|
|
1637
|
+
result.untestedLiveFiles.push(fp);
|
|
1638
|
+
}
|
|
1639
|
+
}
|
|
1640
|
+
result.deadPostException = result.untestedDead;
|
|
1641
|
+
result.deadDrop = result.deadPreException - result.untestedDead;
|
|
1642
|
+
return result;
|
|
1643
|
+
}
|
|
1644
|
+
/**
|
|
1645
|
+
* Spec 60 R3 — group unreferenced modules by basename, surfacing the pattern of
|
|
1646
|
+
* the same file name appearing in several sibling directories (e.g. two
|
|
1647
|
+
* `ErrorState.tsx`, three `services.ts` under separate `reports` folders). Only
|
|
1648
|
+
* basenames with ≥2 files become clusters; a singleton dead file is not a duplicate.
|
|
1649
|
+
*/
|
|
1650
|
+
export function clusterDeadModules(deadFiles) {
|
|
1651
|
+
const byBasename = new Map();
|
|
1652
|
+
for (const fp of deadFiles) {
|
|
1653
|
+
const segments = fp.replace(/\\/g, '/').split('/').filter(Boolean);
|
|
1654
|
+
const basename = segments[segments.length - 1] ?? fp;
|
|
1655
|
+
const list = byBasename.get(basename) ?? [];
|
|
1656
|
+
list.push(fp);
|
|
1657
|
+
byBasename.set(basename, list);
|
|
1658
|
+
}
|
|
1659
|
+
const clusters = [];
|
|
1660
|
+
for (const [basename, files] of byBasename) {
|
|
1661
|
+
if (files.length >= 2) {
|
|
1662
|
+
clusters.push({ basename, count: files.length, files });
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1665
|
+
clusters.sort((a, b) => b.count - a.count || a.basename.localeCompare(b.basename));
|
|
1666
|
+
return clusters;
|
|
1667
|
+
}
|
|
1563
1668
|
/**
|
|
1564
1669
|
* Build `calls` cross-references by resolving each entity's extracted callee
|
|
1565
1670
|
* names against the corpus entity name index. Library calls (fetch, map, …)
|
|
@@ -1774,6 +1879,8 @@ export function createDependencyGraphReducer() {
|
|
|
1774
1879
|
}
|
|
1775
1880
|
// ── File-level reachability: unreferenced modules + ranking axis ──
|
|
1776
1881
|
const fileFacts = clFileFacts(allFacts);
|
|
1882
|
+
let testCoverage;
|
|
1883
|
+
let deadClusters = [];
|
|
1777
1884
|
if (fileFacts.size > 0) {
|
|
1778
1885
|
// `context.config` is the reducer's merged config (namespace + `_infra`);
|
|
1779
1886
|
// a bare reducer context in a unit test omits it, so fall back to the
|
|
@@ -1807,10 +1914,34 @@ export function createDependencyGraphReducer() {
|
|
|
1807
1914
|
// neutral default without it.
|
|
1808
1915
|
}
|
|
1809
1916
|
}
|
|
1917
|
+
// Spec 60 R1 — persist the file-level import edges (reverse adjacency:
|
|
1918
|
+
// module → its direct importers) so "what tests exercise this module"
|
|
1919
|
+
// is answerable downstream from `importersOf`, not the symbol-level
|
|
1920
|
+
// `function_dependencies` table.
|
|
1921
|
+
if (context.indexHandle?.rawDb) {
|
|
1922
|
+
try {
|
|
1923
|
+
const db = context.indexHandle.rawDb;
|
|
1924
|
+
const del = db.prepare("DELETE FROM graph_cache WHERE graph_type = 'importers'");
|
|
1925
|
+
const ins = db.prepare("INSERT OR REPLACE INTO graph_cache (graph_type, node_key, neighbor_key, weight) VALUES ('importers', ?, ?, 1)");
|
|
1926
|
+
const tx = db.transaction(() => {
|
|
1927
|
+
del.run();
|
|
1928
|
+
for (const [fp, importers] of importersOf) {
|
|
1929
|
+
for (const importer of importers) {
|
|
1930
|
+
ins.run(fp, importer);
|
|
1931
|
+
}
|
|
1932
|
+
}
|
|
1933
|
+
});
|
|
1934
|
+
tx();
|
|
1935
|
+
}
|
|
1936
|
+
catch {
|
|
1937
|
+
// Importer-edge persistence is advisory, like reachability.
|
|
1938
|
+
}
|
|
1939
|
+
}
|
|
1810
1940
|
// Flag files that export symbols yet are imported by nothing and are
|
|
1811
1941
|
// not framework entry points — a dead module. This is the signal the
|
|
1812
1942
|
// orphaned-nodes check missed: a whole unreferenced file whose every
|
|
1813
1943
|
// internal symbol still forms a connected component.
|
|
1944
|
+
const deadModuleFiles = [];
|
|
1814
1945
|
for (const [fp, info] of fileFacts) {
|
|
1815
1946
|
if (!info.hasExports)
|
|
1816
1947
|
continue;
|
|
@@ -1820,6 +1951,7 @@ export function createDependencyGraphReducer() {
|
|
|
1820
1951
|
continue;
|
|
1821
1952
|
if ((importersOf.get(fp)?.size ?? 0) > 0)
|
|
1822
1953
|
continue;
|
|
1954
|
+
deadModuleFiles.push(fp);
|
|
1823
1955
|
violations.push({
|
|
1824
1956
|
file: fp,
|
|
1825
1957
|
line: 1,
|
|
@@ -1834,6 +1966,12 @@ export function createDependencyGraphReducer() {
|
|
|
1834
1966
|
details: { imports: info.imports },
|
|
1835
1967
|
});
|
|
1836
1968
|
}
|
|
1969
|
+
// Spec 60 R1 — classify each non-test module off the import edge set.
|
|
1970
|
+
testCoverage = classifyTestCoverage(fileFacts, importersOf, packageEntrySet);
|
|
1971
|
+
// Spec 60 R3 — cluster the unreferenced modules by basename so the
|
|
1972
|
+
// "dead-and-duplicated" pattern (same file name in sibling dirs) is
|
|
1973
|
+
// visible as a cluster rather than scattered one-per-file findings.
|
|
1974
|
+
deadClusters = clusterDeadModules(deadModuleFiles);
|
|
1837
1975
|
// Spec 58 R2 — computed-specifier dynamic imports. `import(someVar)`
|
|
1838
1976
|
// cannot be resolved into an edge, so any module in this corpus could
|
|
1839
1977
|
// be its target and `unreferenced-module` is therefore not exhaustive.
|
|
@@ -1854,15 +1992,15 @@ export function createDependencyGraphReducer() {
|
|
|
1854
1992
|
}
|
|
1855
1993
|
const HEALTH_SEVERITY = {
|
|
1856
1994
|
'break-cycles': 'severe',
|
|
1857
|
-
'reduce-coupling': '
|
|
1858
|
-
'split-responsibilities': '
|
|
1995
|
+
'reduce-coupling': 'high',
|
|
1996
|
+
'split-responsibilities': 'high',
|
|
1859
1997
|
'review-orphans': 'severe',
|
|
1860
1998
|
};
|
|
1861
1999
|
for (const s of health.suggestions) {
|
|
1862
2000
|
violations.push({
|
|
1863
2001
|
file: '(multiple)',
|
|
1864
2002
|
line: 0,
|
|
1865
|
-
severity: HEALTH_SEVERITY[s.type] ?? '
|
|
2003
|
+
severity: HEALTH_SEVERITY[s.type] ?? 'high',
|
|
1866
2004
|
message: s.description,
|
|
1867
2005
|
rule: s.type,
|
|
1868
2006
|
type: s.type,
|
|
@@ -1871,7 +2009,12 @@ export function createDependencyGraphReducer() {
|
|
|
1871
2009
|
details: s.affectedNodes ? { affectedNodes: s.affectedNodes } : undefined,
|
|
1872
2010
|
});
|
|
1873
2011
|
}
|
|
1874
|
-
|
|
2012
|
+
const facts = {};
|
|
2013
|
+
if (testCoverage)
|
|
2014
|
+
facts.testCoverage = testCoverage;
|
|
2015
|
+
if (deadClusters.length > 0)
|
|
2016
|
+
facts.deadClusters = deadClusters;
|
|
2017
|
+
return { violations, facts, factsConsumed: entities.length, ...(diagnostics.length > 0 && { diagnostics }) };
|
|
1875
2018
|
}
|
|
1876
2019
|
catch (e) {
|
|
1877
2020
|
console.error('[dependency-graph reducer] error:', e.message);
|