api-tests-coverage 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (288) hide show
  1. package/README.md +703 -0
  2. package/config.yaml.example +227 -0
  3. package/dist/action/src/index.d.ts +2 -0
  4. package/dist/action/src/index.d.ts.map +1 -0
  5. package/dist/action/src/index.js +349 -0
  6. package/dist/action/src/prComment.d.ts +34 -0
  7. package/dist/action/src/prComment.d.ts.map +1 -0
  8. package/dist/action/src/prComment.js +146 -0
  9. package/dist/src/ast/astAnalysisOrchestrator.d.ts +36 -0
  10. package/dist/src/ast/astAnalysisOrchestrator.d.ts.map +1 -0
  11. package/dist/src/ast/astAnalysisOrchestrator.js +123 -0
  12. package/dist/src/ast/astTypes.d.ts +105 -0
  13. package/dist/src/ast/astTypes.d.ts.map +1 -0
  14. package/dist/src/ast/astTypes.js +9 -0
  15. package/dist/src/ast/languageAnalyzer.d.ts +46 -0
  16. package/dist/src/ast/languageAnalyzer.d.ts.map +1 -0
  17. package/dist/src/ast/languageAnalyzer.js +9 -0
  18. package/dist/src/ast/languageCapabilities.d.ts +24 -0
  19. package/dist/src/ast/languageCapabilities.d.ts.map +1 -0
  20. package/dist/src/ast/languageCapabilities.js +92 -0
  21. package/dist/src/ast/parseFile.d.ts +16 -0
  22. package/dist/src/ast/parseFile.d.ts.map +1 -0
  23. package/dist/src/ast/parseFile.js +65 -0
  24. package/dist/src/ast/parserRegistry.d.ts +39 -0
  25. package/dist/src/ast/parserRegistry.d.ts.map +1 -0
  26. package/dist/src/ast/parserRegistry.js +66 -0
  27. package/dist/src/buildSummary.d.ts +26 -0
  28. package/dist/src/buildSummary.d.ts.map +1 -0
  29. package/dist/src/buildSummary.js +193 -0
  30. package/dist/src/businessCoverage.d.ts +68 -0
  31. package/dist/src/businessCoverage.d.ts.map +1 -0
  32. package/dist/src/businessCoverage.js +290 -0
  33. package/dist/src/compatibilityCoverage.d.ts +83 -0
  34. package/dist/src/compatibilityCoverage.d.ts.map +1 -0
  35. package/dist/src/compatibilityCoverage.js +501 -0
  36. package/dist/src/config/defaultConfig.d.ts +9 -0
  37. package/dist/src/config/defaultConfig.d.ts.map +1 -0
  38. package/dist/src/config/defaultConfig.js +97 -0
  39. package/dist/src/config/index.d.ts +12 -0
  40. package/dist/src/config/index.d.ts.map +1 -0
  41. package/dist/src/config/index.js +37 -0
  42. package/dist/src/config/loadConfig.d.ts +29 -0
  43. package/dist/src/config/loadConfig.d.ts.map +1 -0
  44. package/dist/src/config/loadConfig.js +135 -0
  45. package/dist/src/config/mergeConfig.d.ts +15 -0
  46. package/dist/src/config/mergeConfig.d.ts.map +1 -0
  47. package/dist/src/config/mergeConfig.js +57 -0
  48. package/dist/src/config/schema.d.ts +15 -0
  49. package/dist/src/config/schema.d.ts.map +1 -0
  50. package/dist/src/config/schema.js +30 -0
  51. package/dist/src/config/types.d.ts +175 -0
  52. package/dist/src/config/types.d.ts.map +1 -0
  53. package/dist/src/config/types.js +9 -0
  54. package/dist/src/config/validateConfig.d.ts +22 -0
  55. package/dist/src/config/validateConfig.d.ts.map +1 -0
  56. package/dist/src/config/validateConfig.js +171 -0
  57. package/dist/src/config.d.ts +168 -0
  58. package/dist/src/config.d.ts.map +1 -0
  59. package/dist/src/config.js +204 -0
  60. package/dist/src/coverage/deep-analysis/callGraph.d.ts +67 -0
  61. package/dist/src/coverage/deep-analysis/callGraph.d.ts.map +1 -0
  62. package/dist/src/coverage/deep-analysis/callGraph.js +275 -0
  63. package/dist/src/coverage/deep-analysis/deepEndpointResolver.d.ts +23 -0
  64. package/dist/src/coverage/deep-analysis/deepEndpointResolver.d.ts.map +1 -0
  65. package/dist/src/coverage/deep-analysis/deepEndpointResolver.js +394 -0
  66. package/dist/src/coverage/deep-analysis/index.d.ts +17 -0
  67. package/dist/src/coverage/deep-analysis/index.d.ts.map +1 -0
  68. package/dist/src/coverage/deep-analysis/index.js +63 -0
  69. package/dist/src/coverage/deep-analysis/resolveAssertions.d.ts +60 -0
  70. package/dist/src/coverage/deep-analysis/resolveAssertions.d.ts.map +1 -0
  71. package/dist/src/coverage/deep-analysis/resolveAssertions.js +121 -0
  72. package/dist/src/coverage/deep-analysis/resolveConstants.d.ts +36 -0
  73. package/dist/src/coverage/deep-analysis/resolveConstants.d.ts.map +1 -0
  74. package/dist/src/coverage/deep-analysis/resolveConstants.js +92 -0
  75. package/dist/src/coverage/deep-analysis/resolveEnums.d.ts +55 -0
  76. package/dist/src/coverage/deep-analysis/resolveEnums.d.ts.map +1 -0
  77. package/dist/src/coverage/deep-analysis/resolveEnums.js +152 -0
  78. package/dist/src/coverage/deep-analysis/resolveMethodChains.d.ts +70 -0
  79. package/dist/src/coverage/deep-analysis/resolveMethodChains.d.ts.map +1 -0
  80. package/dist/src/coverage/deep-analysis/resolveMethodChains.js +152 -0
  81. package/dist/src/coverage/deep-analysis/resolvePaths.d.ts +80 -0
  82. package/dist/src/coverage/deep-analysis/resolvePaths.d.ts.map +1 -0
  83. package/dist/src/coverage/deep-analysis/resolvePaths.js +216 -0
  84. package/dist/src/coverage/deep-analysis/resolveRequestWrappers.d.ts +71 -0
  85. package/dist/src/coverage/deep-analysis/resolveRequestWrappers.d.ts.map +1 -0
  86. package/dist/src/coverage/deep-analysis/resolveRequestWrappers.js +226 -0
  87. package/dist/src/coverage/deep-analysis/symbolTable.d.ts +58 -0
  88. package/dist/src/coverage/deep-analysis/symbolTable.d.ts.map +1 -0
  89. package/dist/src/coverage/deep-analysis/symbolTable.js +230 -0
  90. package/dist/src/coverage/deep-analysis/types.d.ts +122 -0
  91. package/dist/src/coverage/deep-analysis/types.d.ts.map +1 -0
  92. package/dist/src/coverage/deep-analysis/types.js +21 -0
  93. package/dist/src/discovery/fileClassifier.d.ts +50 -0
  94. package/dist/src/discovery/fileClassifier.d.ts.map +1 -0
  95. package/dist/src/discovery/fileClassifier.js +238 -0
  96. package/dist/src/discovery/projectDiscovery.d.ts +66 -0
  97. package/dist/src/discovery/projectDiscovery.d.ts.map +1 -0
  98. package/dist/src/discovery/projectDiscovery.js +287 -0
  99. package/dist/src/endpointCoverage.d.ts +70 -0
  100. package/dist/src/endpointCoverage.d.ts.map +1 -0
  101. package/dist/src/endpointCoverage.js +381 -0
  102. package/dist/src/errorCoverage.d.ts +93 -0
  103. package/dist/src/errorCoverage.d.ts.map +1 -0
  104. package/dist/src/errorCoverage.js +698 -0
  105. package/dist/src/index.d.ts +3 -0
  106. package/dist/src/index.d.ts.map +1 -0
  107. package/dist/src/index.js +1441 -0
  108. package/dist/src/inference/businessRuleInference.d.ts +63 -0
  109. package/dist/src/inference/businessRuleInference.d.ts.map +1 -0
  110. package/dist/src/inference/businessRuleInference.js +268 -0
  111. package/dist/src/inference/integrationFlowInference.d.ts +56 -0
  112. package/dist/src/inference/integrationFlowInference.d.ts.map +1 -0
  113. package/dist/src/inference/integrationFlowInference.js +266 -0
  114. package/dist/src/integrationCoverage.d.ts +72 -0
  115. package/dist/src/integrationCoverage.d.ts.map +1 -0
  116. package/dist/src/integrationCoverage.js +317 -0
  117. package/dist/src/intelligence/index.d.ts +20 -0
  118. package/dist/src/intelligence/index.d.ts.map +1 -0
  119. package/dist/src/intelligence/index.js +105 -0
  120. package/dist/src/intelligence/linkageEngine.d.ts +20 -0
  121. package/dist/src/intelligence/linkageEngine.d.ts.map +1 -0
  122. package/dist/src/intelligence/linkageEngine.js +522 -0
  123. package/dist/src/intelligence/markdownReporter.d.ts +12 -0
  124. package/dist/src/intelligence/markdownReporter.d.ts.map +1 -0
  125. package/dist/src/intelligence/markdownReporter.js +265 -0
  126. package/dist/src/intelligence/riskScoring.d.ts +53 -0
  127. package/dist/src/intelligence/riskScoring.d.ts.map +1 -0
  128. package/dist/src/intelligence/riskScoring.js +181 -0
  129. package/dist/src/intelligence/types.d.ts +121 -0
  130. package/dist/src/intelligence/types.d.ts.map +1 -0
  131. package/dist/src/intelligence/types.js +8 -0
  132. package/dist/src/languageDetection.d.ts +100 -0
  133. package/dist/src/languageDetection.d.ts.map +1 -0
  134. package/dist/src/languageDetection.js +349 -0
  135. package/dist/src/languages/java/index.d.ts +16 -0
  136. package/dist/src/languages/java/index.d.ts.map +1 -0
  137. package/dist/src/languages/java/index.js +103 -0
  138. package/dist/src/languages/java/parser.d.ts +7 -0
  139. package/dist/src/languages/java/parser.d.ts.map +1 -0
  140. package/dist/src/languages/java/parser.js +50 -0
  141. package/dist/src/languages/java/semanticBuilder.d.ts +21 -0
  142. package/dist/src/languages/java/semanticBuilder.d.ts.map +1 -0
  143. package/dist/src/languages/java/semanticBuilder.js +358 -0
  144. package/dist/src/languages/javascript/annotationExtractor.d.ts +20 -0
  145. package/dist/src/languages/javascript/annotationExtractor.d.ts.map +1 -0
  146. package/dist/src/languages/javascript/annotationExtractor.js +94 -0
  147. package/dist/src/languages/javascript/assertionResolver.d.ts +18 -0
  148. package/dist/src/languages/javascript/assertionResolver.d.ts.map +1 -0
  149. package/dist/src/languages/javascript/assertionResolver.js +150 -0
  150. package/dist/src/languages/javascript/callResolver.d.ts +23 -0
  151. package/dist/src/languages/javascript/callResolver.d.ts.map +1 -0
  152. package/dist/src/languages/javascript/callResolver.js +236 -0
  153. package/dist/src/languages/javascript/httpInteractionExtractor.d.ts +23 -0
  154. package/dist/src/languages/javascript/httpInteractionExtractor.d.ts.map +1 -0
  155. package/dist/src/languages/javascript/httpInteractionExtractor.js +205 -0
  156. package/dist/src/languages/javascript/index.d.ts +20 -0
  157. package/dist/src/languages/javascript/index.d.ts.map +1 -0
  158. package/dist/src/languages/javascript/index.js +136 -0
  159. package/dist/src/languages/javascript/parser.d.ts +14 -0
  160. package/dist/src/languages/javascript/parser.d.ts.map +1 -0
  161. package/dist/src/languages/javascript/parser.js +38 -0
  162. package/dist/src/languages/javascript/symbolResolver.d.ts +31 -0
  163. package/dist/src/languages/javascript/symbolResolver.d.ts.map +1 -0
  164. package/dist/src/languages/javascript/symbolResolver.js +183 -0
  165. package/dist/src/languages/kotlin/index.d.ts +16 -0
  166. package/dist/src/languages/kotlin/index.d.ts.map +1 -0
  167. package/dist/src/languages/kotlin/index.js +151 -0
  168. package/dist/src/languages/kotlin/parser.d.ts +11 -0
  169. package/dist/src/languages/kotlin/parser.d.ts.map +1 -0
  170. package/dist/src/languages/kotlin/parser.js +74 -0
  171. package/dist/src/languages/python/index.d.ts +15 -0
  172. package/dist/src/languages/python/index.d.ts.map +1 -0
  173. package/dist/src/languages/python/index.js +293 -0
  174. package/dist/src/languages/ruby/index.d.ts +15 -0
  175. package/dist/src/languages/ruby/index.d.ts.map +1 -0
  176. package/dist/src/languages/ruby/index.js +274 -0
  177. package/dist/src/languages/shared/treeSitterUtils.d.ts +43 -0
  178. package/dist/src/languages/shared/treeSitterUtils.d.ts.map +1 -0
  179. package/dist/src/languages/shared/treeSitterUtils.js +100 -0
  180. package/dist/src/languages/typescript/index.d.ts +14 -0
  181. package/dist/src/languages/typescript/index.d.ts.map +1 -0
  182. package/dist/src/languages/typescript/index.js +25 -0
  183. package/dist/src/lib/index.d.ts +228 -0
  184. package/dist/src/lib/index.d.ts.map +1 -0
  185. package/dist/src/lib/index.js +486 -0
  186. package/dist/src/mcp/client/index.d.ts +37 -0
  187. package/dist/src/mcp/client/index.d.ts.map +1 -0
  188. package/dist/src/mcp/client/index.js +235 -0
  189. package/dist/src/mcp/config.d.ts +50 -0
  190. package/dist/src/mcp/config.d.ts.map +1 -0
  191. package/dist/src/mcp/config.js +125 -0
  192. package/dist/src/mcp/events.d.ts +24 -0
  193. package/dist/src/mcp/events.d.ts.map +1 -0
  194. package/dist/src/mcp/events.js +48 -0
  195. package/dist/src/mcp/fallback/index.d.ts +50 -0
  196. package/dist/src/mcp/fallback/index.d.ts.map +1 -0
  197. package/dist/src/mcp/fallback/index.js +216 -0
  198. package/dist/src/mcp/index.d.ts +67 -0
  199. package/dist/src/mcp/index.d.ts.map +1 -0
  200. package/dist/src/mcp/index.js +212 -0
  201. package/dist/src/mcp/normalizer.d.ts +21 -0
  202. package/dist/src/mcp/normalizer.d.ts.map +1 -0
  203. package/dist/src/mcp/normalizer.js +99 -0
  204. package/dist/src/mcp/prompts/index.d.ts +86 -0
  205. package/dist/src/mcp/prompts/index.d.ts.map +1 -0
  206. package/dist/src/mcp/prompts/index.js +304 -0
  207. package/dist/src/mcp/templates/index.d.ts +35 -0
  208. package/dist/src/mcp/templates/index.d.ts.map +1 -0
  209. package/dist/src/mcp/templates/index.js +143 -0
  210. package/dist/src/mcp/testing/mock-server/index.d.ts +47 -0
  211. package/dist/src/mcp/testing/mock-server/index.d.ts.map +1 -0
  212. package/dist/src/mcp/testing/mock-server/index.js +157 -0
  213. package/dist/src/mcp/types.d.ts +127 -0
  214. package/dist/src/mcp/types.d.ts.map +1 -0
  215. package/dist/src/mcp/types.js +8 -0
  216. package/dist/src/observability.d.ts +138 -0
  217. package/dist/src/observability.d.ts.map +1 -0
  218. package/dist/src/observability.js +519 -0
  219. package/dist/src/parameterCoverage.d.ts +75 -0
  220. package/dist/src/parameterCoverage.d.ts.map +1 -0
  221. package/dist/src/parameterCoverage.js +629 -0
  222. package/dist/src/perfResilienceCoverage.d.ts +155 -0
  223. package/dist/src/perfResilienceCoverage.d.ts.map +1 -0
  224. package/dist/src/perfResilienceCoverage.js +670 -0
  225. package/dist/src/pluginLoader.d.ts +51 -0
  226. package/dist/src/pluginLoader.d.ts.map +1 -0
  227. package/dist/src/pluginLoader.js +72 -0
  228. package/dist/src/publishing.d.ts +63 -0
  229. package/dist/src/publishing.d.ts.map +1 -0
  230. package/dist/src/publishing.js +379 -0
  231. package/dist/src/qualityGate.d.ts +58 -0
  232. package/dist/src/qualityGate.d.ts.map +1 -0
  233. package/dist/src/qualityGate.js +118 -0
  234. package/dist/src/reporting.d.ts +41 -0
  235. package/dist/src/reporting.d.ts.map +1 -0
  236. package/dist/src/reporting.js +278 -0
  237. package/dist/src/screenshots.d.ts +71 -0
  238. package/dist/src/screenshots.d.ts.map +1 -0
  239. package/dist/src/screenshots.js +141 -0
  240. package/dist/src/security/gate/index.d.ts +11 -0
  241. package/dist/src/security/gate/index.d.ts.map +1 -0
  242. package/dist/src/security/gate/index.js +65 -0
  243. package/dist/src/security/index.d.ts +30 -0
  244. package/dist/src/security/index.d.ts.map +1 -0
  245. package/dist/src/security/index.js +342 -0
  246. package/dist/src/security/normalizers/semgrep.d.ts +10 -0
  247. package/dist/src/security/normalizers/semgrep.d.ts.map +1 -0
  248. package/dist/src/security/normalizers/semgrep.js +104 -0
  249. package/dist/src/security/normalizers/trivy.d.ts +10 -0
  250. package/dist/src/security/normalizers/trivy.d.ts.map +1 -0
  251. package/dist/src/security/normalizers/trivy.js +78 -0
  252. package/dist/src/security/normalizers/zap.d.ts +10 -0
  253. package/dist/src/security/normalizers/zap.d.ts.map +1 -0
  254. package/dist/src/security/normalizers/zap.js +104 -0
  255. package/dist/src/security/scanners/semgrep.d.ts +6 -0
  256. package/dist/src/security/scanners/semgrep.d.ts.map +1 -0
  257. package/dist/src/security/scanners/semgrep.js +125 -0
  258. package/dist/src/security/scanners/trivy.d.ts +6 -0
  259. package/dist/src/security/scanners/trivy.d.ts.map +1 -0
  260. package/dist/src/security/scanners/trivy.js +115 -0
  261. package/dist/src/security/scanners/zap.d.ts +6 -0
  262. package/dist/src/security/scanners/zap.d.ts.map +1 -0
  263. package/dist/src/security/scanners/zap.js +135 -0
  264. package/dist/src/security/types.d.ts +146 -0
  265. package/dist/src/security/types.d.ts.map +1 -0
  266. package/dist/src/security/types.js +6 -0
  267. package/dist/src/securityCoverage.d.ts +116 -0
  268. package/dist/src/securityCoverage.d.ts.map +1 -0
  269. package/dist/src/securityCoverage.js +725 -0
  270. package/dist/src/summary/buildSummary.d.ts +28 -0
  271. package/dist/src/summary/buildSummary.d.ts.map +1 -0
  272. package/dist/src/summary/buildSummary.js +257 -0
  273. package/dist/src/summary/evaluateMetrics.d.ts +31 -0
  274. package/dist/src/summary/evaluateMetrics.d.ts.map +1 -0
  275. package/dist/src/summary/evaluateMetrics.js +118 -0
  276. package/dist/src/summary/index.d.ts +10 -0
  277. package/dist/src/summary/index.d.ts.map +1 -0
  278. package/dist/src/summary/index.js +22 -0
  279. package/dist/src/summary/markdownRenderer.d.ts +139 -0
  280. package/dist/src/summary/markdownRenderer.d.ts.map +1 -0
  281. package/dist/src/summary/markdownRenderer.js +459 -0
  282. package/dist/src/summary/prSummary.d.ts +24 -0
  283. package/dist/src/summary/prSummary.d.ts.map +1 -0
  284. package/dist/src/summary/prSummary.js +233 -0
  285. package/dist/src/summary/summaryTypes.d.ts +35 -0
  286. package/dist/src/summary/summaryTypes.d.ts.map +1 -0
  287. package/dist/src/summary/summaryTypes.js +27 -0
  288. package/package.json +84 -0
@@ -0,0 +1,50 @@
1
+ /**
2
+ * File Classification Engine
3
+ *
4
+ * Determines the role of each file in the project. Only files classified as
5
+ * `test_code` or `bdd_scenarios` may contribute to coverage evidence.
6
+ *
7
+ * Specification files, metadata files (business rules, integration flows),
8
+ * and configuration files are explicitly excluded from coverage calculations.
9
+ */
10
+ export type FileCategory = 'specification' | 'service_code' | 'test_code' | 'bdd_scenarios' | 'contracts' | 'performance' | 'security_reports' | 'configuration' | 'metadata' | 'unknown';
11
+ export interface ClassifiedFile {
12
+ filePath: string;
13
+ category: FileCategory;
14
+ /** True only when category is test_code or bdd_scenarios */
15
+ isCoverageEvidence: boolean;
16
+ }
17
+ /** Files that must NEVER contribute to coverage evidence */
18
+ export declare const COVERAGE_EVIDENCE_CATEGORIES: ReadonlySet<FileCategory>;
19
+ /**
20
+ * Classify a single file path into a `FileCategory`.
21
+ *
22
+ * Classification priority (first match wins):
23
+ * 1. Known specification basenames / includes
24
+ * 2. Known metadata basenames
25
+ * 3. Known configuration basenames
26
+ * 4. `.feature` extension → bdd_scenarios
27
+ * 5. Contract path patterns
28
+ * 6. Security report directory patterns
29
+ * 7. Performance artifact directory patterns
30
+ * 8. Test file name patterns (*.test.*, *.spec.*, *Test.*, *Tests.*, *Spec.*)
31
+ * 9. Remaining source extensions → service_code
32
+ * 10. Fallback → unknown
33
+ */
34
+ export declare function classifyFile(filePath: string): ClassifiedFile;
35
+ /**
36
+ * Classify multiple file paths at once.
37
+ */
38
+ export declare function classifyFiles(filePaths: string[]): ClassifiedFile[];
39
+ /**
40
+ * Filter a list of classified files to only those that may contribute to
41
+ * coverage evidence (test_code and bdd_scenarios).
42
+ */
43
+ export declare function filterCoverageEvidence(files: ClassifiedFile[]): ClassifiedFile[];
44
+ /**
45
+ * Return true if this file basename looks like a test file.
46
+ * Supports patterns: *.test.*, *.spec.*, *Test.java, *Tests.java, *Spec.*,
47
+ * test_*.py, *_test.py, *_spec.rb, spec/**
48
+ */
49
+ export declare function isTestFile(basename: string): boolean;
50
+ //# sourceMappingURL=fileClassifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileClassifier.d.ts","sourceRoot":"","sources":["../../../src/discovery/fileClassifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,MAAM,MAAM,YAAY,GACpB,eAAe,GACf,cAAc,GACd,WAAW,GACX,eAAe,GACf,WAAW,GACX,aAAa,GACb,kBAAkB,GAClB,eAAe,GACf,UAAU,GACV,SAAS,CAAC;AAEd,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,YAAY,CAAC;IACvB,4DAA4D;IAC5D,kBAAkB,EAAE,OAAO,CAAC;CAC7B;AAED,4DAA4D;AAC5D,eAAO,MAAM,4BAA4B,EAAE,WAAW,CAAC,YAAY,CAGjE,CAAC;AAkEH;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,CA4E7D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,cAAc,EAAE,CAEnE;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,cAAc,EAAE,CAEhF;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAapD"}
@@ -0,0 +1,238 @@
1
+ "use strict";
2
+ /**
3
+ * File Classification Engine
4
+ *
5
+ * Determines the role of each file in the project. Only files classified as
6
+ * `test_code` or `bdd_scenarios` may contribute to coverage evidence.
7
+ *
8
+ * Specification files, metadata files (business rules, integration flows),
9
+ * and configuration files are explicitly excluded from coverage calculations.
10
+ */
11
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ var desc = Object.getOwnPropertyDescriptor(m, k);
14
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
15
+ desc = { enumerable: true, get: function() { return m[k]; } };
16
+ }
17
+ Object.defineProperty(o, k2, desc);
18
+ }) : (function(o, m, k, k2) {
19
+ if (k2 === undefined) k2 = k;
20
+ o[k2] = m[k];
21
+ }));
22
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
23
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
24
+ }) : function(o, v) {
25
+ o["default"] = v;
26
+ });
27
+ var __importStar = (this && this.__importStar) || (function () {
28
+ var ownKeys = function(o) {
29
+ ownKeys = Object.getOwnPropertyNames || function (o) {
30
+ var ar = [];
31
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
32
+ return ar;
33
+ };
34
+ return ownKeys(o);
35
+ };
36
+ return function (mod) {
37
+ if (mod && mod.__esModule) return mod;
38
+ var result = {};
39
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
40
+ __setModuleDefault(result, mod);
41
+ return result;
42
+ };
43
+ })();
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.COVERAGE_EVIDENCE_CATEGORIES = void 0;
46
+ exports.classifyFile = classifyFile;
47
+ exports.classifyFiles = classifyFiles;
48
+ exports.filterCoverageEvidence = filterCoverageEvidence;
49
+ exports.isTestFile = isTestFile;
50
+ const path = __importStar(require("path"));
51
+ /** Files that must NEVER contribute to coverage evidence */
52
+ exports.COVERAGE_EVIDENCE_CATEGORIES = new Set([
53
+ 'test_code',
54
+ 'bdd_scenarios',
55
+ ]);
56
+ // ─── Classification rules ────────────────────────────────────────────────────
57
+ /** Basename/path patterns for specification files */
58
+ const SPEC_BASENAMES = new Set([
59
+ 'openapi.yaml',
60
+ 'openapi.yml',
61
+ 'openapi.json',
62
+ 'swagger.yaml',
63
+ 'swagger.yml',
64
+ 'swagger.json',
65
+ ]);
66
+ /** Basename patterns that match when the file name includes one of these */
67
+ const SPEC_INCLUDES = ['openapi', 'swagger'];
68
+ /** Basename patterns for metadata files (rules / flows / contracts) */
69
+ const METADATA_BASENAMES = new Set([
70
+ 'business-rules.yaml',
71
+ 'business-rules.yml',
72
+ 'business-rules.json',
73
+ 'integration-flows.yaml',
74
+ 'integration-flows.yml',
75
+ 'integration-flows.json',
76
+ ]);
77
+ /** Basename patterns for analyzer / project configuration */
78
+ const CONFIG_BASENAMES = new Set([
79
+ 'qintel-analyzer.yaml',
80
+ 'qintel-analyzer.yml',
81
+ 'config.yaml',
82
+ 'config.yml',
83
+ 'coverage.config.json',
84
+ 'package.json',
85
+ 'pom.xml',
86
+ 'build.gradle',
87
+ 'build.gradle.kts',
88
+ 'requirements.txt',
89
+ 'Gemfile',
90
+ 'Gemfile.lock',
91
+ 'tsconfig.json',
92
+ 'jest.config.js',
93
+ 'jest.config.ts',
94
+ '.eslintrc.json',
95
+ '.eslintrc.js',
96
+ '.eslintrc.yaml',
97
+ '.eslintrc.yml',
98
+ ]);
99
+ /** Extensions mapped directly to a category */
100
+ const EXTENSION_MAP = {
101
+ '.feature': 'bdd_scenarios',
102
+ };
103
+ /** Glob-style path-segment patterns for security reports */
104
+ const SECURITY_REPORT_DIRS = ['zap', 'trivy', 'semgrep'];
105
+ /** Glob-style path-segment patterns for performance artifacts */
106
+ const PERFORMANCE_DIRS = ['jmeter', 'k6', 'gatling', 'locust'];
107
+ /** Extensions for contract files */
108
+ const CONTRACT_EXTENSIONS = new Set(['.pact.json']);
109
+ // ─── Core classifier ─────────────────────────────────────────────────────────
110
+ /**
111
+ * Classify a single file path into a `FileCategory`.
112
+ *
113
+ * Classification priority (first match wins):
114
+ * 1. Known specification basenames / includes
115
+ * 2. Known metadata basenames
116
+ * 3. Known configuration basenames
117
+ * 4. `.feature` extension → bdd_scenarios
118
+ * 5. Contract path patterns
119
+ * 6. Security report directory patterns
120
+ * 7. Performance artifact directory patterns
121
+ * 8. Test file name patterns (*.test.*, *.spec.*, *Test.*, *Tests.*, *Spec.*)
122
+ * 9. Remaining source extensions → service_code
123
+ * 10. Fallback → unknown
124
+ */
125
+ function classifyFile(filePath) {
126
+ const basename = path.basename(filePath).toLowerCase();
127
+ const ext = path.extname(filePath).toLowerCase();
128
+ const normalizedPath = filePath.replace(/\\/g, '/').toLowerCase();
129
+ const segments = normalizedPath.split('/');
130
+ // 1. Specification
131
+ if (SPEC_BASENAMES.has(basename)) {
132
+ return make(filePath, 'specification');
133
+ }
134
+ for (const inc of SPEC_INCLUDES) {
135
+ if (basename.includes(inc) && (ext === '.yaml' || ext === '.yml' || ext === '.json')) {
136
+ return make(filePath, 'specification');
137
+ }
138
+ }
139
+ // 2. Metadata (business rules / integration flows)
140
+ if (METADATA_BASENAMES.has(basename)) {
141
+ return make(filePath, 'metadata');
142
+ }
143
+ // 3. Configuration
144
+ if (CONFIG_BASENAMES.has(basename) || ext === '.env' || basename.endsWith('.config.json') || basename.endsWith('.config.js') || basename.endsWith('.config.ts')) {
145
+ return make(filePath, 'configuration');
146
+ }
147
+ // 4. BDD feature files
148
+ if (ext === '.feature') {
149
+ return make(filePath, 'bdd_scenarios');
150
+ }
151
+ // 5. Contract files (*.pact.json, contracts/**/*.json)
152
+ if (basename.endsWith('.pact.json')) {
153
+ return make(filePath, 'contracts');
154
+ }
155
+ if (segments.includes('contracts') && ext === '.json') {
156
+ return make(filePath, 'contracts');
157
+ }
158
+ // 6. Security reports
159
+ for (const dir of SECURITY_REPORT_DIRS) {
160
+ if (segments.includes(dir) && ext === '.json') {
161
+ return make(filePath, 'security_reports');
162
+ }
163
+ }
164
+ // 7. Performance artifacts
165
+ for (const dir of PERFORMANCE_DIRS) {
166
+ if (segments.includes(dir) && (ext === '.jtl' || ext === '.json' || ext === '.csv')) {
167
+ return make(filePath, 'performance');
168
+ }
169
+ }
170
+ // 8. Test code — matches *.test.*, *.spec.*, *Test.*, *Tests.*, *Spec.*
171
+ const basenameOriginal = path.basename(filePath);
172
+ if (isTestFile(basenameOriginal)) {
173
+ return make(filePath, 'test_code');
174
+ }
175
+ // 9. Service code by extension
176
+ const SERVICE_CODE_EXTS = new Set([
177
+ '.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs',
178
+ '.java', '.kt', '.kts',
179
+ '.py',
180
+ '.rb',
181
+ '.go',
182
+ '.cs',
183
+ '.cpp', '.cc', '.h',
184
+ '.rs',
185
+ ]);
186
+ if (SERVICE_CODE_EXTS.has(ext)) {
187
+ return make(filePath, 'service_code');
188
+ }
189
+ // 10. Unknown
190
+ return make(filePath, 'unknown');
191
+ }
192
+ /**
193
+ * Classify multiple file paths at once.
194
+ */
195
+ function classifyFiles(filePaths) {
196
+ return filePaths.map(classifyFile);
197
+ }
198
+ /**
199
+ * Filter a list of classified files to only those that may contribute to
200
+ * coverage evidence (test_code and bdd_scenarios).
201
+ */
202
+ function filterCoverageEvidence(files) {
203
+ return files.filter((f) => exports.COVERAGE_EVIDENCE_CATEGORIES.has(f.category));
204
+ }
205
+ /**
206
+ * Return true if this file basename looks like a test file.
207
+ * Supports patterns: *.test.*, *.spec.*, *Test.java, *Tests.java, *Spec.*,
208
+ * test_*.py, *_test.py, *_spec.rb, spec/**
209
+ */
210
+ function isTestFile(basename) {
211
+ // Exact extension-based patterns
212
+ if (/\.(test|spec)\.[a-zA-Z]+$/.test(basename))
213
+ return true;
214
+ // Java / Kotlin test class conventions
215
+ if (/Test\.(java|kt|kts)$/.test(basename))
216
+ return true;
217
+ if (/Tests\.(java|kt|kts)$/.test(basename))
218
+ return true;
219
+ if (/Spec\.(java|kt|kts|rb|ts|js)$/.test(basename))
220
+ return true;
221
+ // Python conventions
222
+ if (/^test_/.test(basename))
223
+ return true;
224
+ if (/_test\.py$/.test(basename))
225
+ return true;
226
+ // Ruby conventions
227
+ if (/_spec\.rb$/.test(basename))
228
+ return true;
229
+ return false;
230
+ }
231
+ // ─── Helpers ─────────────────────────────────────────────────────────────────
232
+ function make(filePath, category) {
233
+ return {
234
+ filePath,
235
+ category,
236
+ isCoverageEvidence: exports.COVERAGE_EVIDENCE_CATEGORIES.has(category),
237
+ };
238
+ }
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Agnostic Project Discovery Engine
3
+ *
4
+ * Scans the repository tree, classifies files, detects languages and test
5
+ * frameworks, and groups artifacts by function so each analysis pipeline
6
+ * receives the right inputs — even when no configuration file exists.
7
+ *
8
+ * Discovery pipeline:
9
+ * project root → file system scan → file classification →
10
+ * artifact grouping → language detection → framework detection
11
+ */
12
+ import { ClassifiedFile } from './fileClassifier';
13
+ export type DetectedLanguage = 'java' | 'kotlin' | 'python' | 'ruby' | 'javascript' | 'typescript' | 'go' | 'csharp';
14
+ export type DetectedFramework = 'junit' | 'testng' | 'restassured' | 'pytest' | 'unittest' | 'rspec' | 'minitest' | 'jest' | 'mocha' | 'cypress' | 'playwright' | 'cucumber' | 'gherkin';
15
+ export interface DiscoveredArtifacts {
16
+ /** Detected project root */
17
+ projectRoot: string;
18
+ /** All classified files found under the root */
19
+ allFiles: ClassifiedFile[];
20
+ /** OpenAPI / Swagger definition files */
21
+ specs: string[];
22
+ /** Test source files (test_code + bdd_scenarios) */
23
+ testFiles: string[];
24
+ /** BDD feature files specifically */
25
+ featureFiles: string[];
26
+ /** Contract files (Pact, etc.) */
27
+ contractFiles: string[];
28
+ /** Performance test result files (JMeter, k6, etc.) */
29
+ performanceFiles: string[];
30
+ /** Security scan report files */
31
+ securityReportFiles: string[];
32
+ /** Service source code files */
33
+ serviceFiles: string[];
34
+ /** Detected programming languages */
35
+ languages: DetectedLanguage[];
36
+ /** Detected test frameworks */
37
+ frameworks: DetectedFramework[];
38
+ /** Whether each artifact type was explicitly configured vs auto-discovered */
39
+ discoverySource: Record<keyof Omit<DiscoveredArtifacts, 'allFiles' | 'projectRoot' | 'discoverySource' | 'languages' | 'frameworks'>, 'explicit' | 'discovered'>;
40
+ }
41
+ export interface DiscoveryOptions {
42
+ /** Root directory to scan. Defaults to process.cwd() */
43
+ rootDir?: string;
44
+ /**
45
+ * Directories to exclude from the scan.
46
+ * Defaults to node_modules, .git, dist, build, target, .cache, coverage
47
+ */
48
+ excludeDirs?: string[];
49
+ /** Maximum depth for recursive scan. Defaults to 20 */
50
+ maxDepth?: number;
51
+ /** If provided, these paths override the auto-discovered spec files */
52
+ explicitSpecs?: string[];
53
+ /** If provided, these paths override the auto-discovered test files */
54
+ explicitTests?: string[];
55
+ /** If provided, these paths override the auto-discovered contract files */
56
+ explicitContracts?: string[];
57
+ }
58
+ /**
59
+ * Discover all project artifacts from `rootDir`.
60
+ *
61
+ * When explicit inputs are provided (e.g. from config.yaml), they are used
62
+ * directly and the corresponding discovery step is skipped. This ensures
63
+ * "always discovers" behaviour while respecting explicit configuration.
64
+ */
65
+ export declare function discoverProject(options?: DiscoveryOptions): DiscoveredArtifacts;
66
+ //# sourceMappingURL=projectDiscovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectDiscovery.d.ts","sourceRoot":"","sources":["../../../src/discovery/projectDiscovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,EAAgB,cAAc,EAAgB,MAAM,kBAAkB,CAAC;AAI9E,MAAM,MAAM,gBAAgB,GACxB,MAAM,GACN,QAAQ,GACR,QAAQ,GACR,MAAM,GACN,YAAY,GACZ,YAAY,GACZ,IAAI,GACJ,QAAQ,CAAC;AAEb,MAAM,MAAM,iBAAiB,GAEzB,OAAO,GACP,QAAQ,GACR,aAAa,GAEb,QAAQ,GACR,UAAU,GAEV,OAAO,GACP,UAAU,GAEV,MAAM,GACN,OAAO,GACP,SAAS,GACT,YAAY,GAEZ,UAAU,GACV,SAAS,CAAC;AAEd,MAAM,WAAW,mBAAmB;IAClC,4BAA4B;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,yCAAyC;IACzC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,oDAAoD;IACpD,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,qCAAqC;IACrC,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,kCAAkC;IAClC,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,uDAAuD;IACvD,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,iCAAiC;IACjC,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,gCAAgC;IAChC,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,qCAAqC;IACrC,SAAS,EAAE,gBAAgB,EAAE,CAAC;IAC9B,+BAA+B;IAC/B,UAAU,EAAE,iBAAiB,EAAE,CAAC;IAChC,8EAA8E;IAC9E,eAAe,EAAE,MAAM,CAAC,MAAM,IAAI,CAAC,mBAAmB,EAAE,UAAU,GAAG,aAAa,GAAG,iBAAiB,GAAG,WAAW,GAAG,YAAY,CAAC,EAAE,UAAU,GAAG,YAAY,CAAC,CAAC;CAClK;AAED,MAAM,WAAW,gBAAgB;IAC/B,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,uDAAuD;IACvD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uEAAuE;IACvE,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,uEAAuE;IACvE,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,2EAA2E;IAC3E,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B;AAiHD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,GAAE,gBAAqB,GAAG,mBAAmB,CA8EnF"}
@@ -0,0 +1,287 @@
1
+ "use strict";
2
+ /**
3
+ * Agnostic Project Discovery Engine
4
+ *
5
+ * Scans the repository tree, classifies files, detects languages and test
6
+ * frameworks, and groups artifacts by function so each analysis pipeline
7
+ * receives the right inputs — even when no configuration file exists.
8
+ *
9
+ * Discovery pipeline:
10
+ * project root → file system scan → file classification →
11
+ * artifact grouping → language detection → framework detection
12
+ */
13
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ var desc = Object.getOwnPropertyDescriptor(m, k);
16
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
+ desc = { enumerable: true, get: function() { return m[k]; } };
18
+ }
19
+ Object.defineProperty(o, k2, desc);
20
+ }) : (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ o[k2] = m[k];
23
+ }));
24
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
25
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
26
+ }) : function(o, v) {
27
+ o["default"] = v;
28
+ });
29
+ var __importStar = (this && this.__importStar) || (function () {
30
+ var ownKeys = function(o) {
31
+ ownKeys = Object.getOwnPropertyNames || function (o) {
32
+ var ar = [];
33
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
34
+ return ar;
35
+ };
36
+ return ownKeys(o);
37
+ };
38
+ return function (mod) {
39
+ if (mod && mod.__esModule) return mod;
40
+ var result = {};
41
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
42
+ __setModuleDefault(result, mod);
43
+ return result;
44
+ };
45
+ })();
46
+ Object.defineProperty(exports, "__esModule", { value: true });
47
+ exports.discoverProject = discoverProject;
48
+ const fs = __importStar(require("fs"));
49
+ const path = __importStar(require("path"));
50
+ const fileClassifier_1 = require("./fileClassifier");
51
+ // ─── Default exclude list ─────────────────────────────────────────────────────
52
+ const DEFAULT_EXCLUDE_DIRS = new Set([
53
+ 'node_modules',
54
+ '.git',
55
+ 'dist',
56
+ 'build',
57
+ 'target',
58
+ '.cache',
59
+ 'coverage',
60
+ '.nyc_output',
61
+ '__pycache__',
62
+ '.pytest_cache',
63
+ '.tox',
64
+ 'vendor',
65
+ '.bundle',
66
+ '.gradle',
67
+ ]);
68
+ // ─── Language detection ───────────────────────────────────────────────────────
69
+ /** Map build-file basenames to language */
70
+ const BUILD_FILE_LANGUAGE_MAP = {
71
+ 'pom.xml': ['java'],
72
+ 'build.gradle': ['java', 'kotlin'],
73
+ 'build.gradle.kts': ['kotlin'],
74
+ 'settings.gradle': ['java', 'kotlin'],
75
+ 'gradlew': ['java', 'kotlin'],
76
+ 'package.json': ['javascript', 'typescript'],
77
+ 'requirements.txt': ['python'],
78
+ 'setup.py': ['python'],
79
+ 'setup.cfg': ['python'],
80
+ 'pyproject.toml': ['python'],
81
+ 'Gemfile': ['ruby'],
82
+ 'go.mod': ['go'],
83
+ '*.csproj': ['csharp'],
84
+ };
85
+ const EXTENSION_LANGUAGE_MAP = {
86
+ '.java': 'java',
87
+ '.kt': 'kotlin',
88
+ '.kts': 'kotlin',
89
+ '.py': 'python',
90
+ '.rb': 'ruby',
91
+ '.js': 'javascript',
92
+ '.jsx': 'javascript',
93
+ '.mjs': 'javascript',
94
+ '.ts': 'typescript',
95
+ '.tsx': 'typescript',
96
+ '.go': 'go',
97
+ '.cs': 'csharp',
98
+ };
99
+ // ─── Framework detection ──────────────────────────────────────────────────────
100
+ /**
101
+ * Detect test frameworks from test file contents (first 4 KB).
102
+ * This is a deliberate regex-based heuristic — fast for CI usage.
103
+ */
104
+ function detectFrameworksFromContent(content) {
105
+ const found = [];
106
+ if (/import\s+.*JUnit|@Test\b|@RunWith/.test(content))
107
+ found.push('junit');
108
+ if (/testng|@Test.*groups/.test(content))
109
+ found.push('testng');
110
+ if (/RestAssured|given\(\)|when\(\)|then\(\)/.test(content))
111
+ found.push('restassured');
112
+ if (/import\s+pytest|def\s+test_/.test(content))
113
+ found.push('pytest');
114
+ if (/import\s+unittest|class\s+\w+\(.*TestCase\)/.test(content))
115
+ found.push('unittest');
116
+ if (/RSpec\.describe|describe\s+['"]/.test(content))
117
+ found.push('rspec');
118
+ if (/Minitest::Test|test\s+"/.test(content))
119
+ found.push('minitest');
120
+ if (/describe\(|it\(|expect\(|jest\./.test(content))
121
+ found.push('jest');
122
+ if (/require\('mocha'\)|describe\(.*done\)|it\(.*done/.test(content))
123
+ found.push('mocha');
124
+ if (/cy\.|Cypress\./.test(content))
125
+ found.push('cypress');
126
+ if (/test\.goto|page\.click|playwright/.test(content))
127
+ found.push('playwright');
128
+ if (/Given|When|Then|Scenario:/.test(content))
129
+ found.push('cucumber');
130
+ return found;
131
+ }
132
+ // ─── File system scanner ─────────────────────────────────────────────────────
133
+ /**
134
+ * Recursively collect all file paths under `dir`, respecting excludes and depth.
135
+ */
136
+ function scanDirectory(dir, excludeDirs, maxDepth, currentDepth = 0) {
137
+ if (currentDepth > maxDepth)
138
+ return [];
139
+ let results = [];
140
+ let entries;
141
+ try {
142
+ entries = fs.readdirSync(dir, { withFileTypes: true });
143
+ }
144
+ catch {
145
+ return [];
146
+ }
147
+ for (const entry of entries) {
148
+ if (entry.name.startsWith('.') && entry.name !== '.env')
149
+ continue;
150
+ const fullPath = path.join(dir, entry.name);
151
+ if (entry.isDirectory()) {
152
+ if (!excludeDirs.has(entry.name)) {
153
+ results = results.concat(scanDirectory(fullPath, excludeDirs, maxDepth, currentDepth + 1));
154
+ }
155
+ }
156
+ else if (entry.isFile()) {
157
+ results.push(fullPath);
158
+ }
159
+ }
160
+ return results;
161
+ }
162
+ // ─── Discovery engine ─────────────────────────────────────────────────────────
163
+ /**
164
+ * Discover all project artifacts from `rootDir`.
165
+ *
166
+ * When explicit inputs are provided (e.g. from config.yaml), they are used
167
+ * directly and the corresponding discovery step is skipped. This ensures
168
+ * "always discovers" behaviour while respecting explicit configuration.
169
+ */
170
+ function discoverProject(options = {}) {
171
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
172
+ const rootDir = (_a = options.rootDir) !== null && _a !== void 0 ? _a : process.cwd();
173
+ const excludeDirs = new Set([
174
+ ...DEFAULT_EXCLUDE_DIRS,
175
+ ...((_b = options.excludeDirs) !== null && _b !== void 0 ? _b : []),
176
+ ]);
177
+ const maxDepth = (_c = options.maxDepth) !== null && _c !== void 0 ? _c : 20;
178
+ // ── Scan + classify ────────────────────────────────────────────────────────
179
+ const rawPaths = scanDirectory(rootDir, excludeDirs, maxDepth);
180
+ const allFiles = rawPaths.map(fileClassifier_1.classifyFile);
181
+ const byCategory = groupByCategory(allFiles);
182
+ // ── Artifact resolution ────────────────────────────────────────────────────
183
+ const discoverySource = {
184
+ specs: 'discovered',
185
+ testFiles: 'discovered',
186
+ featureFiles: 'discovered',
187
+ contractFiles: 'discovered',
188
+ performanceFiles: 'discovered',
189
+ securityReportFiles: 'discovered',
190
+ serviceFiles: 'discovered',
191
+ };
192
+ let specs = paths((_d = byCategory.specification) !== null && _d !== void 0 ? _d : []);
193
+ if (options.explicitSpecs && options.explicitSpecs.length > 0) {
194
+ specs = options.explicitSpecs;
195
+ discoverySource.specs = 'explicit';
196
+ }
197
+ const featureFiles = paths((_e = byCategory.bdd_scenarios) !== null && _e !== void 0 ? _e : []);
198
+ let testFiles = [
199
+ ...paths((_f = byCategory.test_code) !== null && _f !== void 0 ? _f : []),
200
+ ...featureFiles,
201
+ ];
202
+ if (options.explicitTests && options.explicitTests.length > 0) {
203
+ testFiles = options.explicitTests;
204
+ discoverySource.testFiles = 'explicit';
205
+ discoverySource.featureFiles = 'explicit';
206
+ }
207
+ let contractFiles = paths((_g = byCategory.contracts) !== null && _g !== void 0 ? _g : []);
208
+ if (options.explicitContracts && options.explicitContracts.length > 0) {
209
+ contractFiles = options.explicitContracts;
210
+ discoverySource.contractFiles = 'explicit';
211
+ }
212
+ const performanceFiles = paths((_h = byCategory.performance) !== null && _h !== void 0 ? _h : []);
213
+ const securityReportFiles = paths((_j = byCategory.security_reports) !== null && _j !== void 0 ? _j : []);
214
+ const serviceFiles = paths((_k = byCategory.service_code) !== null && _k !== void 0 ? _k : []);
215
+ // ── Language detection ─────────────────────────────────────────────────────
216
+ const languages = detectLanguages(rawPaths);
217
+ // ── Framework detection ────────────────────────────────────────────────────
218
+ const frameworks = detectFrameworks(testFiles);
219
+ // Add 'cucumber' when feature files are present
220
+ if (featureFiles.length > 0 && !frameworks.includes('cucumber')) {
221
+ frameworks.push('cucumber');
222
+ }
223
+ return {
224
+ projectRoot: rootDir,
225
+ allFiles,
226
+ specs,
227
+ testFiles,
228
+ featureFiles,
229
+ contractFiles,
230
+ performanceFiles,
231
+ securityReportFiles,
232
+ serviceFiles,
233
+ languages: [...new Set(languages)],
234
+ frameworks: [...new Set(frameworks)],
235
+ discoverySource,
236
+ };
237
+ }
238
+ // ─── Language detection helpers ───────────────────────────────────────────────
239
+ function detectLanguages(filePaths) {
240
+ const found = new Set();
241
+ for (const fp of filePaths) {
242
+ const basename = path.basename(fp);
243
+ const ext = path.extname(fp);
244
+ // Check build file mapping
245
+ const byBuild = BUILD_FILE_LANGUAGE_MAP[basename];
246
+ if (byBuild) {
247
+ byBuild.forEach((lang) => found.add(lang));
248
+ }
249
+ // Check extension mapping
250
+ const byExt = EXTENSION_LANGUAGE_MAP[ext];
251
+ if (byExt) {
252
+ found.add(byExt);
253
+ }
254
+ }
255
+ return [...found];
256
+ }
257
+ // ─── Framework detection helpers ──────────────────────────────────────────────
258
+ function detectFrameworks(testFilePaths) {
259
+ const found = new Set();
260
+ // Sample up to 50 test files to limit I/O
261
+ const sample = testFilePaths.slice(0, 50);
262
+ for (const fp of sample) {
263
+ try {
264
+ const content = fs.readFileSync(fp, 'utf-8').slice(0, 4096);
265
+ for (const fw of detectFrameworksFromContent(content)) {
266
+ found.add(fw);
267
+ }
268
+ }
269
+ catch {
270
+ // skip unreadable files
271
+ }
272
+ }
273
+ return [...found];
274
+ }
275
+ // ─── Utility ─────────────────────────────────────────────────────────────────
276
+ function groupByCategory(files) {
277
+ const groups = {};
278
+ for (const f of files) {
279
+ if (!groups[f.category])
280
+ groups[f.category] = [];
281
+ groups[f.category].push(f);
282
+ }
283
+ return groups;
284
+ }
285
+ function paths(files) {
286
+ return files.map((f) => f.filePath);
287
+ }