@yasserkhanorg/e2e-agents 1.9.5 → 1.10.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.
Files changed (51) hide show
  1. package/dist/cli/commands/gate.d.ts.map +1 -1
  2. package/dist/cli/commands/gate.js +4 -1
  3. package/dist/cli/commands/impact.d.ts.map +1 -1
  4. package/dist/cli/commands/impact.js +7 -0
  5. package/dist/cli/commands/llm_health.d.ts.map +1 -1
  6. package/dist/cli/commands/llm_health.js +57 -17
  7. package/dist/cli/usage.d.ts.map +1 -1
  8. package/dist/cli/usage.js +4 -0
  9. package/dist/cli.js +1 -1
  10. package/dist/esm/cli/commands/gate.js +4 -1
  11. package/dist/esm/cli/commands/impact.js +7 -0
  12. package/dist/esm/cli/commands/llm_health.js +57 -17
  13. package/dist/esm/cli/usage.js +4 -0
  14. package/dist/esm/cli.js +1 -1
  15. package/dist/esm/knowledge/api_surface.js +265 -34
  16. package/dist/esm/knowledge/failure_history.js +121 -0
  17. package/dist/esm/knowledge/route_families.js +31 -1
  18. package/dist/esm/pipeline/stage1_impact.js +19 -3
  19. package/dist/esm/pipeline/stage2_coverage.js +28 -7
  20. package/dist/esm/pipeline/stage3_generation.js +20 -1
  21. package/dist/esm/prompts/coverage.js +10 -0
  22. package/dist/esm/prompts/generation.js +41 -7
  23. package/dist/esm/validation/guardrails.js +5 -0
  24. package/dist/index.d.ts +1 -1
  25. package/dist/knowledge/api_surface.d.ts +12 -0
  26. package/dist/knowledge/api_surface.d.ts.map +1 -1
  27. package/dist/knowledge/api_surface.js +268 -34
  28. package/dist/knowledge/failure_history.d.ts +39 -0
  29. package/dist/knowledge/failure_history.d.ts.map +1 -0
  30. package/dist/knowledge/failure_history.js +128 -0
  31. package/dist/knowledge/route_families.d.ts +11 -0
  32. package/dist/knowledge/route_families.d.ts.map +1 -1
  33. package/dist/knowledge/route_families.js +32 -1
  34. package/dist/pipeline/stage1_impact.d.ts +1 -1
  35. package/dist/pipeline/stage1_impact.d.ts.map +1 -1
  36. package/dist/pipeline/stage1_impact.js +18 -2
  37. package/dist/pipeline/stage2_coverage.d.ts.map +1 -1
  38. package/dist/pipeline/stage2_coverage.js +28 -7
  39. package/dist/pipeline/stage3_generation.d.ts.map +1 -1
  40. package/dist/pipeline/stage3_generation.js +20 -1
  41. package/dist/prompts/coverage.d.ts.map +1 -1
  42. package/dist/prompts/coverage.js +10 -0
  43. package/dist/prompts/generation.d.ts +1 -1
  44. package/dist/prompts/generation.d.ts.map +1 -1
  45. package/dist/prompts/generation.js +41 -7
  46. package/dist/validation/guardrails.d.ts +2 -0
  47. package/dist/validation/guardrails.d.ts.map +1 -1
  48. package/dist/validation/guardrails.js +5 -0
  49. package/dist/validation/output_schema.d.ts +3 -0
  50. package/dist/validation/output_schema.d.ts.map +1 -1
  51. package/package.json +1 -1
@@ -0,0 +1,128 @@
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.loadFailureHistory = loadFailureHistory;
6
+ exports.saveFailureHistory = saveFailureHistory;
7
+ exports.recordFailures = recordFailures;
8
+ exports.getConfidenceBoost = getConfidenceBoost;
9
+ exports.getPredictedFailures = getPredictedFailures;
10
+ /**
11
+ * Tracks historical test failure correlations: which tests fail when certain files change.
12
+ * Used to boost confidence in impact analysis — if a file change historically breaks a test,
13
+ * future changes to that file should prioritize that test.
14
+ *
15
+ * Data is stored as a JSON file at .e2e-ai-agents/failure-history.json.
16
+ */
17
+ const fs_1 = require("fs");
18
+ const path_1 = require("path");
19
+ const DEFAULT_HISTORY = {
20
+ correlations: [],
21
+ totalRuns: 0,
22
+ updatedAt: new Date().toISOString(),
23
+ };
24
+ function loadFailureHistory(testsRoot) {
25
+ const historyPath = (0, path_1.join)(testsRoot, '.e2e-ai-agents', 'failure-history.json');
26
+ if (!(0, fs_1.existsSync)(historyPath)) {
27
+ return { ...DEFAULT_HISTORY };
28
+ }
29
+ try {
30
+ const raw = JSON.parse((0, fs_1.readFileSync)(historyPath, 'utf-8'));
31
+ if (!Array.isArray(raw.correlations)) {
32
+ return { ...DEFAULT_HISTORY };
33
+ }
34
+ return raw;
35
+ }
36
+ catch {
37
+ return { ...DEFAULT_HISTORY };
38
+ }
39
+ }
40
+ function saveFailureHistory(testsRoot, history) {
41
+ const historyPath = (0, path_1.join)(testsRoot, '.e2e-ai-agents', 'failure-history.json');
42
+ try {
43
+ const dir = (0, path_1.dirname)(historyPath);
44
+ if (!(0, fs_1.existsSync)(dir)) {
45
+ (0, fs_1.mkdirSync)(dir, { recursive: true });
46
+ }
47
+ history.updatedAt = new Date().toISOString();
48
+ (0, fs_1.writeFileSync)(historyPath, JSON.stringify(history, null, 2), 'utf-8');
49
+ }
50
+ catch {
51
+ // Non-fatal — history is advisory, not required
52
+ }
53
+ }
54
+ /**
55
+ * Record that a set of changed files caused a set of spec failures.
56
+ * Call this after a test run where failures were observed.
57
+ */
58
+ function recordFailures(history, changedFiles, failedSpecs) {
59
+ const now = new Date().toISOString();
60
+ const updated = { ...history, totalRuns: history.totalRuns + 1, correlations: [...history.correlations] };
61
+ for (const changedFile of changedFiles) {
62
+ for (const specFile of failedSpecs) {
63
+ const existing = updated.correlations.find((c) => c.changedFile === changedFile && c.specFile === specFile);
64
+ if (existing) {
65
+ existing.count++;
66
+ existing.lastSeen = now;
67
+ }
68
+ else {
69
+ updated.correlations.push({
70
+ changedFile,
71
+ specFile,
72
+ count: 1,
73
+ lastSeen: now,
74
+ });
75
+ }
76
+ }
77
+ }
78
+ // Prune stale correlations (not seen in 90 days)
79
+ const cutoff = new Date();
80
+ cutoff.setDate(cutoff.getDate() - 90);
81
+ const cutoffStr = cutoff.toISOString();
82
+ updated.correlations = updated.correlations.filter((c) => c.lastSeen >= cutoffStr);
83
+ return updated;
84
+ }
85
+ /**
86
+ * Get a confidence boost (0-20) for a file based on historical failure patterns.
87
+ * A file that historically causes test failures gets a higher confidence boost
88
+ * when detected as impacted, meaning the system is more confident it needs testing.
89
+ */
90
+ function getConfidenceBoost(history, changedFile) {
91
+ const correlations = history.correlations.filter((c) => c.changedFile === changedFile);
92
+ if (correlations.length === 0) {
93
+ return 0;
94
+ }
95
+ // More correlations and higher counts = more confidence
96
+ const totalCount = correlations.reduce((sum, c) => sum + c.count, 0);
97
+ const uniqueSpecs = correlations.length;
98
+ // Scale: 1 correlation = +5, 3+ = +10, 5+ with high counts = +15, max +20
99
+ if (totalCount >= 10 && uniqueSpecs >= 5)
100
+ return 20;
101
+ if (totalCount >= 5 && uniqueSpecs >= 3)
102
+ return 15;
103
+ if (totalCount >= 3)
104
+ return 10;
105
+ return 5;
106
+ }
107
+ /**
108
+ * Get the most likely failing specs for a set of changed files, based on history.
109
+ * Returns specs sorted by correlation strength (count * recency).
110
+ */
111
+ function getPredictedFailures(history, changedFiles, limit = 10) {
112
+ const specScores = new Map();
113
+ for (const changedFile of changedFiles) {
114
+ for (const c of history.correlations) {
115
+ if (c.changedFile !== changedFile)
116
+ continue;
117
+ // Score: count weighted by recency (days since last seen)
118
+ const daysSince = (Date.now() - new Date(c.lastSeen).getTime()) / (1000 * 60 * 60 * 24);
119
+ const recencyWeight = Math.max(0.1, 1 - daysSince / 90);
120
+ const score = c.count * recencyWeight;
121
+ specScores.set(c.specFile, (specScores.get(c.specFile) || 0) + score);
122
+ }
123
+ }
124
+ return Array.from(specScores.entries())
125
+ .map(([specFile, score]) => ({ specFile, score }))
126
+ .sort((a, b) => b.score - a.score)
127
+ .slice(0, limit);
128
+ }
@@ -1,4 +1,9 @@
1
1
  export type FeaturePriority = 'P0' | 'P1' | 'P2';
2
+ export type AssertionType = 'state-change' | 'cross-user' | 'persistence' | 'negative' | 'permission' | 'data-integrity' | 'error-handling';
3
+ export interface AssertionPattern {
4
+ type: AssertionType;
5
+ pattern: string;
6
+ }
2
7
  export interface RouteFeature {
3
8
  id: string;
4
9
  routes?: string[];
@@ -9,6 +14,7 @@ export interface RouteFeature {
9
14
  tags?: string[];
10
15
  priority?: FeaturePriority;
11
16
  userFlows?: string[];
17
+ assertionPatterns?: AssertionPattern[];
12
18
  }
13
19
  export interface ApiEndpoint {
14
20
  method: string;
@@ -31,6 +37,7 @@ export interface RouteFamily {
31
37
  features?: RouteFeature[];
32
38
  apiEndpoints?: ApiEndpoint[];
33
39
  testType?: TestType;
40
+ assertionPatterns?: AssertionPattern[];
34
41
  }
35
42
  export interface RouteFamilyManifest {
36
43
  families: RouteFamily[];
@@ -73,6 +80,10 @@ export declare function getRoutesForBinding(manifest: RouteFamilyManifest, bindi
73
80
  family: string;
74
81
  feature?: string;
75
82
  }): string[];
83
+ export declare function getAssertionPatternsForBinding(manifest: RouteFamilyManifest, binding: {
84
+ family: string;
85
+ feature?: string;
86
+ }): AssertionPattern[];
76
87
  export declare function clearManifestCache(): void;
77
88
  /**
78
89
  * Build heuristic route families from changed files when no manifest exists.
@@ -1 +1 @@
1
- {"version":3,"file":"route_families.d.ts","sourceRoot":"","sources":["../../src/knowledge/route_families.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,eAAe,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEjD,MAAM,WAAW,YAAY;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,MAAM,QAAQ,GAAG,IAAI,GAAG,KAAK,GAAG,MAAM,CAAC;AAE7C,MAAM,WAAW,WAAW;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,QAAQ,CAAC,EAAE,YAAY,EAAE,CAAC;IAC1B,YAAY,CAAC,EAAE,WAAW,EAAE,CAAC;IAC7B,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IAChC,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,KAAK,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC;CACvD;AAED,MAAM,WAAW,iBAAiB;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;CACpB;AAID,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAwBtE;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAE/E;AAuHD,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,iBAAiB,GAAG,mBAAmB,GAAG,IAAI,CAyCjH;AAED,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,mBAAmB,GAAG,WAAW,EAAE,CAyCxG;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAEtG;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAE/F;AAED,wBAAgB,qBAAqB,CACjC,QAAQ,EAAE,mBAAmB,EAC7B,OAAO,EAAE;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAC,GAC5C,MAAM,EAAE,CAaV;AAED,wBAAgB,4BAA4B,CACxC,QAAQ,EAAE,mBAAmB,EAC7B,OAAO,EAAE;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAC,GAC5C,MAAM,EAAE,CAaV;AAED,wBAAgB,qBAAqB,CACjC,QAAQ,EAAE,mBAAmB,EAC7B,OAAO,EAAE;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAC,GAC5C,eAAe,CAYjB;AAED,wBAAgB,sBAAsB,CAClC,QAAQ,EAAE,mBAAmB,EAC7B,OAAO,EAAE;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAC,GAC5C,MAAM,EAAE,CAYV;AAED,wBAAgB,mBAAmB,CAC/B,QAAQ,EAAE,mBAAmB,EAC7B,OAAO,EAAE;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAC,GAC5C,MAAM,EAAE,CAYV;AAED,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,YAAY,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,mBAAmB,CAsCrG;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,mBAAmB,GAAG,MAAM,CAmBvE"}
1
+ {"version":3,"file":"route_families.d.ts","sourceRoot":"","sources":["../../src/knowledge/route_families.ts"],"names":[],"mappings":"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"}
@@ -13,6 +13,7 @@ exports.getCypressSpecDirsForBinding = getCypressSpecDirsForBinding;
13
13
  exports.getPriorityForBinding = getPriorityForBinding;
14
14
  exports.getUserFlowsForBinding = getUserFlowsForBinding;
15
15
  exports.getRoutesForBinding = getRoutesForBinding;
16
+ exports.getAssertionPatternsForBinding = getAssertionPatternsForBinding;
16
17
  exports.clearManifestCache = clearManifestCache;
17
18
  exports.buildHeuristicFamilies = buildHeuristicFamilies;
18
19
  exports.serializeManifest = serializeManifest;
@@ -122,8 +123,22 @@ function validateFamily(family) {
122
123
  if (testType) {
123
124
  result.testType = testType;
124
125
  }
126
+ if (Array.isArray(obj.assertionPatterns)) {
127
+ result.assertionPatterns = validateAssertionPatterns(obj.assertionPatterns);
128
+ }
125
129
  return result;
126
130
  }
131
+ const VALID_ASSERTION_TYPES = [
132
+ 'state-change', 'cross-user', 'persistence', 'negative',
133
+ 'permission', 'data-integrity', 'error-handling',
134
+ ];
135
+ function validateAssertionPatterns(patterns) {
136
+ return patterns
137
+ .filter((p) => p != null && typeof p === 'object')
138
+ .filter((p) => typeof p.type === 'string' && typeof p.pattern === 'string')
139
+ .filter((p) => VALID_ASSERTION_TYPES.includes(p.type))
140
+ .map((p) => ({ type: p.type, pattern: p.pattern }));
141
+ }
127
142
  function validateFeature(feature) {
128
143
  if (!feature || typeof feature !== 'object') {
129
144
  return null;
@@ -157,6 +172,9 @@ function validateFeature(feature) {
157
172
  if (Array.isArray(obj.userFlows)) {
158
173
  result.userFlows = obj.userFlows.filter((v) => typeof v === 'string');
159
174
  }
175
+ if (Array.isArray(obj.assertionPatterns)) {
176
+ result.assertionPatterns = validateAssertionPatterns(obj.assertionPatterns);
177
+ }
160
178
  return result;
161
179
  }
162
180
  function loadRouteFamilyManifest(testsRoot, config) {
@@ -310,6 +328,19 @@ function getRoutesForBinding(manifest, binding) {
310
328
  }
311
329
  return family.routes;
312
330
  }
331
+ function getAssertionPatternsForBinding(manifest, binding) {
332
+ const family = getFamilyById(manifest, binding.family);
333
+ if (!family) {
334
+ return [];
335
+ }
336
+ if (binding.feature) {
337
+ const feature = getFeatureById(family, binding.feature);
338
+ if (feature?.assertionPatterns && feature.assertionPatterns.length > 0) {
339
+ return feature.assertionPatterns;
340
+ }
341
+ }
342
+ return family.assertionPatterns || [];
343
+ }
313
344
  function clearManifestCache() {
314
345
  manifestCache.clear();
315
346
  }
@@ -361,7 +392,7 @@ function serializeManifest(manifest) {
361
392
  const cleaned = { ...f };
362
393
  const optionalArrays = [
363
394
  'pageObjects', 'components', 'webappPaths', 'serverPaths',
364
- 'specDirs', 'cypressSpecDirs', 'tags', 'userFlows', 'features', 'apiEndpoints',
395
+ 'specDirs', 'cypressSpecDirs', 'tags', 'userFlows', 'features', 'apiEndpoints', 'assertionPatterns',
365
396
  ];
366
397
  for (const key of optionalArrays) {
367
398
  if (!cleaned[key] || (Array.isArray(cleaned[key]) && cleaned[key].length === 0)) {
@@ -15,5 +15,5 @@ export interface ImpactResult {
15
15
  warnings: string[];
16
16
  providerName: string;
17
17
  }
18
- export declare function runImpactStage(familyGroups: FamilyGroup[], manifest: RouteFamilyManifest | null, specIndex: SpecIndex, apiSurface: ApiSurfaceCatalog, context: LoadedContext, config: ImpactConfig): Promise<ImpactResult>;
18
+ export declare function runImpactStage(familyGroups: FamilyGroup[], manifest: RouteFamilyManifest | null, specIndex: SpecIndex, apiSurface: ApiSurfaceCatalog, context: LoadedContext, config: ImpactConfig, testsRoot?: string): Promise<ImpactResult>;
19
19
  //# sourceMappingURL=stage1_impact.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"stage1_impact.d.ts","sourceRoot":"","sources":["../../src/pipeline/stage1_impact.ts"],"names":[],"mappings":"AAOA,OAAO,EAAgB,KAAK,mBAAmB,EAAC,MAAM,gCAAgC,CAAC;AACvF,OAAO,EAAoB,KAAK,SAAS,EAAC,MAAM,4BAA4B,CAAC;AAC7E,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,6BAA6B,CAAC;AACnE,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,gCAAgC,CAAC;AAClE,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,wBAAwB,CAAC;AACxD,OAAO,KAAK,EAAC,YAAY,EAA+B,MAAM,gCAAgC,CAAC;AAG/F,MAAM,WAAW,YAAY;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IACzB,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACxB;AAgBD,wBAAsB,cAAc,CAChC,YAAY,EAAE,WAAW,EAAE,EAC3B,QAAQ,EAAE,mBAAmB,GAAG,IAAI,EACpC,SAAS,EAAE,SAAS,EACpB,UAAU,EAAE,iBAAiB,EAC7B,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,YAAY,GACrB,OAAO,CAAC,YAAY,CAAC,CAmHvB"}
1
+ {"version":3,"file":"stage1_impact.d.ts","sourceRoot":"","sources":["../../src/pipeline/stage1_impact.ts"],"names":[],"mappings":"AAOA,OAAO,EAAgD,KAAK,mBAAmB,EAAC,MAAM,gCAAgC,CAAC;AAEvH,OAAO,EAAoB,KAAK,SAAS,EAAC,MAAM,4BAA4B,CAAC;AAC7E,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,6BAA6B,CAAC;AACnE,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,gCAAgC,CAAC;AAClE,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,wBAAwB,CAAC;AACxD,OAAO,KAAK,EAAC,YAAY,EAA+B,MAAM,gCAAgC,CAAC;AAG/F,MAAM,WAAW,YAAY;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IACzB,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACxB;AAgBD,wBAAsB,cAAc,CAChC,YAAY,EAAE,WAAW,EAAE,EAC3B,QAAQ,EAAE,mBAAmB,GAAG,IAAI,EACpC,SAAS,EAAE,SAAS,EACpB,UAAU,EAAE,iBAAiB,EAC7B,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,YAAY,EACpB,SAAS,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,YAAY,CAAC,CAqIvB"}
@@ -7,6 +7,7 @@ const provider_factory_js_1 = require("../provider_factory.js");
7
7
  const impact_js_1 = require("../prompts/impact.js");
8
8
  const context_loader_js_1 = require("../knowledge/context_loader.js");
9
9
  const route_families_js_1 = require("../knowledge/route_families.js");
10
+ const failure_history_js_1 = require("../knowledge/failure_history.js");
10
11
  const spec_index_js_1 = require("../knowledge/spec_index.js");
11
12
  const guardrails_js_1 = require("../validation/guardrails.js");
12
13
  function normalizePriority(value) {
@@ -21,7 +22,7 @@ async function getProvider(config) {
21
22
  }
22
23
  return provider_factory_js_1.LLMProviderFactory.createFromEnv();
23
24
  }
24
- async function runImpactStage(familyGroups, manifest, specIndex, apiSurface, context, config) {
25
+ async function runImpactStage(familyGroups, manifest, specIndex, apiSurface, context, config, testsRoot) {
25
26
  const warnings = [];
26
27
  const allDecisions = [];
27
28
  if (familyGroups.length === 0) {
@@ -38,6 +39,8 @@ async function runImpactStage(familyGroups, manifest, specIndex, apiSurface, con
38
39
  return { decisions: [], warnings, providerName: 'none' };
39
40
  }
40
41
  const contextBlock = (0, context_loader_js_1.formatContextForPrompt)(context);
42
+ // Load historical failure correlations for confidence boosting
43
+ const failureHistory = testsRoot ? (0, failure_history_js_1.loadFailureHistory)(testsRoot) : null;
41
44
  for (const group of familyGroups) {
42
45
  const family = manifest ? (0, route_families_js_1.getFamilyById)(manifest, group.familyId) : null;
43
46
  if (!family) {
@@ -86,15 +89,27 @@ async function runImpactStage(familyGroups, manifest, specIndex, apiSurface, con
86
89
  if (!flow.id || !flow.changedFiles || !Array.isArray(flow.changedFiles)) {
87
90
  continue;
88
91
  }
92
+ // Compute confidence with optional historical failure boost
93
+ const changedFilesList = Array.isArray(flow.changedFiles)
94
+ ? flow.changedFiles.filter((f) => typeof f === 'string')
95
+ : [];
96
+ const historyBoost = failureHistory
97
+ ? Math.max(...changedFilesList.map((f) => (0, failure_history_js_1.getConfidenceBoost)(failureHistory, f)), 0)
98
+ : 0;
89
99
  const confidence = typeof flow.confidence === 'number'
90
- ? Math.max(0, Math.min(100, flow.confidence))
100
+ ? Math.min(100, Math.max(0, flow.confidence) + historyBoost)
91
101
  : (0, guardrails_js_1.computeConfidence)({
92
102
  hasRouteFamily: true,
93
103
  hasSpecificRoute: Boolean(flow.route),
94
104
  hasPageObject: Boolean(flow.pageObjects && flow.pageObjects.length > 0),
95
105
  hasUserAction: Boolean(flow.userActions && flow.userActions.length > 0),
96
106
  hasExistingSpecCited: false,
107
+ historyBoost,
97
108
  });
109
+ // Resolve assertion patterns from manifest for this flow's family/feature
110
+ const assertionPatterns = manifest
111
+ ? (0, route_families_js_1.getAssertionPatternsForBinding)(manifest, { family: group.familyId, feature: group.featureId })
112
+ : [];
98
113
  const decision = {
99
114
  flowId: flow.id,
100
115
  flowName: flow.name || flow.id,
@@ -110,6 +125,7 @@ async function runImpactStage(familyGroups, manifest, specIndex, apiSurface, con
110
125
  blockingReason: (0, guardrails_js_1.shouldForceCannotDetermine)(confidence) ? 'Confidence too low to determine action.' : undefined,
111
126
  priority: normalizePriority(flow.priority),
112
127
  userActions: Array.isArray(flow.userActions) ? flow.userActions.filter((a) => typeof a === 'string') : [],
128
+ assertionPatterns: assertionPatterns.length > 0 ? assertionPatterns : undefined,
113
129
  };
114
130
  allDecisions.push(decision);
115
131
  }
@@ -1 +1 @@
1
- {"version":3,"file":"stage2_coverage.d.ts","sourceRoot":"","sources":["../../src/pipeline/stage2_coverage.ts"],"names":[],"mappings":"AAMA,OAAO,EAA8C,KAAK,aAAa,EAAC,MAAM,gCAAgC,CAAC;AAC/G,OAAO,EAAoB,KAAK,SAAS,EAAC,MAAM,4BAA4B,CAAC;AAC7E,OAAO,KAAK,EAAC,YAAY,EAA4B,MAAM,gCAAgC,CAAC;AAC5F,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,kCAAkC,CAAC;AAExE,MAAM,WAAW,cAAc;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,OAAO,CAAC,EAAE,iBAAiB,CAAC;CAC/B;AAED,MAAM,WAAW,cAAc;IAC3B,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACxB;AAYD,wBAAsB,gBAAgB,CAClC,SAAS,EAAE,YAAY,EAAE,EACzB,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,aAAa,EACtB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,cAAc,GACvB,OAAO,CAAC,cAAc,CAAC,CAoIzB"}
1
+ {"version":3,"file":"stage2_coverage.d.ts","sourceRoot":"","sources":["../../src/pipeline/stage2_coverage.ts"],"names":[],"mappings":"AAMA,OAAO,EAA8C,KAAK,aAAa,EAAC,MAAM,gCAAgC,CAAC;AAC/G,OAAO,EAAoB,KAAK,SAAS,EAAC,MAAM,4BAA4B,CAAC;AAC7E,OAAO,KAAK,EAAC,YAAY,EAA4B,MAAM,gCAAgC,CAAC;AAC5F,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,kCAAkC,CAAC;AAExE,MAAM,WAAW,cAAc;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,OAAO,CAAC,EAAE,iBAAiB,CAAC;CAC/B;AAED,MAAM,WAAW,cAAc;IAC3B,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACxB;AAYD,wBAAsB,gBAAgB,CAClC,SAAS,EAAE,YAAY,EAAE,EACzB,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,aAAa,EACtB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,cAAc,GACvB,OAAO,CAAC,cAAc,CAAC,CAyJzB"}
@@ -46,13 +46,26 @@ async function runCoverageStage(decisions, specIndex, context, testsRoot, config
46
46
  for (const [familyId, familyDecisions] of byFamily) {
47
47
  // Gather relevant specs
48
48
  const specs = (0, spec_index_js_1.getSpecsForFamily)(specIndex, familyId);
49
- const specsWithContent = specs
50
- .map((s) => {
49
+ // Two-tier approach: send all spec titles (compact), full content for top matches only
50
+ const allSpecSummaries = specs.map((s) => ({
51
+ relativePath: s.relativePath,
52
+ testTitles: s.testTitles,
53
+ }));
54
+ // Load full content with a total budget of 200K chars (~50K tokens) to avoid blowing context windows
55
+ const MAX_TOTAL_SPEC_CHARS = 200000;
56
+ let totalSpecChars = 0;
57
+ const specsWithContent = [];
58
+ for (const s of specs) {
59
+ if (specsWithContent.length >= 30)
60
+ break;
51
61
  const content = (0, context_loader_js_1.loadSpecFileContent)(testsRoot, s.relativePath, maxSpecChars);
52
- return content ? { relativePath: s.relativePath, content, testTitles: s.testTitles } : null;
53
- })
54
- .filter((s) => s !== null)
55
- .slice(0, 15); // Limit to 15 specs per family to stay within token budget
62
+ if (!content)
63
+ continue;
64
+ if (totalSpecChars + content.length > MAX_TOTAL_SPEC_CHARS)
65
+ break;
66
+ totalSpecChars += content.length;
67
+ specsWithContent.push({ relativePath: s.relativePath, content, testTitles: s.testTitles });
68
+ }
56
69
  if (specsWithContent.length === 0) {
57
70
  // No specs to evaluate — mark all as create_spec
58
71
  for (const d of familyDecisions) {
@@ -73,10 +86,18 @@ async function runCoverageStage(decisions, specIndex, context, testsRoot, config
73
86
  evidence: d.evidence,
74
87
  priority: d.priority,
75
88
  }));
89
+ // Include titles-only summaries for specs beyond the content limit
90
+ const extraSummaries = allSpecSummaries
91
+ .slice(specsWithContent.length)
92
+ .map((s) => ` - ${s.relativePath}: ${s.testTitles.join(', ')}`)
93
+ .join('\n');
94
+ const extraContext = extraSummaries
95
+ ? `\nADDITIONAL SPECS (titles only, no content loaded):\n${extraSummaries}\n`
96
+ : '';
76
97
  const prompt = (0, coverage_js_1.buildCoveragePrompt)({
77
98
  flows,
78
99
  specs: specsWithContent,
79
- contextBlock,
100
+ contextBlock: contextBlock + extraContext,
80
101
  profile: config.profile,
81
102
  });
82
103
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"stage3_generation.d.ts","sourceRoot":"","sources":["../../src/pipeline/stage3_generation.ts"],"names":[],"mappings":"AAQA,OAAO,EAAC,mBAAmB,EAAC,MAAM,gCAAgC,CAAC;AAInE,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,gCAAgC,CAAC;AACjE,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,6BAA6B,CAAC;AACnE,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,kCAAkC,CAAC;AAExE,MAAM,WAAW,gBAAgB;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,yEAAyE;IACzE,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,+EAA+E;IAC/E,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,iBAAiB,CAAC;CAC/B;AAED,MAAM,WAAW,aAAa;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,aAAa,GAAG,eAAe,CAAC;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,yCAAyC;IACzC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,gBAAgB;IAC7B,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,sCAAsC;IACtC,cAAc,EAAE,MAAM,CAAC;IACvB,6CAA6C;IAC7C,aAAa,EAAE,MAAM,CAAC;IACtB,sCAAsC;IACtC,WAAW,EAAE,MAAM,CAAC;CACvB;AAyCD,wBAAsB,kBAAkB,CACpC,SAAS,EAAE,YAAY,EAAE,EACzB,UAAU,EAAE,iBAAiB,EAC7B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,gBAAgB,GACzB,OAAO,CAAC,gBAAgB,CAAC,CA2I3B;AAqHD,OAAO,EAAC,mBAAmB,EAAC,CAAC"}
1
+ {"version":3,"file":"stage3_generation.d.ts","sourceRoot":"","sources":["../../src/pipeline/stage3_generation.ts"],"names":[],"mappings":"AAQA,OAAO,EAAC,mBAAmB,EAAC,MAAM,gCAAgC,CAAC;AAInE,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,gCAAgC,CAAC;AACjE,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,6BAA6B,CAAC;AACnE,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,kCAAkC,CAAC;AAExE,MAAM,WAAW,gBAAgB;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,yEAAyE;IACzE,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,+EAA+E;IAC/E,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,iBAAiB,CAAC;CAC/B;AAED,MAAM,WAAW,aAAa;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,aAAa,GAAG,eAAe,CAAC;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,yCAAyC;IACzC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,gBAAgB;IAC7B,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,sCAAsC;IACtC,cAAc,EAAE,MAAM,CAAC;IACvB,6CAA6C;IAC7C,aAAa,EAAE,MAAM,CAAC;IACtB,sCAAsC;IACtC,WAAW,EAAE,MAAM,CAAC;CACvB;AAyCD,wBAAsB,kBAAkB,CACpC,SAAS,EAAE,YAAY,EAAE,EACzB,UAAU,EAAE,iBAAiB,EAC7B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,gBAAgB,GACzB,OAAO,CAAC,gBAAgB,CAAC,CA8J3B;AAqHD,OAAO,EAAC,mBAAmB,EAAC,CAAC"}
@@ -106,10 +106,29 @@ async function runGenerationStage(decisions, apiSurface, testsRoot, config) {
106
106
  skipped.push(`${decision.flowId}: invalid code returned`);
107
107
  continue;
108
108
  }
109
- // Hallucination detection
109
+ // Hallucination detection — block specs with hallucinated methods
110
110
  const hallucinationWarnings = (0, generation_js_1.detectHallucinatedMethods)(parsed.code, apiSurface);
111
111
  if (hallucinationWarnings.length > 0) {
112
112
  warnings.push(`Flow ${decision.flowId}: suspected hallucinated methods: ${hallucinationWarnings.join(', ')}`);
113
+ if (!config.warnOnHallucinations) {
114
+ // Block: move to needs-review instead of writing to specs dir
115
+ if (!dryRun) {
116
+ const reviewDir = (0, path_1.join)(testsRoot, 'generated-needs-review');
117
+ (0, fs_1.mkdirSync)(reviewDir, { recursive: true });
118
+ const safeName = decision.flowId.replace(/[^a-zA-Z0-9_-]/g, '_').toLowerCase();
119
+ const reviewPath = (0, path_1.join)(reviewDir, `${safeName}-${Date.now().toString(36)}.spec.ts`);
120
+ (0, fs_1.writeFileSync)(reviewPath, `${parsed.code}\n`, 'utf-8');
121
+ warnings.push(`Flow ${decision.flowId}: blocked — moved to ${reviewPath}`);
122
+ }
123
+ generated.push({
124
+ flowId: decision.flowId,
125
+ specPath,
126
+ mode,
127
+ written: false,
128
+ hallucinationWarnings,
129
+ });
130
+ continue;
131
+ }
113
132
  }
114
133
  let written = false;
115
134
  if (!dryRun) {
@@ -1 +1 @@
1
- {"version":3,"file":"coverage.d.ts","sourceRoot":"","sources":["../../src/prompts/coverage.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,yBAAyB,CAAC;AAE/D,MAAM,WAAW,kBAAkB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IAClC,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAC5B,KAAK,EAAE,KAAK,CAAC;QACT,YAAY,EAAE,MAAM,CAAC;QACrB,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,EAAE,CAAC;KACxB,CAAC,CAAC;IACH,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,iBAAiB,CAAC;CAC/B;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,qBAAqB,GAAG,MAAM,CAyCtE;AAED,MAAM,WAAW,qBAAqB;IAClC,QAAQ,EAAE,KAAK,CAAC;QACZ,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;QACf,aAAa,CAAC,EAAE,KAAK,CAAC;YAClB,IAAI,EAAE,MAAM,CAAC;YACb,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;YACtB,aAAa,CAAC,EAAE,MAAM,CAAC;YACvB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;SAC/B,CAAC,CAAC;QACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;QAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,UAAU,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC,CAAC;CACN;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,qBAAqB,GAAG,IAAI,CAMhF"}
1
+ {"version":3,"file":"coverage.d.ts","sourceRoot":"","sources":["../../src/prompts/coverage.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,yBAAyB,CAAC;AAE/D,MAAM,WAAW,kBAAkB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IAClC,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAC5B,KAAK,EAAE,KAAK,CAAC;QACT,YAAY,EAAE,MAAM,CAAC;QACrB,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,EAAE,CAAC;KACxB,CAAC,CAAC;IACH,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,iBAAiB,CAAC;CAC/B;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,qBAAqB,GAAG,MAAM,CAmDtE;AAED,MAAM,WAAW,qBAAqB;IAClC,QAAQ,EAAE,KAAK,CAAC;QACZ,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;QACf,aAAa,CAAC,EAAE,KAAK,CAAC;YAClB,IAAI,EAAE,MAAM,CAAC;YACb,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;YACtB,aAAa,CAAC,EAAE,MAAM,CAAC;YACvB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;SAC/B,CAAC,CAAC;QACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;QAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,UAAU,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC,CAAC;CACN;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,qBAAqB,GAAG,IAAI,CAMhF"}
@@ -44,6 +44,16 @@ function buildCoveragePrompt(ctx) {
44
44
  '- For add_scenarios, specify which existing spec file to extend in targetSpec.',
45
45
  `- For create_spec, suggest a path following ${ctx.profile?.projectName || 'Mattermost'} conventions.`,
46
46
  '- Prefer adding scenarios to existing specs over creating new spec files.',
47
+ '',
48
+ 'SEMANTIC MATCHING RULES (critical for accuracy):',
49
+ '- A happy-path test does NOT cover the negative/error path of the same feature.',
50
+ ' "user can edit post" does NOT cover "user without permission cannot edit post".',
51
+ '- A test for one user role does NOT cover a different role.',
52
+ ' "admin can delete channel" does NOT cover "member cannot delete channel".',
53
+ '- A test for creation does NOT cover editing or deletion of the same entity.',
54
+ '- "partial" means: same feature area but different specific scenario.',
55
+ '- "full" means: the exact user action sequence and outcome is tested.',
56
+ '- When in doubt between "full" and "partial", choose "partial".',
47
57
  ].join('\n');
48
58
  }
49
59
  function parseCoverageResponse(text) {
@@ -19,7 +19,7 @@ export interface GenerationAgentResponse {
19
19
  export declare function parseGenerationResponse(text: string, expectedPath: string, mode: 'create_spec' | 'add_scenarios', flowId: string, profile?: GenerationProfile): GenerationAgentResponse | null;
20
20
  /**
21
21
  * Returns method names that appear in generated code but do not exist in the API surface.
22
- * Used for logging; does not block generation.
22
+ * Detects all call patterns: await X.Y(), X.Y(), const z = X.Y(), chained calls.
23
23
  */
24
24
  export declare function detectHallucinatedMethods(code: string, apiSurface: ApiSurfaceCatalog): string[];
25
25
  //# sourceMappingURL=generation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"generation.d.ts","sourceRoot":"","sources":["../../src/prompts/generation.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,gCAAgC,CAAC;AACjE,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,6BAA6B,CAAC;AAGnE,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,yBAAyB,CAAC;AAG/D,MAAM,WAAW,uBAAuB;IACpC,QAAQ,EAAE,YAAY,CAAC;IACvB,UAAU,EAAE,iBAAiB,CAAC;IAC9B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,aAAa,GAAG,eAAe,CAAC;IACtC,OAAO,CAAC,EAAE,iBAAiB,CAAC;CAC/B;AA6BD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,uBAAuB,GAAG,MAAM,CAyH1E;AA8ED,MAAM,WAAW,uBAAuB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,aAAa,GAAG,eAAe,CAAC;IACtC,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,uBAAuB,CACnC,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,aAAa,GAAG,eAAe,EACrC,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,iBAAiB,GAC5B,uBAAuB,GAAG,IAAI,CAuBhC;AAwBD;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,iBAAiB,GAAG,MAAM,EAAE,CAc/F"}
1
+ {"version":3,"file":"generation.d.ts","sourceRoot":"","sources":["../../src/prompts/generation.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,YAAY,EAAmB,MAAM,gCAAgC,CAAC;AACnF,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,6BAA6B,CAAC;AAGnE,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,yBAAyB,CAAC;AAG/D,MAAM,WAAW,uBAAuB;IACpC,QAAQ,EAAE,YAAY,CAAC;IACvB,UAAU,EAAE,iBAAiB,CAAC;IAC9B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,aAAa,GAAG,eAAe,CAAC;IACtC,OAAO,CAAC,EAAE,iBAAiB,CAAC;CAC/B;AA0CD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,uBAAuB,GAAG,MAAM,CA0H1E;AAgFD,MAAM,WAAW,uBAAuB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,aAAa,GAAG,eAAe,CAAC;IACtC,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,uBAAuB,CACnC,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,aAAa,GAAG,eAAe,EACrC,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,iBAAiB,GAC5B,uBAAuB,GAAG,IAAI,CAuBhC;AAwBD;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,iBAAiB,GAAG,MAAM,EAAE,CAsC/F"}
@@ -27,6 +27,18 @@ function resolveRelevantPageObjects(apiSurface, decision) {
27
27
  }
28
28
  return [...new Set(relevant)].slice(0, 10);
29
29
  }
30
+ function buildAssertionPatternsBlock(patterns) {
31
+ if (!patterns || patterns.length === 0) {
32
+ return [];
33
+ }
34
+ return [
35
+ 'REQUIRED ASSERTION PATTERNS:',
36
+ 'Your tests MUST include assertions that verify each of these behaviors.',
37
+ 'Do NOT just check element visibility — verify the actual business outcome.',
38
+ ...patterns.map((p) => ` - [${p.type}] ${p.pattern}`),
39
+ '',
40
+ ];
41
+ }
30
42
  function buildGenerationPrompt(ctx) {
31
43
  const profile = ctx.profile;
32
44
  const isMM = profile ? (0, generation_profile_js_1.isMattermostProfile)(profile) : true;
@@ -127,6 +139,7 @@ function buildGenerationPrompt(ctx) {
127
139
  'USER ACTIONS:',
128
140
  ctx.decision.userActions.map((a) => ` - ${(0, sanitize_js_1.sanitizeForPrompt)(a)}`).join('\n') || ' (none specified)',
129
141
  '',
142
+ ...buildAssertionPatternsBlock(ctx.decision.assertionPatterns),
130
143
  'AVAILABLE PAGE OBJECTS AND METHODS:',
131
144
  apiBlock,
132
145
  existingBlock,
@@ -162,6 +175,8 @@ function buildApiTestPrompt(ctx, profile, scenariosBlock, routeFamilyTag) {
162
175
  '',
163
176
  'USER ACTIONS:',
164
177
  ctx.decision.userActions.map((a) => ` - ${(0, sanitize_js_1.sanitizeForPrompt)(a)}`).join('\n') || ' (none specified)',
178
+ '',
179
+ ...buildAssertionPatternsBlock(ctx.decision.assertionPatterns),
165
180
  existingBlock,
166
181
  '',
167
182
  'MANDATORY RULES:',
@@ -251,18 +266,37 @@ const BUILT_IN_METHODS = new Set([
251
266
  ]);
252
267
  /**
253
268
  * Returns method names that appear in generated code but do not exist in the API surface.
254
- * Used for logging; does not block generation.
269
+ * Detects all call patterns: await X.Y(), X.Y(), const z = X.Y(), chained calls.
255
270
  */
256
271
  function detectHallucinatedMethods(code, apiSurface) {
257
272
  const allMethods = new Set(apiSurface.pageObjects.flatMap((po) => po.methods.map((m) => m.name)));
258
- const suspected = [];
259
- const callRe = /\bawait\s+\w+\.([a-zA-Z_]\w*)\s*\(/g;
273
+ const suspected = new Set();
274
+ const callPatterns = [
275
+ /\bawait\s+\w+\.([a-zA-Z_]\w*)\s*\(/g,
276
+ /\b(?:const|let|var)\s+\w+\s*=\s*\w+\.([a-zA-Z_]\w*)\s*\(/g,
277
+ /\b\w+Page\.([a-zA-Z_]\w*)\s*\(/g, // any *Page object (channelsPage, settingsPage, etc.)
278
+ /\b(?:pw|page|this)\.\w*\.?([a-zA-Z_]\w*)\s*\(/g,
279
+ ];
280
+ const generalCallRe = /\b[a-zA-Z_]\w*\.([a-zA-Z_]\w*)\s*\(/g;
281
+ for (const re of callPatterns) {
282
+ let match;
283
+ while ((match = re.exec(code)) !== null) {
284
+ const methodName = match[1];
285
+ if (!BUILT_IN_METHODS.has(methodName) && !allMethods.has(methodName) && methodName.length > 3) {
286
+ suspected.add(methodName);
287
+ }
288
+ }
289
+ }
260
290
  let match;
261
- while ((match = callRe.exec(code)) !== null) {
291
+ while ((match = generalCallRe.exec(code)) !== null) {
262
292
  const methodName = match[1];
263
- if (!BUILT_IN_METHODS.has(methodName) && !allMethods.has(methodName) && methodName.length > 3) {
264
- suspected.push(methodName);
293
+ if (!BUILT_IN_METHODS.has(methodName) &&
294
+ !allMethods.has(methodName) &&
295
+ methodName.length > 3 &&
296
+ !methodName.startsWith('to') &&
297
+ !methodName.startsWith('get')) {
298
+ suspected.add(methodName);
265
299
  }
266
300
  }
267
- return [...new Set(suspected)];
301
+ return [...suspected];
268
302
  }
@@ -5,6 +5,8 @@ export interface EvidenceCheck {
5
5
  hasPageObject: boolean;
6
6
  hasUserAction: boolean;
7
7
  hasExistingSpecCited: boolean;
8
+ /** Historical failure correlation boost (0-20) from failure_history */
9
+ historyBoost?: number;
8
10
  }
9
11
  export type ConfidenceClass = 'high' | 'medium' | 'low';
10
12
  export declare const EVIDENCE_THRESHOLDS: {
@@ -1 +1 @@
1
- {"version":3,"file":"guardrails.d.ts","sourceRoot":"","sources":["../../src/validation/guardrails.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,gCAAgC,CAAC;AAExE,MAAM,WAAW,aAAa;IAC1B,cAAc,EAAE,OAAO,CAAC;IACxB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,aAAa,EAAE,OAAO,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;IACvB,oBAAoB,EAAE,OAAO,CAAC;CACjC;AAED,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AAExD,eAAO,MAAM,mBAAmB;;;;;CAKtB,CAAC;AAEX,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAkB9D;AAED,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,CAQtE;AAED,wBAAgB,0BAA0B,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAEtE;AAED,wBAAgB,4BAA4B,CACxC,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,mBAAmB,GAC9B,OAAO,CAwBT;AAeD,wBAAgB,2BAA2B,CACvC,SAAS,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAC,CAAC,GACnC,MAAM,CAMR;AAED,wBAAgB,wBAAwB,CACpC,SAAS,EAAE,KAAK,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAC,CAAC,GACvD,eAAe,CAUjB;AAGD,YAAY,EAAC,kBAAkB,EAAE,cAAc,EAAC,MAAM,8BAA8B,CAAC;AACrF,OAAO,EAAC,gBAAgB,EAAE,YAAY,EAAC,MAAM,8BAA8B,CAAC"}
1
+ {"version":3,"file":"guardrails.d.ts","sourceRoot":"","sources":["../../src/validation/guardrails.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,gCAAgC,CAAC;AAExE,MAAM,WAAW,aAAa;IAC1B,cAAc,EAAE,OAAO,CAAC;IACxB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,aAAa,EAAE,OAAO,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;IACvB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,uEAAuE;IACvE,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AAExD,eAAO,MAAM,mBAAmB;;;;;CAKtB,CAAC;AAEX,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAuB9D;AAED,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,CAQtE;AAED,wBAAgB,0BAA0B,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAEtE;AAED,wBAAgB,4BAA4B,CACxC,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,mBAAmB,GAC9B,OAAO,CAwBT;AAeD,wBAAgB,2BAA2B,CACvC,SAAS,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAC,CAAC,GACnC,MAAM,CAMR;AAED,wBAAgB,wBAAwB,CACpC,SAAS,EAAE,KAAK,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAC,CAAC,GACvD,eAAe,CAUjB;AAGD,YAAY,EAAC,kBAAkB,EAAE,cAAc,EAAC,MAAM,8BAA8B,CAAC;AACrF,OAAO,EAAC,gBAAgB,EAAE,YAAY,EAAC,MAAM,8BAA8B,CAAC"}
@@ -32,6 +32,11 @@ function computeConfidence(check) {
32
32
  if (check.hasExistingSpecCited) {
33
33
  score += 15;
34
34
  }
35
+ // Historical failure correlation: if this file historically causes test failures,
36
+ // we're more confident it needs testing now
37
+ if (check.historyBoost) {
38
+ score += check.historyBoost;
39
+ }
35
40
  return Math.min(100, score);
36
41
  }
37
42
  function classifyConfidence(confidence) {
@@ -9,6 +9,8 @@ export interface ExistingSpecCoverage {
9
9
  coverageLevel: CoverageLevel;
10
10
  missingScenarios?: string[];
11
11
  }
12
+ export type { AssertionPattern } from '../knowledge/route_families.js';
13
+ import type { AssertionPattern } from '../knowledge/route_families.js';
12
14
  export interface FlowDecision {
13
15
  flowId: string;
14
16
  flowName: string;
@@ -27,6 +29,7 @@ export interface FlowDecision {
27
29
  blockingReason?: string;
28
30
  priority: FlowPriority;
29
31
  userActions: string[];
32
+ assertionPatterns?: AssertionPattern[];
30
33
  }
31
34
  export interface FlowDecisionSummary {
32
35
  changedFiles: number;
@@ -1 +1 @@
1
- {"version":3,"file":"output_schema.d.ts","sourceRoot":"","sources":["../../src/validation/output_schema.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,UAAU,GAAG,cAAc,GAAG,eAAe,GAAG,aAAa,GAAG,kBAAkB,CAAC;AAC/F,MAAM,MAAM,cAAc,GAAG,IAAI,GAAG,SAAS,GAAG,cAAc,GAAG,eAAe,CAAC;AACjF,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAC9C,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AACxD,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;AAExD,MAAM,WAAW,oBAAoB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,aAAa,EAAE,aAAa,CAAC;IAC7B,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,YAAY;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,cAAc,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,oBAAoB,EAAE,CAAC;IACtC,MAAM,EAAE,UAAU,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,YAAY,CAAC;IACvB,WAAW,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,mBAAmB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE;QACb,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;QACtB,WAAW,EAAE,MAAM,CAAC;QACpB,gBAAgB,EAAE,MAAM,CAAC;KAC5B,CAAC;IACF,iBAAiB,EAAE,eAAe,CAAC;CACtC;AAED,MAAM,WAAW,kBAAkB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,mBAAmB,CAAC;IAC7B,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,EAAE;QACH,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC5B,CAAC;CACL;AAMD,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,OAAO,GAAG;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAC,CA0C1F;AAED,wBAAgB,YAAY,CAAC,SAAS,EAAE,YAAY,EAAE,GAAG,mBAAmB,CAmC3E"}
1
+ {"version":3,"file":"output_schema.d.ts","sourceRoot":"","sources":["../../src/validation/output_schema.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,UAAU,GAAG,cAAc,GAAG,eAAe,GAAG,aAAa,GAAG,kBAAkB,CAAC;AAC/F,MAAM,MAAM,cAAc,GAAG,IAAI,GAAG,SAAS,GAAG,cAAc,GAAG,eAAe,CAAC;AACjF,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAC9C,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AACxD,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;AAExD,MAAM,WAAW,oBAAoB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,aAAa,EAAE,aAAa,CAAC;IAC7B,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B;AAED,YAAY,EAAC,gBAAgB,EAAC,MAAM,gCAAgC,CAAC;AACrE,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,gCAAgC,CAAC;AAErE,MAAM,WAAW,YAAY;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,cAAc,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,oBAAoB,EAAE,CAAC;IACtC,MAAM,EAAE,UAAU,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,YAAY,CAAC;IACvB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,iBAAiB,CAAC,EAAE,gBAAgB,EAAE,CAAC;CAC1C;AAED,MAAM,WAAW,mBAAmB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE;QACb,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;QACtB,WAAW,EAAE,MAAM,CAAC;QACpB,gBAAgB,EAAE,MAAM,CAAC;KAC5B,CAAC;IACF,iBAAiB,EAAE,eAAe,CAAC;CACtC;AAED,MAAM,WAAW,kBAAkB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,mBAAmB,CAAC;IAC7B,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,EAAE;QACH,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC5B,CAAC;CACL;AAMD,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,OAAO,GAAG;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAC,CA0C1F;AAED,wBAAgB,YAAY,CAAC,SAAS,EAAE,YAAY,EAAE,GAAG,mBAAmB,CAmC3E"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yasserkhanorg/e2e-agents",
3
- "version": "1.9.5",
3
+ "version": "1.10.1",
4
4
  "description": "AI-powered E2E test impact analysis, generation, and healing. Analyzes code changes to identify affected Playwright tests, detects coverage gaps, and generates or repairs specs using pluggable LLM providers (Claude, OpenAI, Ollama). Includes MCP server, traceability, and CI/CD integration.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/esm/index.js",