@yasserkhanorg/e2e-agents 0.5.16 → 0.7.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 (113) hide show
  1. package/dist/agent/pipeline.d.ts +1 -1
  2. package/dist/agent/pipeline.d.ts.map +1 -1
  3. package/dist/agent/plan.d.ts +2 -13
  4. package/dist/agent/plan.d.ts.map +1 -1
  5. package/dist/agent/plan.js +0 -365
  6. package/dist/agent/types.d.ts +42 -0
  7. package/dist/agent/types.d.ts.map +1 -0
  8. package/dist/agent/types.js +4 -0
  9. package/dist/api.d.ts +14 -14
  10. package/dist/api.d.ts.map +1 -1
  11. package/dist/api.js +67 -59
  12. package/dist/cli.js +86 -176
  13. package/dist/engine/ai_enrichment.d.ts +43 -0
  14. package/dist/engine/ai_enrichment.d.ts.map +1 -0
  15. package/dist/engine/ai_enrichment.js +235 -0
  16. package/dist/engine/diff_loader.d.ts +11 -0
  17. package/dist/engine/diff_loader.d.ts.map +1 -0
  18. package/dist/engine/diff_loader.js +74 -0
  19. package/dist/engine/impact_engine.d.ts +36 -0
  20. package/dist/engine/impact_engine.d.ts.map +1 -0
  21. package/dist/engine/impact_engine.js +196 -0
  22. package/dist/engine/plan_builder.d.ts +10 -0
  23. package/dist/engine/plan_builder.d.ts.map +1 -0
  24. package/dist/engine/plan_builder.js +374 -0
  25. package/dist/esm/agent/plan.js +1 -360
  26. package/dist/esm/agent/types.js +3 -0
  27. package/dist/esm/api.js +62 -54
  28. package/dist/esm/cli.js +87 -177
  29. package/dist/esm/engine/ai_enrichment.js +232 -0
  30. package/dist/esm/engine/diff_loader.js +70 -0
  31. package/dist/esm/engine/impact_engine.js +191 -0
  32. package/dist/esm/engine/plan_builder.js +368 -0
  33. package/dist/esm/index.js +6 -3
  34. package/dist/esm/knowledge/route_families.js +59 -1
  35. package/dist/index.d.ts +9 -4
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +14 -5
  38. package/dist/knowledge/route_families.d.ts +19 -0
  39. package/dist/knowledge/route_families.d.ts.map +1 -1
  40. package/dist/knowledge/route_families.js +62 -1
  41. package/package.json +1 -1
  42. package/dist/agent/ai_flow_analysis.d.ts +0 -13
  43. package/dist/agent/ai_flow_analysis.d.ts.map +0 -1
  44. package/dist/agent/ai_flow_analysis.js +0 -334
  45. package/dist/agent/ai_mapping.d.ts +0 -14
  46. package/dist/agent/ai_mapping.d.ts.map +0 -1
  47. package/dist/agent/ai_mapping.js +0 -560
  48. package/dist/agent/analysis.d.ts +0 -64
  49. package/dist/agent/analysis.d.ts.map +0 -1
  50. package/dist/agent/analysis.js +0 -292
  51. package/dist/agent/blast_radius.d.ts +0 -4
  52. package/dist/agent/blast_radius.d.ts.map +0 -1
  53. package/dist/agent/blast_radius.js +0 -37
  54. package/dist/agent/dependency_graph.d.ts +0 -14
  55. package/dist/agent/dependency_graph.d.ts.map +0 -1
  56. package/dist/agent/dependency_graph.js +0 -227
  57. package/dist/agent/flags.d.ts +0 -23
  58. package/dist/agent/flags.d.ts.map +0 -1
  59. package/dist/agent/flags.js +0 -171
  60. package/dist/agent/flow_catalog.d.ts +0 -25
  61. package/dist/agent/flow_catalog.d.ts.map +0 -1
  62. package/dist/agent/flow_catalog.js +0 -115
  63. package/dist/agent/flow_mapping.d.ts +0 -10
  64. package/dist/agent/flow_mapping.d.ts.map +0 -1
  65. package/dist/agent/flow_mapping.js +0 -84
  66. package/dist/agent/framework.d.ts +0 -13
  67. package/dist/agent/framework.d.ts.map +0 -1
  68. package/dist/agent/framework.js +0 -149
  69. package/dist/agent/gap_suggestions.d.ts +0 -14
  70. package/dist/agent/gap_suggestions.d.ts.map +0 -1
  71. package/dist/agent/gap_suggestions.js +0 -101
  72. package/dist/agent/generator.d.ts +0 -10
  73. package/dist/agent/generator.d.ts.map +0 -1
  74. package/dist/agent/generator.js +0 -115
  75. package/dist/agent/operational_insights.d.ts +0 -41
  76. package/dist/agent/operational_insights.d.ts.map +0 -1
  77. package/dist/agent/operational_insights.js +0 -127
  78. package/dist/agent/report.d.ts +0 -97
  79. package/dist/agent/report.d.ts.map +0 -1
  80. package/dist/agent/report.js +0 -159
  81. package/dist/agent/runner.d.ts +0 -7
  82. package/dist/agent/runner.d.ts.map +0 -1
  83. package/dist/agent/runner.js +0 -898
  84. package/dist/agent/selectors.d.ts +0 -10
  85. package/dist/agent/selectors.d.ts.map +0 -1
  86. package/dist/agent/selectors.js +0 -75
  87. package/dist/agent/subsystem_risk.d.ts +0 -23
  88. package/dist/agent/subsystem_risk.d.ts.map +0 -1
  89. package/dist/agent/subsystem_risk.js +0 -207
  90. package/dist/agent/tests.d.ts +0 -19
  91. package/dist/agent/tests.d.ts.map +0 -1
  92. package/dist/agent/tests.js +0 -116
  93. package/dist/agent/traceability.d.ts +0 -22
  94. package/dist/agent/traceability.d.ts.map +0 -1
  95. package/dist/agent/traceability.js +0 -183
  96. package/dist/esm/agent/ai_flow_analysis.js +0 -331
  97. package/dist/esm/agent/ai_mapping.js +0 -557
  98. package/dist/esm/agent/analysis.js +0 -287
  99. package/dist/esm/agent/blast_radius.js +0 -34
  100. package/dist/esm/agent/dependency_graph.js +0 -224
  101. package/dist/esm/agent/flags.js +0 -160
  102. package/dist/esm/agent/flow_catalog.js +0 -112
  103. package/dist/esm/agent/flow_mapping.js +0 -81
  104. package/dist/esm/agent/framework.js +0 -145
  105. package/dist/esm/agent/gap_suggestions.js +0 -98
  106. package/dist/esm/agent/generator.js +0 -112
  107. package/dist/esm/agent/operational_insights.js +0 -124
  108. package/dist/esm/agent/report.js +0 -156
  109. package/dist/esm/agent/runner.js +0 -894
  110. package/dist/esm/agent/selectors.js +0 -71
  111. package/dist/esm/agent/subsystem_risk.js +0 -204
  112. package/dist/esm/agent/tests.js +0 -111
  113. package/dist/esm/agent/traceability.js +0 -180
@@ -1,292 +0,0 @@
1
- "use strict";
2
- // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
3
- // See LICENSE.txt for license information.
4
- Object.defineProperty(exports, "__esModule", { value: true });
5
- exports.analyzeFiles = analyzeFiles;
6
- exports.isTestFilePath = isTestFilePath;
7
- exports.scanRepositoryFlows = scanRepositoryFlows;
8
- const fs_1 = require("fs");
9
- const path_1 = require("path");
10
- const glob_1 = require("glob");
11
- const flags_js_1 = require("./flags.js");
12
- const utils_js_1 = require("./utils.js");
13
- const subsystem_risk_js_1 = require("./subsystem_risk.js");
14
- const TEST_PATH_PATTERN = /(^|\/)__tests__(\/|$)|(^|\/)tests?(\/|$)|\.(spec|test)\.[a-z0-9]+$/i;
15
- const SCREEN_DIRS = new Set(['pages', 'screens', 'views', 'routes']);
16
- const FEATURE_DIRS = new Set(['features', 'modules', 'flows']);
17
- const COMPONENT_DIRS = new Set(['components', 'widgets', 'ui']);
18
- const STATE_DIRS = new Set(['state', 'store', 'stores', 'reducers', 'actions', 'context', 'hooks']);
19
- const STYLE_EXTS = new Set(['css', 'scss', 'sass', 'less', 'styl']);
20
- const UI_EXTS = new Set(['tsx', 'jsx']);
21
- const CODE_EXTS = new Set(['ts', 'js', 'tsx', 'jsx']);
22
- const INTERACTION_PATTERN = /(onClick|onSubmit|onChange|type=['"]submit['"]|role=['"]button['"]|aria-label=)/;
23
- const PRIORITY_RANK = {
24
- P0: 0,
25
- P1: 1,
26
- P2: 2,
27
- };
28
- function deriveFlowFromPath(relativePath) {
29
- const segments = (0, utils_js_1.normalizePath)(relativePath).split('/').filter(Boolean);
30
- const baseName = (0, utils_js_1.baseNameWithoutExt)(relativePath);
31
- const base = baseName.toLowerCase() === 'index' && segments.length > 1 ? segments[segments.length - 2] : baseName;
32
- for (let i = 0; i < segments.length; i += 1) {
33
- const segment = segments[i].toLowerCase();
34
- if (SCREEN_DIRS.has(segment)) {
35
- const next = segments[i + 1] ? segments[i + 1] : base;
36
- return { id: (0, utils_js_1.normalizePath)(next), name: (0, utils_js_1.titleCase)(next), kind: 'screen' };
37
- }
38
- if (FEATURE_DIRS.has(segment)) {
39
- const next = segments[i + 1] ? segments[i + 1] : base;
40
- return { id: (0, utils_js_1.normalizePath)(next), name: (0, utils_js_1.titleCase)(next), kind: 'flow' };
41
- }
42
- }
43
- return { id: (0, utils_js_1.normalizePath)(base), name: (0, utils_js_1.titleCase)(base), kind: 'flow' };
44
- }
45
- function extractKeywords(relativePath) {
46
- const segments = (0, utils_js_1.normalizePath)(relativePath).split('/').filter(Boolean);
47
- const base = (0, utils_js_1.baseNameWithoutExt)(relativePath);
48
- const tokens = segments.flatMap((segment) => (0, utils_js_1.tokenize)(segment));
49
- tokens.push(...(0, utils_js_1.tokenize)(base));
50
- return (0, utils_js_1.uniqueTokens)(tokens);
51
- }
52
- function detectInteractions(content) {
53
- if (!content)
54
- return false;
55
- return INTERACTION_PATTERN.test(content);
56
- }
57
- function isScreenPath(relativePath) {
58
- const segments = (0, utils_js_1.normalizePath)(relativePath).split('/').map((segment) => segment.toLowerCase());
59
- if (segments.some((segment) => segment === 'selectors' || segment === 'reducers' || segment === 'actions')) {
60
- return false;
61
- }
62
- return segments.some((segment) => SCREEN_DIRS.has(segment));
63
- }
64
- function isComponentPath(relativePath) {
65
- const segments = (0, utils_js_1.normalizePath)(relativePath).split('/').map((segment) => segment.toLowerCase());
66
- return segments.some((segment) => COMPONENT_DIRS.has(segment));
67
- }
68
- function isStatePath(relativePath) {
69
- const segments = (0, utils_js_1.normalizePath)(relativePath).split('/').map((segment) => segment.toLowerCase());
70
- return segments.some((segment) => STATE_DIRS.has(segment));
71
- }
72
- function scoreFile(file, risk) {
73
- let score = 1;
74
- const reasons = [];
75
- if (file.isScreen) {
76
- score += 3;
77
- reasons.push('Screen-level change');
78
- }
79
- if (file.isComponent) {
80
- score += 2;
81
- reasons.push('Shared component change');
82
- }
83
- if (file.isUI) {
84
- score += 2;
85
- reasons.push('UI logic change');
86
- }
87
- if (file.isState) {
88
- score += 2;
89
- reasons.push('State or data flow change');
90
- }
91
- if (file.isStyle) {
92
- score += 1;
93
- reasons.push('Visual styling change');
94
- }
95
- if (file.hasInteractions) {
96
- score += 2;
97
- reasons.push('Interactive element change');
98
- }
99
- const keywordHit = file.keywords.find((keyword) => risk.criticalKeywords.includes(keyword));
100
- if (keywordHit) {
101
- score += 2;
102
- reasons.push(`Critical keyword: ${keywordHit}`);
103
- }
104
- if (file.subsystemRisk) {
105
- const scoreDelta = file.subsystemRisk.scoreDelta;
106
- if (scoreDelta !== 0) {
107
- score += scoreDelta;
108
- reasons.push(`Subsystem risk adjustment: ${scoreDelta > 0 ? '+' : ''}${scoreDelta}`);
109
- }
110
- reasons.push(...file.subsystemRisk.reasons);
111
- }
112
- return { score, reasons };
113
- }
114
- function mergePriorityFloor(current, candidate) {
115
- if (!candidate) {
116
- return current;
117
- }
118
- if (!current) {
119
- return candidate;
120
- }
121
- return PRIORITY_RANK[candidate] < PRIORITY_RANK[current] ? candidate : current;
122
- }
123
- function analyzeFiles(appRoot, relativePaths, config) {
124
- const files = [];
125
- const defaultAudience = config.audience.defaultRoles;
126
- const defaultFlagState = config.flags.defaultState;
127
- const warnings = [];
128
- const subsystemRisk = (0, subsystem_risk_js_1.loadSubsystemRiskResolver)(config.impact.subsystemRisk);
129
- warnings.push(...subsystemRisk.warnings);
130
- let subsystemRiskMatchedFiles = 0;
131
- let subsystemRiskRuleMatches = 0;
132
- for (const relativePath of relativePaths) {
133
- if (isTestFilePath(relativePath)) {
134
- continue;
135
- }
136
- const fullPath = (0, path_1.join)(appRoot, relativePath);
137
- const exists = (0, fs_1.existsSync)(fullPath);
138
- const extension = (0, utils_js_1.fileExtension)(relativePath);
139
- const content = exists && CODE_EXTS.has(extension) ? (0, utils_js_1.safeReadTextFile)(fullPath) : null;
140
- const { id, name, kind } = deriveFlowFromPath(relativePath);
141
- const audience = (0, flags_js_1.inferAudienceFromPath)(relativePath, config);
142
- const flags = (0, flags_js_1.extractFlagHits)(content, config);
143
- const subsystemRiskMatches = subsystemRisk.matchFile((0, utils_js_1.normalizePath)(relativePath));
144
- let subsystemRiskScoreDelta = 0;
145
- let subsystemRiskPriorityFloor;
146
- const subsystemRiskRules = (0, utils_js_1.uniqueTokens)(subsystemRiskMatches.map((entry) => entry.ruleId));
147
- const subsystemRiskReasons = (0, utils_js_1.uniqueTokens)(subsystemRiskMatches.flatMap((entry) => entry.reasons));
148
- if (subsystemRiskMatches.length > 0) {
149
- subsystemRiskMatchedFiles += 1;
150
- subsystemRiskRuleMatches += subsystemRiskMatches.length;
151
- subsystemRiskScoreDelta = subsystemRiskMatches.reduce((acc, entry) => acc + entry.scoreDelta, 0);
152
- for (const match of subsystemRiskMatches) {
153
- subsystemRiskPriorityFloor = mergePriorityFloor(subsystemRiskPriorityFloor, match.priorityFloor);
154
- }
155
- }
156
- const subsystemKeywords = (0, utils_js_1.uniqueTokens)(subsystemRiskMatches.flatMap((entry) => entry.keywords));
157
- const analysis = {
158
- relativePath: (0, utils_js_1.normalizePath)(relativePath),
159
- extension,
160
- exists,
161
- content,
162
- isUI: UI_EXTS.has(extension),
163
- isScreen: isScreenPath(relativePath),
164
- isComponent: isComponentPath(relativePath),
165
- isState: isStatePath(relativePath),
166
- isStyle: STYLE_EXTS.has(extension),
167
- hasInteractions: detectInteractions(content),
168
- keywords: (0, utils_js_1.uniqueTokens)([...extractKeywords(relativePath), ...subsystemKeywords]),
169
- flowId: id,
170
- flowName: name,
171
- flowKind: kind,
172
- audience,
173
- flags,
174
- subsystemRisk: subsystemRiskMatches.length > 0
175
- ? {
176
- rules: subsystemRiskRules,
177
- scoreDelta: subsystemRiskScoreDelta,
178
- priorityFloor: subsystemRiskPriorityFloor,
179
- reasons: subsystemRiskReasons,
180
- }
181
- : undefined,
182
- };
183
- files.push(analysis);
184
- }
185
- const flowMap = new Map();
186
- for (const file of files) {
187
- const { score, reasons } = scoreFile(file, config.risk);
188
- const existing = flowMap.get(file.flowId);
189
- if (!existing) {
190
- flowMap.set(file.flowId, {
191
- id: file.flowId,
192
- name: file.flowName,
193
- kind: file.flowKind,
194
- score,
195
- priority: 'P2',
196
- reasons: [...reasons],
197
- keywords: [...file.keywords],
198
- files: [file.relativePath],
199
- audience: file.audience,
200
- flags: file.flags,
201
- priorityFloor: file.subsystemRisk?.priorityFloor,
202
- subsystemRiskBoost: file.subsystemRisk?.scoreDelta || 0,
203
- subsystemRiskRules: file.subsystemRisk?.rules || [],
204
- });
205
- }
206
- else {
207
- existing.score += score;
208
- existing.files.push(file.relativePath);
209
- existing.reasons.push(...reasons);
210
- existing.keywords.push(...file.keywords);
211
- existing.audience = (0, flags_js_1.normalizeRoles)([...(existing.audience || []), ...file.audience], defaultAudience);
212
- existing.flags = (0, flags_js_1.mergeFlags)([...(existing.flags || []), ...file.flags], defaultFlagState);
213
- existing.priorityFloor = mergePriorityFloor(existing.priorityFloor, file.subsystemRisk?.priorityFloor);
214
- existing.subsystemRiskBoost = (existing.subsystemRiskBoost || 0) + (file.subsystemRisk?.scoreDelta || 0);
215
- existing.subsystemRiskRules = (0, utils_js_1.uniqueTokens)([...(existing.subsystemRiskRules || []), ...(file.subsystemRisk?.rules || [])]);
216
- }
217
- }
218
- let boostedFlows = 0;
219
- const flows = Array.from(flowMap.values()).map((flow) => {
220
- const uniqueReason = (0, utils_js_1.uniqueTokens)(flow.reasons);
221
- const uniqueKeywords = (0, utils_js_1.uniqueTokens)(flow.keywords);
222
- const computedPriority = flow.score >= config.risk.p0Threshold
223
- ? 'P0'
224
- : flow.score >= config.risk.p1Threshold
225
- ? 'P1'
226
- : 'P2';
227
- const priority = mergePriorityFloor(computedPriority, flow.priorityFloor) || computedPriority;
228
- if ((flow.subsystemRiskBoost || 0) !== 0 || (flow.priorityFloor && flow.priorityFloor !== computedPriority)) {
229
- boostedFlows += 1;
230
- }
231
- return {
232
- ...flow,
233
- reasons: uniqueReason.map((reason) => reason),
234
- keywords: uniqueKeywords,
235
- priority,
236
- };
237
- });
238
- return {
239
- files,
240
- flows,
241
- warnings,
242
- subsystemRisk: {
243
- source: 'map',
244
- enabled: subsystemRisk.info.enabled,
245
- mapPath: subsystemRisk.info.mapPath,
246
- mapFound: subsystemRisk.info.mapFound,
247
- rulesLoaded: subsystemRisk.info.rulesLoaded,
248
- filesMatched: subsystemRiskMatchedFiles,
249
- ruleMatches: subsystemRiskRuleMatches,
250
- boostedFlows,
251
- },
252
- };
253
- }
254
- function isTestFilePath(relativePath) {
255
- return TEST_PATH_PATTERN.test((0, utils_js_1.normalizePath)(relativePath));
256
- }
257
- function scanRepositoryFlows(appRoot, limit = 250, patterns, exclude) {
258
- const defaultPatterns = [
259
- '**/pages/**/*.{tsx,jsx,ts,js}',
260
- '**/screens/**/*.{tsx,jsx,ts,js}',
261
- '**/views/**/*.{tsx,jsx,ts,js}',
262
- '**/routes/**/*.{tsx,jsx,ts,js}',
263
- ];
264
- const useDefaults = !(patterns && patterns.length > 0);
265
- const activePatterns = useDefaults ? defaultPatterns : patterns;
266
- const matches = new Set();
267
- const ignorePatterns = [
268
- '**/node_modules/**',
269
- '**/.git/**',
270
- '**/__tests__/**',
271
- '**/tests/**',
272
- ...(useDefaults ? ['**/selectors/**', '**/reducers/**', '**/actions/**'] : []),
273
- ...(exclude || []),
274
- ];
275
- for (const pattern of activePatterns) {
276
- const files = (0, glob_1.globSync)(pattern, {
277
- cwd: appRoot,
278
- ignore: ignorePatterns,
279
- nodir: true,
280
- });
281
- for (const file of files) {
282
- matches.add((0, utils_js_1.normalizePath)(file));
283
- if (matches.size >= limit) {
284
- break;
285
- }
286
- }
287
- if (matches.size >= limit) {
288
- break;
289
- }
290
- }
291
- return Array.from(matches);
292
- }
@@ -1,4 +0,0 @@
1
- import type { AgentConfig } from './config.js';
2
- import type { FileAnalysis, FlowImpact } from './analysis.js';
3
- export declare function applyBlastRadius(flows: FlowImpact[], files: FileAnalysis[], config: AgentConfig): FlowImpact[];
4
- //# sourceMappingURL=blast_radius.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"blast_radius.d.ts","sourceRoot":"","sources":["../../src/agent/blast_radius.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,WAAW,EAAe,MAAM,aAAa,CAAC;AAC3D,OAAO,KAAK,EAAC,YAAY,EAAE,UAAU,EAAC,MAAM,eAAe,CAAC;AAG5D,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,MAAM,EAAE,WAAW,GAAG,UAAU,EAAE,CAmC9G"}
@@ -1,37 +0,0 @@
1
- "use strict";
2
- // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
3
- // See LICENSE.txt for license information.
4
- Object.defineProperty(exports, "__esModule", { value: true });
5
- exports.applyBlastRadius = applyBlastRadius;
6
- const flags_js_1 = require("./flags.js");
7
- function applyBlastRadius(flows, files, config) {
8
- if (flows.length === 0) {
9
- return flows;
10
- }
11
- const fileMap = new Map();
12
- for (const file of files) {
13
- fileMap.set(file.relativePath, file);
14
- }
15
- return flows.map((flow) => {
16
- const collectedFlags = [...(flow.flags || [])];
17
- const collectedAudience = [...(flow.audience || [])];
18
- for (const filePath of flow.files) {
19
- const file = fileMap.get(filePath);
20
- if (!file) {
21
- continue;
22
- }
23
- collectedFlags.push(...file.flags);
24
- collectedAudience.push(...file.audience);
25
- }
26
- const mergedFlags = (0, flags_js_1.mergeFlags)(collectedFlags, config.flags.defaultState);
27
- const mergedAudience = (0, flags_js_1.normalizeRoles)(collectedAudience, config.audience.defaultRoles);
28
- const blastRadius = (0, flags_js_1.computeBlastRadius)(mergedAudience, mergedFlags, config);
29
- return {
30
- ...flow,
31
- audience: mergedAudience,
32
- flags: mergedFlags,
33
- blastRadius,
34
- score: flow.score + blastRadius.scoreDelta,
35
- };
36
- });
37
- }
@@ -1,14 +0,0 @@
1
- import type { DependencyGraphImpactConfig } from './config.js';
2
- export interface DependencyGraphExpansion {
3
- source: 'static-dependency-graph';
4
- seedFiles: string[];
5
- impactedFiles: string[];
6
- expandedFiles: string[];
7
- analyzedFiles: number;
8
- analyzedEdges: number;
9
- maxDepth: number;
10
- truncated: boolean;
11
- warnings: string[];
12
- }
13
- export declare function expandByDependencyGraph(appRoot: string, changedFiles: string[], cfg: DependencyGraphImpactConfig): DependencyGraphExpansion;
14
- //# sourceMappingURL=dependency_graph.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"dependency_graph.d.ts","sourceRoot":"","sources":["../../src/agent/dependency_graph.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAC,2BAA2B,EAAC,MAAM,aAAa,CAAC;AAG7D,MAAM,WAAW,wBAAwB;IACrC,MAAM,EAAE,yBAAyB,CAAC;IAClC,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACtB;AA6ID,wBAAgB,uBAAuB,CACnC,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EAAE,EACtB,GAAG,EAAE,2BAA2B,GACjC,wBAAwB,CAsH1B"}
@@ -1,227 +0,0 @@
1
- "use strict";
2
- // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
3
- // See LICENSE.txt for license information.
4
- Object.defineProperty(exports, "__esModule", { value: true });
5
- exports.expandByDependencyGraph = expandByDependencyGraph;
6
- const glob_1 = require("glob");
7
- const path_1 = require("path");
8
- const utils_js_1 = require("./utils.js");
9
- const IMPORT_REGEXES = [
10
- /import\s+[\s\S]*?\s+from\s+['"]([^'"]+)['"]/g,
11
- /import\s+['"]([^'"]+)['"]/g,
12
- /export\s+[\s\S]*?\s+from\s+['"]([^'"]+)['"]/g,
13
- /require\(\s*['"]([^'"]+)['"]\s*\)/g,
14
- /import\(\s*['"]([^'"]+)['"]\s*\)/g,
15
- ];
16
- const RESOLVABLE_EXTENSIONS = ['ts', 'tsx', 'js', 'jsx', 'mjs', 'cjs'];
17
- function extractImportSpecifiers(content) {
18
- const imports = [];
19
- for (const regex of IMPORT_REGEXES) {
20
- regex.lastIndex = 0;
21
- let match = regex.exec(content);
22
- while (match) {
23
- const specifier = match[1];
24
- if (specifier) {
25
- imports.push(specifier);
26
- }
27
- match = regex.exec(content);
28
- }
29
- }
30
- return Array.from(new Set(imports));
31
- }
32
- function listCandidateFiles(appRoot, cfg) {
33
- const files = new Set();
34
- for (const pattern of cfg.filePatterns) {
35
- const matches = (0, glob_1.globSync)(pattern, {
36
- cwd: appRoot,
37
- nodir: true,
38
- ignore: cfg.excludePatterns,
39
- });
40
- for (const match of matches) {
41
- files.add((0, utils_js_1.normalizePath)(match));
42
- }
43
- }
44
- return Array.from(files);
45
- }
46
- function resolveWithCandidates(candidateBase, fileSet) {
47
- if (fileSet.has(candidateBase)) {
48
- return candidateBase;
49
- }
50
- for (const ext of RESOLVABLE_EXTENSIONS) {
51
- const withExt = `${candidateBase}.${ext}`;
52
- if (fileSet.has(withExt)) {
53
- return withExt;
54
- }
55
- }
56
- for (const ext of RESOLVABLE_EXTENSIONS) {
57
- const indexPath = `${candidateBase}/index.${ext}`;
58
- if (fileSet.has(indexPath)) {
59
- return indexPath;
60
- }
61
- }
62
- return null;
63
- }
64
- function expandAliasTarget(pattern, target, specifier) {
65
- const normalizedPattern = (0, utils_js_1.normalizePath)(pattern);
66
- const normalizedTarget = (0, utils_js_1.normalizePath)(target);
67
- const normalizedSpecifier = (0, utils_js_1.normalizePath)(specifier);
68
- if (normalizedPattern.endsWith('/*')) {
69
- const prefix = normalizedPattern.slice(0, -2);
70
- if (normalizedSpecifier === prefix || normalizedSpecifier.startsWith(`${prefix}/`)) {
71
- const suffix = normalizedSpecifier === prefix ? '' : normalizedSpecifier.slice(prefix.length + 1);
72
- if (normalizedTarget.endsWith('/*')) {
73
- const targetPrefix = normalizedTarget.slice(0, -2);
74
- return suffix ? (0, utils_js_1.normalizePath)(`${targetPrefix}/${suffix}`) : (0, utils_js_1.normalizePath)(targetPrefix);
75
- }
76
- return (0, utils_js_1.normalizePath)(normalizedTarget);
77
- }
78
- return null;
79
- }
80
- if (normalizedPattern === normalizedSpecifier) {
81
- if (normalizedTarget.endsWith('/*')) {
82
- return (0, utils_js_1.normalizePath)(normalizedTarget.slice(0, -2));
83
- }
84
- return (0, utils_js_1.normalizePath)(normalizedTarget);
85
- }
86
- return null;
87
- }
88
- function resolvePathAliasImport(specifier, fileSet, cfg) {
89
- for (const [pattern, targets] of Object.entries(cfg.pathAliases)) {
90
- for (const target of targets) {
91
- const aliasPath = expandAliasTarget(pattern, target, specifier);
92
- if (!aliasPath) {
93
- continue;
94
- }
95
- const resolved = resolveWithCandidates(aliasPath, fileSet);
96
- if (resolved) {
97
- return resolved;
98
- }
99
- }
100
- }
101
- return null;
102
- }
103
- function resolveImport(fromFile, specifier, fileSet, cfg) {
104
- if (specifier.startsWith('.')) {
105
- const fromDir = (0, path_1.dirname)(fromFile);
106
- const relativeCandidate = (0, utils_js_1.normalizePath)((0, path_1.normalize)((0, path_1.join)(fromDir, specifier)));
107
- return resolveWithCandidates(relativeCandidate, fileSet);
108
- }
109
- const aliasResolved = resolvePathAliasImport(specifier, fileSet, cfg);
110
- if (aliasResolved) {
111
- return aliasResolved;
112
- }
113
- for (const root of cfg.aliasRoots) {
114
- const rootedCandidate = (0, utils_js_1.normalizePath)((0, path_1.normalize)((0, path_1.join)(root, specifier)));
115
- const resolved = resolveWithCandidates(rootedCandidate, fileSet);
116
- if (resolved) {
117
- return resolved;
118
- }
119
- }
120
- const directCandidate = (0, utils_js_1.normalizePath)(specifier);
121
- return resolveWithCandidates(directCandidate, fileSet);
122
- }
123
- function expandByDependencyGraph(appRoot, changedFiles, cfg) {
124
- const warnings = [];
125
- if (!cfg.enabled) {
126
- return {
127
- source: 'static-dependency-graph',
128
- seedFiles: [],
129
- impactedFiles: [],
130
- expandedFiles: [],
131
- analyzedFiles: 0,
132
- analyzedEdges: 0,
133
- maxDepth: 0,
134
- truncated: false,
135
- warnings,
136
- };
137
- }
138
- const candidates = listCandidateFiles(appRoot, cfg);
139
- const fileSet = new Set(candidates);
140
- if (candidates.length === 0) {
141
- warnings.push('Dependency graph found no candidate source files.');
142
- }
143
- const reverse = new Map();
144
- let analyzedEdges = 0;
145
- for (const file of candidates) {
146
- const fullPath = (0, path_1.join)(appRoot, file);
147
- const content = (0, utils_js_1.safeReadTextFile)(fullPath);
148
- if (!content) {
149
- continue;
150
- }
151
- const imports = extractImportSpecifiers(content);
152
- for (const specifier of imports) {
153
- const resolved = resolveImport(file, specifier, fileSet, cfg);
154
- if (!resolved) {
155
- continue;
156
- }
157
- if (!reverse.has(resolved)) {
158
- reverse.set(resolved, new Set());
159
- }
160
- reverse.get(resolved)?.add(file);
161
- analyzedEdges += 1;
162
- }
163
- }
164
- const seeds = Array.from(new Set(changedFiles
165
- .map((file) => (0, utils_js_1.normalizePath)(file))
166
- .filter((file) => fileSet.has(file))));
167
- if (seeds.length === 0) {
168
- warnings.push('No changed files were found in dependency graph candidates.');
169
- return {
170
- source: 'static-dependency-graph',
171
- seedFiles: [],
172
- impactedFiles: [],
173
- expandedFiles: [],
174
- analyzedFiles: candidates.length,
175
- analyzedEdges,
176
- maxDepth: cfg.maxDepth,
177
- truncated: false,
178
- warnings,
179
- };
180
- }
181
- const impacted = new Set(seeds);
182
- const queue = seeds.map((file) => ({ file, depth: 0 }));
183
- let truncated = false;
184
- while (queue.length > 0) {
185
- const next = queue.shift();
186
- if (!next) {
187
- continue;
188
- }
189
- if (next.depth >= cfg.maxDepth) {
190
- continue;
191
- }
192
- const dependents = reverse.get(next.file);
193
- if (!dependents) {
194
- continue;
195
- }
196
- for (const dependent of dependents) {
197
- if (impacted.has(dependent)) {
198
- continue;
199
- }
200
- if (impacted.size - seeds.length >= cfg.maxExpandedFiles) {
201
- truncated = true;
202
- break;
203
- }
204
- impacted.add(dependent);
205
- queue.push({ file: dependent, depth: next.depth + 1 });
206
- }
207
- if (truncated) {
208
- break;
209
- }
210
- }
211
- const impactedFiles = Array.from(impacted);
212
- const expandedFiles = impactedFiles.filter((file) => !seeds.includes(file));
213
- if (truncated) {
214
- warnings.push(`Dependency expansion was truncated at maxExpandedFiles=${cfg.maxExpandedFiles}.`);
215
- }
216
- return {
217
- source: 'static-dependency-graph',
218
- seedFiles: seeds,
219
- impactedFiles,
220
- expandedFiles,
221
- analyzedFiles: candidates.length,
222
- analyzedEdges,
223
- maxDepth: cfg.maxDepth,
224
- truncated,
225
- warnings,
226
- };
227
- }
@@ -1,23 +0,0 @@
1
- import type { AgentConfig, AudienceRole, FlagState } from './config.js';
2
- export type FlagSource = 'featureFlag' | 'configFlag' | 'testGate';
3
- export interface FlagHit {
4
- name: string;
5
- source: FlagSource;
6
- defaultState: FlagState;
7
- }
8
- export interface BlastRadius {
9
- audience: AudienceRole[];
10
- flags: FlagHit[];
11
- summary: string;
12
- scoreDelta: number;
13
- }
14
- export declare function normalizeRole(role: string): AudienceRole | null;
15
- export declare function normalizeRoles(roles: string[], fallback: AudienceRole[]): AudienceRole[];
16
- export declare function normalizeFlagSource(source?: string): FlagSource;
17
- export declare function normalizeFlagState(value: string | undefined, fallback: FlagState): FlagState;
18
- export declare function mergeFlags(flags: FlagHit[], defaultState: FlagState): FlagHit[];
19
- export declare function extractFlagHits(content: string | null, config: AgentConfig): FlagHit[];
20
- export declare function inferAudienceFromPath(relativePath: string, config: AgentConfig): AudienceRole[];
21
- export declare function formatFlags(flags: FlagHit[]): string;
22
- export declare function computeBlastRadius(audience: AudienceRole[], flags: FlagHit[], config: AgentConfig): BlastRadius;
23
- //# sourceMappingURL=flags.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"flags.d.ts","sourceRoot":"","sources":["../../src/agent/flags.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,WAAW,EAAE,YAAY,EAAE,SAAS,EAAC,MAAM,aAAa,CAAC;AAEtE,MAAM,MAAM,UAAU,GAAG,aAAa,GAAG,YAAY,GAAG,UAAU,CAAC;AAEnE,MAAM,WAAW,OAAO;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,CAAC;IACnB,YAAY,EAAE,SAAS,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IACxB,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACtB;AAkCD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAG/D;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,YAAY,EAAE,CAOxF;AAED,wBAAgB,mBAAmB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,UAAU,CAe/D;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,SAAS,GAAG,SAAS,CAS5F;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,YAAY,EAAE,SAAS,GAAG,OAAO,EAAE,CAY/E;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,EAAE,CAiCtF;AAED,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,YAAY,EAAE,CAa/F;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,MAAM,CAKpD;AAED,wBAAgB,kBAAkB,CAC9B,QAAQ,EAAE,YAAY,EAAE,EACxB,KAAK,EAAE,OAAO,EAAE,EAChB,MAAM,EAAE,WAAW,GACpB,WAAW,CAqCb"}