@yasserkhanorg/e2e-agents 0.3.2 → 0.3.4

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 (87) hide show
  1. package/README.md +29 -20
  2. package/dist/agent/config.d.ts +3 -0
  3. package/dist/agent/config.d.ts.map +1 -1
  4. package/dist/agent/config.js +38 -0
  5. package/dist/agent/operational_insights.d.ts +1 -1
  6. package/dist/agent/operational_insights.d.ts.map +1 -1
  7. package/dist/agent/operational_insights.js +2 -1
  8. package/dist/agent/pipeline.d.ts +8 -1
  9. package/dist/agent/pipeline.d.ts.map +1 -1
  10. package/dist/agent/pipeline.js +844 -33
  11. package/dist/agent/plan.d.ts +39 -0
  12. package/dist/agent/plan.d.ts.map +1 -1
  13. package/dist/agent/plan.js +146 -0
  14. package/dist/agent/report.d.ts +16 -0
  15. package/dist/agent/report.d.ts.map +1 -1
  16. package/dist/agent/report.js +12 -0
  17. package/dist/agent/runner.d.ts.map +1 -1
  18. package/dist/agent/runner.js +66 -11
  19. package/dist/agent/tests.d.ts.map +1 -1
  20. package/dist/agent/tests.js +12 -2
  21. package/dist/api.d.ts.map +1 -1
  22. package/dist/api.js +1 -0
  23. package/dist/cli.js +111 -7
  24. package/dist/esm/agent/config.js +38 -0
  25. package/dist/esm/agent/operational_insights.js +2 -1
  26. package/dist/esm/agent/pipeline.js +844 -33
  27. package/dist/esm/agent/plan.js +145 -1
  28. package/dist/esm/agent/report.js +12 -0
  29. package/dist/esm/agent/runner.js +66 -11
  30. package/dist/esm/agent/tests.js +12 -2
  31. package/dist/esm/api.js +2 -1
  32. package/dist/esm/cli.js +112 -8
  33. package/package.json +1 -1
  34. package/schemas/impact.schema.json +37 -0
  35. package/schemas/plan.schema.json +48 -0
  36. package/dist/agent/cache_utils.d.ts +0 -38
  37. package/dist/agent/cache_utils.d.ts.map +0 -1
  38. package/dist/agent/cache_utils.js +0 -67
  39. package/dist/agent/impact-analyzer.d.ts +0 -114
  40. package/dist/agent/impact-analyzer.d.ts.map +0 -1
  41. package/dist/agent/impact-analyzer.js +0 -557
  42. package/dist/agent/index.d.ts +0 -21
  43. package/dist/agent/index.d.ts.map +0 -1
  44. package/dist/agent/index.js +0 -38
  45. package/dist/agent/model-router.d.ts +0 -57
  46. package/dist/agent/model-router.d.ts.map +0 -1
  47. package/dist/agent/model-router.js +0 -154
  48. package/dist/agent/report-generator.d.ts +0 -24
  49. package/dist/agent/report-generator.d.ts.map +0 -1
  50. package/dist/agent/report-generator.js +0 -250
  51. package/dist/agent/spec-bridge.d.ts +0 -101
  52. package/dist/agent/spec-bridge.d.ts.map +0 -1
  53. package/dist/agent/spec-bridge.js +0 -273
  54. package/dist/agent/spec-builder.d.ts +0 -102
  55. package/dist/agent/spec-builder.d.ts.map +0 -1
  56. package/dist/agent/spec-builder.js +0 -273
  57. package/dist/agent/telemetry.d.ts +0 -84
  58. package/dist/agent/telemetry.d.ts.map +0 -1
  59. package/dist/agent/telemetry.js +0 -220
  60. package/dist/agent/validators/selector-validator.d.ts +0 -74
  61. package/dist/agent/validators/selector-validator.d.ts.map +0 -1
  62. package/dist/agent/validators/selector-validator.js +0 -165
  63. package/dist/e2e-test-gen/index.d.ts +0 -51
  64. package/dist/e2e-test-gen/index.d.ts.map +0 -1
  65. package/dist/e2e-test-gen/index.js +0 -57
  66. package/dist/e2e-test-gen/spec_parser.d.ts +0 -142
  67. package/dist/e2e-test-gen/spec_parser.d.ts.map +0 -1
  68. package/dist/e2e-test-gen/spec_parser.js +0 -786
  69. package/dist/e2e-test-gen/types.d.ts +0 -185
  70. package/dist/e2e-test-gen/types.d.ts.map +0 -1
  71. package/dist/e2e-test-gen/types.js +0 -4
  72. package/dist/esm/agent/cache_utils.js +0 -63
  73. package/dist/esm/agent/impact-analyzer.js +0 -548
  74. package/dist/esm/agent/index.js +0 -22
  75. package/dist/esm/agent/model-router.js +0 -150
  76. package/dist/esm/agent/report-generator.js +0 -247
  77. package/dist/esm/agent/spec-bridge.js +0 -267
  78. package/dist/esm/agent/spec-builder.js +0 -267
  79. package/dist/esm/agent/telemetry.js +0 -216
  80. package/dist/esm/agent/validators/selector-validator.js +0 -160
  81. package/dist/esm/e2e-test-gen/index.js +0 -50
  82. package/dist/esm/e2e-test-gen/spec_parser.js +0 -782
  83. package/dist/esm/e2e-test-gen/types.js +0 -3
  84. package/dist/esm/plan-and-test-constants.js +0 -126
  85. package/dist/plan-and-test-constants.d.ts +0 -110
  86. package/dist/plan-and-test-constants.d.ts.map +0 -1
  87. package/dist/plan-and-test-constants.js +0 -132
package/dist/esm/cli.js CHANGED
@@ -7,7 +7,7 @@ import { resolveConfig } from './agent/config.js';
7
7
  import { AnthropicProvider } from './anthropic_provider.js';
8
8
  import { LLMProviderError } from './provider_interface.js';
9
9
  import { runGap, runImpact } from './agent/runner.js';
10
- import { attachDeveloperActions, buildPlanFromImpactReport, renderCiSummaryMarkdown, writeCiSummary, writePlanReport } from './agent/plan.js';
10
+ import { appendPlanMetrics, attachDeveloperActions, buildPlanFromImpactReport, renderCiSummaryMarkdown, writeCiSummary, writePlanReport, } from './agent/plan.js';
11
11
  import { applyOperationalInsights } from './agent/operational_insights.js';
12
12
  import { appendFeedbackAndRecompute } from './agent/feedback.js';
13
13
  import { finalizeGeneratedTests } from './agent/handoff.js';
@@ -59,6 +59,9 @@ function printUsage() {
59
59
  'Usage:',
60
60
  ' e2e-ai-agents impact --path <app-root> [options]',
61
61
  ' e2e-ai-agents gap --path <app-root> [options]',
62
+ ' e2e-ai-agents plan --path <app-root> [options]',
63
+ ' e2e-ai-agents generate --path <app-root> [options]',
64
+ ' e2e-ai-agents heal --path <app-root> --traceability-report <json> [options]',
62
65
  ' e2e-ai-agents suggest --path <app-root> [options]',
63
66
  ' e2e-ai-agents approve-and-generate --path <app-root> [options]',
64
67
  ' e2e-ai-agents auto-heal-pr --path <app-root> [options]',
@@ -84,10 +87,12 @@ function printUsage() {
84
87
  ' --pipeline-base-url Base URL for Playwright runs',
85
88
  ' --pipeline-browser Browser: chrome|chromium|firefox|webkit',
86
89
  ' --pipeline-headless Run in headless mode',
90
+ ' --pipeline-headed Run in headed mode',
87
91
  ' --pipeline-project Playwright project name',
88
92
  ' --pipeline-parallel Enable parallel mode in generator',
89
93
  ' --pipeline-dry-run Do not execute pipeline (report only)',
90
94
  ' --pipeline-mcp Use Playwright MCP server for exploration/healing',
95
+ ' --pipeline-mcp-allow-fallback Allow non-MCP fallback if official MCP setup fails',
91
96
  ' --spec <path> Optional spec PDF for context',
92
97
  ' --since <git-ref> Git ref for impact analysis (default HEAD~1)',
93
98
  ' --time <minutes> Time limit in minutes',
@@ -97,6 +102,8 @@ function printUsage() {
97
102
  ' --policy-safe-merge-confidence <n> Confidence needed for safe-to-merge',
98
103
  ' --policy-force-full-on-warnings <n> Escalate to full at warning count',
99
104
  ' --policy-risky-patterns <globs> Comma-separated risky file globs',
105
+ ' --policy-enforcement-mode <mode> advisory | warn | block',
106
+ ' --policy-block-actions <actions> Comma-separated CI actions to block/warn',
100
107
  ' --ci-comment-path <path> Write CI markdown summary',
101
108
  ' --github-output <path> Write GitHub Actions outputs',
102
109
  ' --fail-on-must-add-tests Exit non-zero on must-add-tests decision',
@@ -130,6 +137,9 @@ function parseArgs(argv) {
130
137
  const command = argv[0];
131
138
  if (command === 'impact'
132
139
  || command === 'gap'
140
+ || command === 'plan'
141
+ || command === 'generate'
142
+ || command === 'heal'
133
143
  || command === 'suggest'
134
144
  || command === 'approve-and-generate'
135
145
  || command === 'auto-heal-pr'
@@ -203,6 +213,10 @@ function parseArgs(argv) {
203
213
  parsed.pipelineMcp = true;
204
214
  continue;
205
215
  }
216
+ if (arg === '--pipeline-mcp-allow-fallback') {
217
+ parsed.pipelineMcpAllowFallback = true;
218
+ continue;
219
+ }
206
220
  if (arg === '--pipeline-scenarios' && next) {
207
221
  const value = Number(next);
208
222
  if (Number.isFinite(value)) {
@@ -233,6 +247,10 @@ function parseArgs(argv) {
233
247
  parsed.pipelineHeadless = true;
234
248
  continue;
235
249
  }
250
+ if (arg === '--pipeline-headed') {
251
+ parsed.pipelineHeadless = false;
252
+ continue;
253
+ }
236
254
  if (arg === '--pipeline-project' && next) {
237
255
  parsed.pipelineProject = next;
238
256
  i += 1;
@@ -309,6 +327,21 @@ function parseArgs(argv) {
309
327
  i += 1;
310
328
  continue;
311
329
  }
330
+ if (arg === '--policy-enforcement-mode' && next) {
331
+ if (next === 'advisory' || next === 'warn' || next === 'block') {
332
+ parsed.policyEnforcementMode = next;
333
+ }
334
+ i += 1;
335
+ continue;
336
+ }
337
+ if (arg === '--policy-block-actions' && next) {
338
+ parsed.policyBlockActions = next
339
+ .split(',')
340
+ .map((value) => value.trim())
341
+ .filter((value) => (value === 'run-now' || value === 'must-add-tests' || value === 'safe-to-merge'));
342
+ i += 1;
343
+ continue;
344
+ }
312
345
  if (arg === '--ci-comment-path' && next) {
313
346
  parsed.ciCommentPath = next;
314
347
  i += 1;
@@ -612,6 +645,7 @@ async function main() {
612
645
  parallel: args.pipelineParallel,
613
646
  dryRun: args.pipelineDryRun,
614
647
  mcp: args.pipelineMcp,
648
+ mcpAllowFallback: args.pipelineMcpAllowFallback,
615
649
  },
616
650
  });
617
651
  if (args.allowFallback) {
@@ -686,17 +720,72 @@ async function main() {
686
720
  }
687
721
  return;
688
722
  }
723
+ if (args.command === 'heal') {
724
+ if (!args.path && !autoConfig) {
725
+ // eslint-disable-next-line no-console
726
+ console.error('Error: --path is required for heal command');
727
+ process.exit(1);
728
+ }
729
+ if (!args.traceabilityReportPath) {
730
+ // eslint-disable-next-line no-console
731
+ console.error('Error: --traceability-report <path> is required for heal command');
732
+ process.exit(1);
733
+ }
734
+ const { config } = resolveConfig(process.cwd(), autoConfig, {
735
+ path: args.path,
736
+ testsRoot: args.testsRoot,
737
+ mode: 'gap',
738
+ framework: args.framework,
739
+ pipeline: {
740
+ enabled: true,
741
+ scenarios: args.pipelineScenarios,
742
+ outputDir: args.pipelineOutput,
743
+ baseUrl: args.pipelineBaseUrl,
744
+ browser: args.pipelineBrowser,
745
+ headless: args.pipelineHeadless,
746
+ project: args.pipelineProject,
747
+ parallel: args.pipelineParallel,
748
+ dryRun: args.pipelineDryRun,
749
+ mcp: args.pipelineMcp,
750
+ mcpAllowFallback: args.pipelineMcpAllowFallback,
751
+ },
752
+ });
753
+ const reportRoot = config.testsRoot || config.path;
754
+ const unstableSpecs = extractPlaywrightUnstableSpecs(args.traceabilityReportPath, [reportRoot, config.path]);
755
+ if (unstableSpecs.length === 0) {
756
+ // eslint-disable-next-line no-console
757
+ console.log('Heal targeted unstable specs: 0');
758
+ return;
759
+ }
760
+ const targetedSummary = runTargetedSpecHeal(reportRoot, unstableSpecs.map((spec) => ({
761
+ specPath: spec.specPath,
762
+ status: spec.status,
763
+ reason: `Playwright report: failingTests=${spec.failingTests}, flakyTests=${spec.flakyTests}`,
764
+ })), {
765
+ ...config.pipeline,
766
+ enabled: true,
767
+ heal: true,
768
+ });
769
+ const healedCount = targetedSummary.results.filter((result) => result.healStatus === 'success').length;
770
+ // eslint-disable-next-line no-console
771
+ console.log(`Heal targeted unstable specs: ${unstableSpecs.length} (healed=${healedCount})`);
772
+ if (targetedSummary.warnings.length > 0) {
773
+ // eslint-disable-next-line no-console
774
+ console.log(`Heal warnings: ${targetedSummary.warnings.join(' | ')}`);
775
+ }
776
+ return;
777
+ }
689
778
  if (!args.path && !autoConfig) {
690
779
  // eslint-disable-next-line no-console
691
780
  console.error('Error: --path is required (or provide a config file with path set)');
692
781
  printUsage();
693
782
  process.exit(1);
694
783
  }
695
- const forcePipelineFromApproval = args.command === 'approve-and-generate';
784
+ const forcePipelineFromApproval = args.command === 'approve-and-generate' || args.command === 'generate';
696
785
  const { config } = resolveConfig(process.cwd(), autoConfig, {
697
786
  path: args.path,
698
787
  testsRoot: args.testsRoot,
699
- mode: (args.command === 'gap' || args.command === 'approve-and-generate') ? 'gap' : 'impact',
788
+ mode: (args.command === 'gap' || args.command === 'approve-and-generate' || args.command === 'generate') ? 'gap' : 'impact',
700
789
  framework: args.framework,
701
790
  timeLimitMinutes: args.timeLimitMinutes,
702
791
  budget: {
@@ -721,17 +810,22 @@ async function main() {
721
810
  parallel: args.pipelineParallel,
722
811
  dryRun: args.pipelineDryRun,
723
812
  mcp: args.pipelineMcp !== undefined ? args.pipelineMcp : forcePipelineFromApproval,
813
+ mcpAllowFallback: args.pipelineMcpAllowFallback,
724
814
  }
725
815
  : undefined,
726
816
  policy: args.policyMinConfidence !== undefined ||
727
817
  args.policySafeMergeConfidence !== undefined ||
728
818
  args.policyWarningsThreshold !== undefined ||
729
- (args.policyRiskyPatterns && args.policyRiskyPatterns.length > 0)
819
+ (args.policyRiskyPatterns && args.policyRiskyPatterns.length > 0) ||
820
+ args.policyEnforcementMode !== undefined ||
821
+ (args.policyBlockActions && args.policyBlockActions.length > 0)
730
822
  ? {
731
823
  minConfidenceForTargeted: args.policyMinConfidence,
732
824
  safeMergeMinConfidence: args.policySafeMergeConfidence,
733
825
  forceFullOnWarningsAtOrAbove: args.policyWarningsThreshold,
734
826
  riskyFilePatterns: args.policyRiskyPatterns,
827
+ enforcementMode: args.policyEnforcementMode,
828
+ blockOnActions: args.policyBlockActions,
735
829
  }
736
830
  : undefined,
737
831
  });
@@ -742,7 +836,7 @@ async function main() {
742
836
  await runImpact(config, { apply: args.apply });
743
837
  return;
744
838
  }
745
- if (args.command === 'suggest') {
839
+ if (args.command === 'suggest' || args.command === 'plan') {
746
840
  await runImpact(config, { apply: args.apply });
747
841
  const reportRoot = config.testsRoot || config.path;
748
842
  const impactPath = join(reportRoot, '.e2e-ai-agents', 'impact.json');
@@ -760,24 +854,33 @@ async function main() {
760
854
  const planPath = writePlanReport(reportRoot, plan);
761
855
  const summaryMarkdown = renderCiSummaryMarkdown(plan);
762
856
  const summaryPath = writeCiSummary(reportRoot, summaryMarkdown, args.ciCommentPath);
857
+ const metrics = appendPlanMetrics(reportRoot, plan);
763
858
  const ghaOutput = args.githubOutputPath || process.env.GITHUB_OUTPUT;
764
859
  if (ghaOutput) {
765
860
  appendFileSync(ghaOutput, `run_set=${plan.runSet}\n`);
766
861
  appendFileSync(ghaOutput, `action=${plan.decision.action}\n`);
767
862
  appendFileSync(ghaOutput, `confidence=${plan.confidence}\n`);
863
+ appendFileSync(ghaOutput, `enforcement_mode=${plan.enforcement.mode}\n`);
864
+ appendFileSync(ghaOutput, `enforcement_should_fail=${plan.enforcement.shouldFail}\n`);
768
865
  appendFileSync(ghaOutput, `recommended_tests_count=${plan.recommendedTests.length}\n`);
769
866
  appendFileSync(ghaOutput, `required_new_tests_count=${plan.requiredNewTests.length}\n`);
770
867
  appendFileSync(ghaOutput, `plan_path=${planPath}\n`);
771
868
  appendFileSync(ghaOutput, `summary_path=${summaryPath}\n`);
869
+ appendFileSync(ghaOutput, `metrics_events_path=${metrics.eventsPath}\n`);
870
+ appendFileSync(ghaOutput, `metrics_summary_path=${metrics.summaryPath}\n`);
772
871
  }
773
872
  // eslint-disable-next-line no-console
774
873
  console.log(`Suggested run set: ${plan.runSet} (confidence ${plan.confidence})`);
775
874
  // eslint-disable-next-line no-console
776
875
  console.log(`Decision: ${plan.decision.action} - ${plan.decision.summary}`);
777
876
  // eslint-disable-next-line no-console
877
+ console.log(`Enforcement: ${plan.enforcement.mode} (shouldFail=${plan.enforcement.shouldFail})`);
878
+ // eslint-disable-next-line no-console
778
879
  console.log(`Plan data: ${planPath}`);
779
880
  // eslint-disable-next-line no-console
780
881
  console.log(`CI summary: ${summaryPath}`);
882
+ // eslint-disable-next-line no-console
883
+ console.log(`Plan metrics: ${metrics.summaryPath}`);
781
884
  if (plan.nextActions) {
782
885
  // eslint-disable-next-line no-console
783
886
  console.log(`Next action (run existing): ${plan.nextActions.runRecommendedTests || plan.nextActions.runSmokeSuite}`);
@@ -786,13 +889,14 @@ async function main() {
786
889
  // eslint-disable-next-line no-console
787
890
  console.log(`Next action (heal): ${plan.nextActions.healGeneratedTests}`);
788
891
  }
789
- if (args.failOnMustAddTests && plan.decision.action === 'must-add-tests') {
892
+ const failOnLegacyFlag = args.failOnMustAddTests && plan.decision.action === 'must-add-tests';
893
+ if (failOnLegacyFlag || plan.enforcement.shouldFail) {
790
894
  process.exit(2);
791
895
  }
792
896
  return;
793
897
  }
794
- if (args.command === 'approve-and-generate') {
795
- await runGap(config, { apply: true });
898
+ if (args.command === 'approve-and-generate' || args.command === 'generate') {
899
+ await runGap(config, { apply: args.apply });
796
900
  return;
797
901
  }
798
902
  await runGap(config, { apply: args.apply });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yasserkhanorg/e2e-agents",
3
- "version": "0.3.2",
3
+ "version": "0.3.4",
4
4
  "description": "Pluggable LLM provider library for AI-powered test automation. Use Claude, Ollama, or your own LLM. Integrate with Playwright, Jest, or any test framework. MCP server for test agents, cost tracking, and hybrid provider mode.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -18,6 +18,28 @@
18
18
  "mode": {
19
19
  "const": "impact"
20
20
  },
21
+ "runMetadata": {
22
+ "type": "object",
23
+ "required": [
24
+ "runId",
25
+ "startedAt",
26
+ "completedAt",
27
+ "durationMs",
28
+ "sinceRef",
29
+ "appPath",
30
+ "testsRoot"
31
+ ],
32
+ "properties": {
33
+ "runId": {"type": "string"},
34
+ "startedAt": {"type": "string", "format": "date-time"},
35
+ "completedAt": {"type": "string", "format": "date-time"},
36
+ "durationMs": {"type": "number"},
37
+ "sinceRef": {"type": "string"},
38
+ "appPath": {"type": "string"},
39
+ "testsRoot": {"type": "string"}
40
+ },
41
+ "additionalProperties": false
42
+ },
21
43
  "changedFiles": {
22
44
  "type": "array",
23
45
  "items": {
@@ -370,6 +392,21 @@
370
392
  },
371
393
  "error": {
372
394
  "type": "string"
395
+ },
396
+ "failureCategory": {
397
+ "enum": [
398
+ "config",
399
+ "environment",
400
+ "generation",
401
+ "validation",
402
+ "runtime",
403
+ "quality",
404
+ "path-safety",
405
+ "unknown"
406
+ ]
407
+ },
408
+ "failureCode": {
409
+ "type": "string"
373
410
  }
374
411
  },
375
412
  "additionalProperties": false
@@ -5,6 +5,7 @@
5
5
  "type": "object",
6
6
  "required": [
7
7
  "schemaVersion",
8
+ "runId",
8
9
  "generatedAt",
9
10
  "source",
10
11
  "runSet",
@@ -14,12 +15,19 @@
14
15
  "requiredNewTests",
15
16
  "policy",
16
17
  "decision",
18
+ "enforcement",
17
19
  "metrics"
18
20
  ],
19
21
  "properties": {
20
22
  "schemaVersion": {
21
23
  "const": "1.0.0"
22
24
  },
25
+ "runId": {
26
+ "type": "string"
27
+ },
28
+ "sourceRunId": {
29
+ "type": "string"
30
+ },
23
31
  "generatedAt": {
24
32
  "type": "string",
25
33
  "format": "date-time"
@@ -108,6 +116,15 @@
108
116
  "items": {
109
117
  "type": "string"
110
118
  }
119
+ },
120
+ "enforcementMode": {
121
+ "enum": ["advisory", "warn", "block"]
122
+ },
123
+ "blockOnActions": {
124
+ "type": "array",
125
+ "items": {
126
+ "enum": ["run-now", "must-add-tests", "safe-to-merge"]
127
+ }
111
128
  }
112
129
  },
113
130
  "additionalProperties": false
@@ -139,6 +156,37 @@
139
156
  },
140
157
  "additionalProperties": false
141
158
  },
159
+ "enforcement": {
160
+ "type": "object",
161
+ "required": [
162
+ "mode",
163
+ "blockOnActions",
164
+ "matchedAction",
165
+ "shouldFail",
166
+ "summary"
167
+ ],
168
+ "properties": {
169
+ "mode": {
170
+ "enum": ["advisory", "warn", "block"]
171
+ },
172
+ "blockOnActions": {
173
+ "type": "array",
174
+ "items": {
175
+ "enum": ["run-now", "must-add-tests", "safe-to-merge"]
176
+ }
177
+ },
178
+ "matchedAction": {
179
+ "type": "boolean"
180
+ },
181
+ "shouldFail": {
182
+ "type": "boolean"
183
+ },
184
+ "summary": {
185
+ "type": "string"
186
+ }
187
+ },
188
+ "additionalProperties": false
189
+ },
142
190
  "insights": {
143
191
  "type": "object",
144
192
  "properties": {
@@ -1,38 +0,0 @@
1
- /**
2
- * Simple TTL cache for repository context and file reads
3
- * Provides 90% faster access on cache hits
4
- * Default TTL: 5 minutes
5
- */
6
- export interface CacheEntry<T> {
7
- value: T;
8
- timestamp: number;
9
- }
10
- export declare class SimpleCache<T> {
11
- private cache;
12
- private ttlMs;
13
- constructor(ttlMs?: number);
14
- /**
15
- * Get value from cache if it exists and hasn't expired
16
- */
17
- get(key: string): T | undefined;
18
- /**
19
- * Set value in cache with current timestamp
20
- */
21
- set(key: string, value: T): void;
22
- /**
23
- * Clear all entries from cache
24
- */
25
- clear(): void;
26
- /**
27
- * Get cache size
28
- */
29
- size(): number;
30
- /**
31
- * Get cache statistics
32
- */
33
- stats(): {
34
- size: number;
35
- entries: number;
36
- };
37
- }
38
- //# sourceMappingURL=cache_utils.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cache_utils.d.ts","sourceRoot":"","sources":["../../src/agent/cache_utils.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AAEH,MAAM,WAAW,UAAU,CAAC,CAAC;IACzB,KAAK,EAAE,CAAC,CAAC;IACT,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,WAAW,CAAC,CAAC;IACtB,OAAO,CAAC,KAAK,CAAyC;IACtD,OAAO,CAAC,KAAK,CAAS;gBAEV,KAAK,GAAE,MAAsB;IAKzC;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAe/B;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI;IAOhC;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,IAAI,IAAI,MAAM;IAId;;OAEG;IACH,KAAK,IAAI;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAC;CAgB3C"}
@@ -1,67 +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.SimpleCache = void 0;
6
- class SimpleCache {
7
- constructor(ttlMs = 5 * 60 * 1000) {
8
- this.cache = new Map();
9
- // Default: 5 minutes
10
- this.ttlMs = ttlMs;
11
- }
12
- /**
13
- * Get value from cache if it exists and hasn't expired
14
- */
15
- get(key) {
16
- const entry = this.cache.get(key);
17
- if (!entry) {
18
- return undefined;
19
- }
20
- // Check if entry has expired
21
- if (Date.now() - entry.timestamp > this.ttlMs) {
22
- this.cache.delete(key);
23
- return undefined;
24
- }
25
- return entry.value;
26
- }
27
- /**
28
- * Set value in cache with current timestamp
29
- */
30
- set(key, value) {
31
- this.cache.set(key, {
32
- value,
33
- timestamp: Date.now(),
34
- });
35
- }
36
- /**
37
- * Clear all entries from cache
38
- */
39
- clear() {
40
- this.cache.clear();
41
- }
42
- /**
43
- * Get cache size
44
- */
45
- size() {
46
- return this.cache.size;
47
- }
48
- /**
49
- * Get cache statistics
50
- */
51
- stats() {
52
- // Clean expired entries
53
- const now = Date.now();
54
- let expired = 0;
55
- for (const [key, entry] of this.cache.entries()) {
56
- if (now - entry.timestamp > this.ttlMs) {
57
- this.cache.delete(key);
58
- expired++;
59
- }
60
- }
61
- return {
62
- size: this.cache.size,
63
- entries: this.cache.size,
64
- };
65
- }
66
- }
67
- exports.SimpleCache = SimpleCache;
@@ -1,114 +0,0 @@
1
- /**
2
- * Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
3
- * See LICENSE.txt for license information.
4
- *
5
- * Impact Analysis Engine
6
- *
7
- * Analyzes code changes and identifies which user flows are affected,
8
- * then maps those flows to test coverage gaps.
9
- */
10
- export interface GitChange {
11
- path: string;
12
- status: 'added' | 'modified' | 'deleted';
13
- ref?: string;
14
- }
15
- export interface ChangeAnalysis {
16
- file: string;
17
- status: 'added' | 'modified' | 'deleted';
18
- linesAdded: number;
19
- linesRemoved: number;
20
- functions: string[];
21
- classes: string[];
22
- imports: Array<{
23
- from: string;
24
- names: string[];
25
- }>;
26
- }
27
- export interface Flow {
28
- id: string;
29
- name: string;
30
- priority: 'P0' | 'P1' | 'P2';
31
- keywords: string[];
32
- paths: string[];
33
- tests: string[];
34
- audience: string[];
35
- flags: Array<{
36
- name: string;
37
- source: string;
38
- }>;
39
- }
40
- export interface FlowImpact {
41
- flow: Flow;
42
- matchType: 'path' | 'keyword' | 'import' | 'combined';
43
- confidence: number;
44
- affectedFiles: string[];
45
- existingTests: string[];
46
- testGaps: string[];
47
- reasons: string[];
48
- }
49
- export interface FlowGroup {
50
- id: string;
51
- name: string;
52
- description: string;
53
- flows: string[];
54
- testStrategy: 'sequential' | 'parallel' | 'mixed';
55
- priority: string;
56
- affectedFlows: FlowImpact[];
57
- }
58
- export interface ImpactReport {
59
- timestamp: string;
60
- gitRef: string;
61
- totalChanges: number;
62
- affectedFlows: FlowImpact[];
63
- flowGroups: FlowGroup[];
64
- ungroupedFlows: FlowImpact[];
65
- priorityBreakdown: {
66
- p0: number;
67
- p1: number;
68
- p2: number;
69
- };
70
- testCoverage: {
71
- total: number;
72
- covered: number;
73
- gaps: number;
74
- };
75
- recommendations: string[];
76
- hasP0Impact: boolean;
77
- }
78
- /**
79
- * Intelligently detect the best git reference for comparison:
80
- * - If on feature branch: use origin/master, origin/main, or master
81
- * - If on main branch: use HEAD~1
82
- * Returns the best available reference to compare against
83
- */
84
- export declare function detectComparisonBase(): string;
85
- /**
86
- * Get git changes since a given reference
87
- * Filters to only include frontend files (webapp and e2e-tests)
88
- */
89
- export declare function getGitChanges(since?: string): GitChange[];
90
- /**
91
- * Load flow catalog from flows.json
92
- */
93
- export declare function loadFlowCatalog(catalogPath?: string): Flow[];
94
- /**
95
- * Match a flow to changed files
96
- */
97
- export declare function matchFlowToChanges(flow: Flow, changes: ChangeAnalysis[]): FlowImpact | null;
98
- /**
99
- * Find existing tests for a flow
100
- */
101
- export declare function findExistingTests(flow: Flow, repoRoot?: string): string[];
102
- /**
103
- * Identify test coverage gaps for a flow
104
- */
105
- export declare function identifyTestGaps(flow: Flow, existingTests: string[]): string[];
106
- /**
107
- * Analyze code impact and return comprehensive report
108
- */
109
- export declare function analyzeImpact(changes: GitChange[], flows: Flow[], options?: {
110
- verbose?: boolean;
111
- includeTests?: boolean;
112
- repoRoot?: string;
113
- }): Promise<ImpactReport>;
114
- //# sourceMappingURL=impact-analyzer.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"impact-analyzer.d.ts","sourceRoot":"","sources":["../../src/agent/impact-analyzer.ts"],"names":[],"mappings":"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"}