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.
- package/README.md +703 -0
- package/config.yaml.example +227 -0
- package/dist/action/src/index.d.ts +2 -0
- package/dist/action/src/index.d.ts.map +1 -0
- package/dist/action/src/index.js +349 -0
- package/dist/action/src/prComment.d.ts +34 -0
- package/dist/action/src/prComment.d.ts.map +1 -0
- package/dist/action/src/prComment.js +146 -0
- package/dist/src/ast/astAnalysisOrchestrator.d.ts +36 -0
- package/dist/src/ast/astAnalysisOrchestrator.d.ts.map +1 -0
- package/dist/src/ast/astAnalysisOrchestrator.js +123 -0
- package/dist/src/ast/astTypes.d.ts +105 -0
- package/dist/src/ast/astTypes.d.ts.map +1 -0
- package/dist/src/ast/astTypes.js +9 -0
- package/dist/src/ast/languageAnalyzer.d.ts +46 -0
- package/dist/src/ast/languageAnalyzer.d.ts.map +1 -0
- package/dist/src/ast/languageAnalyzer.js +9 -0
- package/dist/src/ast/languageCapabilities.d.ts +24 -0
- package/dist/src/ast/languageCapabilities.d.ts.map +1 -0
- package/dist/src/ast/languageCapabilities.js +92 -0
- package/dist/src/ast/parseFile.d.ts +16 -0
- package/dist/src/ast/parseFile.d.ts.map +1 -0
- package/dist/src/ast/parseFile.js +65 -0
- package/dist/src/ast/parserRegistry.d.ts +39 -0
- package/dist/src/ast/parserRegistry.d.ts.map +1 -0
- package/dist/src/ast/parserRegistry.js +66 -0
- package/dist/src/buildSummary.d.ts +26 -0
- package/dist/src/buildSummary.d.ts.map +1 -0
- package/dist/src/buildSummary.js +193 -0
- package/dist/src/businessCoverage.d.ts +68 -0
- package/dist/src/businessCoverage.d.ts.map +1 -0
- package/dist/src/businessCoverage.js +290 -0
- package/dist/src/compatibilityCoverage.d.ts +83 -0
- package/dist/src/compatibilityCoverage.d.ts.map +1 -0
- package/dist/src/compatibilityCoverage.js +501 -0
- package/dist/src/config/defaultConfig.d.ts +9 -0
- package/dist/src/config/defaultConfig.d.ts.map +1 -0
- package/dist/src/config/defaultConfig.js +97 -0
- package/dist/src/config/index.d.ts +12 -0
- package/dist/src/config/index.d.ts.map +1 -0
- package/dist/src/config/index.js +37 -0
- package/dist/src/config/loadConfig.d.ts +29 -0
- package/dist/src/config/loadConfig.d.ts.map +1 -0
- package/dist/src/config/loadConfig.js +135 -0
- package/dist/src/config/mergeConfig.d.ts +15 -0
- package/dist/src/config/mergeConfig.d.ts.map +1 -0
- package/dist/src/config/mergeConfig.js +57 -0
- package/dist/src/config/schema.d.ts +15 -0
- package/dist/src/config/schema.d.ts.map +1 -0
- package/dist/src/config/schema.js +30 -0
- package/dist/src/config/types.d.ts +175 -0
- package/dist/src/config/types.d.ts.map +1 -0
- package/dist/src/config/types.js +9 -0
- package/dist/src/config/validateConfig.d.ts +22 -0
- package/dist/src/config/validateConfig.d.ts.map +1 -0
- package/dist/src/config/validateConfig.js +171 -0
- package/dist/src/config.d.ts +168 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js +204 -0
- package/dist/src/coverage/deep-analysis/callGraph.d.ts +67 -0
- package/dist/src/coverage/deep-analysis/callGraph.d.ts.map +1 -0
- package/dist/src/coverage/deep-analysis/callGraph.js +275 -0
- package/dist/src/coverage/deep-analysis/deepEndpointResolver.d.ts +23 -0
- package/dist/src/coverage/deep-analysis/deepEndpointResolver.d.ts.map +1 -0
- package/dist/src/coverage/deep-analysis/deepEndpointResolver.js +394 -0
- package/dist/src/coverage/deep-analysis/index.d.ts +17 -0
- package/dist/src/coverage/deep-analysis/index.d.ts.map +1 -0
- package/dist/src/coverage/deep-analysis/index.js +63 -0
- package/dist/src/coverage/deep-analysis/resolveAssertions.d.ts +60 -0
- package/dist/src/coverage/deep-analysis/resolveAssertions.d.ts.map +1 -0
- package/dist/src/coverage/deep-analysis/resolveAssertions.js +121 -0
- package/dist/src/coverage/deep-analysis/resolveConstants.d.ts +36 -0
- package/dist/src/coverage/deep-analysis/resolveConstants.d.ts.map +1 -0
- package/dist/src/coverage/deep-analysis/resolveConstants.js +92 -0
- package/dist/src/coverage/deep-analysis/resolveEnums.d.ts +55 -0
- package/dist/src/coverage/deep-analysis/resolveEnums.d.ts.map +1 -0
- package/dist/src/coverage/deep-analysis/resolveEnums.js +152 -0
- package/dist/src/coverage/deep-analysis/resolveMethodChains.d.ts +70 -0
- package/dist/src/coverage/deep-analysis/resolveMethodChains.d.ts.map +1 -0
- package/dist/src/coverage/deep-analysis/resolveMethodChains.js +152 -0
- package/dist/src/coverage/deep-analysis/resolvePaths.d.ts +80 -0
- package/dist/src/coverage/deep-analysis/resolvePaths.d.ts.map +1 -0
- package/dist/src/coverage/deep-analysis/resolvePaths.js +216 -0
- package/dist/src/coverage/deep-analysis/resolveRequestWrappers.d.ts +71 -0
- package/dist/src/coverage/deep-analysis/resolveRequestWrappers.d.ts.map +1 -0
- package/dist/src/coverage/deep-analysis/resolveRequestWrappers.js +226 -0
- package/dist/src/coverage/deep-analysis/symbolTable.d.ts +58 -0
- package/dist/src/coverage/deep-analysis/symbolTable.d.ts.map +1 -0
- package/dist/src/coverage/deep-analysis/symbolTable.js +230 -0
- package/dist/src/coverage/deep-analysis/types.d.ts +122 -0
- package/dist/src/coverage/deep-analysis/types.d.ts.map +1 -0
- package/dist/src/coverage/deep-analysis/types.js +21 -0
- package/dist/src/discovery/fileClassifier.d.ts +50 -0
- package/dist/src/discovery/fileClassifier.d.ts.map +1 -0
- package/dist/src/discovery/fileClassifier.js +238 -0
- package/dist/src/discovery/projectDiscovery.d.ts +66 -0
- package/dist/src/discovery/projectDiscovery.d.ts.map +1 -0
- package/dist/src/discovery/projectDiscovery.js +287 -0
- package/dist/src/endpointCoverage.d.ts +70 -0
- package/dist/src/endpointCoverage.d.ts.map +1 -0
- package/dist/src/endpointCoverage.js +381 -0
- package/dist/src/errorCoverage.d.ts +93 -0
- package/dist/src/errorCoverage.d.ts.map +1 -0
- package/dist/src/errorCoverage.js +698 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +1441 -0
- package/dist/src/inference/businessRuleInference.d.ts +63 -0
- package/dist/src/inference/businessRuleInference.d.ts.map +1 -0
- package/dist/src/inference/businessRuleInference.js +268 -0
- package/dist/src/inference/integrationFlowInference.d.ts +56 -0
- package/dist/src/inference/integrationFlowInference.d.ts.map +1 -0
- package/dist/src/inference/integrationFlowInference.js +266 -0
- package/dist/src/integrationCoverage.d.ts +72 -0
- package/dist/src/integrationCoverage.d.ts.map +1 -0
- package/dist/src/integrationCoverage.js +317 -0
- package/dist/src/intelligence/index.d.ts +20 -0
- package/dist/src/intelligence/index.d.ts.map +1 -0
- package/dist/src/intelligence/index.js +105 -0
- package/dist/src/intelligence/linkageEngine.d.ts +20 -0
- package/dist/src/intelligence/linkageEngine.d.ts.map +1 -0
- package/dist/src/intelligence/linkageEngine.js +522 -0
- package/dist/src/intelligence/markdownReporter.d.ts +12 -0
- package/dist/src/intelligence/markdownReporter.d.ts.map +1 -0
- package/dist/src/intelligence/markdownReporter.js +265 -0
- package/dist/src/intelligence/riskScoring.d.ts +53 -0
- package/dist/src/intelligence/riskScoring.d.ts.map +1 -0
- package/dist/src/intelligence/riskScoring.js +181 -0
- package/dist/src/intelligence/types.d.ts +121 -0
- package/dist/src/intelligence/types.d.ts.map +1 -0
- package/dist/src/intelligence/types.js +8 -0
- package/dist/src/languageDetection.d.ts +100 -0
- package/dist/src/languageDetection.d.ts.map +1 -0
- package/dist/src/languageDetection.js +349 -0
- package/dist/src/languages/java/index.d.ts +16 -0
- package/dist/src/languages/java/index.d.ts.map +1 -0
- package/dist/src/languages/java/index.js +103 -0
- package/dist/src/languages/java/parser.d.ts +7 -0
- package/dist/src/languages/java/parser.d.ts.map +1 -0
- package/dist/src/languages/java/parser.js +50 -0
- package/dist/src/languages/java/semanticBuilder.d.ts +21 -0
- package/dist/src/languages/java/semanticBuilder.d.ts.map +1 -0
- package/dist/src/languages/java/semanticBuilder.js +358 -0
- package/dist/src/languages/javascript/annotationExtractor.d.ts +20 -0
- package/dist/src/languages/javascript/annotationExtractor.d.ts.map +1 -0
- package/dist/src/languages/javascript/annotationExtractor.js +94 -0
- package/dist/src/languages/javascript/assertionResolver.d.ts +18 -0
- package/dist/src/languages/javascript/assertionResolver.d.ts.map +1 -0
- package/dist/src/languages/javascript/assertionResolver.js +150 -0
- package/dist/src/languages/javascript/callResolver.d.ts +23 -0
- package/dist/src/languages/javascript/callResolver.d.ts.map +1 -0
- package/dist/src/languages/javascript/callResolver.js +236 -0
- package/dist/src/languages/javascript/httpInteractionExtractor.d.ts +23 -0
- package/dist/src/languages/javascript/httpInteractionExtractor.d.ts.map +1 -0
- package/dist/src/languages/javascript/httpInteractionExtractor.js +205 -0
- package/dist/src/languages/javascript/index.d.ts +20 -0
- package/dist/src/languages/javascript/index.d.ts.map +1 -0
- package/dist/src/languages/javascript/index.js +136 -0
- package/dist/src/languages/javascript/parser.d.ts +14 -0
- package/dist/src/languages/javascript/parser.d.ts.map +1 -0
- package/dist/src/languages/javascript/parser.js +38 -0
- package/dist/src/languages/javascript/symbolResolver.d.ts +31 -0
- package/dist/src/languages/javascript/symbolResolver.d.ts.map +1 -0
- package/dist/src/languages/javascript/symbolResolver.js +183 -0
- package/dist/src/languages/kotlin/index.d.ts +16 -0
- package/dist/src/languages/kotlin/index.d.ts.map +1 -0
- package/dist/src/languages/kotlin/index.js +151 -0
- package/dist/src/languages/kotlin/parser.d.ts +11 -0
- package/dist/src/languages/kotlin/parser.d.ts.map +1 -0
- package/dist/src/languages/kotlin/parser.js +74 -0
- package/dist/src/languages/python/index.d.ts +15 -0
- package/dist/src/languages/python/index.d.ts.map +1 -0
- package/dist/src/languages/python/index.js +293 -0
- package/dist/src/languages/ruby/index.d.ts +15 -0
- package/dist/src/languages/ruby/index.d.ts.map +1 -0
- package/dist/src/languages/ruby/index.js +274 -0
- package/dist/src/languages/shared/treeSitterUtils.d.ts +43 -0
- package/dist/src/languages/shared/treeSitterUtils.d.ts.map +1 -0
- package/dist/src/languages/shared/treeSitterUtils.js +100 -0
- package/dist/src/languages/typescript/index.d.ts +14 -0
- package/dist/src/languages/typescript/index.d.ts.map +1 -0
- package/dist/src/languages/typescript/index.js +25 -0
- package/dist/src/lib/index.d.ts +228 -0
- package/dist/src/lib/index.d.ts.map +1 -0
- package/dist/src/lib/index.js +486 -0
- package/dist/src/mcp/client/index.d.ts +37 -0
- package/dist/src/mcp/client/index.d.ts.map +1 -0
- package/dist/src/mcp/client/index.js +235 -0
- package/dist/src/mcp/config.d.ts +50 -0
- package/dist/src/mcp/config.d.ts.map +1 -0
- package/dist/src/mcp/config.js +125 -0
- package/dist/src/mcp/events.d.ts +24 -0
- package/dist/src/mcp/events.d.ts.map +1 -0
- package/dist/src/mcp/events.js +48 -0
- package/dist/src/mcp/fallback/index.d.ts +50 -0
- package/dist/src/mcp/fallback/index.d.ts.map +1 -0
- package/dist/src/mcp/fallback/index.js +216 -0
- package/dist/src/mcp/index.d.ts +67 -0
- package/dist/src/mcp/index.d.ts.map +1 -0
- package/dist/src/mcp/index.js +212 -0
- package/dist/src/mcp/normalizer.d.ts +21 -0
- package/dist/src/mcp/normalizer.d.ts.map +1 -0
- package/dist/src/mcp/normalizer.js +99 -0
- package/dist/src/mcp/prompts/index.d.ts +86 -0
- package/dist/src/mcp/prompts/index.d.ts.map +1 -0
- package/dist/src/mcp/prompts/index.js +304 -0
- package/dist/src/mcp/templates/index.d.ts +35 -0
- package/dist/src/mcp/templates/index.d.ts.map +1 -0
- package/dist/src/mcp/templates/index.js +143 -0
- package/dist/src/mcp/testing/mock-server/index.d.ts +47 -0
- package/dist/src/mcp/testing/mock-server/index.d.ts.map +1 -0
- package/dist/src/mcp/testing/mock-server/index.js +157 -0
- package/dist/src/mcp/types.d.ts +127 -0
- package/dist/src/mcp/types.d.ts.map +1 -0
- package/dist/src/mcp/types.js +8 -0
- package/dist/src/observability.d.ts +138 -0
- package/dist/src/observability.d.ts.map +1 -0
- package/dist/src/observability.js +519 -0
- package/dist/src/parameterCoverage.d.ts +75 -0
- package/dist/src/parameterCoverage.d.ts.map +1 -0
- package/dist/src/parameterCoverage.js +629 -0
- package/dist/src/perfResilienceCoverage.d.ts +155 -0
- package/dist/src/perfResilienceCoverage.d.ts.map +1 -0
- package/dist/src/perfResilienceCoverage.js +670 -0
- package/dist/src/pluginLoader.d.ts +51 -0
- package/dist/src/pluginLoader.d.ts.map +1 -0
- package/dist/src/pluginLoader.js +72 -0
- package/dist/src/publishing.d.ts +63 -0
- package/dist/src/publishing.d.ts.map +1 -0
- package/dist/src/publishing.js +379 -0
- package/dist/src/qualityGate.d.ts +58 -0
- package/dist/src/qualityGate.d.ts.map +1 -0
- package/dist/src/qualityGate.js +118 -0
- package/dist/src/reporting.d.ts +41 -0
- package/dist/src/reporting.d.ts.map +1 -0
- package/dist/src/reporting.js +278 -0
- package/dist/src/screenshots.d.ts +71 -0
- package/dist/src/screenshots.d.ts.map +1 -0
- package/dist/src/screenshots.js +141 -0
- package/dist/src/security/gate/index.d.ts +11 -0
- package/dist/src/security/gate/index.d.ts.map +1 -0
- package/dist/src/security/gate/index.js +65 -0
- package/dist/src/security/index.d.ts +30 -0
- package/dist/src/security/index.d.ts.map +1 -0
- package/dist/src/security/index.js +342 -0
- package/dist/src/security/normalizers/semgrep.d.ts +10 -0
- package/dist/src/security/normalizers/semgrep.d.ts.map +1 -0
- package/dist/src/security/normalizers/semgrep.js +104 -0
- package/dist/src/security/normalizers/trivy.d.ts +10 -0
- package/dist/src/security/normalizers/trivy.d.ts.map +1 -0
- package/dist/src/security/normalizers/trivy.js +78 -0
- package/dist/src/security/normalizers/zap.d.ts +10 -0
- package/dist/src/security/normalizers/zap.d.ts.map +1 -0
- package/dist/src/security/normalizers/zap.js +104 -0
- package/dist/src/security/scanners/semgrep.d.ts +6 -0
- package/dist/src/security/scanners/semgrep.d.ts.map +1 -0
- package/dist/src/security/scanners/semgrep.js +125 -0
- package/dist/src/security/scanners/trivy.d.ts +6 -0
- package/dist/src/security/scanners/trivy.d.ts.map +1 -0
- package/dist/src/security/scanners/trivy.js +115 -0
- package/dist/src/security/scanners/zap.d.ts +6 -0
- package/dist/src/security/scanners/zap.d.ts.map +1 -0
- package/dist/src/security/scanners/zap.js +135 -0
- package/dist/src/security/types.d.ts +146 -0
- package/dist/src/security/types.d.ts.map +1 -0
- package/dist/src/security/types.js +6 -0
- package/dist/src/securityCoverage.d.ts +116 -0
- package/dist/src/securityCoverage.d.ts.map +1 -0
- package/dist/src/securityCoverage.js +725 -0
- package/dist/src/summary/buildSummary.d.ts +28 -0
- package/dist/src/summary/buildSummary.d.ts.map +1 -0
- package/dist/src/summary/buildSummary.js +257 -0
- package/dist/src/summary/evaluateMetrics.d.ts +31 -0
- package/dist/src/summary/evaluateMetrics.d.ts.map +1 -0
- package/dist/src/summary/evaluateMetrics.js +118 -0
- package/dist/src/summary/index.d.ts +10 -0
- package/dist/src/summary/index.d.ts.map +1 -0
- package/dist/src/summary/index.js +22 -0
- package/dist/src/summary/markdownRenderer.d.ts +139 -0
- package/dist/src/summary/markdownRenderer.d.ts.map +1 -0
- package/dist/src/summary/markdownRenderer.js +459 -0
- package/dist/src/summary/prSummary.d.ts +24 -0
- package/dist/src/summary/prSummary.d.ts.map +1 -0
- package/dist/src/summary/prSummary.js +233 -0
- package/dist/src/summary/summaryTypes.d.ts +35 -0
- package/dist/src/summary/summaryTypes.d.ts.map +1 -0
- package/dist/src/summary/summaryTypes.js +27 -0
- package/package.json +84 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
export type FlowStepType = 'api' | 'event' | 'external';
|
|
2
|
+
export interface FlowStep {
|
|
3
|
+
/** Unique step ID, e.g. "FLOW001-step1" */
|
|
4
|
+
id: string;
|
|
5
|
+
/** Human-readable description of what this step does */
|
|
6
|
+
description: string;
|
|
7
|
+
/** The type of interaction: api call, published event, external service, etc. */
|
|
8
|
+
type?: FlowStepType;
|
|
9
|
+
/** HTTP method for api-type steps, e.g. "GET" */
|
|
10
|
+
method?: string;
|
|
11
|
+
/** URL path for api-type steps, e.g. "/users/{id}" */
|
|
12
|
+
path?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Keywords used to detect this step in a test's description or body.
|
|
15
|
+
* A test trace is matched to a step when at least one keyword appears.
|
|
16
|
+
*/
|
|
17
|
+
keywords: string[];
|
|
18
|
+
}
|
|
19
|
+
export interface IntegrationFlow {
|
|
20
|
+
/** Unique flow ID, e.g. "FLOW001" */
|
|
21
|
+
id: string;
|
|
22
|
+
/** Short human-readable name for the flow */
|
|
23
|
+
name: string;
|
|
24
|
+
/** Detailed description of the end-to-end business scenario */
|
|
25
|
+
description: string;
|
|
26
|
+
/** The ordered list of steps that make up this flow */
|
|
27
|
+
steps: FlowStep[];
|
|
28
|
+
}
|
|
29
|
+
export interface IntegrationFlowsFile {
|
|
30
|
+
flows: IntegrationFlow[];
|
|
31
|
+
}
|
|
32
|
+
export interface StepCoverage {
|
|
33
|
+
step: FlowStep;
|
|
34
|
+
covered: boolean;
|
|
35
|
+
matchedTests: string[];
|
|
36
|
+
}
|
|
37
|
+
export interface FlowCoverage {
|
|
38
|
+
flow: IntegrationFlow;
|
|
39
|
+
/** "complete" if all steps covered, "partial" if some steps covered, "missing" if none covered */
|
|
40
|
+
status: 'complete' | 'partial' | 'missing';
|
|
41
|
+
/** Test files that contain at least one matching trace for this flow */
|
|
42
|
+
testFiles: string[];
|
|
43
|
+
/** Coverage detail for each individual step */
|
|
44
|
+
steps: StepCoverage[];
|
|
45
|
+
}
|
|
46
|
+
export interface IntegrationCoverageReport {
|
|
47
|
+
total: number;
|
|
48
|
+
complete: number;
|
|
49
|
+
partial: number;
|
|
50
|
+
missing: number;
|
|
51
|
+
percentage: number;
|
|
52
|
+
flows: FlowCoverage[];
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Parse a YAML or JSON integration flows definition file.
|
|
56
|
+
* The file must contain a top-level `flows` array.
|
|
57
|
+
*/
|
|
58
|
+
export declare function parseIntegrationFlows(flowsPath: string): IntegrationFlow[];
|
|
59
|
+
/**
|
|
60
|
+
* Analyse test files matching the given glob pattern and determine which
|
|
61
|
+
* integration flows are covered, partially covered, or missing.
|
|
62
|
+
*/
|
|
63
|
+
export declare function analyzeIntegrationCoverage(flows: IntegrationFlow[], testGlob: string): Promise<FlowCoverage[]>;
|
|
64
|
+
/**
|
|
65
|
+
* Build the coverage summary from a list of per-flow coverages.
|
|
66
|
+
*/
|
|
67
|
+
export declare function buildIntegrationCoverageReport(coverages: FlowCoverage[]): IntegrationCoverageReport;
|
|
68
|
+
/**
|
|
69
|
+
* Write JSON and HTML integration-coverage reports to the given directory.
|
|
70
|
+
*/
|
|
71
|
+
export declare function generateIntegrationReports(report: IntegrationCoverageReport, reportsDir: string): void;
|
|
72
|
+
//# sourceMappingURL=integrationCoverage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integrationCoverage.d.ts","sourceRoot":"","sources":["../../src/integrationCoverage.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,OAAO,GAAG,UAAU,CAAC;AAExD,MAAM,WAAW,QAAQ;IACvB,2CAA2C;IAC3C,EAAE,EAAE,MAAM,CAAC;IACX,wDAAwD;IACxD,WAAW,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,iDAAiD;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sDAAsD;IACtD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,qCAAqC;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,WAAW,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,eAAe,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,eAAe,CAAC;IACtB,kGAAkG;IAClG,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,SAAS,CAAC;IAC3C,wEAAwE;IACxE,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,+CAA+C;IAC/C,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AAID;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,EAAE,CAsB1E;AAkFD;;;GAGG;AACH,wBAAsB,0BAA0B,CAC9C,KAAK,EAAE,eAAe,EAAE,EACxB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,YAAY,EAAE,CAAC,CAqDzB;AAID;;GAEG;AACH,wBAAgB,8BAA8B,CAC5C,SAAS,EAAE,YAAY,EAAE,GACxB,yBAAyB,CAQ3B;AAID;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,yBAAyB,EACjC,UAAU,EAAE,MAAM,GACjB,IAAI,CAgIN"}
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.parseIntegrationFlows = parseIntegrationFlows;
|
|
40
|
+
exports.analyzeIntegrationCoverage = analyzeIntegrationCoverage;
|
|
41
|
+
exports.buildIntegrationCoverageReport = buildIntegrationCoverageReport;
|
|
42
|
+
exports.generateIntegrationReports = generateIntegrationReports;
|
|
43
|
+
const fs = __importStar(require("fs"));
|
|
44
|
+
const path = __importStar(require("path"));
|
|
45
|
+
const yaml = __importStar(require("js-yaml"));
|
|
46
|
+
const fast_glob_1 = __importDefault(require("fast-glob"));
|
|
47
|
+
// ─── Parsing ──────────────────────────────────────────────────────────────────
|
|
48
|
+
/**
|
|
49
|
+
* Parse a YAML or JSON integration flows definition file.
|
|
50
|
+
* The file must contain a top-level `flows` array.
|
|
51
|
+
*/
|
|
52
|
+
function parseIntegrationFlows(flowsPath) {
|
|
53
|
+
const raw = fs.readFileSync(flowsPath, 'utf-8');
|
|
54
|
+
const ext = path.extname(flowsPath).toLowerCase();
|
|
55
|
+
let parsed;
|
|
56
|
+
if (ext === '.json') {
|
|
57
|
+
parsed = JSON.parse(raw);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
parsed = yaml.load(raw);
|
|
61
|
+
}
|
|
62
|
+
if (!parsed ||
|
|
63
|
+
typeof parsed !== 'object' ||
|
|
64
|
+
!Array.isArray(parsed.flows)) {
|
|
65
|
+
throw new Error(`Invalid integration flows file: expected a top-level "flows" array in ${flowsPath}`);
|
|
66
|
+
}
|
|
67
|
+
return parsed.flows;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Extract all test/it declarations from a file, together with their
|
|
71
|
+
* description string and the surrounding code up to the next declaration.
|
|
72
|
+
*/
|
|
73
|
+
function extractTestEntries(filePath, fileContents) {
|
|
74
|
+
const entries = [];
|
|
75
|
+
const declPattern = /\b(?:test|it)\s*\(\s*(['"`])([\s\S]*?)\1/g;
|
|
76
|
+
const positions = [];
|
|
77
|
+
let m;
|
|
78
|
+
while ((m = declPattern.exec(fileContents)) !== null) {
|
|
79
|
+
positions.push({ start: m.index, desc: m[2] });
|
|
80
|
+
}
|
|
81
|
+
for (let i = 0; i < positions.length; i++) {
|
|
82
|
+
const start = positions[i].start;
|
|
83
|
+
const end = i + 1 < positions.length ? positions[i + 1].start : fileContents.length;
|
|
84
|
+
entries.push({
|
|
85
|
+
description: positions[i].desc,
|
|
86
|
+
content: fileContents.slice(start, end),
|
|
87
|
+
filePath,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
return entries;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Determine whether a test entry matches a given step via keywords or step-ID annotation.
|
|
94
|
+
*
|
|
95
|
+
* A match occurs when:
|
|
96
|
+
* 1. The test description or content contains `@step <stepId>` (case-insensitive), OR
|
|
97
|
+
* 2. The test description (lowercased) contains at least one of the keywords, OR
|
|
98
|
+
* 3. The test is annotated with `@flow <flowId>` AND a keyword appears anywhere in the content.
|
|
99
|
+
*
|
|
100
|
+
* Keywords are checked against the description for general matching to avoid false positives.
|
|
101
|
+
* When a @flow annotation is present, content-based keyword matching is also allowed since
|
|
102
|
+
* the test explicitly declares it exercises that flow.
|
|
103
|
+
*/
|
|
104
|
+
function testMatchesStep(entry, step, flowId) {
|
|
105
|
+
const descLower = entry.description.toLowerCase();
|
|
106
|
+
// Annotation-based match: @step FLOW001-step1
|
|
107
|
+
const stepAnnotationPattern = new RegExp(`@step\\s+${step.id}`, 'i');
|
|
108
|
+
if (stepAnnotationPattern.test(entry.description) || stepAnnotationPattern.test(entry.content)) {
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
// Keyword-based match (checked against description only for precision)
|
|
112
|
+
for (const kw of step.keywords) {
|
|
113
|
+
if (descLower.includes(kw.toLowerCase())) {
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// When a test is annotated with @flow <flowId>, also match keywords against content
|
|
118
|
+
const flowAnnotationPattern = new RegExp(`@flow\\s+${flowId}`, 'i');
|
|
119
|
+
if (flowAnnotationPattern.test(entry.description) ||
|
|
120
|
+
flowAnnotationPattern.test(entry.content)) {
|
|
121
|
+
const contentLower = entry.content.toLowerCase();
|
|
122
|
+
for (const kw of step.keywords) {
|
|
123
|
+
if (contentLower.includes(kw.toLowerCase())) {
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Analyse test files matching the given glob pattern and determine which
|
|
132
|
+
* integration flows are covered, partially covered, or missing.
|
|
133
|
+
*/
|
|
134
|
+
async function analyzeIntegrationCoverage(flows, testGlob) {
|
|
135
|
+
const testFiles = await (0, fast_glob_1.default)(testGlob, { onlyFiles: true });
|
|
136
|
+
// Pre-read all test files and extract test entries
|
|
137
|
+
const allEntries = [];
|
|
138
|
+
for (const filePath of testFiles) {
|
|
139
|
+
const contents = fs.readFileSync(filePath, 'utf-8');
|
|
140
|
+
allEntries.push(...extractTestEntries(filePath, contents));
|
|
141
|
+
}
|
|
142
|
+
return flows.map((flow) => {
|
|
143
|
+
const matchedFiles = new Set();
|
|
144
|
+
// For each step, find the tests that exercise it
|
|
145
|
+
const stepCoverages = flow.steps.map((step) => {
|
|
146
|
+
const matchedTests = [];
|
|
147
|
+
for (const entry of allEntries) {
|
|
148
|
+
// A test matches a step if:
|
|
149
|
+
// - the test is annotated with @flow <flowId> AND matches step keywords/annotation, OR
|
|
150
|
+
// - the test matches step keywords/annotation regardless of flow annotation
|
|
151
|
+
if (testMatchesStep(entry, step, flow.id)) {
|
|
152
|
+
matchedTests.push(entry.description);
|
|
153
|
+
matchedFiles.add(entry.filePath);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return {
|
|
157
|
+
step,
|
|
158
|
+
covered: matchedTests.length > 0,
|
|
159
|
+
matchedTests,
|
|
160
|
+
};
|
|
161
|
+
});
|
|
162
|
+
const coveredSteps = stepCoverages.filter((s) => s.covered).length;
|
|
163
|
+
const totalSteps = stepCoverages.length;
|
|
164
|
+
let status;
|
|
165
|
+
if (totalSteps === 0 || coveredSteps === 0) {
|
|
166
|
+
status = 'missing';
|
|
167
|
+
}
|
|
168
|
+
else if (coveredSteps === totalSteps) {
|
|
169
|
+
status = 'complete';
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
status = 'partial';
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
flow,
|
|
176
|
+
status,
|
|
177
|
+
testFiles: Array.from(matchedFiles),
|
|
178
|
+
steps: stepCoverages,
|
|
179
|
+
};
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
// ─── Report building ──────────────────────────────────────────────────────────
|
|
183
|
+
/**
|
|
184
|
+
* Build the coverage summary from a list of per-flow coverages.
|
|
185
|
+
*/
|
|
186
|
+
function buildIntegrationCoverageReport(coverages) {
|
|
187
|
+
const total = coverages.length;
|
|
188
|
+
const complete = coverages.filter((c) => c.status === 'complete').length;
|
|
189
|
+
const partial = coverages.filter((c) => c.status === 'partial').length;
|
|
190
|
+
const missing = coverages.filter((c) => c.status === 'missing').length;
|
|
191
|
+
const percentage = total === 0 ? 0 : Math.round((complete / total) * 10000) / 100;
|
|
192
|
+
return { total, complete, partial, missing, percentage, flows: coverages };
|
|
193
|
+
}
|
|
194
|
+
// ─── Report generation ────────────────────────────────────────────────────────
|
|
195
|
+
/**
|
|
196
|
+
* Write JSON and HTML integration-coverage reports to the given directory.
|
|
197
|
+
*/
|
|
198
|
+
function generateIntegrationReports(report, reportsDir) {
|
|
199
|
+
if (!fs.existsSync(reportsDir)) {
|
|
200
|
+
fs.mkdirSync(reportsDir, { recursive: true });
|
|
201
|
+
}
|
|
202
|
+
// ── JSON ─────────────────────────────────────────────────────────────────
|
|
203
|
+
const jsonPath = path.join(reportsDir, 'integration-coverage.json');
|
|
204
|
+
const jsonReport = {
|
|
205
|
+
total: report.total,
|
|
206
|
+
complete: report.complete,
|
|
207
|
+
partial: report.partial,
|
|
208
|
+
missing: report.missing,
|
|
209
|
+
percentage: report.percentage,
|
|
210
|
+
flows: report.flows.map(({ flow, status, testFiles, steps }) => ({
|
|
211
|
+
id: flow.id,
|
|
212
|
+
name: flow.name,
|
|
213
|
+
description: flow.description,
|
|
214
|
+
status,
|
|
215
|
+
testFiles,
|
|
216
|
+
steps: steps.map(({ step, covered, matchedTests }) => ({
|
|
217
|
+
id: step.id,
|
|
218
|
+
description: step.description,
|
|
219
|
+
type: step.type,
|
|
220
|
+
method: step.method,
|
|
221
|
+
path: step.path,
|
|
222
|
+
covered,
|
|
223
|
+
matchedTests,
|
|
224
|
+
})),
|
|
225
|
+
})),
|
|
226
|
+
};
|
|
227
|
+
fs.writeFileSync(jsonPath, JSON.stringify(jsonReport, null, 2), 'utf-8');
|
|
228
|
+
// ── HTML ─────────────────────────────────────────────────────────────────
|
|
229
|
+
const htmlPath = path.join(reportsDir, 'integration-coverage.html');
|
|
230
|
+
const statusIcon = (s) => {
|
|
231
|
+
if (s === 'complete')
|
|
232
|
+
return '✅ Complete';
|
|
233
|
+
if (s === 'partial')
|
|
234
|
+
return '⚠️ Partial';
|
|
235
|
+
return '❌ Missing';
|
|
236
|
+
};
|
|
237
|
+
const flowRows = report.flows
|
|
238
|
+
.map(({ flow, status, steps }) => {
|
|
239
|
+
const rowClass = status === 'complete' ? 'complete' : status === 'partial' ? 'partial' : 'missing';
|
|
240
|
+
const stepRows = steps
|
|
241
|
+
.map(({ step, covered, matchedTests }) => {
|
|
242
|
+
var _a;
|
|
243
|
+
const stepClass = covered ? 'covered' : 'uncovered';
|
|
244
|
+
const stepStatus = covered ? '✅' : '❌';
|
|
245
|
+
const tests = matchedTests.length > 0 ? matchedTests.join('<br>') : '—';
|
|
246
|
+
const methodPath = step.method && step.path ? `${step.method} ${step.path}` : (_a = step.type) !== null && _a !== void 0 ? _a : '—';
|
|
247
|
+
return ` <tr class="step ${stepClass}">
|
|
248
|
+
<td></td>
|
|
249
|
+
<td class="step-id">${step.id}</td>
|
|
250
|
+
<td>${step.description}</td>
|
|
251
|
+
<td>${methodPath}</td>
|
|
252
|
+
<td>${stepStatus}</td>
|
|
253
|
+
<td>${tests}</td>
|
|
254
|
+
</tr>`;
|
|
255
|
+
})
|
|
256
|
+
.join('\n');
|
|
257
|
+
return ` <tr class="flow ${rowClass}">
|
|
258
|
+
<td><strong>${flow.id}</strong></td>
|
|
259
|
+
<td>${flow.name}</td>
|
|
260
|
+
<td>${flow.description}</td>
|
|
261
|
+
<td>${statusIcon(status)}</td>
|
|
262
|
+
<td></td>
|
|
263
|
+
<td></td>
|
|
264
|
+
</tr>
|
|
265
|
+
${stepRows}`;
|
|
266
|
+
})
|
|
267
|
+
.join('\n');
|
|
268
|
+
const html = `<!DOCTYPE html>
|
|
269
|
+
<html lang="en">
|
|
270
|
+
<head>
|
|
271
|
+
<meta charset="UTF-8">
|
|
272
|
+
<title>Integration Flow Coverage Report</title>
|
|
273
|
+
<style>
|
|
274
|
+
body { font-family: sans-serif; padding: 2rem; }
|
|
275
|
+
h1 { margin-bottom: 0.5rem; }
|
|
276
|
+
.summary { margin-bottom: 1.5rem; font-size: 1.1rem; }
|
|
277
|
+
table { border-collapse: collapse; width: 100%; }
|
|
278
|
+
th, td { border: 1px solid #ccc; padding: 0.5rem 1rem; text-align: left; }
|
|
279
|
+
th { background: #f0f0f0; }
|
|
280
|
+
tr.flow.complete { background: #e6ffe6; font-weight: bold; }
|
|
281
|
+
tr.flow.partial { background: #fff9e6; font-weight: bold; }
|
|
282
|
+
tr.flow.missing { background: #ffe6e6; font-weight: bold; }
|
|
283
|
+
tr.step { font-size: 0.9rem; }
|
|
284
|
+
tr.step td { padding: 0.3rem 1rem; }
|
|
285
|
+
tr.step.covered { background: #f0fff0; }
|
|
286
|
+
tr.step.uncovered { background: #fff0f0; }
|
|
287
|
+
td.step-id { font-style: italic; padding-left: 2rem; }
|
|
288
|
+
</style>
|
|
289
|
+
</head>
|
|
290
|
+
<body>
|
|
291
|
+
<h1>Integration Flow Coverage Report</h1>
|
|
292
|
+
<div class="summary">
|
|
293
|
+
Total flows: <strong>${report.total}</strong> |
|
|
294
|
+
Complete: <strong>${report.complete}</strong> |
|
|
295
|
+
Partial: <strong>${report.partial}</strong> |
|
|
296
|
+
Missing: <strong>${report.missing}</strong> |
|
|
297
|
+
Coverage: <strong>${report.percentage}%</strong>
|
|
298
|
+
</div>
|
|
299
|
+
<table>
|
|
300
|
+
<thead>
|
|
301
|
+
<tr>
|
|
302
|
+
<th>Flow ID</th>
|
|
303
|
+
<th>Name</th>
|
|
304
|
+
<th>Description</th>
|
|
305
|
+
<th>Status</th>
|
|
306
|
+
<th>Step</th>
|
|
307
|
+
<th>Matched Tests</th>
|
|
308
|
+
</tr>
|
|
309
|
+
</thead>
|
|
310
|
+
<tbody>
|
|
311
|
+
${flowRows}
|
|
312
|
+
</tbody>
|
|
313
|
+
</table>
|
|
314
|
+
</body>
|
|
315
|
+
</html>`;
|
|
316
|
+
fs.writeFileSync(htmlPath, html, 'utf-8');
|
|
317
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coverage Intelligence – Main Engine & Public API.
|
|
3
|
+
*
|
|
4
|
+
* Orchestrates the linkage engine, risk scorer, summary builder, and markdown
|
|
5
|
+
* reporter to produce a complete IntelligenceReport from coverage inputs.
|
|
6
|
+
*/
|
|
7
|
+
export * from './types';
|
|
8
|
+
export * from './riskScoring';
|
|
9
|
+
export { runLinkageEngine, buildRecommendationFromFinding } from './linkageEngine';
|
|
10
|
+
export { renderCoverageIntelligenceMd, renderMissingTestsMd, renderRiskPrioritizationMd, writeIntelligenceReports, } from './markdownReporter';
|
|
11
|
+
import type { IntelligenceInput, IntelligenceReport } from './types';
|
|
12
|
+
/**
|
|
13
|
+
* Run the full Coverage Intelligence engine.
|
|
14
|
+
*
|
|
15
|
+
* Inspects all coverage results and security findings, produces functional
|
|
16
|
+
* findings, missing-test recommendations, risk scores, and (optionally) writes
|
|
17
|
+
* AI-friendly reports to disk.
|
|
18
|
+
*/
|
|
19
|
+
export declare function runIntelligenceEngine(input: IntelligenceInput): IntelligenceReport;
|
|
20
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/intelligence/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,SAAS,CAAC;AACxB,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,gBAAgB,EAAE,8BAA8B,EAAE,MAAM,iBAAiB,CAAC;AACnF,OAAO,EACL,4BAA4B,EAC5B,oBAAoB,EACpB,0BAA0B,EAC1B,wBAAwB,GACzB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EACV,iBAAiB,EACjB,kBAAkB,EAInB,MAAM,SAAS,CAAC;AAgEjB;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,iBAAiB,GACvB,kBAAkB,CAkBpB"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Coverage Intelligence – Main Engine & Public API.
|
|
4
|
+
*
|
|
5
|
+
* Orchestrates the linkage engine, risk scorer, summary builder, and markdown
|
|
6
|
+
* reporter to produce a complete IntelligenceReport from coverage inputs.
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
20
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
21
|
+
};
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.writeIntelligenceReports = exports.renderRiskPrioritizationMd = exports.renderMissingTestsMd = exports.renderCoverageIntelligenceMd = exports.buildRecommendationFromFinding = exports.runLinkageEngine = void 0;
|
|
24
|
+
exports.runIntelligenceEngine = runIntelligenceEngine;
|
|
25
|
+
__exportStar(require("./types"), exports);
|
|
26
|
+
__exportStar(require("./riskScoring"), exports);
|
|
27
|
+
var linkageEngine_1 = require("./linkageEngine");
|
|
28
|
+
Object.defineProperty(exports, "runLinkageEngine", { enumerable: true, get: function () { return linkageEngine_1.runLinkageEngine; } });
|
|
29
|
+
Object.defineProperty(exports, "buildRecommendationFromFinding", { enumerable: true, get: function () { return linkageEngine_1.buildRecommendationFromFinding; } });
|
|
30
|
+
var markdownReporter_1 = require("./markdownReporter");
|
|
31
|
+
Object.defineProperty(exports, "renderCoverageIntelligenceMd", { enumerable: true, get: function () { return markdownReporter_1.renderCoverageIntelligenceMd; } });
|
|
32
|
+
Object.defineProperty(exports, "renderMissingTestsMd", { enumerable: true, get: function () { return markdownReporter_1.renderMissingTestsMd; } });
|
|
33
|
+
Object.defineProperty(exports, "renderRiskPrioritizationMd", { enumerable: true, get: function () { return markdownReporter_1.renderRiskPrioritizationMd; } });
|
|
34
|
+
Object.defineProperty(exports, "writeIntelligenceReports", { enumerable: true, get: function () { return markdownReporter_1.writeIntelligenceReports; } });
|
|
35
|
+
const linkageEngine_2 = require("./linkageEngine");
|
|
36
|
+
const markdownReporter_2 = require("./markdownReporter");
|
|
37
|
+
// ─── Summary builder ──────────────────────────────────────────────────────────
|
|
38
|
+
function buildSummary(findings, recommendations) {
|
|
39
|
+
var _a, _b, _c, _d;
|
|
40
|
+
const findingsBySeverity = {
|
|
41
|
+
LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0,
|
|
42
|
+
};
|
|
43
|
+
for (const f of findings) {
|
|
44
|
+
findingsBySeverity[f.severity] = ((_a = findingsBySeverity[f.severity]) !== null && _a !== void 0 ? _a : 0) + 1;
|
|
45
|
+
}
|
|
46
|
+
const recommendationsByPriority = {
|
|
47
|
+
P0: 0, P1: 0, P2: 0, P3: 0,
|
|
48
|
+
};
|
|
49
|
+
for (const r of recommendations) {
|
|
50
|
+
recommendationsByPriority[r.priority] = ((_b = recommendationsByPriority[r.priority]) !== null && _b !== void 0 ? _b : 0) + 1;
|
|
51
|
+
}
|
|
52
|
+
const scores = recommendations.map((r) => r.riskScore);
|
|
53
|
+
const maxRiskScore = scores.length ? Math.max(...scores) : 0;
|
|
54
|
+
const avgRiskScore = scores.length
|
|
55
|
+
? Math.round(scores.reduce((a, b) => a + b, 0) / scores.length)
|
|
56
|
+
: 0;
|
|
57
|
+
const criticalUncoveredItems = ((_c = findingsBySeverity.CRITICAL) !== null && _c !== void 0 ? _c : 0) + ((_d = findingsBySeverity.HIGH) !== null && _d !== void 0 ? _d : 0);
|
|
58
|
+
const unprotectedSecurityFindings = findings.filter((f) => f.source === 'security-scan' ||
|
|
59
|
+
f.category === 'security-finding-unprotected' ||
|
|
60
|
+
f.category === 'missing-auth-test').length;
|
|
61
|
+
// Top risk areas = endpoints / rules with highest-scored recommendations
|
|
62
|
+
const topRiskAreas = recommendations
|
|
63
|
+
.slice(0, 5)
|
|
64
|
+
.map((r) => {
|
|
65
|
+
var _a;
|
|
66
|
+
return r.endpoint
|
|
67
|
+
? `${(_a = r.endpoint.method) !== null && _a !== void 0 ? _a : 'GET'} ${r.endpoint.path} (score ${r.riskScore})`
|
|
68
|
+
: `${r.title} (score ${r.riskScore})`;
|
|
69
|
+
});
|
|
70
|
+
return {
|
|
71
|
+
totalFindings: findings.length,
|
|
72
|
+
findingsBySeverity,
|
|
73
|
+
totalRecommendations: recommendations.length,
|
|
74
|
+
recommendationsByPriority,
|
|
75
|
+
maxRiskScore,
|
|
76
|
+
avgRiskScore,
|
|
77
|
+
criticalUncoveredItems,
|
|
78
|
+
unprotectedSecurityFindings,
|
|
79
|
+
topRiskAreas,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
// ─── Main entry point ─────────────────────────────────────────────────────────
|
|
83
|
+
/**
|
|
84
|
+
* Run the full Coverage Intelligence engine.
|
|
85
|
+
*
|
|
86
|
+
* Inspects all coverage results and security findings, produces functional
|
|
87
|
+
* findings, missing-test recommendations, risk scores, and (optionally) writes
|
|
88
|
+
* AI-friendly reports to disk.
|
|
89
|
+
*/
|
|
90
|
+
function runIntelligenceEngine(input) {
|
|
91
|
+
var _a;
|
|
92
|
+
const { findings, recommendations } = (0, linkageEngine_2.runLinkageEngine)(input);
|
|
93
|
+
const summary = buildSummary(findings, recommendations);
|
|
94
|
+
const report = {
|
|
95
|
+
generatedAt: new Date().toISOString(),
|
|
96
|
+
projectName: (_a = input.projectName) !== null && _a !== void 0 ? _a : 'unknown',
|
|
97
|
+
findings,
|
|
98
|
+
recommendations,
|
|
99
|
+
summary,
|
|
100
|
+
};
|
|
101
|
+
if (input.outDir) {
|
|
102
|
+
(0, markdownReporter_2.writeIntelligenceReports)(report, input.outDir);
|
|
103
|
+
}
|
|
104
|
+
return report;
|
|
105
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coverage Intelligence – Linkage Engine.
|
|
3
|
+
*
|
|
4
|
+
* Inspects coverage results and security findings to produce FunctionalFinding
|
|
5
|
+
* objects and link them to MissingTestRecommendation records.
|
|
6
|
+
*
|
|
7
|
+
* The engine is deterministic and does not require MCP to run.
|
|
8
|
+
*/
|
|
9
|
+
import type { FunctionalFinding, MissingTestRecommendation, IntelligenceInput } from './types';
|
|
10
|
+
export declare function buildRecommendationFromFinding(finding: FunctionalFinding, primaryLanguage?: string, primaryFramework?: string): MissingTestRecommendation;
|
|
11
|
+
export interface LinkageResult {
|
|
12
|
+
findings: FunctionalFinding[];
|
|
13
|
+
recommendations: MissingTestRecommendation[];
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Run the full linkage engine over coverage + security results.
|
|
17
|
+
* Returns all functional findings and deduplicated recommendations.
|
|
18
|
+
*/
|
|
19
|
+
export declare function runLinkageEngine(input: IntelligenceInput): LinkageResult;
|
|
20
|
+
//# sourceMappingURL=linkageEngine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linkageEngine.d.ts","sourceRoot":"","sources":["../../../src/intelligence/linkageEngine.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACV,iBAAiB,EACjB,yBAAyB,EACzB,iBAAiB,EAIlB,MAAM,SAAS,CAAC;AA0ejB,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,iBAAiB,EAC1B,eAAe,CAAC,EAAE,MAAM,EACxB,gBAAgB,CAAC,EAAE,MAAM,GACxB,yBAAyB,CAgD3B;AAwBD,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,eAAe,EAAE,yBAAyB,EAAE,CAAC;CAC9C;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,iBAAiB,GAAG,aAAa,CAmDxE"}
|