code-auditor-mcp 4.0.0 → 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.
Files changed (279) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +80 -0
  3. package/dist/__tests__/fixtures/spec-52/item-04-storage-sql-exec-in-loop.d.ts.map +1 -1
  4. package/dist/__tests__/fixtures/spec-52/item-05-upsert-forms.d.ts +4 -4
  5. package/dist/__tests__/fixtures/spec-52/item-05-upsert-forms.d.ts.map +1 -1
  6. package/dist/analyzers/analyzerUtils.d.ts.map +1 -1
  7. package/dist/analyzers/analyzerUtils.js +2 -2
  8. package/dist/analyzers/analyzerUtils.js.map +1 -1
  9. package/dist/analyzers/applicability.d.ts +13 -0
  10. package/dist/analyzers/applicability.d.ts.map +1 -1
  11. package/dist/analyzers/applicability.js +1 -1
  12. package/dist/analyzers/applicability.js.map +1 -1
  13. package/dist/analyzers/cross-language/APIContractAnalyzer.d.ts.map +1 -1
  14. package/dist/analyzers/cross-language/DependencyGraphBuilder.d.ts +1 -1
  15. package/dist/analyzers/cross-language/DependencyGraphBuilder.d.ts.map +1 -1
  16. package/dist/analyzers/cross-language/DependencyGraphBuilder.js +3 -3
  17. package/dist/analyzers/cross-language/DependencyGraphBuilder.js.map +1 -1
  18. package/dist/analyzers/cross-language/SchemaValidator.d.ts.map +1 -1
  19. package/dist/analyzers/cross-language/SchemaValidator.js.map +1 -1
  20. package/dist/analyzers/crossDomain/CrossDomainAnalyzer.d.ts +1 -1
  21. package/dist/analyzers/crossDomain/CrossDomainAnalyzer.d.ts.map +1 -1
  22. package/dist/analyzers/crossDomain/CrossDomainAnalyzer.js +28 -7
  23. package/dist/analyzers/crossDomain/CrossDomainAnalyzer.js.map +1 -1
  24. package/dist/analyzers/documentationAnalyzer.js +5 -5
  25. package/dist/analyzers/documentationAnalyzer.js.map +1 -1
  26. package/dist/analyzers/orm/adapterRegistry.d.ts.map +1 -1
  27. package/dist/analyzers/orm/drizzleAdapter.d.ts.map +1 -1
  28. package/dist/analyzers/orm/prismaAdapter.d.ts.map +1 -1
  29. package/dist/analyzers/provenance.d.ts +10 -1
  30. package/dist/analyzers/provenance.d.ts.map +1 -1
  31. package/dist/analyzers/provenance.js +138 -1
  32. package/dist/analyzers/provenance.js.map +1 -1
  33. package/dist/analyzers/reactAnalyzer.js +8 -8
  34. package/dist/analyzers/reactAnalyzer.js.map +1 -1
  35. package/dist/analyzers/ruleRegistry.js +2 -2
  36. package/dist/analyzers/ruleRegistry.js.map +1 -1
  37. package/dist/analyzers/universal/UniversalConventionsAnalyzer.d.ts +2 -2
  38. package/dist/analyzers/universal/UniversalConventionsAnalyzer.d.ts.map +1 -1
  39. package/dist/analyzers/universal/UniversalConventionsAnalyzer.js +7 -7
  40. package/dist/analyzers/universal/UniversalConventionsAnalyzer.js.map +1 -1
  41. package/dist/analyzers/universal/UniversalDRYAnalyzer.d.ts +4 -4
  42. package/dist/analyzers/universal/UniversalDRYAnalyzer.d.ts.map +1 -1
  43. package/dist/analyzers/universal/UniversalDRYAnalyzer.js +10 -10
  44. package/dist/analyzers/universal/UniversalDRYAnalyzer.js.map +1 -1
  45. package/dist/analyzers/universal/UniversalDataAccessAnalyzer.d.ts.map +1 -1
  46. package/dist/analyzers/universal/UniversalDataAccessAnalyzer.js +283 -39
  47. package/dist/analyzers/universal/UniversalDataAccessAnalyzer.js.map +1 -1
  48. package/dist/analyzers/universal/UniversalDocumentationAnalyzer.d.ts +1 -1
  49. package/dist/analyzers/universal/UniversalDocumentationAnalyzer.d.ts.map +1 -1
  50. package/dist/analyzers/universal/UniversalDocumentationAnalyzer.js +7 -7
  51. package/dist/analyzers/universal/UniversalDocumentationAnalyzer.js.map +1 -1
  52. package/dist/analyzers/universal/UniversalSOLIDAnalyzer.d.ts +18 -0
  53. package/dist/analyzers/universal/UniversalSOLIDAnalyzer.d.ts.map +1 -1
  54. package/dist/analyzers/universal/UniversalSOLIDAnalyzer.js +57 -11
  55. package/dist/analyzers/universal/UniversalSOLIDAnalyzer.js.map +1 -1
  56. package/dist/analyzers/universal/UniversalSchemaAnalyzer.d.ts.map +1 -1
  57. package/dist/analyzers/universal/UniversalSchemaAnalyzer.js +1 -0
  58. package/dist/analyzers/universal/UniversalSchemaAnalyzer.js.map +1 -1
  59. package/dist/analyzers/universal/UniversalSecretsAnalyzer.d.ts.map +1 -1
  60. package/dist/analyzers/universal/UniversalStylesAnalyzer.d.ts +1 -1
  61. package/dist/analyzers/universal/UniversalStylesAnalyzer.d.ts.map +1 -1
  62. package/dist/analyzers/universal/UniversalStylesAnalyzer.js +66 -31
  63. package/dist/analyzers/universal/UniversalStylesAnalyzer.js.map +1 -1
  64. package/dist/analyzers/universal/schema/codeAnalysis.d.ts +21 -21
  65. package/dist/analyzers/universal/schema/codeAnalysis.d.ts.map +1 -1
  66. package/dist/analyzers/universal/schema/codeAnalysis.js +199 -45
  67. package/dist/analyzers/universal/schema/codeAnalysis.js.map +1 -1
  68. package/dist/analyzers/universal/schema/config.d.ts +6 -6
  69. package/dist/analyzers/universal/schema/config.d.ts.map +1 -1
  70. package/dist/analyzers/universal/schema/jsonSchema.js +1 -1
  71. package/dist/analyzers/universal/schema/jsonSchema.js.map +1 -1
  72. package/dist/analyzers/universal/schema/types.d.ts +10 -0
  73. package/dist/analyzers/universal/schema/types.d.ts.map +1 -1
  74. package/dist/analyzers/universal/schema/violations.d.ts +1 -1
  75. package/dist/analyzers/universal/schema/violations.d.ts.map +1 -1
  76. package/dist/auditRouter.js +2 -2
  77. package/dist/auditRouter.js.map +1 -1
  78. package/dist/auditRunner.d.ts +1 -1
  79. package/dist/auditRunner.d.ts.map +1 -1
  80. package/dist/auditRunner.js +46 -13
  81. package/dist/auditRunner.js.map +1 -1
  82. package/dist/churn/churnExtractor.js.map +1 -1
  83. package/dist/cli.js +93 -28
  84. package/dist/cli.js.map +1 -1
  85. package/dist/codeIndexDB.d.ts.map +1 -1
  86. package/dist/codeIndexDB.js +19 -3
  87. package/dist/codeIndexDB.js.map +1 -1
  88. package/dist/codeIndexService.d.ts.map +1 -1
  89. package/dist/codeIndexService.js.map +1 -1
  90. package/dist/componentScanner.js.map +1 -1
  91. package/dist/config/configLoader.js +1 -1
  92. package/dist/config/configLoader.js.map +1 -1
  93. package/dist/config/defaults.d.ts +2 -2
  94. package/dist/config/defaults.d.ts.map +1 -1
  95. package/dist/config/defaults.js +10 -3
  96. package/dist/config/defaults.js.map +1 -1
  97. package/dist/constants.d.ts +1 -1
  98. package/dist/conventions/conventionMiner.js.map +1 -1
  99. package/dist/coverage/lcovParser.js.map +1 -1
  100. package/dist/daemon/args.js.map +1 -1
  101. package/dist/daemon/core.d.ts.map +1 -1
  102. package/dist/daemon/core.js +18 -9
  103. package/dist/daemon/core.js.map +1 -1
  104. package/dist/daemon/lspServer.d.ts.map +1 -1
  105. package/dist/daemon/lspServer.js +1 -1
  106. package/dist/daemon/lspServer.js.map +1 -1
  107. package/dist/daemon/main.js.map +1 -1
  108. package/dist/daemon/resolve.js.map +1 -1
  109. package/dist/daemon/socketServer.d.ts.map +1 -1
  110. package/dist/enforcement/gate.js +2 -2
  111. package/dist/functionScanner.d.ts.map +1 -1
  112. package/dist/generators/AWSQConfigGenerator.d.ts.map +1 -1
  113. package/dist/generators/AiderConfigGenerator.d.ts.map +1 -1
  114. package/dist/generators/BaseConfigGenerator.d.ts.map +1 -1
  115. package/dist/generators/BaseConfigGenerator.js.map +1 -1
  116. package/dist/generators/ClaudeConfigGenerator.d.ts.map +1 -1
  117. package/dist/generators/ClineConfigGenerator.d.ts.map +1 -1
  118. package/dist/generators/CodeiumConfigGenerator.d.ts.map +1 -1
  119. package/dist/generators/CodexConfigGenerator.d.ts.map +1 -1
  120. package/dist/generators/ConfigGeneratorFactory.d.ts.map +1 -1
  121. package/dist/generators/ConfigGeneratorFactory.js.map +1 -1
  122. package/dist/generators/ContinueConfigGenerator.d.ts.map +1 -1
  123. package/dist/generators/CopilotConfigGenerator.d.ts.map +1 -1
  124. package/dist/generators/CursorConfigGenerator.d.ts.map +1 -1
  125. package/dist/generators/GeminiConfigGenerator.d.ts.map +1 -1
  126. package/dist/generators/JetBrainsConfigGenerator.d.ts.map +1 -1
  127. package/dist/generators/VSCodeConfigGenerator.d.ts.map +1 -1
  128. package/dist/generators/ZCodeConfigGenerator.d.ts.map +1 -1
  129. package/dist/graph/importClassification.d.ts +46 -8
  130. package/dist/graph/importClassification.d.ts.map +1 -1
  131. package/dist/graph/importClassification.js +207 -35
  132. package/dist/graph/importClassification.js.map +1 -1
  133. package/dist/graph/outputFormatter.js.map +1 -1
  134. package/dist/hooks/codex.d.ts.map +1 -1
  135. package/dist/hooks/codex.js +1 -1
  136. package/dist/hooks/codex.js.map +1 -1
  137. package/dist/hooks/core.d.ts +1 -1
  138. package/dist/hooks/core.d.ts.map +1 -1
  139. package/dist/hooks/core.js +4 -4
  140. package/dist/hooks/core.js.map +1 -1
  141. package/dist/hooks/cursor.d.ts.map +1 -1
  142. package/dist/hooks/cursor.js +2 -2
  143. package/dist/hooks/cursor.js.map +1 -1
  144. package/dist/index.d.ts.map +1 -1
  145. package/dist/installer.js.map +1 -1
  146. package/dist/invariants/invariant-rules.schema.json +1 -1
  147. package/dist/invariants/ruleEngine.js.map +1 -1
  148. package/dist/invariants/ruleValidator.js +1 -1
  149. package/dist/invariants/ruleValidator.js.map +1 -1
  150. package/dist/invariants/types.d.ts +1 -1
  151. package/dist/invariants/types.d.ts.map +1 -1
  152. package/dist/languages/LanguageOrchestrator.d.ts +2 -2
  153. package/dist/languages/LanguageOrchestrator.d.ts.map +1 -1
  154. package/dist/languages/LanguageOrchestrator.js.map +1 -1
  155. package/dist/languages/LanguageRegistry.d.ts.map +1 -1
  156. package/dist/languages/RuntimeManager.d.ts.map +1 -1
  157. package/dist/languages/RuntimeManager.js +2 -2
  158. package/dist/languages/RuntimeManager.js.map +1 -1
  159. package/dist/languages/UniversalAnalyzer.d.ts.map +1 -1
  160. package/dist/languages/UniversalAnalyzer.js.map +1 -1
  161. package/dist/languages/adapterBridge.js.map +1 -1
  162. package/dist/languages/go/GoAdapter.d.ts.map +1 -1
  163. package/dist/languages/go/GoAdapter.js.map +1 -1
  164. package/dist/languages/go/analyzer +0 -0
  165. package/dist/languages/go/analyzer-src/analyzer.go +3 -3
  166. package/dist/languages/go/analyzer-src/solid.go +5 -5
  167. package/dist/languages/goBinary.js.map +1 -1
  168. package/dist/languages/tree-sitter/TreeSitterCssAdapter.d.ts.map +1 -1
  169. package/dist/languages/tree-sitter/TreeSitterCssAdapter.js.map +1 -1
  170. package/dist/languages/tree-sitter/converter.js.map +1 -1
  171. package/dist/languages/tree-sitter/parser.js.map +1 -1
  172. package/dist/languages/types.d.ts +15 -0
  173. package/dist/languages/types.d.ts.map +1 -1
  174. package/dist/languages/typescript/TreeSitterTypeScriptAdapter.d.ts +11 -0
  175. package/dist/languages/typescript/TreeSitterTypeScriptAdapter.d.ts.map +1 -1
  176. package/dist/languages/typescript/TreeSitterTypeScriptAdapter.js +34 -0
  177. package/dist/languages/typescript/TreeSitterTypeScriptAdapter.js.map +1 -1
  178. package/dist/ledger.js +1 -1
  179. package/dist/ledger.js.map +1 -1
  180. package/dist/mcp-tools/projectTasks.d.ts +37 -37
  181. package/dist/mcp-tools/projectTasks.js +2 -2
  182. package/dist/mcp-tools/projectTasks.js.map +1 -1
  183. package/dist/mcp-tools/whitelistTools.d.ts +17 -17
  184. package/dist/mcp-tools/whitelistTools.d.ts.map +1 -1
  185. package/dist/mcp-tools/workflowGuide.js +3 -3
  186. package/dist/mcp-tools/workflowGuide.js.map +1 -1
  187. package/dist/mcp-tools-shared.d.ts.map +1 -1
  188. package/dist/mcp-tools-shared.js +13 -13
  189. package/dist/mcp-tools-shared.js.map +1 -1
  190. package/dist/mcp-ui-simple.js +6 -6
  191. package/dist/mcp-ui-simple.js.map +1 -1
  192. package/dist/mcp.js +14 -14
  193. package/dist/mcp.js.map +1 -1
  194. package/dist/mcpAuditJobs.js +7 -7
  195. package/dist/mcpAuditJobs.js.map +1 -1
  196. package/dist/mcpAutoIndex.js +1 -1
  197. package/dist/mcpAutoIndex.js.map +1 -1
  198. package/dist/mcpToolErrors.d.ts.map +1 -1
  199. package/dist/mcpToolErrors.js.map +1 -1
  200. package/dist/native-bootstrap.js.map +1 -1
  201. package/dist/nextFile.d.ts +2 -2
  202. package/dist/nextFile.d.ts.map +1 -1
  203. package/dist/nextFile.js +3 -3
  204. package/dist/nextFile.js.map +1 -1
  205. package/dist/nextFileIncremental.d.ts +9 -2
  206. package/dist/nextFileIncremental.d.ts.map +1 -1
  207. package/dist/nextFileIncremental.js +41 -23
  208. package/dist/nextFileIncremental.js.map +1 -1
  209. package/dist/pipeline.d.ts +2 -2
  210. package/dist/pipeline.d.ts.map +1 -1
  211. package/dist/pipeline.js +45 -0
  212. package/dist/pipeline.js.map +1 -1
  213. package/dist/pipelineAdapters.d.ts +39 -2
  214. package/dist/pipelineAdapters.d.ts.map +1 -1
  215. package/dist/pipelineAdapters.js +230 -29
  216. package/dist/pipelineAdapters.js.map +1 -1
  217. package/dist/reporting/csvReportGenerator.d.ts.map +1 -1
  218. package/dist/reporting/csvReportGenerator.js +6 -6
  219. package/dist/reporting/csvReportGenerator.js.map +1 -1
  220. package/dist/reporting/htmlReportGenerator.d.ts.map +1 -1
  221. package/dist/reporting/htmlReportGenerator.js +11 -11
  222. package/dist/reporting/htmlReportGenerator.js.map +1 -1
  223. package/dist/reporting/jsonReportGenerator.d.ts.map +1 -1
  224. package/dist/reporting/jsonReportGenerator.js +1 -1
  225. package/dist/reporting/jsonReportGenerator.js.map +1 -1
  226. package/dist/reporting/reportGenerator.d.ts.map +1 -1
  227. package/dist/reporting/sarifReportGenerator.d.ts.map +1 -1
  228. package/dist/reporting/sarifReportGenerator.js +1 -1
  229. package/dist/reporting/sarifReportGenerator.js.map +1 -1
  230. package/dist/reporting/sizeDistribution.d.ts +17 -0
  231. package/dist/reporting/sizeDistribution.d.ts.map +1 -0
  232. package/dist/reporting/sizeDistribution.js +93 -0
  233. package/dist/reporting/sizeDistribution.js.map +1 -0
  234. package/dist/scripts/benchmarkWorkers.js +1 -1
  235. package/dist/scripts/benchmarkWorkers.js.map +1 -1
  236. package/dist/search/QueryParser.d.ts.map +1 -1
  237. package/dist/search/QueryParser.js.map +1 -1
  238. package/dist/services/CodeMapGenerator.d.ts.map +1 -1
  239. package/dist/services/CodeMapGenerator.js.map +1 -1
  240. package/dist/services/ProjectTaskRepository.d.ts.map +1 -1
  241. package/dist/services/ProjectTaskRepository.js.map +1 -1
  242. package/dist/services/auditJobService.js.map +1 -1
  243. package/dist/services/fileAccounting.d.ts.map +1 -1
  244. package/dist/services/projectTaskHelpers.js.map +1 -1
  245. package/dist/services/whitelistService.d.ts.map +1 -1
  246. package/dist/sqlite/betterSqlite3.d.ts.map +1 -1
  247. package/dist/sqlite/betterSqlite3.js.map +1 -1
  248. package/dist/sqlite/nodeSqlite.d.ts.map +1 -1
  249. package/dist/sqlite/nodeSqlite.js.map +1 -1
  250. package/dist/structuralSignature.js.map +1 -1
  251. package/dist/styles/styleExtractor.js.map +1 -1
  252. package/dist/styles/styleIndexer.js.map +1 -1
  253. package/dist/styles/tailwindConfigLoader.js.map +1 -1
  254. package/dist/styles/tailwindProbe.d.ts.map +1 -1
  255. package/dist/styles/tailwindUtilityExpander.d.ts.map +1 -1
  256. package/dist/styles/tailwindUtilityExpander.js.map +1 -1
  257. package/dist/telemetry.d.ts +1 -1
  258. package/dist/telemetry.d.ts.map +1 -1
  259. package/dist/telemetry.js.map +1 -1
  260. package/dist/tool-registry.d.ts.map +1 -1
  261. package/dist/types/crossLanguage.d.ts +1 -1
  262. package/dist/types/crossLanguage.d.ts.map +1 -1
  263. package/dist/types.d.ts +99 -5
  264. package/dist/types.d.ts.map +1 -1
  265. package/dist/types.js +3 -3
  266. package/dist/types.js.map +1 -1
  267. package/dist/ui/InteractivePrompts.d.ts.map +1 -1
  268. package/dist/ui/InteractivePrompts.js.map +1 -1
  269. package/dist/utils/componentPatterns.js.map +1 -1
  270. package/dist/utils/fileDiscovery.js.map +1 -1
  271. package/dist/utils/jsDocParser.js.map +1 -1
  272. package/dist/version.generated.d.ts +1 -1
  273. package/dist/version.generated.js +1 -1
  274. package/dist/workers/auditWorker.js.map +1 -1
  275. package/package.json +4 -3
  276. package/plugin/.claude-plugin/plugin.json +1 -1
  277. package/plugin/skills/code-auditor/SKILL-RULE-KINDS.md +7 -7
  278. package/plugin/skills/code-auditor/SKILL.md +9 -9
  279. package/server.json +2 -2
@@ -15,8 +15,14 @@
15
15
  * analyzer.analyze([]) with rawDb injected through config
16
16
  * - Invariants: Stage 3 reducer — receives full file list, runs rule engine
17
17
  */
18
- import type { Stage2Visitor, Stage3Reducer, Stage4Reducer, Violation } from './types.js';
19
- export declare function createSolidVisitor(): Stage2Visitor;
18
+ import type { Stage2Visitor, Stage3Reducer, Stage4Reducer, Violation, TestCoverageReport, DeadCluster } from './types.js';
19
+ import type { SizeSample } from './analyzers/universal/UniversalSOLIDAnalyzer.js';
20
+ export interface SolidVisitorBundle {
21
+ visitor: Stage2Visitor;
22
+ /** Spec 60 R2 — extract the raw size readings accumulated by the SOLID analyzer. */
23
+ getSizeSamples: () => Promise<SizeSample[]>;
24
+ }
25
+ export declare function createSolidVisitor(): SolidVisitorBundle;
20
26
  export interface DryVisitorBundle {
21
27
  visitor: Stage2Visitor;
22
28
  /** Extract accumulated dryPairs after the pipeline finishes stage 2. */
@@ -105,7 +111,37 @@ export declare function createConventionsReducer(): Stage3Reducer;
105
111
  * Uses analyzer.analyze([]) with rawDb injected.
106
112
  */
107
113
  export declare function createCrossDomainReducer(): Stage4Reducer;
114
+ interface ClFileInfo {
115
+ imports: string[];
116
+ hasExports: boolean;
117
+ /** Dynamic `import()`/`require()` calls whose specifier is computed (not a
118
+ * static string) and therefore cannot be resolved into an import edge. */
119
+ unresolvedDynamicImports: Array<{
120
+ line: number;
121
+ expression: string;
122
+ }>;
123
+ }
108
124
  export declare function createCrossLanguageEntityVisitor(): Stage2Visitor;
125
+ /**
126
+ * Spec 60 R1 — classify every non-test source module as `tested`,
127
+ * `untested-live`, or `untested-dead` off the file-level import edges
128
+ * (`importersOf`), not `function_dependencies`.
129
+ *
130
+ * A module is `tested` when a test file imports it *directly* (the edge set is
131
+ * alias-aware — built by `clResolveImport` through `classifyImportSpecifier`).
132
+ * `untested-dead` is the *post*-exception dead bucket: a file imported by
133
+ * nothing *and* not a framework entry point. `deadPreException` is the
134
+ * empty-importers count before the entry-point exception, so the drop
135
+ * (`deadPreException - untestedDead`) attributes the entry points exempted.
136
+ */
137
+ export declare function classifyTestCoverage(fileFacts: Map<string, ClFileInfo>, importersOf: Map<string, Set<string>>, packageEntrySet: ReadonlySet<string>): TestCoverageReport;
138
+ /**
139
+ * Spec 60 R3 — group unreferenced modules by basename, surfacing the pattern of
140
+ * the same file name appearing in several sibling directories (e.g. two
141
+ * `ErrorState.tsx`, three `services.ts` under separate `reports` folders). Only
142
+ * basenames with ≥2 files become clusters; a singleton dead file is not a duplicate.
143
+ */
144
+ export declare function clusterDeadModules(deadFiles: string[]): DeadCluster[];
109
145
  export declare function createSchemaValidatorReducer(): Stage4Reducer;
110
146
  export declare function createAPIContractReducer(): Stage4Reducer;
111
147
  export declare function createDependencyGraphReducer(): Stage4Reducer;
@@ -141,4 +177,5 @@ export declare function createSchemaJsonVisitor(): Stage2Visitor;
141
177
  * Builds the complete known-tables catalog and checks all table references against it.
142
178
  */
143
179
  export declare function createSchemaReducer(): Stage3Reducer;
180
+ export {};
144
181
  //# sourceMappingURL=pipelineAdapters.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pipelineAdapters.d.ts","sourceRoot":"","sources":["../src/pipelineAdapters.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH,OAAO,KAAK,EAGV,aAAa,EACb,aAAa,EACb,aAAa,EACb,SAAS,EAIV,MAAM,YAAY,CAAC;AAoEpB,wBAAgB,kBAAkB,IAAI,aAAa,CAyBlD;AAID,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,aAAa,CAAC;IACvB,wEAAwE;IACxE,WAAW,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC;QAC/B,eAAe,EAAE,MAAM,CAAC;QACxB,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QACpE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QACpE,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC,CAAC;CACL;AAED,wBAAgB,gBAAgB,CAAC,iBAAiB,CAAC,EAAE,GAAG,EAAE,GAAG,gBAAgB,CAqC5E;AAID,wBAAgB,uBAAuB,IAAI,aAAa,CAsBvD;AAID,wBAAgB,0BAA0B,IAAI,aAAa,CAsB1D;AAID,wBAAgB,oBAAoB,IAAI,aAAa,CAsBpD;AAcD;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,wBAAgB,0BAA0B,IAAI,aAAa,CAiW1D;AAID,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,aAAa,CAAC;IACvB;;;OAGG;IACH,sBAAsB,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;CAC/D;AAED,wBAAgB,kBAAkB,IAAI,kBAAkB,CAuFvD;AAMD;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,aAAa,CA6BtD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,IAAI,aAAa,CAkCzD;AAwHD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,IAAI,aAAa,CAmLnD;AAID;;;;GAIG;AACH,wBAAgB,wBAAwB,IAAI,aAAa,CAgDxD;AAID;;;;GAIG;AACH,wBAAgB,wBAAwB,IAAI,aAAa,CAqCxD;AA0fD,wBAAgB,gCAAgC,IAAI,aAAa,CAoChE;AAmKD,wBAAgB,4BAA4B,IAAI,aAAa,CAsD5D;AAID,wBAAgB,wBAAwB,IAAI,aAAa,CAkCxD;AAID,wBAAgB,4BAA4B,IAAI,aAAa,CAoK5D;AAID;;;;GAIG;AACH,wBAAgB,uBAAuB,IAAI,aAAa,CAkFvD;AAaD;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,aAAa,CA4BtD;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI,aAAa,CAgLvD;AAED;;GAEG;AACH,wBAAgB,yBAAyB,IAAI,aAAa,CAoCzD;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,aAAa,CAmBvD;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,IAAI,aAAa,CAiSnD"}
1
+ {"version":3,"file":"pipelineAdapters.d.ts","sourceRoot":"","sources":["../src/pipelineAdapters.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH,OAAO,KAAK,EAGV,aAAa,EACb,aAAa,EACb,aAAa,EACb,SAAS,EAIT,kBAAkB,EAClB,WAAW,EACZ,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iDAAiD,CAAC;AAmElF,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,aAAa,CAAC;IACvB,oFAAoF;IACpF,cAAc,EAAE,MAAM,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;CAC7C;AAED,wBAAgB,kBAAkB,IAAI,kBAAkB,CAqCvD;AAID,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,aAAa,CAAC;IACvB,wEAAwE;IACxE,WAAW,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC;QAC/B,eAAe,EAAE,MAAM,CAAC;QACxB,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QACpE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QACpE,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC,CAAC;CACL;AAED,wBAAgB,gBAAgB,CAAC,iBAAiB,CAAC,EAAE,GAAG,EAAE,GAAG,gBAAgB,CAqC5E;AAID,wBAAgB,uBAAuB,IAAI,aAAa,CAsBvD;AAID,wBAAgB,0BAA0B,IAAI,aAAa,CAsB1D;AAID,wBAAgB,oBAAoB,IAAI,aAAa,CAsBpD;AAcD;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,wBAAgB,0BAA0B,IAAI,aAAa,CAwW1D;AAID,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,aAAa,CAAC;IACvB;;;OAGG;IACH,sBAAsB,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;CAC/D;AAED,wBAAgB,kBAAkB,IAAI,kBAAkB,CAuFvD;AAMD;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,aAAa,CA6BtD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,IAAI,aAAa,CAkCzD;AAwHD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,IAAI,aAAa,CAwLnD;AAID;;;;GAIG;AACH,wBAAgB,wBAAwB,IAAI,aAAa,CAgDxD;AAID;;;;GAIG;AACH,wBAAgB,wBAAwB,IAAI,aAAa,CAqCxD;AAmJD,UAAU,UAAU;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;IACpB;+EAC2E;IAC3E,wBAAwB,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACvE;AAiWD,wBAAgB,gCAAgC,IAAI,aAAa,CAoChE;AAiID;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,EAClC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,EACrC,eAAe,EAAE,WAAW,CAAC,MAAM,CAAC,GACnC,kBAAkB,CA0DpB;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,WAAW,EAAE,CAkBrE;AA+DD,wBAAgB,4BAA4B,IAAI,aAAa,CAsD5D;AAID,wBAAgB,wBAAwB,IAAI,aAAa,CAkCxD;AAID,wBAAgB,4BAA4B,IAAI,aAAa,CA4N5D;AAID;;;;GAIG;AACH,wBAAgB,uBAAuB,IAAI,aAAa,CAkFvD;AAaD;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,aAAa,CA4BtD;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI,aAAa,CAsLvD;AAED;;GAEG;AACH,wBAAgB,yBAAyB,IAAI,aAAa,CAoCzD;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,aAAa,CAmBvD;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,IAAI,aAAa,CA0TnD"}
@@ -21,7 +21,6 @@ import { RULE_REGISTRY } from './analyzers/ruleRegistry.js';
21
21
  import { TYPESCRIPT_EXTENSIONS, JAVASCRIPT_EXTENSIONS, getLanguageFromPath } from './utils/fileDiscovery.js';
22
22
  import { walkAST, isExported, getNodeText, getFieldNode, getLineAndColumn, calculateComplexity, getFunctionBody, } from './languages/adapterBridge.js';
23
23
  import { buildImportMap, extractFunctionCalls, } from './utils/dependencyExtractor.js';
24
- import { resolveDependency, basenameNoExt } from './graph/importGraph.js';
25
24
  import { classifyImportSpecifier, DEFAULT_VIRTUAL_MODULES } from './graph/importClassification.js';
26
25
  import { isReactComponent, detectComponentType, getComponentName, } from './utils/reactDetection.js';
27
26
  import { findTableReferences, checkNamingConventions, checkQueryPatterns, checkSQLInjection, checkUnresolvedQueries, getNearestTableSuggestions, } from './analyzers/universal/schema/codeAnalysis.js';
@@ -50,10 +49,9 @@ function lazySingleton(loader) {
50
49
  return promise;
51
50
  };
52
51
  }
53
- // ── SOLID visitor ────────────────────────────────────────────────────────────
54
52
  export function createSolidVisitor() {
55
53
  const getAnalyzer = lazySingleton(() => import('./analyzers/universal/UniversalSOLIDAnalyzer.js').then((m) => new m.UniversalSOLIDAnalyzer()));
56
- return {
54
+ const visitor = {
57
55
  name: 'solid',
58
56
  stage: 'visitor',
59
57
  getRuleIds: () => getRuleIdsFor('solid'),
@@ -69,6 +67,18 @@ export function createSolidVisitor() {
69
67
  description: 'Detects violations of SOLID principles',
70
68
  category: 'architecture',
71
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
+ };
72
82
  }
73
83
  export function createDryVisitor(fullFunctionIndex) {
74
84
  const getAnalyzer = lazySingleton(() => import('./analyzers/universal/UniversalDRYAnalyzer.js').then((m) => new m.UniversalDRYAnalyzer()));
@@ -408,6 +418,9 @@ export function createFunctionIndexVisitor() {
408
418
  const { classification, resolvedPath } = classifyImportSpecifier(imp.source, filePath, corpusFiles, {
409
419
  virtualModules,
410
420
  aliasPatterns: tsconfigAliases?.pathPatterns ?? [],
421
+ pathMappings: tsconfigAliases?.paths ?? {},
422
+ baseUrl: tsconfigAliases?.baseUrl,
423
+ projectRoot: context.projectRoot,
411
424
  });
412
425
  indexFacts.push({
413
426
  table: 'import_specifiers',
@@ -542,7 +555,7 @@ export function createReactVisitor() {
542
555
  }
543
556
  }
544
557
  catch {
545
- // Cross-component checks are advisory
558
+ // Cross-component checks are high
546
559
  }
547
560
  return violations;
548
561
  },
@@ -856,7 +869,12 @@ export function createStylesReducer() {
856
869
  const factsConsumed = context.indexHandle.count('style_declarations')
857
870
  + context.indexHandle.count('style_tokens')
858
871
  + context.indexHandle.count('style_class_usage');
859
- return { violations: result.violations ?? [], facts: {}, factsConsumed };
872
+ return {
873
+ violations: result.violations ?? [],
874
+ facts: {},
875
+ factsConsumed,
876
+ ...((result.diagnostics?.length ?? 0) > 0 && { diagnostics: result.diagnostics }),
877
+ };
860
878
  }
861
879
  catch {
862
880
  return { violations: [], facts: {} };
@@ -1507,27 +1525,35 @@ function clIsEntryPointFile(fp) {
1507
1525
  return true;
1508
1526
  return false;
1509
1527
  }
1528
+ /** Resolve one import specifier to zero or one internal file via the classifier. */
1529
+ function clResolveImport(dep, sourceFile, options) {
1530
+ const { classification, resolvedPath } = classifyImportSpecifier(dep, sourceFile, options.corpusFiles, {
1531
+ virtualModules: options.virtualModules,
1532
+ aliasPatterns: options.tsconfigAliases?.pathPatterns ?? [],
1533
+ pathMappings: options.tsconfigAliases?.paths ?? {},
1534
+ baseUrl: options.tsconfigAliases?.baseUrl,
1535
+ projectRoot: options.projectRoot,
1536
+ });
1537
+ if (classification === 'internal-resolved' && resolvedPath)
1538
+ return [resolvedPath];
1539
+ return [];
1540
+ }
1510
1541
  /**
1511
1542
  * Compute file-level reachability from per-file imports.
1512
1543
  *
1513
1544
  * A file is a framework entry point (live → 1.0), imported by another file
1514
- * (live → 0.5), or referenced by nothing (dead → 0.0). The resolver mirrors
1515
- * importGraph.ts and handles relative paths, npm/alias basenames, and fuzzy
1516
- * path-segment matches.
1545
+ * (live → 0.5), or referenced by nothing (dead → 0.0). Resolution goes through
1546
+ * `classifyImportSpecifier` (relative paths and tsconfig `paths` aliases like
1547
+ * `@/`) instead of the legacy basename/fuzzy matcher, so an alias import creates
1548
+ * a real edge and a bare package import never fabricates a local one.
1517
1549
  */
1518
- function clComputeReachability(fileFacts) {
1550
+ function clComputeReachability(fileFacts, options) {
1519
1551
  const filePaths = new Set(fileFacts.keys());
1520
- const moduleToFile = new Map();
1521
- for (const fp of filePaths) {
1522
- const bn = basenameNoExt(fp);
1523
- if (!moduleToFile.has(bn))
1524
- moduleToFile.set(bn, new Set());
1525
- moduleToFile.get(bn).add(fp);
1526
- }
1552
+ const packageEntries = options.packageEntryPoints ?? new Set();
1527
1553
  const importersOf = new Map();
1528
1554
  for (const [fp, info] of fileFacts) {
1529
1555
  for (const dep of info.imports) {
1530
- const targets = resolveDependency(dep, filePaths, moduleToFile, fp);
1556
+ const targets = clResolveImport(dep, fp, options);
1531
1557
  for (const t of targets) {
1532
1558
  if (t === fp)
1533
1559
  continue;
@@ -1539,12 +1565,106 @@ function clComputeReachability(fileFacts) {
1539
1565
  }
1540
1566
  const reachability = new Map();
1541
1567
  for (const fp of filePaths) {
1542
- const entry = clIsEntryPointFile(fp);
1568
+ const entry = clIsEntryPointFile(fp) || packageEntries.has(fp);
1543
1569
  const imported = (importersOf.get(fp)?.size ?? 0) > 0;
1544
1570
  reachability.set(fp, entry ? 1 : imported ? 0.5 : 0);
1545
1571
  }
1546
1572
  return { reachability, importersOf };
1547
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
+ }
1548
1668
  /**
1549
1669
  * Build `calls` cross-references by resolving each entity's extracted callee
1550
1670
  * names against the corpus entity name index. Library calls (fetch, map, …)
@@ -1759,8 +1879,21 @@ export function createDependencyGraphReducer() {
1759
1879
  }
1760
1880
  // ── File-level reachability: unreferenced modules + ranking axis ──
1761
1881
  const fileFacts = clFileFacts(allFacts);
1882
+ let testCoverage;
1883
+ let deadClusters = [];
1762
1884
  if (fileFacts.size > 0) {
1763
- const { reachability, importersOf } = clComputeReachability(fileFacts);
1885
+ // `context.config` is the reducer's merged config (namespace + `_infra`);
1886
+ // a bare reducer context in a unit test omits it, so fall back to the
1887
+ // file facts themselves as the corpus and a no-alias classification.
1888
+ const infraConfig = (context.config ?? {});
1889
+ const packageEntrySet = new Set(infraConfig.packageEntryPoints ?? []);
1890
+ const { reachability, importersOf } = clComputeReachability(fileFacts, {
1891
+ corpusFiles: new Set(infraConfig.corpusFiles ?? [...fileFacts.keys()]),
1892
+ virtualModules: infraConfig.importVirtualModules ?? DEFAULT_VIRTUAL_MODULES,
1893
+ tsconfigAliases: infraConfig.tsconfigAliases,
1894
+ packageEntryPoints: packageEntrySet,
1895
+ projectRoot: context.projectRoot ?? '',
1896
+ });
1764
1897
  // Persist reachability to graph_cache so the post-pipeline reorder
1765
1898
  // (auditRunner hotspot block) can rank every finding by live/dead.
1766
1899
  if (context.indexHandle?.rawDb) {
@@ -1781,19 +1914,44 @@ export function createDependencyGraphReducer() {
1781
1914
  // neutral default without it.
1782
1915
  }
1783
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
+ }
1784
1940
  // Flag files that export symbols yet are imported by nothing and are
1785
1941
  // not framework entry points — a dead module. This is the signal the
1786
1942
  // orphaned-nodes check missed: a whole unreferenced file whose every
1787
1943
  // internal symbol still forms a connected component.
1944
+ const deadModuleFiles = [];
1788
1945
  for (const [fp, info] of fileFacts) {
1789
1946
  if (!info.hasExports)
1790
1947
  continue;
1791
1948
  if (clIsTestFile(fp))
1792
1949
  continue;
1793
- if (clIsEntryPointFile(fp))
1950
+ if (clIsEntryPointFile(fp) || packageEntrySet.has(fp))
1794
1951
  continue;
1795
1952
  if ((importersOf.get(fp)?.size ?? 0) > 0)
1796
1953
  continue;
1954
+ deadModuleFiles.push(fp);
1797
1955
  violations.push({
1798
1956
  file: fp,
1799
1957
  line: 1,
@@ -1808,6 +1966,12 @@ export function createDependencyGraphReducer() {
1808
1966
  details: { imports: info.imports },
1809
1967
  });
1810
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);
1811
1975
  // Spec 58 R2 — computed-specifier dynamic imports. `import(someVar)`
1812
1976
  // cannot be resolved into an edge, so any module in this corpus could
1813
1977
  // be its target and `unreferenced-module` is therefore not exhaustive.
@@ -1828,15 +1992,15 @@ export function createDependencyGraphReducer() {
1828
1992
  }
1829
1993
  const HEALTH_SEVERITY = {
1830
1994
  'break-cycles': 'severe',
1831
- 'reduce-coupling': 'advisory',
1832
- 'split-responsibilities': 'advisory',
1995
+ 'reduce-coupling': 'high',
1996
+ 'split-responsibilities': 'high',
1833
1997
  'review-orphans': 'severe',
1834
1998
  };
1835
1999
  for (const s of health.suggestions) {
1836
2000
  violations.push({
1837
2001
  file: '(multiple)',
1838
2002
  line: 0,
1839
- severity: HEALTH_SEVERITY[s.type] ?? 'advisory',
2003
+ severity: HEALTH_SEVERITY[s.type] ?? 'high',
1840
2004
  message: s.description,
1841
2005
  rule: s.type,
1842
2006
  type: s.type,
@@ -1845,7 +2009,12 @@ export function createDependencyGraphReducer() {
1845
2009
  details: s.affectedNodes ? { affectedNodes: s.affectedNodes } : undefined,
1846
2010
  });
1847
2011
  }
1848
- return { violations, facts: {}, factsConsumed: entities.length, ...(diagnostics.length > 0 && { diagnostics }) };
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 }) };
1849
2018
  }
1850
2019
  catch (e) {
1851
2020
  console.error('[dependency-graph reducer] error:', e.message);
@@ -2093,6 +2262,7 @@ export function createSchemaCodeVisitor() {
2093
2262
  line: usage.line,
2094
2263
  column: usage.column,
2095
2264
  raw_query: usage.rawQuery,
2265
+ origin: usage.origin ?? null,
2096
2266
  },
2097
2267
  });
2098
2268
  }
@@ -2111,9 +2281,14 @@ export function createSchemaCodeVisitor() {
2111
2281
  }
2112
2282
  // Check SQL injection
2113
2283
  violations.push(...checkSQLInjection(ast, adapter, sourceCode));
2114
- // Emit facts for the Stage 3 reducer
2284
+ // Emit facts for the Stage 3 reducer. Fluent-builder references
2285
+ // (`origin: 'query-builder'`) are excluded from the unknown-table check:
2286
+ // a scratch/test table name carried by `db('t').select(...)` is not a
2287
+ // schema catalog miss, and feeding it in flips the 10:1 fail-open ratio.
2115
2288
  const fileFacts = {
2116
- tableRefs: tableRefs.map((r) => ({
2289
+ tableRefs: tableRefs
2290
+ .filter((r) => r.origin !== 'query-builder')
2291
+ .map((r) => ({
2117
2292
  table: r.table,
2118
2293
  type: r.type,
2119
2294
  line: r.location.line,
@@ -2283,12 +2458,18 @@ export function createSchemaReducer() {
2283
2458
  // Genuinely-new tables introduced by this migration (excludes rename/rebuild
2284
2459
  // churn like `ALTER … RENAME TO x_old` + re-CREATE of the same name).
2285
2460
  const createdHere = [];
2461
+ const createdTables = new Set();
2462
+ const droppedTables = new Set();
2286
2463
  for (const op of sqlFile.ops) {
2464
+ const t = stripIdentifier(op.table);
2287
2465
  if (op.op === 'CREATE') {
2288
- const t = stripIdentifier(op.table);
2466
+ createdTables.add(t);
2289
2467
  if (!before.has(t))
2290
2468
  createdHere.push(t);
2291
2469
  }
2470
+ else if (op.op === 'DROP') {
2471
+ droppedTables.add(t);
2472
+ }
2292
2473
  }
2293
2474
  for (const op of sqlFile.ops) {
2294
2475
  const t = stripIdentifier(op.table);
@@ -2299,6 +2480,21 @@ export function createSchemaReducer() {
2299
2480
  dropProvenance.delete(t);
2300
2481
  }
2301
2482
  }
2483
+ // A table created and dropped within this same file is a self-contained
2484
+ // fixture — a scratch table a test or script creates, uses, then tears
2485
+ // down. Its DROP is teardown, not a migration, so it must neither surface
2486
+ // as a stale-table-reference nor leave the name unknown: keep it known and
2487
+ // clear the drop provenance this file recorded for it. (A genuine dropped
2488
+ // table stays stale because its DROP lives in a migration that never also
2489
+ // CREATEs it — e.g. recall's `generation_queue`, dropped in 0198.)
2490
+ for (const t of createdTables) {
2491
+ if (droppedTables.has(t)) {
2492
+ knownTables.add(t);
2493
+ if (dropProvenance.get(t)?.migrationFile === sqlFile.filePath) {
2494
+ dropProvenance.delete(t);
2495
+ }
2496
+ }
2497
+ }
2302
2498
  }
2303
2499
  // 1b. ORM tables from code files — with provenance from the table-source registry
2304
2500
  for (const [filePath, fact] of perFile()) {
@@ -2403,9 +2599,14 @@ export function createSchemaReducer() {
2403
2599
  symbol: ref.table,
2404
2600
  resolution: {
2405
2601
  action: 'update-stale-reference',
2602
+ // The tables `created` are evidence the migration replaced the
2603
+ // dropped table, not proof of a drop-in successor — schemas can
2604
+ // be split or changed incompatibly, in which case the file must
2605
+ // be removed rather than updated. The summary names them as
2606
+ // context and leaves update-vs-remove to the reviewer.
2406
2607
  summary: created.length > 0
2407
- ? `The table '${ref.table}' was dropped in ${migrationName}. That migration creates ${joinEnglish(created)} — update this reference to a table that still exists.`
2408
- : `The table '${ref.table}' was dropped in ${migrationName} and not recreated — update or remove this reference.`,
2608
+ ? `The table '${ref.table}' was dropped in ${migrationName}. That migration introduces ${joinEnglish(created)} — review this reference and update or remove it.`
2609
+ : `The table '${ref.table}' was dropped in ${migrationName} and was not recreated — update or remove this reference.`,
2409
2610
  symbols: created.length > 0 ? created : [ref.table],
2410
2611
  files: [ref.file],
2411
2612
  lines: [ref.line],