cxgrd 0.1.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 +221 -0
- package/dist/auth/audit-usage.d.ts +30 -0
- package/dist/auth/audit-usage.d.ts.map +1 -0
- package/dist/auth/audit-usage.js +104 -0
- package/dist/auth/audit-usage.js.map +1 -0
- package/dist/auth/auth-session.d.ts +17 -0
- package/dist/auth/auth-session.d.ts.map +1 -0
- package/dist/auth/auth-session.js +102 -0
- package/dist/auth/auth-session.js.map +1 -0
- package/dist/auth/auth-store.d.ts +17 -0
- package/dist/auth/auth-store.d.ts.map +1 -0
- package/dist/auth/auth-store.js +44 -0
- package/dist/auth/auth-store.js.map +1 -0
- package/dist/auth/entitlements.d.ts +14 -0
- package/dist/auth/entitlements.d.ts.map +1 -0
- package/dist/auth/entitlements.js +62 -0
- package/dist/auth/entitlements.js.map +1 -0
- package/dist/auth/open-browser.d.ts +2 -0
- package/dist/auth/open-browser.d.ts.map +1 -0
- package/dist/auth/open-browser.js +20 -0
- package/dist/auth/open-browser.js.map +1 -0
- package/dist/auth/plans.d.ts +10 -0
- package/dist/auth/plans.d.ts.map +1 -0
- package/dist/auth/plans.js +37 -0
- package/dist/auth/plans.js.map +1 -0
- package/dist/auth/plans.test.d.ts +2 -0
- package/dist/auth/plans.test.d.ts.map +1 -0
- package/dist/auth/plans.test.js +23 -0
- package/dist/auth/plans.test.js.map +1 -0
- package/dist/cg-directory.d.ts +37 -0
- package/dist/cg-directory.d.ts.map +1 -0
- package/dist/cg-directory.js +129 -0
- package/dist/cg-directory.js.map +1 -0
- package/dist/check/check-runner.d.ts +3 -0
- package/dist/check/check-runner.d.ts.map +1 -0
- package/dist/check/check-runner.js +48 -0
- package/dist/check/check-runner.js.map +1 -0
- package/dist/check/compiler-service.d.ts +6 -0
- package/dist/check/compiler-service.d.ts.map +1 -0
- package/dist/check/compiler-service.js +69 -0
- package/dist/check/compiler-service.js.map +1 -0
- package/dist/check/parsers/cargo.d.ts +3 -0
- package/dist/check/parsers/cargo.d.ts.map +1 -0
- package/dist/check/parsers/cargo.js +34 -0
- package/dist/check/parsers/cargo.js.map +1 -0
- package/dist/check/parsers/parsers.test.d.ts +2 -0
- package/dist/check/parsers/parsers.test.d.ts.map +1 -0
- package/dist/check/parsers/parsers.test.js +51 -0
- package/dist/check/parsers/parsers.test.js.map +1 -0
- package/dist/check/parsers/pyright.d.ts +3 -0
- package/dist/check/parsers/pyright.d.ts.map +1 -0
- package/dist/check/parsers/pyright.js +27 -0
- package/dist/check/parsers/pyright.js.map +1 -0
- package/dist/check/parsers/tsc-cli.d.ts +3 -0
- package/dist/check/parsers/tsc-cli.d.ts.map +1 -0
- package/dist/check/parsers/tsc-cli.js +22 -0
- package/dist/check/parsers/tsc-cli.js.map +1 -0
- package/dist/check/project-tooling.d.ts +18 -0
- package/dist/check/project-tooling.d.ts.map +1 -0
- package/dist/check/project-tooling.js +105 -0
- package/dist/check/project-tooling.js.map +1 -0
- package/dist/check/run-command.d.ts +8 -0
- package/dist/check/run-command.d.ts.map +1 -0
- package/dist/check/run-command.js +50 -0
- package/dist/check/run-command.js.map +1 -0
- package/dist/check/scope.d.ts +11 -0
- package/dist/check/scope.d.ts.map +1 -0
- package/dist/check/scope.js +46 -0
- package/dist/check/scope.js.map +1 -0
- package/dist/check/scope.test.d.ts +2 -0
- package/dist/check/scope.test.d.ts.map +1 -0
- package/dist/check/scope.test.js +15 -0
- package/dist/check/scope.test.js.map +1 -0
- package/dist/check/strict-mode.d.ts +5 -0
- package/dist/check/strict-mode.d.ts.map +1 -0
- package/dist/check/strict-mode.js +32 -0
- package/dist/check/strict-mode.js.map +1 -0
- package/dist/check/strict-mode.test.d.ts +2 -0
- package/dist/check/strict-mode.test.d.ts.map +1 -0
- package/dist/check/strict-mode.test.js +53 -0
- package/dist/check/strict-mode.test.js.map +1 -0
- package/dist/check/structural-checks.d.ts +3 -0
- package/dist/check/structural-checks.d.ts.map +1 -0
- package/dist/check/structural-checks.js +111 -0
- package/dist/check/structural-checks.js.map +1 -0
- package/dist/check/types.d.ts +40 -0
- package/dist/check/types.d.ts.map +1 -0
- package/dist/check/types.js +2 -0
- package/dist/check/types.js.map +1 -0
- package/dist/check/verifiers/python.d.ts +7 -0
- package/dist/check/verifiers/python.d.ts.map +1 -0
- package/dist/check/verifiers/python.js +43 -0
- package/dist/check/verifiers/python.js.map +1 -0
- package/dist/check/verifiers/rust.d.ts +7 -0
- package/dist/check/verifiers/rust.d.ts.map +1 -0
- package/dist/check/verifiers/rust.js +39 -0
- package/dist/check/verifiers/rust.js.map +1 -0
- package/dist/check/verifiers/typescript.d.ts +7 -0
- package/dist/check/verifiers/typescript.d.ts.map +1 -0
- package/dist/check/verifiers/typescript.js +108 -0
- package/dist/check/verifiers/typescript.js.map +1 -0
- package/dist/commands/auth.d.ts +4 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +51 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/check.d.ts +9 -0
- package/dist/commands/check.d.ts.map +1 -0
- package/dist/commands/check.js +145 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +76 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/init-hooks.d.ts +15 -0
- package/dist/commands/init-hooks.d.ts.map +1 -0
- package/dist/commands/init-hooks.js +102 -0
- package/dist/commands/init-hooks.js.map +1 -0
- package/dist/commands/input.d.ts +2 -0
- package/dist/commands/input.d.ts.map +1 -0
- package/dist/commands/input.js +139 -0
- package/dist/commands/input.js.map +1 -0
- package/dist/commands/prompt.d.ts +2 -0
- package/dist/commands/prompt.d.ts.map +1 -0
- package/dist/commands/prompt.js +70 -0
- package/dist/commands/prompt.js.map +1 -0
- package/dist/commands/scan.d.ts +5 -0
- package/dist/commands/scan.d.ts.map +1 -0
- package/dist/commands/scan.js +163 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/commands/watch.d.ts +11 -0
- package/dist/commands/watch.d.ts.map +1 -0
- package/dist/commands/watch.js +74 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/config/env.d.ts +5 -0
- package/dist/config/env.d.ts.map +1 -0
- package/dist/config/env.js +60 -0
- package/dist/config/env.js.map +1 -0
- package/dist/graph.d.ts +34 -0
- package/dist/graph.d.ts.map +1 -0
- package/dist/graph.js +123 -0
- package/dist/graph.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +176 -0
- package/dist/index.js.map +1 -0
- package/dist/memory/pattern-analyzer.d.ts +17 -0
- package/dist/memory/pattern-analyzer.d.ts.map +1 -0
- package/dist/memory/pattern-analyzer.js +56 -0
- package/dist/memory/pattern-analyzer.js.map +1 -0
- package/dist/memory/repo-memory.d.ts +14 -0
- package/dist/memory/repo-memory.d.ts.map +1 -0
- package/dist/memory/repo-memory.js +71 -0
- package/dist/memory/repo-memory.js.map +1 -0
- package/dist/memory/types.d.ts +32 -0
- package/dist/memory/types.d.ts.map +1 -0
- package/dist/memory/types.js +2 -0
- package/dist/memory/types.js.map +1 -0
- package/dist/prompt/llm-client.d.ts +8 -0
- package/dist/prompt/llm-client.d.ts.map +1 -0
- package/dist/prompt/llm-client.js +96 -0
- package/dist/prompt/llm-client.js.map +1 -0
- package/dist/prompt/subgraph.d.ts +26 -0
- package/dist/prompt/subgraph.d.ts.map +1 -0
- package/dist/prompt/subgraph.js +96 -0
- package/dist/prompt/subgraph.js.map +1 -0
- package/dist/scanner.d.ts +13 -0
- package/dist/scanner.d.ts.map +1 -0
- package/dist/scanner.js +92 -0
- package/dist/scanner.js.map +1 -0
- package/dist/team/audit.d.ts +4 -0
- package/dist/team/audit.d.ts.map +1 -0
- package/dist/team/audit.js +16 -0
- package/dist/team/audit.js.map +1 -0
- package/dist/team/cloud-client.d.ts +7 -0
- package/dist/team/cloud-client.d.ts.map +1 -0
- package/dist/team/cloud-client.js +106 -0
- package/dist/team/cloud-client.js.map +1 -0
- package/dist/team/dev-store.d.ts +9 -0
- package/dist/team/dev-store.d.ts.map +1 -0
- package/dist/team/dev-store.js +69 -0
- package/dist/team/dev-store.js.map +1 -0
- package/dist/team/graph-sync.d.ts +10 -0
- package/dist/team/graph-sync.d.ts.map +1 -0
- package/dist/team/graph-sync.js +78 -0
- package/dist/team/graph-sync.js.map +1 -0
- package/dist/team/policy-cache.d.ts +7 -0
- package/dist/team/policy-cache.d.ts.map +1 -0
- package/dist/team/policy-cache.js +31 -0
- package/dist/team/policy-cache.js.map +1 -0
- package/dist/team/policy-engine.d.ts +3 -0
- package/dist/team/policy-engine.d.ts.map +1 -0
- package/dist/team/policy-engine.js +35 -0
- package/dist/team/policy-engine.js.map +1 -0
- package/dist/team/policy-engine.test.d.ts +2 -0
- package/dist/team/policy-engine.test.d.ts.map +1 -0
- package/dist/team/policy-engine.test.js +29 -0
- package/dist/team/policy-engine.test.js.map +1 -0
- package/dist/team/repo-identity.d.ts +7 -0
- package/dist/team/repo-identity.d.ts.map +1 -0
- package/dist/team/repo-identity.js +41 -0
- package/dist/team/repo-identity.js.map +1 -0
- package/dist/team/types.d.ts +53 -0
- package/dist/team/types.d.ts.map +1 -0
- package/dist/team/types.js +2 -0
- package/dist/team/types.js.map +1 -0
- package/dist/toolchain/probe.d.ts +9 -0
- package/dist/toolchain/probe.d.ts.map +1 -0
- package/dist/toolchain/probe.js +123 -0
- package/dist/toolchain/probe.js.map +1 -0
- package/dist/toolchain/project-languages.d.ts +4 -0
- package/dist/toolchain/project-languages.d.ts.map +1 -0
- package/dist/toolchain/project-languages.js +41 -0
- package/dist/toolchain/project-languages.js.map +1 -0
- package/dist/toolchain/types.d.ts +32 -0
- package/dist/toolchain/types.d.ts.map +1 -0
- package/dist/toolchain/types.js +2 -0
- package/dist/toolchain/types.js.map +1 -0
- package/dist/utils/blast-radius-analyzer.d.ts +95 -0
- package/dist/utils/blast-radius-analyzer.d.ts.map +1 -0
- package/dist/utils/blast-radius-analyzer.js +277 -0
- package/dist/utils/blast-radius-analyzer.js.map +1 -0
- package/dist/utils/change-detector.d.ts +43 -0
- package/dist/utils/change-detector.d.ts.map +1 -0
- package/dist/utils/change-detector.js +190 -0
- package/dist/utils/change-detector.js.map +1 -0
- package/dist/utils/cli-formatter.d.ts +80 -0
- package/dist/utils/cli-formatter.d.ts.map +1 -0
- package/dist/utils/cli-formatter.js +205 -0
- package/dist/utils/cli-formatter.js.map +1 -0
- package/dist/utils/git-hook-manager.d.ts +81 -0
- package/dist/utils/git-hook-manager.d.ts.map +1 -0
- package/dist/utils/git-hook-manager.js +243 -0
- package/dist/utils/git-hook-manager.js.map +1 -0
- package/dist/utils/project-watcher.d.ts +91 -0
- package/dist/utils/project-watcher.d.ts.map +1 -0
- package/dist/utils/project-watcher.js +215 -0
- package/dist/utils/project-watcher.js.map +1 -0
- package/package.json +56 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced Blast Radius Analyzer
|
|
3
|
+
*
|
|
4
|
+
* Determines what breaks when you change a file:
|
|
5
|
+
* - Direct impact (files that import/depend on the changed file)
|
|
6
|
+
* - Transitive impact (files that depend on the dependent files)
|
|
7
|
+
* - Severity scoring (high/medium/low based on multiple factors)
|
|
8
|
+
* - Change classification (what type of change is it)
|
|
9
|
+
*/
|
|
10
|
+
export interface ChangeType {
|
|
11
|
+
type: 'function' | 'class' | 'type' | 'export' | 'import' | 'schema' | 'config' | 'unknown';
|
|
12
|
+
description: string;
|
|
13
|
+
confidence: number;
|
|
14
|
+
}
|
|
15
|
+
export interface ImpactedFile {
|
|
16
|
+
path: string;
|
|
17
|
+
reason: string;
|
|
18
|
+
severity: 'critical' | 'high' | 'medium' | 'low';
|
|
19
|
+
distance: number;
|
|
20
|
+
impactType: 'direct' | 'transitive' | 'potential';
|
|
21
|
+
changeRequired: boolean;
|
|
22
|
+
suggestedFix?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface BlastRadiusResult {
|
|
25
|
+
directlyAffected: number;
|
|
26
|
+
transitivelyAffected: number;
|
|
27
|
+
potentiallyAffected: number;
|
|
28
|
+
totalRisk: number;
|
|
29
|
+
riskLevel: 'critical' | 'high' | 'medium' | 'low';
|
|
30
|
+
affectedFiles: ImpactedFile[];
|
|
31
|
+
changeTypes: ChangeType[];
|
|
32
|
+
recommendations: string[];
|
|
33
|
+
}
|
|
34
|
+
interface FileNode {
|
|
35
|
+
path: string;
|
|
36
|
+
language: string;
|
|
37
|
+
dependencies: Array<{
|
|
38
|
+
to: string;
|
|
39
|
+
type: string;
|
|
40
|
+
}>;
|
|
41
|
+
symbols: string[];
|
|
42
|
+
imports?: string[];
|
|
43
|
+
exports?: string[];
|
|
44
|
+
}
|
|
45
|
+
interface DependencyGraph {
|
|
46
|
+
files: Record<string, FileNode>;
|
|
47
|
+
stats: any;
|
|
48
|
+
}
|
|
49
|
+
export declare class BlastRadiusAnalyzer {
|
|
50
|
+
private graph;
|
|
51
|
+
private reverseGraph;
|
|
52
|
+
constructor(graph: DependencyGraph);
|
|
53
|
+
/**
|
|
54
|
+
* Build reverse dependency graph for quick lookups
|
|
55
|
+
*/
|
|
56
|
+
private buildReverseGraph;
|
|
57
|
+
/**
|
|
58
|
+
* Analyze impact of changing specific files
|
|
59
|
+
*/
|
|
60
|
+
analyze(changedFiles: string[]): BlastRadiusResult;
|
|
61
|
+
/**
|
|
62
|
+
* Recursively find all files impacted by a change
|
|
63
|
+
*/
|
|
64
|
+
private findImpactedFiles;
|
|
65
|
+
/**
|
|
66
|
+
* Generate human-readable reason for impact
|
|
67
|
+
*/
|
|
68
|
+
private generateReason;
|
|
69
|
+
/**
|
|
70
|
+
* Classify the type of change being made
|
|
71
|
+
*/
|
|
72
|
+
private classifyChanges;
|
|
73
|
+
/**
|
|
74
|
+
* Calculate severity for each impacted file based on multiple factors
|
|
75
|
+
*/
|
|
76
|
+
private calculateSeverities;
|
|
77
|
+
/**
|
|
78
|
+
* Heuristics to identify important files
|
|
79
|
+
*/
|
|
80
|
+
private isImportantFile;
|
|
81
|
+
/**
|
|
82
|
+
* Aggregate results and generate recommendations
|
|
83
|
+
*/
|
|
84
|
+
private aggregateResults;
|
|
85
|
+
/**
|
|
86
|
+
* Generate actionable recommendations based on analysis
|
|
87
|
+
*/
|
|
88
|
+
private generateRecommendations;
|
|
89
|
+
/**
|
|
90
|
+
* Detailed analysis for a specific file
|
|
91
|
+
*/
|
|
92
|
+
analyzeFile(filePath: string): any;
|
|
93
|
+
}
|
|
94
|
+
export {};
|
|
95
|
+
//# sourceMappingURL=blast-radius-analyzer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blast-radius-analyzer.d.ts","sourceRoot":"","sources":["../../src/utils/blast-radius-analyzer.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,UAAU,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;IAC5F,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACjD,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,QAAQ,GAAG,YAAY,GAAG,WAAW,CAAC;IAClD,cAAc,EAAE,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,gBAAgB,EAAE,MAAM,CAAC;IACzB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IAClD,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,UAAU,QAAQ;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,UAAU,eAAe;IACvB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAChC,KAAK,EAAE,GAAG,CAAC;CACZ;AAED,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,YAAY,CAAuC;gBAE/C,KAAK,EAAE,eAAe;IAKlC;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAWzB;;OAEG;IACH,OAAO,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,iBAAiB;IAyBlD;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAgCzB;;OAEG;IACH,OAAO,CAAC,cAAc;IAMtB;;OAEG;IACH,OAAO,CAAC,eAAe;IA2CvB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAmC3B;;OAEG;IACH,OAAO,CAAC,eAAe;IAiBvB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAyCxB;;OAEG;IACH,OAAO,CAAC,uBAAuB;IA8C/B;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,GAAG;CAgBnC"}
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced Blast Radius Analyzer
|
|
3
|
+
*
|
|
4
|
+
* Determines what breaks when you change a file:
|
|
5
|
+
* - Direct impact (files that import/depend on the changed file)
|
|
6
|
+
* - Transitive impact (files that depend on the dependent files)
|
|
7
|
+
* - Severity scoring (high/medium/low based on multiple factors)
|
|
8
|
+
* - Change classification (what type of change is it)
|
|
9
|
+
*/
|
|
10
|
+
export class BlastRadiusAnalyzer {
|
|
11
|
+
constructor(graph) {
|
|
12
|
+
this.reverseGraph = new Map(); // file -> files that depend on it
|
|
13
|
+
this.graph = graph;
|
|
14
|
+
this.buildReverseGraph();
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Build reverse dependency graph for quick lookups
|
|
18
|
+
*/
|
|
19
|
+
buildReverseGraph() {
|
|
20
|
+
for (const [filePath, node] of Object.entries(this.graph.files || {})) {
|
|
21
|
+
for (const dep of node.dependencies || []) {
|
|
22
|
+
if (!this.reverseGraph.has(dep.to)) {
|
|
23
|
+
this.reverseGraph.set(dep.to, new Set());
|
|
24
|
+
}
|
|
25
|
+
this.reverseGraph.get(dep.to).add(filePath);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Analyze impact of changing specific files
|
|
31
|
+
*/
|
|
32
|
+
analyze(changedFiles) {
|
|
33
|
+
const affected = new Map();
|
|
34
|
+
const visited = new Set();
|
|
35
|
+
// Find all impacted files recursively
|
|
36
|
+
for (const file of changedFiles) {
|
|
37
|
+
this.findImpactedFiles(file, 1, affected, visited);
|
|
38
|
+
}
|
|
39
|
+
// Classify changes and calculate severity
|
|
40
|
+
const changeTypes = this.classifyChanges(changedFiles);
|
|
41
|
+
const impactedArray = Array.from(affected.values());
|
|
42
|
+
const severityMap = this.calculateSeverities(impactedArray, changeTypes);
|
|
43
|
+
// Update severities
|
|
44
|
+
impactedArray.forEach(file => {
|
|
45
|
+
file.severity = severityMap.get(file.path) || 'low';
|
|
46
|
+
});
|
|
47
|
+
// Calculate overall risk
|
|
48
|
+
const result = this.aggregateResults(impactedArray, changeTypes);
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Recursively find all files impacted by a change
|
|
53
|
+
*/
|
|
54
|
+
findImpactedFiles(file, depth, affected, visited, maxDepth = 5) {
|
|
55
|
+
if (visited.has(file) || depth > maxDepth)
|
|
56
|
+
return;
|
|
57
|
+
visited.add(file);
|
|
58
|
+
// Find files that depend on the current file
|
|
59
|
+
const dependents = this.reverseGraph.get(file) || new Set();
|
|
60
|
+
for (const dependent of dependents) {
|
|
61
|
+
if (!affected.has(dependent)) {
|
|
62
|
+
affected.set(dependent, {
|
|
63
|
+
path: dependent,
|
|
64
|
+
reason: this.generateReason(file, dependent),
|
|
65
|
+
severity: 'medium', // Will be recalculated
|
|
66
|
+
distance: depth,
|
|
67
|
+
impactType: depth === 1 ? 'direct' : 'transitive',
|
|
68
|
+
changeRequired: true,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
// Recursively find transitive dependencies
|
|
72
|
+
if (depth < 3) {
|
|
73
|
+
this.findImpactedFiles(dependent, depth + 1, affected, visited, maxDepth);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Generate human-readable reason for impact
|
|
79
|
+
*/
|
|
80
|
+
generateReason(from, to) {
|
|
81
|
+
const fromName = from.split('/').pop() || from;
|
|
82
|
+
const toName = to.split('/').pop() || to;
|
|
83
|
+
return `Depends on ${fromName}`;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Classify the type of change being made
|
|
87
|
+
*/
|
|
88
|
+
classifyChanges(changedFiles) {
|
|
89
|
+
const changes = [];
|
|
90
|
+
const keywords = {
|
|
91
|
+
function: ['function', 'method', 'handler', 'callback'],
|
|
92
|
+
class: ['class', 'interface', 'type', 'abstract'],
|
|
93
|
+
export: ['export', 'default export'],
|
|
94
|
+
schema: ['schema', 'model', 'entity', 'database'],
|
|
95
|
+
config: ['config', 'settings', '.env', 'constants'],
|
|
96
|
+
};
|
|
97
|
+
for (const file of changedFiles) {
|
|
98
|
+
const fileContent = file.toLowerCase();
|
|
99
|
+
let matchedType = 'unknown';
|
|
100
|
+
let confidence = 0.3;
|
|
101
|
+
// Heuristic classification based on file path and content hints
|
|
102
|
+
if (fileContent.includes('schema') || fileContent.includes('model')) {
|
|
103
|
+
matchedType = 'schema';
|
|
104
|
+
confidence = 0.8;
|
|
105
|
+
}
|
|
106
|
+
else if (fileContent.includes('config') || fileContent.includes('const')) {
|
|
107
|
+
matchedType = 'config';
|
|
108
|
+
confidence = 0.8;
|
|
109
|
+
}
|
|
110
|
+
else if (fileContent.includes('service') || fileContent.includes('handler')) {
|
|
111
|
+
matchedType = 'function';
|
|
112
|
+
confidence = 0.6;
|
|
113
|
+
}
|
|
114
|
+
else if (fileContent.includes('component') || fileContent.includes('util')) {
|
|
115
|
+
matchedType = 'class';
|
|
116
|
+
confidence = 0.5;
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
matchedType = 'unknown';
|
|
120
|
+
confidence = 0.3;
|
|
121
|
+
}
|
|
122
|
+
changes.push({
|
|
123
|
+
type: matchedType,
|
|
124
|
+
description: `${matchedType} change detected`,
|
|
125
|
+
confidence,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
return changes;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Calculate severity for each impacted file based on multiple factors
|
|
132
|
+
*/
|
|
133
|
+
calculateSeverities(files, changeTypes) {
|
|
134
|
+
const severities = new Map();
|
|
135
|
+
for (const file of files) {
|
|
136
|
+
let score = 0; // 0-100
|
|
137
|
+
// Factor 1: Distance (closer = higher severity)
|
|
138
|
+
score += (4 - file.distance) * 20; // 0-80 points
|
|
139
|
+
// Factor 2: Impact type
|
|
140
|
+
if (file.impactType === 'direct')
|
|
141
|
+
score += 15;
|
|
142
|
+
else if (file.impactType === 'transitive')
|
|
143
|
+
score += 5;
|
|
144
|
+
// Factor 3: File importance heuristics
|
|
145
|
+
if (this.isImportantFile(file.path))
|
|
146
|
+
score += 10;
|
|
147
|
+
// Factor 4: Change confidence from classification
|
|
148
|
+
const avgChangeConfidence = changeTypes.length > 0
|
|
149
|
+
? changeTypes.reduce((sum, c) => sum + c.confidence, 0) / changeTypes.length
|
|
150
|
+
: 0.5;
|
|
151
|
+
score += avgChangeConfidence * 20;
|
|
152
|
+
// Determine severity level
|
|
153
|
+
if (score >= 80)
|
|
154
|
+
severities.set(file.path, 'critical');
|
|
155
|
+
else if (score >= 60)
|
|
156
|
+
severities.set(file.path, 'high');
|
|
157
|
+
else if (score >= 40)
|
|
158
|
+
severities.set(file.path, 'medium');
|
|
159
|
+
else
|
|
160
|
+
severities.set(file.path, 'low');
|
|
161
|
+
}
|
|
162
|
+
return severities;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Heuristics to identify important files
|
|
166
|
+
*/
|
|
167
|
+
isImportantFile(path) {
|
|
168
|
+
const important = [
|
|
169
|
+
'index',
|
|
170
|
+
'main',
|
|
171
|
+
'app',
|
|
172
|
+
'core',
|
|
173
|
+
'api',
|
|
174
|
+
'server',
|
|
175
|
+
'middleware',
|
|
176
|
+
'auth',
|
|
177
|
+
'schema',
|
|
178
|
+
];
|
|
179
|
+
const lowerPath = path.toLowerCase();
|
|
180
|
+
return important.some(keyword => lowerPath.includes(keyword));
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Aggregate results and generate recommendations
|
|
184
|
+
*/
|
|
185
|
+
aggregateResults(files, changeTypes) {
|
|
186
|
+
const critical = files.filter(f => f.severity === 'critical').length;
|
|
187
|
+
const high = files.filter(f => f.severity === 'high').length;
|
|
188
|
+
const medium = files.filter(f => f.severity === 'medium').length;
|
|
189
|
+
const low = files.filter(f => f.severity === 'low').length;
|
|
190
|
+
// Calculate overall risk (0-100)
|
|
191
|
+
let totalRisk = critical * 25 + high * 15 + medium * 8 + low * 2;
|
|
192
|
+
totalRisk = Math.min(100, totalRisk / Math.max(1, files.length) + files.length * 2);
|
|
193
|
+
// Determine risk level
|
|
194
|
+
let riskLevel = 'low';
|
|
195
|
+
if (totalRisk >= 75)
|
|
196
|
+
riskLevel = 'critical';
|
|
197
|
+
else if (totalRisk >= 50)
|
|
198
|
+
riskLevel = 'high';
|
|
199
|
+
else if (totalRisk >= 25)
|
|
200
|
+
riskLevel = 'medium';
|
|
201
|
+
// Generate recommendations
|
|
202
|
+
const recommendations = this.generateRecommendations(files, changeTypes, riskLevel);
|
|
203
|
+
const direct = files.filter(f => f.distance === 1).length;
|
|
204
|
+
const transitive = files.filter(f => f.distance > 1).length;
|
|
205
|
+
return {
|
|
206
|
+
directlyAffected: direct,
|
|
207
|
+
transitivelyAffected: transitive,
|
|
208
|
+
potentiallyAffected: 0,
|
|
209
|
+
totalRisk: Math.round(totalRisk),
|
|
210
|
+
riskLevel,
|
|
211
|
+
affectedFiles: files.sort((a, b) => {
|
|
212
|
+
const severityOrder = { critical: 0, high: 1, medium: 2, low: 3 };
|
|
213
|
+
return (severityOrder[a.severity] || 4) - (severityOrder[b.severity] || 4);
|
|
214
|
+
}),
|
|
215
|
+
changeTypes,
|
|
216
|
+
recommendations,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Generate actionable recommendations based on analysis
|
|
221
|
+
*/
|
|
222
|
+
generateRecommendations(files, changeTypes, riskLevel) {
|
|
223
|
+
const recommendations = [];
|
|
224
|
+
// Critical files
|
|
225
|
+
const criticalFiles = files.filter(f => f.severity === 'critical');
|
|
226
|
+
if (criticalFiles.length > 0) {
|
|
227
|
+
recommendations.push(`⚠️ ${criticalFiles.length} critical files impacted. Review these carefully:`);
|
|
228
|
+
}
|
|
229
|
+
// Change type specific recommendations
|
|
230
|
+
for (const change of changeTypes) {
|
|
231
|
+
if (change.type === 'schema') {
|
|
232
|
+
recommendations.push('📊 Schema change detected: Update database migrations and models');
|
|
233
|
+
}
|
|
234
|
+
else if (change.type === 'export') {
|
|
235
|
+
recommendations.push('📤 Export change detected: Update all imports in affected files');
|
|
236
|
+
}
|
|
237
|
+
else if (change.type === 'config') {
|
|
238
|
+
recommendations.push('⚙️ Configuration change: Verify environment variables across deployment');
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
// Risk-level recommendations
|
|
242
|
+
if (riskLevel === 'critical' || riskLevel === 'high') {
|
|
243
|
+
recommendations.push('🚨 Consider writing additional tests for affected modules');
|
|
244
|
+
recommendations.push('🔍 Run full test suite before deploying');
|
|
245
|
+
}
|
|
246
|
+
else if (riskLevel === 'medium') {
|
|
247
|
+
recommendations.push('✓ Run tests for directly affected modules');
|
|
248
|
+
}
|
|
249
|
+
// Hotfix recommendations
|
|
250
|
+
if (files.length > 15) {
|
|
251
|
+
recommendations.push(`💡 Large blast radius (${files.length} files). Consider breaking change into smaller PRs`);
|
|
252
|
+
}
|
|
253
|
+
if (recommendations.length === 0) {
|
|
254
|
+
recommendations.push('✓ Low risk change. Proceed with caution.');
|
|
255
|
+
}
|
|
256
|
+
return recommendations;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Detailed analysis for a specific file
|
|
260
|
+
*/
|
|
261
|
+
analyzeFile(filePath) {
|
|
262
|
+
const node = this.graph.files[filePath];
|
|
263
|
+
if (!node)
|
|
264
|
+
return null;
|
|
265
|
+
const dependsOn = node.dependencies || [];
|
|
266
|
+
const dependedOnBy = Array.from(this.reverseGraph.get(filePath) || []);
|
|
267
|
+
return {
|
|
268
|
+
path: filePath,
|
|
269
|
+
language: node.language,
|
|
270
|
+
dependsOn,
|
|
271
|
+
dependedOnBy,
|
|
272
|
+
symbols: node.symbols || [],
|
|
273
|
+
riskScore: dependedOnBy.length * 2 + dependsOn.length,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
//# sourceMappingURL=blast-radius-analyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blast-radius-analyzer.js","sourceRoot":"","sources":["../../src/utils/blast-radius-analyzer.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA2CH,MAAM,OAAO,mBAAmB;IAI9B,YAAY,KAAsB;QAF1B,iBAAY,GAA6B,IAAI,GAAG,EAAE,CAAC,CAAC,kCAAkC;QAG5F,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,iBAAiB,EAAE,CAAC;IAC3B,CAAC;IAED;;OAEG;IACK,iBAAiB;QACvB,KAAK,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC;YACtE,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,YAAY,IAAI,EAAE,EAAE,CAAC;gBAC1C,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;oBACnC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;gBAC3C,CAAC;gBACD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,YAAsB;QAC5B,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAwB,CAAC;QACjD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;QAElC,sCAAsC;QACtC,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;YAChC,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;QACrD,CAAC;QAED,0CAA0C;QAC1C,MAAM,WAAW,GAAG,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC;QACvD,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QACpD,MAAM,WAAW,GAAG,IAAI,CAAC,mBAAmB,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;QAEzE,oBAAoB;QACpB,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;YAC3B,IAAI,CAAC,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC;QACtD,CAAC,CAAC,CAAC;QAEH,yBAAyB;QACzB,MAAM,MAAM,GAAG,IAAI,CAAC,gBAAgB,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;QAEjE,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACK,iBAAiB,CACvB,IAAY,EACZ,KAAa,EACb,QAAmC,EACnC,OAAoB,EACpB,WAAmB,CAAC;QAEpB,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,GAAG,QAAQ;YAAE,OAAO;QAClD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAElB,6CAA6C;QAC7C,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,EAAE,CAAC;QAE5D,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC7B,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE;oBACtB,IAAI,EAAE,SAAS;oBACf,MAAM,EAAE,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,SAAS,CAAC;oBAC5C,QAAQ,EAAE,QAAQ,EAAE,uBAAuB;oBAC3C,QAAQ,EAAE,KAAK;oBACf,UAAU,EAAE,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY;oBACjD,cAAc,EAAE,IAAI;iBACrB,CAAC,CAAC;YACL,CAAC;YAED,2CAA2C;YAC3C,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;gBACd,IAAI,CAAC,iBAAiB,CAAC,SAAS,EAAE,KAAK,GAAG,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;YAC5E,CAAC;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACK,cAAc,CAAC,IAAY,EAAE,EAAU;QAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC;QAC/C,MAAM,MAAM,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;QACzC,OAAO,cAAc,QAAQ,EAAE,CAAC;IAClC,CAAC;IAED;;OAEG;IACK,eAAe,CAAC,YAAsB;QAC5C,MAAM,OAAO,GAAiB,EAAE,CAAC;QACjC,MAAM,QAAQ,GAAG;YACf,QAAQ,EAAE,CAAC,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,CAAC;YACvD,KAAK,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,CAAC;YACjD,MAAM,EAAE,CAAC,QAAQ,EAAE,gBAAgB,CAAC;YACpC,MAAM,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,CAAC;YACjD,MAAM,EAAE,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC;SACpD,CAAC;QAEF,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;YAChC,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;YACvC,IAAI,WAAW,GAA8E,SAAgB,CAAC;YAC9G,IAAI,UAAU,GAAG,GAAG,CAAC;YAErB,gEAAgE;YAChE,IAAI,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gBACpE,WAAW,GAAG,QAAQ,CAAC;gBACvB,UAAU,GAAG,GAAG,CAAC;YACnB,CAAC;iBAAM,IAAI,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC3E,WAAW,GAAG,QAAQ,CAAC;gBACvB,UAAU,GAAG,GAAG,CAAC;YACnB,CAAC;iBAAM,IAAI,WAAW,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC9E,WAAW,GAAG,UAAU,CAAC;gBACzB,UAAU,GAAG,GAAG,CAAC;YACnB,CAAC;iBAAM,IAAI,WAAW,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC7E,WAAW,GAAG,OAAO,CAAC;gBACtB,UAAU,GAAG,GAAG,CAAC;YACnB,CAAC;iBAAM,CAAC;gBACN,WAAW,GAAG,SAAgB,CAAC;gBAC/B,UAAU,GAAG,GAAG,CAAC;YACnB,CAAC;YAED,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,WAAW;gBACjB,WAAW,EAAE,GAAG,WAAW,kBAAkB;gBAC7C,UAAU;aACX,CAAC,CAAC;QACL,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;OAEG;IACK,mBAAmB,CACzB,KAAqB,EACrB,WAAyB;QAEzB,MAAM,UAAU,GAAG,IAAI,GAAG,EAAkD,CAAC;QAE7E,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,QAAQ;YAEvB,gDAAgD;YAChD,KAAK,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,cAAc;YAEjD,wBAAwB;YACxB,IAAI,IAAI,CAAC,UAAU,KAAK,QAAQ;gBAAE,KAAK,IAAI,EAAE,CAAC;iBACzC,IAAI,IAAI,CAAC,UAAU,KAAK,YAAY;gBAAE,KAAK,IAAI,CAAC,CAAC;YAEtD,uCAAuC;YACvC,IAAI,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,KAAK,IAAI,EAAE,CAAC;YAEjD,kDAAkD;YAClD,MAAM,mBAAmB,GAAG,WAAW,CAAC,MAAM,GAAG,CAAC;gBAChD,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,GAAG,WAAW,CAAC,MAAM;gBAC5E,CAAC,CAAC,GAAG,CAAC;YACR,KAAK,IAAI,mBAAmB,GAAG,EAAE,CAAC;YAElC,2BAA2B;YAC3B,IAAI,KAAK,IAAI,EAAE;gBAAE,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;iBAClD,IAAI,KAAK,IAAI,EAAE;gBAAE,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;iBACnD,IAAI,KAAK,IAAI,EAAE;gBAAE,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;;gBACrD,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACxC,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;IAED;;OAEG;IACK,eAAe,CAAC,IAAY;QAClC,MAAM,SAAS,GAAG;YAChB,OAAO;YACP,MAAM;YACN,KAAK;YACL,MAAM;YACN,KAAK;YACL,QAAQ;YACR,YAAY;YACZ,MAAM;YACN,QAAQ;SACT,CAAC;QAEF,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QACrC,OAAO,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;IAChE,CAAC;IAED;;OAEG;IACK,gBAAgB,CAAC,KAAqB,EAAE,WAAyB;QACvE,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC,MAAM,CAAC;QACrE,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC,MAAM,CAAC;QAC7D,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,MAAM,CAAC;QACjE,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,KAAK,CAAC,CAAC,MAAM,CAAC;QAE3D,iCAAiC;QACjC,IAAI,SAAS,GAAG,QAAQ,GAAG,EAAE,GAAG,IAAI,GAAG,EAAE,GAAG,MAAM,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;QACjE,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAEpF,uBAAuB;QACvB,IAAI,SAAS,GAA2C,KAAK,CAAC;QAC9D,IAAI,SAAS,IAAI,EAAE;YAAE,SAAS,GAAG,UAAU,CAAC;aACvC,IAAI,SAAS,IAAI,EAAE;YAAE,SAAS,GAAG,MAAM,CAAC;aACxC,IAAI,SAAS,IAAI,EAAE;YAAE,SAAS,GAAG,QAAQ,CAAC;QAE/C,2BAA2B;QAC3B,MAAM,eAAe,GAAG,IAAI,CAAC,uBAAuB,CAClD,KAAK,EACL,WAAW,EACX,SAAS,CACV,CAAC;QAEF,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;QAC1D,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;QAE5D,OAAO;YACL,gBAAgB,EAAE,MAAM;YACxB,oBAAoB,EAAE,UAAU;YAChC,mBAAmB,EAAE,CAAC;YACtB,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC;YAChC,SAAS;YACT,aAAa,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;gBACjC,MAAM,aAAa,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;gBAClE,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;YAC7E,CAAC,CAAC;YACF,WAAW;YACX,eAAe;SAChB,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,uBAAuB,CAC7B,KAAqB,EACrB,WAAyB,EACzB,SAAiB;QAEjB,MAAM,eAAe,GAAa,EAAE,CAAC;QAErC,iBAAiB;QACjB,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC;QACnE,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,eAAe,CAAC,IAAI,CAClB,OAAO,aAAa,CAAC,MAAM,mDAAmD,CAC/E,CAAC;QACJ,CAAC;QAED,uCAAuC;QACvC,KAAK,MAAM,MAAM,IAAI,WAAW,EAAE,CAAC;YACjC,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC7B,eAAe,CAAC,IAAI,CAAC,kEAAkE,CAAC,CAAC;YAC3F,CAAC;iBAAM,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACpC,eAAe,CAAC,IAAI,CAAC,iEAAiE,CAAC,CAAC;YAC1F,CAAC;iBAAM,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACpC,eAAe,CAAC,IAAI,CAAC,0EAA0E,CAAC,CAAC;YACnG,CAAC;QACH,CAAC;QAED,6BAA6B;QAC7B,IAAI,SAAS,KAAK,UAAU,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;YACrD,eAAe,CAAC,IAAI,CAAC,2DAA2D,CAAC,CAAC;YAClF,eAAe,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC;QAClE,CAAC;aAAM,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;YAClC,eAAe,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC;QACpE,CAAC;QAED,yBAAyB;QACzB,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;YACtB,eAAe,CAAC,IAAI,CAAC,0BAA0B,KAAK,CAAC,MAAM,oDAAoD,CAAC,CAAC;QACnH,CAAC;QAED,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjC,eAAe,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;QACnE,CAAC;QAED,OAAO,eAAe,CAAC;IACzB,CAAC;IAED;;OAEG;IACH,WAAW,CAAC,QAAgB;QAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QAEvB,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,IAAI,EAAE,CAAC;QAC1C,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;QAEvE,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,SAAS;YACT,YAAY;YACZ,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,EAAE;YAC3B,SAAS,EAAE,YAAY,CAAC,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC,MAAM;SACtD,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Change Detection Utility
|
|
3
|
+
*
|
|
4
|
+
* Detects what files are being changed and extracts intent from descriptions
|
|
5
|
+
*/
|
|
6
|
+
export interface ChangedFilesInfo {
|
|
7
|
+
files: string[];
|
|
8
|
+
stagedFiles: string[];
|
|
9
|
+
unstaged: string[];
|
|
10
|
+
confidence: number;
|
|
11
|
+
}
|
|
12
|
+
export interface IntentMatch {
|
|
13
|
+
files: string[];
|
|
14
|
+
confidence: number;
|
|
15
|
+
intent: string;
|
|
16
|
+
}
|
|
17
|
+
export declare class ChangeDetector {
|
|
18
|
+
private projectRoot;
|
|
19
|
+
constructor(projectRoot: string);
|
|
20
|
+
/**
|
|
21
|
+
* Get currently changed files from git
|
|
22
|
+
*/
|
|
23
|
+
getChangedFiles(): ChangedFilesInfo;
|
|
24
|
+
/**
|
|
25
|
+
* Parse description to identify changed files
|
|
26
|
+
*/
|
|
27
|
+
parseDescription(description: string, availableFiles: string[]): IntentMatch;
|
|
28
|
+
/**
|
|
29
|
+
* Extract patterns from description
|
|
30
|
+
*/
|
|
31
|
+
private extractPatterns;
|
|
32
|
+
/**
|
|
33
|
+
* Git status parsing — uses only --name-only, no --porcelain conflict
|
|
34
|
+
*/
|
|
35
|
+
private getGitStatus;
|
|
36
|
+
/**
|
|
37
|
+
* Suggest related files based on the change description
|
|
38
|
+
*/
|
|
39
|
+
suggestRelatedFiles(changedFiles: string[], allFiles: string[], maxSuggestions?: number): string[];
|
|
40
|
+
private stringSimilarity;
|
|
41
|
+
private levenshteinDistance;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=change-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"change-detector.d.ts","sourceRoot":"","sources":["../../src/utils/change-detector.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,cAAc;IACb,OAAO,CAAC,WAAW;gBAAX,WAAW,EAAE,MAAM;IAEvC;;OAEG;IACH,eAAe,IAAI,gBAAgB;IAsBnC;;OAEG;IACH,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,WAAW;IA0D5E;;OAEG;IACH,OAAO,CAAC,eAAe;IAmCvB;;OAEG;IACH,OAAO,CAAC,YAAY;IAapB;;OAEG;IACH,mBAAmB,CACjB,YAAY,EAAE,MAAM,EAAE,EACtB,QAAQ,EAAE,MAAM,EAAE,EAClB,cAAc,GAAE,MAAU,GACzB,MAAM,EAAE;IAgCX,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,mBAAmB;CAmB5B"}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Change Detection Utility
|
|
3
|
+
*
|
|
4
|
+
* Detects what files are being changed and extracts intent from descriptions
|
|
5
|
+
*/
|
|
6
|
+
import { execSync } from 'child_process';
|
|
7
|
+
export class ChangeDetector {
|
|
8
|
+
constructor(projectRoot) {
|
|
9
|
+
this.projectRoot = projectRoot;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Get currently changed files from git
|
|
13
|
+
*/
|
|
14
|
+
getChangedFiles() {
|
|
15
|
+
try {
|
|
16
|
+
const staged = this.getGitStatus('--cached');
|
|
17
|
+
const unstaged = this.getGitStatus('');
|
|
18
|
+
const allChanged = [...new Set([...staged, ...unstaged])];
|
|
19
|
+
return {
|
|
20
|
+
files: allChanged,
|
|
21
|
+
stagedFiles: staged,
|
|
22
|
+
unstaged,
|
|
23
|
+
confidence: 1.0,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return {
|
|
28
|
+
files: [],
|
|
29
|
+
stagedFiles: [],
|
|
30
|
+
unstaged: [],
|
|
31
|
+
confidence: 0,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Parse description to identify changed files
|
|
37
|
+
*/
|
|
38
|
+
parseDescription(description, availableFiles) {
|
|
39
|
+
const patterns = this.extractPatterns(description);
|
|
40
|
+
const matchedFiles = [];
|
|
41
|
+
let confidence = 0;
|
|
42
|
+
// Pattern 1: "refactor X module"
|
|
43
|
+
for (const pattern of patterns.modules) {
|
|
44
|
+
for (const file of availableFiles) {
|
|
45
|
+
if (file.toLowerCase().includes(pattern.toLowerCase())) {
|
|
46
|
+
matchedFiles.push(file);
|
|
47
|
+
confidence = Math.max(confidence, 0.7);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// Pattern 2: File names mentioned
|
|
52
|
+
for (const file of availableFiles) {
|
|
53
|
+
const fileName = file.split('/').pop() || file;
|
|
54
|
+
if (description.toLowerCase().includes(fileName.toLowerCase())) {
|
|
55
|
+
if (!matchedFiles.includes(file)) {
|
|
56
|
+
matchedFiles.push(file);
|
|
57
|
+
confidence = Math.max(confidence, 0.9);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Pattern 3: Component/feature references
|
|
62
|
+
for (const feature of patterns.features) {
|
|
63
|
+
for (const file of availableFiles) {
|
|
64
|
+
if (file.toLowerCase().includes(feature.toLowerCase())) {
|
|
65
|
+
if (!matchedFiles.includes(file)) {
|
|
66
|
+
matchedFiles.push(file);
|
|
67
|
+
confidence = Math.max(confidence, 0.6);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// If no matches, use heuristics based on keywords
|
|
73
|
+
if (matchedFiles.length === 0) {
|
|
74
|
+
if (description.includes('middleware') || description.includes('auth')) {
|
|
75
|
+
confidence = 0.3;
|
|
76
|
+
}
|
|
77
|
+
if (description.includes('API') || description.includes('endpoint')) {
|
|
78
|
+
confidence = 0.3;
|
|
79
|
+
}
|
|
80
|
+
if (description.includes('database') || description.includes('schema')) {
|
|
81
|
+
confidence = 0.3;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
files: matchedFiles,
|
|
86
|
+
confidence: Math.min(1, confidence),
|
|
87
|
+
intent: description,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Extract patterns from description
|
|
92
|
+
*/
|
|
93
|
+
extractPatterns(description) {
|
|
94
|
+
const modules = [];
|
|
95
|
+
const features = [];
|
|
96
|
+
const actions = [];
|
|
97
|
+
// Extract module names (usually after "module", "service", "in")
|
|
98
|
+
const modulePattern = /(?:module|service|in|for)\s+([a-zA-Z_]+)/gi;
|
|
99
|
+
let match;
|
|
100
|
+
while ((match = modulePattern.exec(description)) !== null) {
|
|
101
|
+
modules.push(match[1]);
|
|
102
|
+
}
|
|
103
|
+
// Extract feature names (usually after "add", "implement", "create")
|
|
104
|
+
const featurePattern = /(?:add|implement|create|build)\s+([a-zA-Z_\s]+)(?:\s+feature|\s+to|$)/gi;
|
|
105
|
+
while ((match = featurePattern.exec(description)) !== null) {
|
|
106
|
+
features.push(match[1].trim());
|
|
107
|
+
}
|
|
108
|
+
// Common action verbs
|
|
109
|
+
const actionKeywords = [
|
|
110
|
+
'refactor', 'fix', 'optimize', 'add', 'remove', 'update', 'implement', 'patch',
|
|
111
|
+
];
|
|
112
|
+
for (const action of actionKeywords) {
|
|
113
|
+
if (description.toLowerCase().includes(action)) {
|
|
114
|
+
actions.push(action);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return { modules, features, actions };
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Git status parsing — uses only --name-only, no --porcelain conflict
|
|
121
|
+
*/
|
|
122
|
+
getGitStatus(flag) {
|
|
123
|
+
try {
|
|
124
|
+
const flagStr = flag ? `${flag} ` : '';
|
|
125
|
+
const output = execSync(`git diff ${flagStr}--name-only --diff-filter=ACMRUXB`, { cwd: this.projectRoot, encoding: 'utf-8' });
|
|
126
|
+
return output.split('\n').filter(f => f.length > 0);
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
return [];
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Suggest related files based on the change description
|
|
134
|
+
*/
|
|
135
|
+
suggestRelatedFiles(changedFiles, allFiles, maxSuggestions = 5) {
|
|
136
|
+
const suggestions = [];
|
|
137
|
+
const changed = new Set(changedFiles);
|
|
138
|
+
for (const file of allFiles) {
|
|
139
|
+
if (changed.has(file))
|
|
140
|
+
continue;
|
|
141
|
+
let score = 0;
|
|
142
|
+
const changedDir = changedFiles[0]?.split('/').slice(0, -1).join('/');
|
|
143
|
+
const fileDir = file.split('/').slice(0, -1).join('/');
|
|
144
|
+
if (changedDir && fileDir === changedDir)
|
|
145
|
+
score += 3;
|
|
146
|
+
for (const c of changedFiles) {
|
|
147
|
+
const similarity = this.stringSimilarity(c, file);
|
|
148
|
+
score += similarity * 2;
|
|
149
|
+
}
|
|
150
|
+
if (file.includes('test') || file.includes('spec'))
|
|
151
|
+
score += 2;
|
|
152
|
+
if (file.includes('types') || file.includes('interface'))
|
|
153
|
+
score += 1;
|
|
154
|
+
if (score > 0) {
|
|
155
|
+
suggestions.push([file, score]);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return suggestions
|
|
159
|
+
.sort((a, b) => b[1] - a[1])
|
|
160
|
+
.slice(0, maxSuggestions)
|
|
161
|
+
.map(([file]) => file);
|
|
162
|
+
}
|
|
163
|
+
stringSimilarity(a, b) {
|
|
164
|
+
const longer = a.length > b.length ? a : b;
|
|
165
|
+
const shorter = a.length > b.length ? b : a;
|
|
166
|
+
if (longer.length === 0)
|
|
167
|
+
return 1;
|
|
168
|
+
const editDistance = this.levenshteinDistance(longer, shorter);
|
|
169
|
+
return (longer.length - editDistance) / longer.length;
|
|
170
|
+
}
|
|
171
|
+
levenshteinDistance(s1, s2) {
|
|
172
|
+
const distances = [];
|
|
173
|
+
for (let i = 0; i <= s1.length; i++)
|
|
174
|
+
distances[i] = [i];
|
|
175
|
+
for (let j = 0; j <= s2.length; j++)
|
|
176
|
+
distances[0][j] = j;
|
|
177
|
+
for (let i = 1; i <= s1.length; i++) {
|
|
178
|
+
for (let j = 1; j <= s2.length; j++) {
|
|
179
|
+
if (s1[i - 1] === s2[j - 1]) {
|
|
180
|
+
distances[i][j] = distances[i - 1][j - 1];
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
distances[i][j] = Math.min(distances[i - 1][j] + 1, distances[i][j - 1] + 1, distances[i - 1][j - 1] + 1);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return distances[s1.length][s2.length];
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=change-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"change-detector.js","sourceRoot":"","sources":["../../src/utils/change-detector.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAezC,MAAM,OAAO,cAAc;IACzB,YAAoB,WAAmB;QAAnB,gBAAW,GAAX,WAAW,CAAQ;IAAG,CAAC;IAE3C;;OAEG;IACH,eAAe;QACb,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;YAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;YACvC,MAAM,UAAU,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,MAAM,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;YAE1D,OAAO;gBACL,KAAK,EAAE,UAAU;gBACjB,WAAW,EAAE,MAAM;gBACnB,QAAQ;gBACR,UAAU,EAAE,GAAG;aAChB,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;gBACL,KAAK,EAAE,EAAE;gBACT,WAAW,EAAE,EAAE;gBACf,QAAQ,EAAE,EAAE;gBACZ,UAAU,EAAE,CAAC;aACd,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;OAEG;IACH,gBAAgB,CAAC,WAAmB,EAAE,cAAwB;QAC5D,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;QACnD,MAAM,YAAY,GAAa,EAAE,CAAC;QAClC,IAAI,UAAU,GAAG,CAAC,CAAC;QAEnB,iCAAiC;QACjC,KAAK,MAAM,OAAO,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;YACvC,KAAK,MAAM,IAAI,IAAI,cAAc,EAAE,CAAC;gBAClC,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;oBACvD,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBACxB,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;gBACzC,CAAC;YACH,CAAC;QACH,CAAC;QAED,kCAAkC;QAClC,KAAK,MAAM,IAAI,IAAI,cAAc,EAAE,CAAC;YAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC;YAC/C,IAAI,WAAW,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;gBAC/D,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;oBACjC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBACxB,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;gBACzC,CAAC;YACH,CAAC;QACH,CAAC;QAED,0CAA0C;QAC1C,KAAK,MAAM,OAAO,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;YACxC,KAAK,MAAM,IAAI,IAAI,cAAc,EAAE,CAAC;gBAClC,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;oBACvD,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;wBACjC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;wBACxB,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;oBACzC,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,kDAAkD;QAClD,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9B,IAAI,WAAW,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBACvE,UAAU,GAAG,GAAG,CAAC;YACnB,CAAC;YACD,IAAI,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;gBACpE,UAAU,GAAG,GAAG,CAAC;YACnB,CAAC;YACD,IAAI,WAAW,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACvE,UAAU,GAAG,GAAG,CAAC;YACnB,CAAC;QACH,CAAC;QAED,OAAO;YACL,KAAK,EAAE,YAAY;YACnB,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC;YACnC,MAAM,EAAE,WAAW;SACpB,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,eAAe,CAAC,WAAmB;QAKzC,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAa,EAAE,CAAC;QAE7B,iEAAiE;QACjE,MAAM,aAAa,GAAG,4CAA4C,CAAC;QACnE,IAAI,KAAK,CAAC;QACV,OAAO,CAAC,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YAC1D,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACzB,CAAC;QAED,qEAAqE;QACrE,MAAM,cAAc,GAAG,yEAAyE,CAAC;QACjG,OAAO,CAAC,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YAC3D,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACjC,CAAC;QAED,sBAAsB;QACtB,MAAM,cAAc,GAAG;YACrB,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,OAAO;SAC/E,CAAC;QACF,KAAK,MAAM,MAAM,IAAI,cAAc,EAAE,CAAC;YACpC,IAAI,WAAW,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC/C,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;IACxC,CAAC;IAED;;OAEG;IACK,YAAY,CAAC,IAAY;QAC/B,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YACvC,MAAM,MAAM,GAAG,QAAQ,CACrB,YAAY,OAAO,mCAAmC,EACtD,EAAE,GAAG,EAAE,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,CAC7C,CAAC;YACF,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACtD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAED;;OAEG;IACH,mBAAmB,CACjB,YAAsB,EACtB,QAAkB,EAClB,iBAAyB,CAAC;QAE1B,MAAM,WAAW,GAA4B,EAAE,CAAC;QAChD,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC;QAEtC,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;YAC5B,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,SAAS;YAEhC,IAAI,KAAK,GAAG,CAAC,CAAC;YAEd,MAAM,UAAU,GAAG,YAAY,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACtE,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACvD,IAAI,UAAU,IAAI,OAAO,KAAK,UAAU;gBAAE,KAAK,IAAI,CAAC,CAAC;YAErD,KAAK,MAAM,CAAC,IAAI,YAAY,EAAE,CAAC;gBAC7B,MAAM,UAAU,GAAG,IAAI,CAAC,gBAAgB,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;gBAClD,KAAK,IAAI,UAAU,GAAG,CAAC,CAAC;YAC1B,CAAC;YAED,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;gBAAE,KAAK,IAAI,CAAC,CAAC;YAC/D,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC;gBAAE,KAAK,IAAI,CAAC,CAAC;YAErE,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;gBACd,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;YAClC,CAAC;QACH,CAAC;QAED,OAAO,WAAW;aACf,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;aAC3B,KAAK,CAAC,CAAC,EAAE,cAAc,CAAC;aACxB,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IAEO,gBAAgB,CAAC,CAAS,EAAE,CAAS;QAC3C,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3C,MAAM,OAAO,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,CAAC,CAAC;QAClC,MAAM,YAAY,GAAG,IAAI,CAAC,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC/D,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,YAAY,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC;IACxD,CAAC;IAEO,mBAAmB,CAAC,EAAU,EAAE,EAAU;QAChD,MAAM,SAAS,GAAe,EAAE,CAAC;QACjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE;YAAE,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACxD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE;YAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACzD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACpC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;oBAC5B,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBAC5C,CAAC;qBAAM,CAAC;oBACN,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CACxB,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EACvB,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EACvB,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAC5B,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QACD,OAAO,SAAS,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;IACzC,CAAC;CACF"}
|