@yasserkhanorg/e2e-agents 0.6.0 → 0.7.1

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.
@@ -19,6 +19,7 @@ export interface GapDetail {
19
19
  files: string[];
20
20
  existingTests?: string[];
21
21
  missingScenarios?: string[];
22
+ source?: 'deterministic' | 'ai+deterministic';
22
23
  }
23
24
  export interface CoveredFlowSummary {
24
25
  id: string;
@@ -31,7 +32,7 @@ export interface PlanReport {
31
32
  runId: string;
32
33
  sourceRunId?: string;
33
34
  generatedAt: string;
34
- source: 'impact';
35
+ source: 'impact' | 'ai+deterministic';
35
36
  runSet: RecommendedRunSet;
36
37
  confidence: number;
37
38
  reasons: string[];
@@ -1 +1 @@
1
- {"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../src/agent/plan.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../src/agent/plan.ts"],"names":[],"mappings":"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"}
package/dist/api.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { type ConfigOverrides } from './agent/config.js';
2
2
  import { type PlanReport } from './agent/plan.js';
3
3
  import { type ImpactResult } from './engine/impact_engine.js';
4
+ import { type AIEnrichmentResult } from './engine/ai_enrichment.js';
4
5
  import { type FinalizeGeneratedTestsOptions, type FinalizeGeneratedTestsResult } from './agent/handoff.js';
5
6
  import { type TraceabilityIngestOptions, type TraceabilityIngestResult } from './agent/traceability_ingest.js';
6
7
  import { type TraceabilityCaptureResult } from './agent/traceability_capture.js';
@@ -40,5 +41,8 @@ export interface RecommendTestsV2Result {
40
41
  }
41
42
  export declare function analyzeImpactDeterministic(options?: AgentApiOptions): ImpactResult;
42
43
  export declare function recommendTestsDeterministic(options?: AgentApiOptions): RecommendTestsV2Result;
44
+ export declare function recommendTestsAI(options?: AgentApiOptions): Promise<RecommendTestsV2Result & {
45
+ aiEnrichment?: AIEnrichmentResult;
46
+ }>;
43
47
  export declare function captureTraceability(options: TraceabilityCaptureApiOptions): TraceabilityCaptureResult;
44
48
  //# sourceMappingURL=api.d.ts.map
package/dist/api.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAIA,OAAO,EAAgB,KAAK,eAAe,EAAC,MAAM,mBAAmB,CAAC;AACtE,OAAO,EAEH,KAAK,UAAU,EAClB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAmC,KAAK,YAAY,EAAC,MAAM,2BAA2B,CAAC;AAQ9F,OAAO,EAAyB,KAAK,6BAA6B,EAAE,KAAK,4BAA4B,EAAC,MAAM,oBAAoB,CAAC;AACjI,OAAO,EAEH,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAChC,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAGH,KAAK,yBAAyB,EACjC,MAAM,iCAAiC,CAAC;AAEzC,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC;IAClE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,aAAa,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,4BAA4B;IACzC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,yBAAyB,CAAC;CACvC;AAED,MAAM,WAAW,6BAA6B;IAC1C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAcD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,6BAA6B,GAAG,4BAA4B,CAE1G;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,4BAA4B,GAAG,wBAAwB,CASlG;AAED,MAAM,WAAW,sBAAsB;IACnC,MAAM,EAAE,YAAY,CAAC;IACrB,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,0BAA0B,CAAC,OAAO,GAAE,eAAoB,GAAG,YAAY,CAQtF;AAED,wBAAgB,2BAA2B,CAAC,OAAO,GAAE,eAAoB,GAAG,sBAAsB,CAcjG;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,6BAA6B,GAAG,yBAAyB,CAkBrG"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAIA,OAAO,EAAgB,KAAK,eAAe,EAAC,MAAM,mBAAmB,CAAC;AACtE,OAAO,EAEH,KAAK,UAAU,EAClB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAmC,KAAK,YAAY,EAAC,MAAM,2BAA2B,CAAC;AAS9F,OAAO,EAAqB,KAAK,kBAAkB,EAAC,MAAM,2BAA2B,CAAC;AAEtF,OAAO,EAAyB,KAAK,6BAA6B,EAAE,KAAK,4BAA4B,EAAC,MAAM,oBAAoB,CAAC;AACjI,OAAO,EAEH,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAChC,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAGH,KAAK,yBAAyB,EACjC,MAAM,iCAAiC,CAAC;AAEzC,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC;IAClE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,aAAa,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,4BAA4B;IACzC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,yBAAyB,CAAC;CACvC;AAED,MAAM,WAAW,6BAA6B;IAC1C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAcD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,6BAA6B,GAAG,4BAA4B,CAE1G;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,4BAA4B,GAAG,wBAAwB,CASlG;AAED,MAAM,WAAW,sBAAsB;IACnC,MAAM,EAAE,YAAY,CAAC;IACrB,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,0BAA0B,CAAC,OAAO,GAAE,eAAoB,GAAG,YAAY,CAQtF;AAED,wBAAgB,2BAA2B,CAAC,OAAO,GAAE,eAAoB,GAAG,sBAAsB,CAcjG;AAED,wBAAsB,gBAAgB,CAAC,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,sBAAsB,GAAG;IAAE,YAAY,CAAC,EAAE,kBAAkB,CAAA;CAAE,CAAC,CAoC7I;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,6BAA6B,GAAG,yBAAyB,CAkBrG"}
package/dist/api.js CHANGED
@@ -6,12 +6,16 @@ exports.handoffGeneratedTests = handoffGeneratedTests;
6
6
  exports.ingestTraceability = ingestTraceability;
7
7
  exports.analyzeImpactDeterministic = analyzeImpactDeterministic;
8
8
  exports.recommendTestsDeterministic = recommendTestsDeterministic;
9
+ exports.recommendTestsAI = recommendTestsAI;
9
10
  exports.captureTraceability = captureTraceability;
10
11
  const config_js_1 = require("./agent/config.js");
11
12
  const plan_js_1 = require("./agent/plan.js");
12
13
  const impact_engine_js_1 = require("./engine/impact_engine.js");
13
14
  const plan_builder_js_1 = require("./engine/plan_builder.js");
14
15
  const git_js_1 = require("./agent/git.js");
16
+ const diff_loader_js_1 = require("./engine/diff_loader.js");
17
+ const ai_enrichment_js_1 = require("./engine/ai_enrichment.js");
18
+ const anthropic_provider_js_1 = require("./anthropic_provider.js");
15
19
  const handoff_js_1 = require("./agent/handoff.js");
16
20
  const traceability_ingest_js_1 = require("./agent/traceability_ingest.js");
17
21
  const traceability_capture_js_1 = require("./agent/traceability_capture.js");
@@ -63,6 +67,40 @@ function recommendTestsDeterministic(options = {}) {
63
67
  (0, plan_js_1.appendPlanMetrics)(reportRoot, plan);
64
68
  return { impact, plan, planPath, ciSummaryMarkdown, ciSummaryPath };
65
69
  }
70
+ async function recommendTestsAI(options = {}) {
71
+ const config = resolveAgent(options, 'impact');
72
+ const reportRoot = config.testsRoot || config.path;
73
+ const gitResult = (0, git_js_1.getChangedFiles)(config.path, config.git.since, { includeUncommitted: config.git.includeUncommitted });
74
+ const impact = (0, impact_engine_js_1.analyzeImpact)(gitResult.files, {
75
+ testsRoot: reportRoot,
76
+ routeFamilies: config.routeFamilies,
77
+ });
78
+ const apiKey = process.env.ANTHROPIC_API_KEY;
79
+ let aiEnrichment;
80
+ if (apiKey) {
81
+ const diffs = (0, diff_loader_js_1.loadDiffs)(config.path, config.git.since, gitResult.files);
82
+ const provider = new anthropic_provider_js_1.AnthropicProvider({ apiKey });
83
+ // Collect all known spec paths from impacted features
84
+ const specSet = new Set();
85
+ for (const feature of impact.impactedFeatures) {
86
+ for (const s of feature.playwrightSpecs) {
87
+ specSet.add(s);
88
+ }
89
+ }
90
+ aiEnrichment = await (0, ai_enrichment_js_1.enrichImpactWithAI)({
91
+ deterministicImpact: impact,
92
+ diffs,
93
+ provider,
94
+ specList: [...specSet],
95
+ });
96
+ }
97
+ const plan = (0, plan_builder_js_1.buildPlanFromImpact)(impact, config.policy, aiEnrichment);
98
+ const planPath = (0, plan_builder_js_1.writePlanReport)(reportRoot, plan);
99
+ const ciSummaryMarkdown = (0, plan_builder_js_1.renderCiSummaryMarkdown)(plan);
100
+ const ciSummaryPath = (0, plan_builder_js_1.writeCiSummary)(reportRoot, ciSummaryMarkdown);
101
+ (0, plan_js_1.appendPlanMetrics)(reportRoot, plan);
102
+ return { impact, plan, planPath, ciSummaryMarkdown, ciSummaryPath, aiEnrichment };
103
+ }
66
104
  function captureTraceability(options) {
67
105
  const cwd = options.cwd || process.cwd();
68
106
  const { config } = (0, config_js_1.resolveConfig)(cwd, options.configPath, {
package/dist/cli.js CHANGED
@@ -8,10 +8,10 @@ const path_1 = require("path");
8
8
  const config_js_1 = require("./agent/config.js");
9
9
  const anthropic_provider_js_1 = require("./anthropic_provider.js");
10
10
  const provider_interface_js_1 = require("./provider_interface.js");
11
- const plan_js_1 = require("./agent/plan.js");
12
11
  const impact_engine_js_1 = require("./engine/impact_engine.js");
13
12
  const plan_builder_js_1 = require("./engine/plan_builder.js");
14
13
  const git_js_1 = require("./agent/git.js");
14
+ const api_js_1 = require("./api.js");
15
15
  const feedback_js_1 = require("./agent/feedback.js");
16
16
  const handoff_js_1 = require("./agent/handoff.js");
17
17
  const traceability_ingest_js_1 = require("./agent/traceability_ingest.js");
@@ -495,6 +495,10 @@ function parseArgs(argv) {
495
495
  i += 1;
496
496
  continue;
497
497
  }
498
+ if (arg === '--no-ai') {
499
+ parsed.noAi = true;
500
+ continue;
501
+ }
498
502
  }
499
503
  return parsed;
500
504
  }
@@ -896,16 +900,55 @@ async function main() {
896
900
  }
897
901
  if (args.command === 'suggest' || args.command === 'plan') {
898
902
  const reportRoot = config.testsRoot || config.path;
899
- const gitResult = (0, git_js_1.getChangedFiles)(config.path, config.git.since, { includeUncommitted: config.git.includeUncommitted });
900
- const impactResult = (0, impact_engine_js_1.analyzeImpact)(gitResult.files, {
901
- testsRoot: reportRoot,
902
- routeFamilies: config.routeFamilies,
903
- });
904
- const plan = (0, plan_builder_js_1.buildPlanFromImpact)(impactResult, config.policy);
905
- const planPath = (0, plan_builder_js_1.writePlanReport)(reportRoot, plan);
906
- const summaryMarkdown = (0, plan_builder_js_1.renderCiSummaryMarkdown)(plan);
907
- const summaryPath = (0, plan_builder_js_1.writeCiSummary)(reportRoot, summaryMarkdown, args.ciCommentPath);
908
- const metrics = (0, plan_js_1.appendPlanMetrics)(reportRoot, plan);
903
+ const apiOptions = {
904
+ cwd: process.cwd(),
905
+ configPath: autoConfig,
906
+ path: args.path,
907
+ profile: args.profile,
908
+ testsRoot: args.testsRoot,
909
+ gitSince: args.gitSince,
910
+ llmProvider: args.llmProvider,
911
+ policy: args.policyMinConfidence !== undefined ||
912
+ args.policySafeMergeConfidence !== undefined ||
913
+ args.policyWarningsThreshold !== undefined ||
914
+ (args.policyRiskyPatterns && args.policyRiskyPatterns.length > 0) ||
915
+ args.policyEnforcementMode !== undefined ||
916
+ (args.policyBlockActions && args.policyBlockActions.length > 0)
917
+ ? {
918
+ minConfidenceForTargeted: args.policyMinConfidence,
919
+ safeMergeMinConfidence: args.policySafeMergeConfidence,
920
+ forceFullOnWarningsAtOrAbove: args.policyWarningsThreshold,
921
+ riskyFilePatterns: args.policyRiskyPatterns,
922
+ enforcementMode: args.policyEnforcementMode,
923
+ blockOnActions: args.policyBlockActions,
924
+ }
925
+ : undefined,
926
+ };
927
+ let result;
928
+ if (args.noAi) {
929
+ result = (0, api_js_1.recommendTestsDeterministic)(apiOptions);
930
+ }
931
+ else {
932
+ result = await (0, api_js_1.recommendTestsAI)(apiOptions);
933
+ if (result.aiEnrichment) {
934
+ const { aiEnrichment } = result;
935
+ // eslint-disable-next-line no-console
936
+ console.log(`AI enrichment: ${aiEnrichment.enrichedFeatures.length} features enriched (${aiEnrichment.tokenUsage.input + aiEnrichment.tokenUsage.output} tokens)`);
937
+ }
938
+ else if (!process.env.ANTHROPIC_API_KEY) {
939
+ // eslint-disable-next-line no-console
940
+ console.log('Tip: set ANTHROPIC_API_KEY to enable AI-powered enrichment');
941
+ }
942
+ }
943
+ const { plan, planPath, ciSummaryMarkdown, ciSummaryPath } = result;
944
+ // Write CI summary to an additional path if --ci-comment-path was specified
945
+ if (args.ciCommentPath) {
946
+ (0, plan_builder_js_1.writeCiSummary)(reportRoot, ciSummaryMarkdown, args.ciCommentPath);
947
+ }
948
+ const summaryPath = ciSummaryPath;
949
+ // Compute metrics paths (api already wrote metrics; derive paths for GHA output)
950
+ const metricsEventsPath = (0, path_1.join)(reportRoot, '.e2e-ai-agents/metrics.jsonl');
951
+ const metricsSummaryPath = (0, path_1.join)(reportRoot, '.e2e-ai-agents/metrics-summary.json');
909
952
  const ghaOutput = args.githubOutputPath || process.env.GITHUB_OUTPUT;
910
953
  if (ghaOutput) {
911
954
  (0, fs_1.appendFileSync)(ghaOutput, `run_set=${plan.runSet}\n`);
@@ -917,8 +960,8 @@ async function main() {
917
960
  (0, fs_1.appendFileSync)(ghaOutput, `required_new_tests_count=${plan.requiredNewTests.length}\n`);
918
961
  (0, fs_1.appendFileSync)(ghaOutput, `plan_path=${planPath}\n`);
919
962
  (0, fs_1.appendFileSync)(ghaOutput, `summary_path=${summaryPath}\n`);
920
- (0, fs_1.appendFileSync)(ghaOutput, `metrics_events_path=${metrics.eventsPath}\n`);
921
- (0, fs_1.appendFileSync)(ghaOutput, `metrics_summary_path=${metrics.summaryPath}\n`);
963
+ (0, fs_1.appendFileSync)(ghaOutput, `metrics_events_path=${metricsEventsPath}\n`);
964
+ (0, fs_1.appendFileSync)(ghaOutput, `metrics_summary_path=${metricsSummaryPath}\n`);
922
965
  }
923
966
  // eslint-disable-next-line no-console
924
967
  console.log(`Suggested run set: ${plan.runSet} (confidence ${plan.confidence})`);
@@ -931,7 +974,7 @@ async function main() {
931
974
  // eslint-disable-next-line no-console
932
975
  console.log(`CI summary: ${summaryPath}`);
933
976
  // eslint-disable-next-line no-console
934
- console.log(`Plan metrics: ${metrics.summaryPath}`);
977
+ console.log(`Plan metrics: ${metricsSummaryPath}`);
935
978
  const failOnLegacyFlag = args.failOnMustAddTests && plan.decision.action === 'must-add-tests';
936
979
  if (failOnLegacyFlag || plan.enforcement.shouldFail) {
937
980
  process.exit(2);
@@ -0,0 +1,43 @@
1
+ import type { LLMProvider } from '../provider_interface.js';
2
+ import type { ImpactResult } from './impact_engine.js';
3
+ import type { FeaturePriority } from '../knowledge/route_families.js';
4
+ export interface EnrichedFeature {
5
+ familyId: string;
6
+ featureId?: string;
7
+ priority: FeaturePriority;
8
+ changedFiles: string[];
9
+ coverageStatus: string;
10
+ playwrightSpecs: string[];
11
+ cypressSpecs: string[];
12
+ userFlows: string[];
13
+ aiReasons: string[];
14
+ aiMissingScenarios: string[];
15
+ aiCoveredBy: string[];
16
+ }
17
+ export interface AIEnrichmentResult {
18
+ enrichedFeatures: EnrichedFeature[];
19
+ unboundFileInsights: Array<{
20
+ file: string;
21
+ likelyFeature: string;
22
+ reason: string;
23
+ }>;
24
+ warnings: string[];
25
+ providerName: string;
26
+ tokenUsage: {
27
+ input: number;
28
+ output: number;
29
+ };
30
+ }
31
+ export interface AIEnrichmentOptions {
32
+ deterministicImpact: ImpactResult;
33
+ diffs: Map<string, string>;
34
+ provider: LLMProvider;
35
+ specList: string[];
36
+ manifestSummary?: string;
37
+ }
38
+ /**
39
+ * Enriches a deterministic impact result with AI-generated reasons,
40
+ * missing test scenarios, and coverage insights.
41
+ */
42
+ export declare function enrichImpactWithAI(options: AIEnrichmentOptions): Promise<AIEnrichmentResult>;
43
+ //# sourceMappingURL=ai_enrichment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai_enrichment.d.ts","sourceRoot":"","sources":["../../src/engine/ai_enrichment.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAC,YAAY,EAAkB,MAAM,oBAAoB,CAAC;AACtE,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,gCAAgC,CAAC;AAGpE,MAAM,WAAW,eAAe;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,eAAe,CAAC;IAC1B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,WAAW,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IAC/B,gBAAgB,EAAE,eAAe,EAAE,CAAC;IACpC,mBAAmB,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC;IAClF,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAC,CAAC;CAC/C;AAED,MAAM,WAAW,mBAAmB;IAChC,mBAAmB,EAAE,YAAY,CAAC;IAClC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3B,QAAQ,EAAE,WAAW,CAAC;IACtB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC5B;AAoJD;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAkIlG"}
@@ -0,0 +1,235 @@
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.enrichImpactWithAI = enrichImpactWithAI;
6
+ const diff_loader_js_1 = require("./diff_loader.js");
7
+ const MAX_SPEC_LIST = 50;
8
+ function normalizePriority(value) {
9
+ if (value === 'P0' || value === 'P1' || value === 'P2') {
10
+ return value;
11
+ }
12
+ return 'P2';
13
+ }
14
+ function buildPrompt(options) {
15
+ const { deterministicImpact, diffs, specList, manifestSummary } = options;
16
+ const { changedFiles, impactedFeatures, unboundFiles } = deterministicImpact;
17
+ const lines = [];
18
+ // Optional manifest summary
19
+ if (manifestSummary) {
20
+ lines.push('## Application Overview');
21
+ lines.push(manifestSummary);
22
+ lines.push('');
23
+ }
24
+ // Changed files section
25
+ lines.push(`## Changed Files (${changedFiles.length} total)`);
26
+ for (const f of changedFiles) {
27
+ lines.push(`- ${f}`);
28
+ }
29
+ lines.push('');
30
+ // Diffs section
31
+ lines.push('## Code Diffs');
32
+ lines.push((0, diff_loader_js_1.formatDiffsForPrompt)(diffs));
33
+ lines.push('');
34
+ // Deterministic features summary
35
+ lines.push('## Deterministic Impact Analysis');
36
+ lines.push('The following features/flows have been deterministically identified as impacted:');
37
+ lines.push('');
38
+ for (const feature of impactedFeatures) {
39
+ const featureIdPart = feature.featureId ? `featureId=${feature.featureId}` : 'featureId=undefined';
40
+ const specCount = feature.playwrightSpecs.length + feature.cypressSpecs.length;
41
+ const specList2 = [...feature.playwrightSpecs, ...feature.cypressSpecs];
42
+ const specsDisplay = specList2.length > 0 ? specList2.join(', ') : 'none';
43
+ lines.push(`- familyId=${feature.familyId} ${featureIdPart} (${feature.priority}): ${specCount} files, coverage=${feature.coverageStatus}, specs=[${specsDisplay}]`);
44
+ }
45
+ lines.push('');
46
+ // Unbound files
47
+ if (unboundFiles.length > 0) {
48
+ lines.push('## Unbound Files (not mapped to any feature)');
49
+ for (const f of unboundFiles) {
50
+ lines.push(`- ${f}`);
51
+ }
52
+ lines.push('');
53
+ }
54
+ // Spec list (capped at 50)
55
+ if (specList.length > 0) {
56
+ const cappedSpecs = specList.slice(0, MAX_SPEC_LIST);
57
+ lines.push(`## Available Test Specs (showing ${cappedSpecs.length} of ${specList.length})`);
58
+ for (const s of cappedSpecs) {
59
+ lines.push(`- ${s}`);
60
+ }
61
+ lines.push('');
62
+ }
63
+ // Instructions
64
+ lines.push('## Instructions');
65
+ lines.push('Return ONLY valid JSON (no markdown fences, no explanation) in this exact shape:');
66
+ lines.push('');
67
+ lines.push(JSON.stringify({
68
+ impactedFlows: [
69
+ {
70
+ id: '<featureId or familyId from the deterministic list above>',
71
+ name: '<human-readable flow name>',
72
+ priority: 'P0|P1|P2',
73
+ reasons: ['<specific reason why this flow is impacted by the changes>'],
74
+ coveredBy: ['<spec file paths that cover this flow>'],
75
+ missingScenarios: ['<specific test scenarios that are missing or should be added>'],
76
+ },
77
+ ],
78
+ unboundFileAnalysis: [
79
+ {
80
+ file: '<path to unbound file>',
81
+ likelyFeature: '<best guess at which feature/family this affects>',
82
+ reason: '<why you think this file belongs to that feature>',
83
+ },
84
+ ],
85
+ }, null, 2));
86
+ return lines.join('\n');
87
+ }
88
+ function extractJSON(text) {
89
+ // Try markdown fenced block first
90
+ const fenced = text.match(/```(?:json)?\s*([\s\S]*?)```/i);
91
+ const candidates = fenced ? [fenced[1], text] : [text];
92
+ for (const candidate of candidates) {
93
+ const start = candidate.indexOf('{');
94
+ const end = candidate.lastIndexOf('}');
95
+ if (start >= 0 && end > start) {
96
+ return candidate.slice(start, end + 1).trim();
97
+ }
98
+ }
99
+ // Fallback: return trimmed text
100
+ return text.trim();
101
+ }
102
+ function toEnrichedFeature(det, aiFlow) {
103
+ return {
104
+ familyId: det.familyId,
105
+ featureId: det.featureId,
106
+ priority: normalizePriority(det.priority),
107
+ changedFiles: det.changedFiles,
108
+ coverageStatus: det.coverageStatus,
109
+ playwrightSpecs: det.playwrightSpecs,
110
+ cypressSpecs: det.cypressSpecs,
111
+ userFlows: det.userFlows,
112
+ aiReasons: aiFlow?.reasons ?? [],
113
+ aiMissingScenarios: aiFlow?.missingScenarios ?? [],
114
+ aiCoveredBy: aiFlow?.coveredBy ?? [],
115
+ };
116
+ }
117
+ /**
118
+ * Enriches a deterministic impact result with AI-generated reasons,
119
+ * missing test scenarios, and coverage insights.
120
+ */
121
+ async function enrichImpactWithAI(options) {
122
+ const { deterministicImpact, provider } = options;
123
+ const warnings = [];
124
+ let tokenUsage = { input: 0, output: 0 };
125
+ const prompt = buildPrompt(options);
126
+ let aiResponse = null;
127
+ let unboundFileInsights = [];
128
+ try {
129
+ const response = await provider.generateText(prompt, {
130
+ maxTokens: 4000,
131
+ temperature: 0,
132
+ timeout: 45000,
133
+ systemPrompt: 'You are an expert E2E test analyst. Return only valid JSON.',
134
+ });
135
+ tokenUsage = {
136
+ input: response.usage?.inputTokens ?? 0,
137
+ output: response.usage?.outputTokens ?? 0,
138
+ };
139
+ const rawJSON = extractJSON(response.text);
140
+ try {
141
+ const parsed = JSON.parse(rawJSON);
142
+ // Validate that impactedFlows is an array
143
+ if (!Array.isArray(parsed.impactedFlows)) {
144
+ warnings.push('AI response parsed but impactedFlows is not an array; returning empty enrichedFeatures');
145
+ return {
146
+ enrichedFeatures: [],
147
+ unboundFileInsights: [],
148
+ warnings,
149
+ providerName: provider.name,
150
+ tokenUsage,
151
+ };
152
+ }
153
+ aiResponse = parsed;
154
+ unboundFileInsights = (parsed.unboundFileAnalysis ?? []).map((item) => ({
155
+ file: item.file,
156
+ likelyFeature: item.likelyFeature,
157
+ reason: item.reason,
158
+ }));
159
+ }
160
+ catch (parseErr) {
161
+ warnings.push(`Failed to parse AI response as JSON: ${parseErr instanceof Error ? parseErr.message : String(parseErr)}`);
162
+ return {
163
+ enrichedFeatures: [],
164
+ unboundFileInsights: [],
165
+ warnings,
166
+ providerName: provider.name,
167
+ tokenUsage,
168
+ };
169
+ }
170
+ }
171
+ catch (err) {
172
+ warnings.push(`AI provider error: ${err instanceof Error ? err.message : String(err)}`);
173
+ return {
174
+ enrichedFeatures: [],
175
+ unboundFileInsights: [],
176
+ warnings,
177
+ providerName: provider.name,
178
+ tokenUsage,
179
+ };
180
+ }
181
+ // Build a map of AI flows by id (featureId or familyId)
182
+ const aiFlowMap = new Map();
183
+ if (aiResponse?.impactedFlows) {
184
+ for (const flow of aiResponse.impactedFlows) {
185
+ aiFlowMap.set(flow.id, flow);
186
+ }
187
+ }
188
+ // Build a set of all deterministic ids for unmatched-flow detection
189
+ const deterministicIds = new Set();
190
+ for (const det of deterministicImpact.impactedFeatures) {
191
+ if (det.featureId) {
192
+ deterministicIds.add(det.featureId);
193
+ }
194
+ deterministicIds.add(det.familyId);
195
+ }
196
+ // Warn on AI flows that don't match any deterministic feature
197
+ for (const flow of aiFlowMap.values()) {
198
+ if (!deterministicIds.has(flow.id)) {
199
+ warnings.push(`AI returned flow '${flow.id}' with no matching deterministic feature (using as-is)`);
200
+ }
201
+ }
202
+ // Merge deterministic features with AI data
203
+ const enrichedFeatures = deterministicImpact.impactedFeatures.map((det) => {
204
+ // Match by featureId first, then by familyId
205
+ const aiFlow = det.featureId
206
+ ? (aiFlowMap.get(det.featureId) ?? aiFlowMap.get(det.familyId))
207
+ : aiFlowMap.get(det.familyId);
208
+ return toEnrichedFeature(det, aiFlow);
209
+ });
210
+ // Include AI flows that had no deterministic match (as-is, with empty deterministic fields)
211
+ for (const flow of aiFlowMap.values()) {
212
+ if (!deterministicIds.has(flow.id)) {
213
+ enrichedFeatures.push({
214
+ familyId: flow.id,
215
+ featureId: undefined,
216
+ priority: normalizePriority(flow.priority),
217
+ changedFiles: [],
218
+ coverageStatus: 'uncovered',
219
+ playwrightSpecs: [],
220
+ cypressSpecs: [],
221
+ userFlows: [],
222
+ aiReasons: flow.reasons ?? [],
223
+ aiMissingScenarios: flow.missingScenarios ?? [],
224
+ aiCoveredBy: flow.coveredBy ?? [],
225
+ });
226
+ }
227
+ }
228
+ return {
229
+ enrichedFeatures,
230
+ unboundFileInsights,
231
+ warnings,
232
+ providerName: provider.name,
233
+ tokenUsage,
234
+ };
235
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Loads git diffs for the given changed files relative to the given since ref.
3
+ * Uses `git merge-base` to find the accurate base ref first.
4
+ * Individual diffs are truncated at 8000 chars and total output is capped at 60000 chars.
5
+ */
6
+ export declare function loadDiffs(appRoot: string, since: string, changedFiles: string[]): Map<string, string>;
7
+ /**
8
+ * Formats a diffs map into a human-readable string suitable for an AI prompt.
9
+ */
10
+ export declare function formatDiffsForPrompt(diffs: Map<string, string>): string;
11
+ //# sourceMappingURL=diff_loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff_loader.d.ts","sourceRoot":"","sources":["../../src/engine/diff_loader.ts"],"names":[],"mappings":"AAqBA;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CA0CrG;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAUvE"}
@@ -0,0 +1,74 @@
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.loadDiffs = loadDiffs;
6
+ exports.formatDiffsForPrompt = formatDiffsForPrompt;
7
+ const child_process_1 = require("child_process");
8
+ const MAX_DIFF_CHARS = 8000;
9
+ const MAX_TOTAL_CHARS = 60000;
10
+ const TRUNCATION_NOTICE = '\n... (diff truncated)';
11
+ function runGitRaw(args, cwd) {
12
+ const result = (0, child_process_1.spawnSync)('git', args, {
13
+ cwd,
14
+ encoding: 'utf-8',
15
+ timeout: 30000,
16
+ });
17
+ if (result.error || result.status !== 0) {
18
+ return null;
19
+ }
20
+ return result.stdout;
21
+ }
22
+ /**
23
+ * Loads git diffs for the given changed files relative to the given since ref.
24
+ * Uses `git merge-base` to find the accurate base ref first.
25
+ * Individual diffs are truncated at 8000 chars and total output is capped at 60000 chars.
26
+ */
27
+ function loadDiffs(appRoot, since, changedFiles) {
28
+ const result = new Map();
29
+ if (changedFiles.length === 0) {
30
+ return result;
31
+ }
32
+ // Try to get accurate merge base
33
+ let baseRef = since;
34
+ const mergeBaseOutput = runGitRaw(['merge-base', since, 'HEAD'], appRoot);
35
+ if (mergeBaseOutput) {
36
+ const candidate = mergeBaseOutput
37
+ .split('\n')
38
+ .map((line) => line.trim())
39
+ .find(Boolean);
40
+ if (candidate) {
41
+ baseRef = candidate;
42
+ }
43
+ }
44
+ let totalChars = 0;
45
+ for (const file of changedFiles) {
46
+ if (totalChars >= MAX_TOTAL_CHARS) {
47
+ break;
48
+ }
49
+ const diffOutput = runGitRaw(['diff', `${baseRef}..HEAD`, '--', file], appRoot);
50
+ if (diffOutput === null) {
51
+ continue;
52
+ }
53
+ let diff = diffOutput;
54
+ if (diff.length > MAX_DIFF_CHARS) {
55
+ diff = diff.slice(0, MAX_DIFF_CHARS) + TRUNCATION_NOTICE;
56
+ }
57
+ result.set(file, diff);
58
+ totalChars += diff.length;
59
+ }
60
+ return result;
61
+ }
62
+ /**
63
+ * Formats a diffs map into a human-readable string suitable for an AI prompt.
64
+ */
65
+ function formatDiffsForPrompt(diffs) {
66
+ if (diffs.size === 0) {
67
+ return 'No diffs available.';
68
+ }
69
+ const sections = [];
70
+ for (const [file, diff] of diffs) {
71
+ sections.push(`--- ${file} ---\n${diff}`);
72
+ }
73
+ return sections.join('\n\n');
74
+ }
@@ -1,8 +1,9 @@
1
1
  import type { PolicyConfig } from '../agent/config.js';
2
2
  import type { ImpactResult } from './impact_engine.js';
3
+ import type { AIEnrichmentResult } from './ai_enrichment.js';
3
4
  import type { PlanReport, GapDetail, CoveredFlowSummary } from '../agent/plan.js';
4
5
  export type { PlanReport, GapDetail, CoveredFlowSummary };
5
- export declare function buildPlanFromImpact(impact: ImpactResult, policyOverride?: Partial<PolicyConfig>): PlanReport;
6
+ export declare function buildPlanFromImpact(impact: ImpactResult, policyOverride?: Partial<PolicyConfig>, aiEnrichment?: AIEnrichmentResult): PlanReport;
6
7
  export declare function writePlanReport(appRoot: string, plan: PlanReport): string;
7
8
  export declare function renderCiSummaryMarkdown(plan: PlanReport): string;
8
9
  export declare function writeCiSummary(appRoot: string, markdown: string, relativePath?: string): string;
@@ -1 +1 @@
1
- {"version":3,"file":"plan_builder.d.ts","sourceRoot":"","sources":["../../src/engine/plan_builder.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAC,YAAY,EAAkB,MAAM,oBAAoB,CAAC;AAItE,OAAO,KAAK,EACR,UAAU,EACV,SAAS,EACT,kBAAkB,EAIrB,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EAAC,UAAU,EAAE,SAAS,EAAE,kBAAkB,EAAC,CAAC;AAqOxD,wBAAgB,mBAAmB,CAC/B,MAAM,EAAE,YAAY,EACpB,cAAc,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GACvC,UAAU,CAiFZ;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,MAAM,CAMzE;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CA8ChE;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,SAAiC,GAAG,MAAM,CAMvH"}
1
+ {"version":3,"file":"plan_builder.d.ts","sourceRoot":"","sources":["../../src/engine/plan_builder.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAC,YAAY,EAAkB,MAAM,oBAAoB,CAAC;AAEtE,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,oBAAoB,CAAC;AAG3D,OAAO,KAAK,EACR,UAAU,EACV,SAAS,EACT,kBAAkB,EAIrB,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EAAC,UAAU,EAAE,SAAS,EAAE,kBAAkB,EAAC,CAAC;AAqOxD,wBAAgB,mBAAmB,CAC/B,MAAM,EAAE,YAAY,EACpB,cAAc,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,EACtC,YAAY,CAAC,EAAE,kBAAkB,GAClC,UAAU,CA8HZ;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,MAAM,CAMzE;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAoDhE;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,SAAiC,GAAG,MAAM,CAMvH"}