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.
Files changed (238) hide show
  1. package/README.md +221 -0
  2. package/dist/auth/audit-usage.d.ts +30 -0
  3. package/dist/auth/audit-usage.d.ts.map +1 -0
  4. package/dist/auth/audit-usage.js +104 -0
  5. package/dist/auth/audit-usage.js.map +1 -0
  6. package/dist/auth/auth-session.d.ts +17 -0
  7. package/dist/auth/auth-session.d.ts.map +1 -0
  8. package/dist/auth/auth-session.js +102 -0
  9. package/dist/auth/auth-session.js.map +1 -0
  10. package/dist/auth/auth-store.d.ts +17 -0
  11. package/dist/auth/auth-store.d.ts.map +1 -0
  12. package/dist/auth/auth-store.js +44 -0
  13. package/dist/auth/auth-store.js.map +1 -0
  14. package/dist/auth/entitlements.d.ts +14 -0
  15. package/dist/auth/entitlements.d.ts.map +1 -0
  16. package/dist/auth/entitlements.js +62 -0
  17. package/dist/auth/entitlements.js.map +1 -0
  18. package/dist/auth/open-browser.d.ts +2 -0
  19. package/dist/auth/open-browser.d.ts.map +1 -0
  20. package/dist/auth/open-browser.js +20 -0
  21. package/dist/auth/open-browser.js.map +1 -0
  22. package/dist/auth/plans.d.ts +10 -0
  23. package/dist/auth/plans.d.ts.map +1 -0
  24. package/dist/auth/plans.js +37 -0
  25. package/dist/auth/plans.js.map +1 -0
  26. package/dist/auth/plans.test.d.ts +2 -0
  27. package/dist/auth/plans.test.d.ts.map +1 -0
  28. package/dist/auth/plans.test.js +23 -0
  29. package/dist/auth/plans.test.js.map +1 -0
  30. package/dist/cg-directory.d.ts +37 -0
  31. package/dist/cg-directory.d.ts.map +1 -0
  32. package/dist/cg-directory.js +129 -0
  33. package/dist/cg-directory.js.map +1 -0
  34. package/dist/check/check-runner.d.ts +3 -0
  35. package/dist/check/check-runner.d.ts.map +1 -0
  36. package/dist/check/check-runner.js +48 -0
  37. package/dist/check/check-runner.js.map +1 -0
  38. package/dist/check/compiler-service.d.ts +6 -0
  39. package/dist/check/compiler-service.d.ts.map +1 -0
  40. package/dist/check/compiler-service.js +69 -0
  41. package/dist/check/compiler-service.js.map +1 -0
  42. package/dist/check/parsers/cargo.d.ts +3 -0
  43. package/dist/check/parsers/cargo.d.ts.map +1 -0
  44. package/dist/check/parsers/cargo.js +34 -0
  45. package/dist/check/parsers/cargo.js.map +1 -0
  46. package/dist/check/parsers/parsers.test.d.ts +2 -0
  47. package/dist/check/parsers/parsers.test.d.ts.map +1 -0
  48. package/dist/check/parsers/parsers.test.js +51 -0
  49. package/dist/check/parsers/parsers.test.js.map +1 -0
  50. package/dist/check/parsers/pyright.d.ts +3 -0
  51. package/dist/check/parsers/pyright.d.ts.map +1 -0
  52. package/dist/check/parsers/pyright.js +27 -0
  53. package/dist/check/parsers/pyright.js.map +1 -0
  54. package/dist/check/parsers/tsc-cli.d.ts +3 -0
  55. package/dist/check/parsers/tsc-cli.d.ts.map +1 -0
  56. package/dist/check/parsers/tsc-cli.js +22 -0
  57. package/dist/check/parsers/tsc-cli.js.map +1 -0
  58. package/dist/check/project-tooling.d.ts +18 -0
  59. package/dist/check/project-tooling.d.ts.map +1 -0
  60. package/dist/check/project-tooling.js +105 -0
  61. package/dist/check/project-tooling.js.map +1 -0
  62. package/dist/check/run-command.d.ts +8 -0
  63. package/dist/check/run-command.d.ts.map +1 -0
  64. package/dist/check/run-command.js +50 -0
  65. package/dist/check/run-command.js.map +1 -0
  66. package/dist/check/scope.d.ts +11 -0
  67. package/dist/check/scope.d.ts.map +1 -0
  68. package/dist/check/scope.js +46 -0
  69. package/dist/check/scope.js.map +1 -0
  70. package/dist/check/scope.test.d.ts +2 -0
  71. package/dist/check/scope.test.d.ts.map +1 -0
  72. package/dist/check/scope.test.js +15 -0
  73. package/dist/check/scope.test.js.map +1 -0
  74. package/dist/check/strict-mode.d.ts +5 -0
  75. package/dist/check/strict-mode.d.ts.map +1 -0
  76. package/dist/check/strict-mode.js +32 -0
  77. package/dist/check/strict-mode.js.map +1 -0
  78. package/dist/check/strict-mode.test.d.ts +2 -0
  79. package/dist/check/strict-mode.test.d.ts.map +1 -0
  80. package/dist/check/strict-mode.test.js +53 -0
  81. package/dist/check/strict-mode.test.js.map +1 -0
  82. package/dist/check/structural-checks.d.ts +3 -0
  83. package/dist/check/structural-checks.d.ts.map +1 -0
  84. package/dist/check/structural-checks.js +111 -0
  85. package/dist/check/structural-checks.js.map +1 -0
  86. package/dist/check/types.d.ts +40 -0
  87. package/dist/check/types.d.ts.map +1 -0
  88. package/dist/check/types.js +2 -0
  89. package/dist/check/types.js.map +1 -0
  90. package/dist/check/verifiers/python.d.ts +7 -0
  91. package/dist/check/verifiers/python.d.ts.map +1 -0
  92. package/dist/check/verifiers/python.js +43 -0
  93. package/dist/check/verifiers/python.js.map +1 -0
  94. package/dist/check/verifiers/rust.d.ts +7 -0
  95. package/dist/check/verifiers/rust.d.ts.map +1 -0
  96. package/dist/check/verifiers/rust.js +39 -0
  97. package/dist/check/verifiers/rust.js.map +1 -0
  98. package/dist/check/verifiers/typescript.d.ts +7 -0
  99. package/dist/check/verifiers/typescript.d.ts.map +1 -0
  100. package/dist/check/verifiers/typescript.js +108 -0
  101. package/dist/check/verifiers/typescript.js.map +1 -0
  102. package/dist/commands/auth.d.ts +4 -0
  103. package/dist/commands/auth.d.ts.map +1 -0
  104. package/dist/commands/auth.js +51 -0
  105. package/dist/commands/auth.js.map +1 -0
  106. package/dist/commands/check.d.ts +9 -0
  107. package/dist/commands/check.d.ts.map +1 -0
  108. package/dist/commands/check.js +145 -0
  109. package/dist/commands/check.js.map +1 -0
  110. package/dist/commands/doctor.d.ts +2 -0
  111. package/dist/commands/doctor.d.ts.map +1 -0
  112. package/dist/commands/doctor.js +76 -0
  113. package/dist/commands/doctor.js.map +1 -0
  114. package/dist/commands/init-hooks.d.ts +15 -0
  115. package/dist/commands/init-hooks.d.ts.map +1 -0
  116. package/dist/commands/init-hooks.js +102 -0
  117. package/dist/commands/init-hooks.js.map +1 -0
  118. package/dist/commands/input.d.ts +2 -0
  119. package/dist/commands/input.d.ts.map +1 -0
  120. package/dist/commands/input.js +139 -0
  121. package/dist/commands/input.js.map +1 -0
  122. package/dist/commands/prompt.d.ts +2 -0
  123. package/dist/commands/prompt.d.ts.map +1 -0
  124. package/dist/commands/prompt.js +70 -0
  125. package/dist/commands/prompt.js.map +1 -0
  126. package/dist/commands/scan.d.ts +5 -0
  127. package/dist/commands/scan.d.ts.map +1 -0
  128. package/dist/commands/scan.js +163 -0
  129. package/dist/commands/scan.js.map +1 -0
  130. package/dist/commands/watch.d.ts +11 -0
  131. package/dist/commands/watch.d.ts.map +1 -0
  132. package/dist/commands/watch.js +74 -0
  133. package/dist/commands/watch.js.map +1 -0
  134. package/dist/config/env.d.ts +5 -0
  135. package/dist/config/env.d.ts.map +1 -0
  136. package/dist/config/env.js +60 -0
  137. package/dist/config/env.js.map +1 -0
  138. package/dist/graph.d.ts +34 -0
  139. package/dist/graph.d.ts.map +1 -0
  140. package/dist/graph.js +123 -0
  141. package/dist/graph.js.map +1 -0
  142. package/dist/index.d.ts +3 -0
  143. package/dist/index.d.ts.map +1 -0
  144. package/dist/index.js +176 -0
  145. package/dist/index.js.map +1 -0
  146. package/dist/memory/pattern-analyzer.d.ts +17 -0
  147. package/dist/memory/pattern-analyzer.d.ts.map +1 -0
  148. package/dist/memory/pattern-analyzer.js +56 -0
  149. package/dist/memory/pattern-analyzer.js.map +1 -0
  150. package/dist/memory/repo-memory.d.ts +14 -0
  151. package/dist/memory/repo-memory.d.ts.map +1 -0
  152. package/dist/memory/repo-memory.js +71 -0
  153. package/dist/memory/repo-memory.js.map +1 -0
  154. package/dist/memory/types.d.ts +32 -0
  155. package/dist/memory/types.d.ts.map +1 -0
  156. package/dist/memory/types.js +2 -0
  157. package/dist/memory/types.js.map +1 -0
  158. package/dist/prompt/llm-client.d.ts +8 -0
  159. package/dist/prompt/llm-client.d.ts.map +1 -0
  160. package/dist/prompt/llm-client.js +96 -0
  161. package/dist/prompt/llm-client.js.map +1 -0
  162. package/dist/prompt/subgraph.d.ts +26 -0
  163. package/dist/prompt/subgraph.d.ts.map +1 -0
  164. package/dist/prompt/subgraph.js +96 -0
  165. package/dist/prompt/subgraph.js.map +1 -0
  166. package/dist/scanner.d.ts +13 -0
  167. package/dist/scanner.d.ts.map +1 -0
  168. package/dist/scanner.js +92 -0
  169. package/dist/scanner.js.map +1 -0
  170. package/dist/team/audit.d.ts +4 -0
  171. package/dist/team/audit.d.ts.map +1 -0
  172. package/dist/team/audit.js +16 -0
  173. package/dist/team/audit.js.map +1 -0
  174. package/dist/team/cloud-client.d.ts +7 -0
  175. package/dist/team/cloud-client.d.ts.map +1 -0
  176. package/dist/team/cloud-client.js +106 -0
  177. package/dist/team/cloud-client.js.map +1 -0
  178. package/dist/team/dev-store.d.ts +9 -0
  179. package/dist/team/dev-store.d.ts.map +1 -0
  180. package/dist/team/dev-store.js +69 -0
  181. package/dist/team/dev-store.js.map +1 -0
  182. package/dist/team/graph-sync.d.ts +10 -0
  183. package/dist/team/graph-sync.d.ts.map +1 -0
  184. package/dist/team/graph-sync.js +78 -0
  185. package/dist/team/graph-sync.js.map +1 -0
  186. package/dist/team/policy-cache.d.ts +7 -0
  187. package/dist/team/policy-cache.d.ts.map +1 -0
  188. package/dist/team/policy-cache.js +31 -0
  189. package/dist/team/policy-cache.js.map +1 -0
  190. package/dist/team/policy-engine.d.ts +3 -0
  191. package/dist/team/policy-engine.d.ts.map +1 -0
  192. package/dist/team/policy-engine.js +35 -0
  193. package/dist/team/policy-engine.js.map +1 -0
  194. package/dist/team/policy-engine.test.d.ts +2 -0
  195. package/dist/team/policy-engine.test.d.ts.map +1 -0
  196. package/dist/team/policy-engine.test.js +29 -0
  197. package/dist/team/policy-engine.test.js.map +1 -0
  198. package/dist/team/repo-identity.d.ts +7 -0
  199. package/dist/team/repo-identity.d.ts.map +1 -0
  200. package/dist/team/repo-identity.js +41 -0
  201. package/dist/team/repo-identity.js.map +1 -0
  202. package/dist/team/types.d.ts +53 -0
  203. package/dist/team/types.d.ts.map +1 -0
  204. package/dist/team/types.js +2 -0
  205. package/dist/team/types.js.map +1 -0
  206. package/dist/toolchain/probe.d.ts +9 -0
  207. package/dist/toolchain/probe.d.ts.map +1 -0
  208. package/dist/toolchain/probe.js +123 -0
  209. package/dist/toolchain/probe.js.map +1 -0
  210. package/dist/toolchain/project-languages.d.ts +4 -0
  211. package/dist/toolchain/project-languages.d.ts.map +1 -0
  212. package/dist/toolchain/project-languages.js +41 -0
  213. package/dist/toolchain/project-languages.js.map +1 -0
  214. package/dist/toolchain/types.d.ts +32 -0
  215. package/dist/toolchain/types.d.ts.map +1 -0
  216. package/dist/toolchain/types.js +2 -0
  217. package/dist/toolchain/types.js.map +1 -0
  218. package/dist/utils/blast-radius-analyzer.d.ts +95 -0
  219. package/dist/utils/blast-radius-analyzer.d.ts.map +1 -0
  220. package/dist/utils/blast-radius-analyzer.js +277 -0
  221. package/dist/utils/blast-radius-analyzer.js.map +1 -0
  222. package/dist/utils/change-detector.d.ts +43 -0
  223. package/dist/utils/change-detector.d.ts.map +1 -0
  224. package/dist/utils/change-detector.js +190 -0
  225. package/dist/utils/change-detector.js.map +1 -0
  226. package/dist/utils/cli-formatter.d.ts +80 -0
  227. package/dist/utils/cli-formatter.d.ts.map +1 -0
  228. package/dist/utils/cli-formatter.js +205 -0
  229. package/dist/utils/cli-formatter.js.map +1 -0
  230. package/dist/utils/git-hook-manager.d.ts +81 -0
  231. package/dist/utils/git-hook-manager.d.ts.map +1 -0
  232. package/dist/utils/git-hook-manager.js +243 -0
  233. package/dist/utils/git-hook-manager.js.map +1 -0
  234. package/dist/utils/project-watcher.d.ts +91 -0
  235. package/dist/utils/project-watcher.d.ts.map +1 -0
  236. package/dist/utils/project-watcher.js +215 -0
  237. package/dist/utils/project-watcher.js.map +1 -0
  238. 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":"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"}
@@ -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":"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"}