@yasserkhanorg/e2e-agents 1.3.2 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/README.md +40 -9
  2. package/dist/agent/feedback.d.ts +16 -0
  3. package/dist/agent/feedback.d.ts.map +1 -1
  4. package/dist/agent/feedback.js +62 -0
  5. package/dist/agent/process_runner.d.ts +1 -1
  6. package/dist/agent/process_runner.d.ts.map +1 -1
  7. package/dist/agent/process_runner.js +3 -3
  8. package/dist/api.d.ts.map +1 -1
  9. package/dist/api.js +5 -2
  10. package/dist/cli/commands/train.d.ts +3 -0
  11. package/dist/cli/commands/train.d.ts.map +1 -0
  12. package/dist/cli/commands/train.js +307 -0
  13. package/dist/cli/parse_args.d.ts.map +1 -1
  14. package/dist/cli/parse_args.js +7 -1
  15. package/dist/cli/types.d.ts +6 -1
  16. package/dist/cli/types.d.ts.map +1 -1
  17. package/dist/cli/usage.d.ts.map +1 -1
  18. package/dist/cli/usage.js +7 -1
  19. package/dist/cli.js +5 -0
  20. package/dist/engine/plan_builder.d.ts +2 -1
  21. package/dist/engine/plan_builder.d.ts.map +1 -1
  22. package/dist/engine/plan_builder.js +22 -9
  23. package/dist/esm/agent/feedback.js +61 -0
  24. package/dist/esm/agent/process_runner.js +3 -3
  25. package/dist/esm/api.js +5 -2
  26. package/dist/esm/cli/commands/train.js +271 -0
  27. package/dist/esm/cli/parse_args.js +7 -1
  28. package/dist/esm/cli/usage.js +7 -1
  29. package/dist/esm/cli.js +5 -0
  30. package/dist/esm/engine/plan_builder.js +22 -9
  31. package/dist/esm/index.js +6 -1
  32. package/dist/esm/knowledge/route_families.js +2 -2
  33. package/dist/esm/pipeline/spec_verifier.js +75 -0
  34. package/dist/esm/pipeline/stage3_generation.js +122 -4
  35. package/dist/esm/pipeline/stage4_heal.js +146 -3
  36. package/dist/esm/prompts/heal.js +4 -0
  37. package/dist/esm/qa-agent/phase2/agent_loop.js +60 -24
  38. package/dist/esm/qa-agent/phase2/exploration_state.js +21 -0
  39. package/dist/esm/qa-agent/phase2/tools.js +99 -1
  40. package/dist/esm/qa-agent/phase3/reporter.js +31 -4
  41. package/dist/esm/training/enricher.js +273 -0
  42. package/dist/esm/training/merger.js +137 -0
  43. package/dist/esm/training/scanner.js +386 -0
  44. package/dist/esm/training/types.js +6 -0
  45. package/dist/esm/training/validator.js +153 -0
  46. package/dist/esm/validation/guardrails.js +1 -0
  47. package/dist/index.d.ts +7 -2
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +16 -1
  50. package/dist/knowledge/route_families.d.ts +2 -0
  51. package/dist/knowledge/route_families.d.ts.map +1 -1
  52. package/dist/knowledge/route_families.js +2 -0
  53. package/dist/pipeline/orchestrator.d.ts.map +1 -1
  54. package/dist/pipeline/spec_verifier.d.ts +20 -0
  55. package/dist/pipeline/spec_verifier.d.ts.map +1 -0
  56. package/dist/pipeline/spec_verifier.js +79 -0
  57. package/dist/pipeline/stage3_generation.d.ts +10 -0
  58. package/dist/pipeline/stage3_generation.d.ts.map +1 -1
  59. package/dist/pipeline/stage3_generation.js +120 -2
  60. package/dist/pipeline/stage4_heal.d.ts +4 -0
  61. package/dist/pipeline/stage4_heal.d.ts.map +1 -1
  62. package/dist/pipeline/stage4_heal.js +145 -2
  63. package/dist/prompts/heal.d.ts +2 -0
  64. package/dist/prompts/heal.d.ts.map +1 -1
  65. package/dist/prompts/heal.js +4 -0
  66. package/dist/qa-agent/phase2/agent_loop.d.ts.map +1 -1
  67. package/dist/qa-agent/phase2/agent_loop.js +60 -24
  68. package/dist/qa-agent/phase2/exploration_state.d.ts.map +1 -1
  69. package/dist/qa-agent/phase2/exploration_state.js +21 -0
  70. package/dist/qa-agent/phase2/tools.d.ts.map +1 -1
  71. package/dist/qa-agent/phase2/tools.js +99 -1
  72. package/dist/qa-agent/phase3/reporter.js +31 -4
  73. package/dist/qa-agent/types.d.ts +9 -1
  74. package/dist/qa-agent/types.d.ts.map +1 -1
  75. package/dist/training/enricher.d.ts +15 -0
  76. package/dist/training/enricher.d.ts.map +1 -0
  77. package/dist/training/enricher.js +278 -0
  78. package/dist/training/merger.d.ts +5 -0
  79. package/dist/training/merger.d.ts.map +1 -0
  80. package/dist/training/merger.js +141 -0
  81. package/dist/training/scanner.d.ts +5 -0
  82. package/dist/training/scanner.d.ts.map +1 -0
  83. package/dist/training/scanner.js +391 -0
  84. package/dist/training/types.d.ts +109 -0
  85. package/dist/training/types.d.ts.map +1 -0
  86. package/dist/training/types.js +9 -0
  87. package/dist/training/validator.d.ts +16 -0
  88. package/dist/training/validator.d.ts.map +1 -0
  89. package/dist/training/validator.js +160 -0
  90. package/dist/validation/guardrails.d.ts +2 -0
  91. package/dist/validation/guardrails.d.ts.map +1 -1
  92. package/dist/validation/guardrails.js +4 -1
  93. package/package.json +1 -1
@@ -0,0 +1,160 @@
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.parseGitLog = parseGitLog;
6
+ exports.getCommitFiles = getCommitFiles;
7
+ exports.validateCommit = validateCommit;
8
+ exports.buildValidationReport = buildValidationReport;
9
+ exports.formatValidationReport = formatValidationReport;
10
+ const child_process_1 = require("child_process");
11
+ const path_1 = require("path");
12
+ const route_families_js_1 = require("../knowledge/route_families.js");
13
+ function parseGitLog(log) {
14
+ const commits = [];
15
+ let current = null;
16
+ for (const line of log.split('\n')) {
17
+ const trimmed = line.trim();
18
+ if (!trimmed) {
19
+ if (current) {
20
+ commits.push(current);
21
+ current = null;
22
+ }
23
+ continue;
24
+ }
25
+ if (trimmed.includes('|') && /^[0-9a-f]{7,40}\|/.test(trimmed)) {
26
+ if (current) {
27
+ commits.push(current);
28
+ }
29
+ const [hash, ...rest] = trimmed.split('|');
30
+ current = { hash, message: rest.join('|'), files: [] };
31
+ }
32
+ else if (current) {
33
+ current.files.push(trimmed);
34
+ }
35
+ }
36
+ if (current) {
37
+ commits.push(current);
38
+ }
39
+ return commits;
40
+ }
41
+ function getCommitFiles(projectRoot, since) {
42
+ const resolved = (0, path_1.resolve)(projectRoot);
43
+ let log;
44
+ try {
45
+ log = (0, child_process_1.execFileSync)('git', ['log', '--name-only', '--pretty=format:%H|%s', `${since}..HEAD`], {
46
+ cwd: resolved,
47
+ encoding: 'utf-8',
48
+ stdio: ['pipe', 'pipe', 'pipe'],
49
+ maxBuffer: 10 * 1024 * 1024,
50
+ });
51
+ }
52
+ catch (error) {
53
+ console.warn(`[train] git log failed: ${error instanceof Error ? error.message : String(error)}`);
54
+ return [];
55
+ }
56
+ return parseGitLog(log);
57
+ }
58
+ function validateCommit(manifest, files, hash, message) {
59
+ // Filter out non-source files
60
+ const sourceFiles = files.filter((f) => {
61
+ return !f.endsWith('.md') && !f.endsWith('.json') && !f.endsWith('.yml') && !f.endsWith('.yaml') &&
62
+ !f.startsWith('.') && !f.includes('node_modules/');
63
+ });
64
+ if (sourceFiles.length === 0) {
65
+ return { hash, message, changedFiles: [], boundFiles: 0, unboundFiles: [], familiesHit: [] };
66
+ }
67
+ const bindings = (0, route_families_js_1.bindFilesToFamilies)(sourceFiles, manifest);
68
+ const bound = bindings.filter((b) => b.bindings.length > 0);
69
+ const unbound = bindings.filter((b) => b.bindings.length === 0);
70
+ const familiesHit = new Set();
71
+ for (const b of bound) {
72
+ for (const binding of b.bindings) {
73
+ familiesHit.add(binding.family);
74
+ }
75
+ }
76
+ return {
77
+ hash,
78
+ message,
79
+ changedFiles: sourceFiles,
80
+ boundFiles: bound.length,
81
+ unboundFiles: unbound.map((b) => b.file),
82
+ familiesHit: Array.from(familiesHit),
83
+ };
84
+ }
85
+ function buildValidationReport(commits, manifest) {
86
+ let totalFiles = 0;
87
+ let boundFiles = 0;
88
+ let unboundFiles = 0;
89
+ const familyHits = {};
90
+ const unboundCounts = {};
91
+ for (const commit of commits) {
92
+ totalFiles += commit.changedFiles.length;
93
+ boundFiles += commit.boundFiles;
94
+ unboundFiles += commit.unboundFiles.length;
95
+ for (const fam of commit.familiesHit) {
96
+ familyHits[fam] = (familyHits[fam] || 0) + 1;
97
+ }
98
+ for (const uf of commit.unboundFiles) {
99
+ unboundCounts[uf] = (unboundCounts[uf] || 0) + 1;
100
+ }
101
+ }
102
+ const allFamilyIds = manifest.families.map((f) => f.id);
103
+ const hitFamilyIds = new Set(Object.keys(familyHits));
104
+ const neverHitFamilies = allFamilyIds.filter((id) => !hitFamilyIds.has(id));
105
+ // Cluster unbound files by directory
106
+ const dirCounts = {};
107
+ for (const [file, count] of Object.entries(unboundCounts)) {
108
+ const dir = file.split('/').slice(0, -1).join('/');
109
+ dirCounts[dir] = (dirCounts[dir] || 0) + count;
110
+ }
111
+ const unboundFileClusters = Object.entries(dirCounts)
112
+ .sort(([, a], [, b]) => b - a)
113
+ .slice(0, 20)
114
+ .map(([pattern, count]) => ({
115
+ pattern: `${pattern}/*`,
116
+ count,
117
+ suggestedFamily: pattern.split('/').pop() || 'unknown',
118
+ }));
119
+ return {
120
+ totalCommits: commits.length,
121
+ totalFiles,
122
+ boundFiles,
123
+ unboundFiles,
124
+ coveragePercent: totalFiles > 0 ? Math.round((boundFiles / totalFiles) * 100) : 100,
125
+ commits,
126
+ familyHits,
127
+ neverHitFamilies,
128
+ unboundFileClusters,
129
+ };
130
+ }
131
+ function formatValidationReport(report) {
132
+ const lines = [];
133
+ lines.push(`Validated against ${report.totalCommits} commits`);
134
+ lines.push('');
135
+ lines.push(`Coverage: ${report.coveragePercent}% of files bound (${report.boundFiles}/${report.totalFiles})`);
136
+ lines.push('');
137
+ // Family hit distribution
138
+ const sorted = Object.entries(report.familyHits).sort(([, a], [, b]) => b - a);
139
+ if (sorted.length > 0) {
140
+ lines.push('Family hit distribution:');
141
+ const maxHits = sorted[0][1];
142
+ for (const [family, hits] of sorted) {
143
+ const bar = '\u2588'.repeat(Math.max(1, Math.round((hits / maxHits) * 12)));
144
+ lines.push(` ${family.padEnd(20)} ${bar} ${hits} commits`);
145
+ }
146
+ if (report.neverHitFamilies.length > 0) {
147
+ lines.push(` (never hit)${' '.repeat(8)}${report.neverHitFamilies.join(', ')}`);
148
+ }
149
+ lines.push('');
150
+ }
151
+ // Unbound file clusters
152
+ if (report.unboundFileClusters.length > 0) {
153
+ lines.push(`Unbound files (${report.unboundFiles} files across ${report.totalCommits} commits):`);
154
+ for (const cluster of report.unboundFileClusters.slice(0, 10)) {
155
+ lines.push(` ${cluster.pattern.padEnd(50)} — ${cluster.count} commits (suggest: ${cluster.suggestedFamily})`);
156
+ }
157
+ lines.push('');
158
+ }
159
+ return lines.join('\n');
160
+ }
@@ -24,4 +24,6 @@ export declare function computeOverallConfidence(decisions: Array<{
24
24
  confidence: number;
25
25
  action: string;
26
26
  }>): ConfidenceClass;
27
+ export type { CompileCheckResult, SmokeRunResult } from '../pipeline/spec_verifier.js';
28
+ export { compileCheckSpec, smokeRunSpec } from '../pipeline/spec_verifier.js';
27
29
  //# sourceMappingURL=guardrails.d.ts.map
@@ -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"}
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"}
@@ -2,7 +2,7 @@
2
2
  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
3
3
  // See LICENSE.txt for license information.
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
- exports.EVIDENCE_THRESHOLDS = void 0;
5
+ exports.smokeRunSpec = exports.compileCheckSpec = exports.EVIDENCE_THRESHOLDS = void 0;
6
6
  exports.computeConfidence = computeConfidence;
7
7
  exports.classifyConfidence = classifyConfidence;
8
8
  exports.shouldForceCannotDetermine = shouldForceCannotDetermine;
@@ -102,3 +102,6 @@ function computeOverallConfidence(decisions) {
102
102
  const avgConfidence = actionable.reduce((sum, d) => sum + d.confidence, 0) / actionable.length;
103
103
  return classifyConfidence(avgConfidence);
104
104
  }
105
+ var spec_verifier_js_1 = require("../pipeline/spec_verifier.js");
106
+ Object.defineProperty(exports, "compileCheckSpec", { enumerable: true, get: function () { return spec_verifier_js_1.compileCheckSpec; } });
107
+ Object.defineProperty(exports, "smokeRunSpec", { enumerable: true, get: function () { return spec_verifier_js_1.smokeRunSpec; } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yasserkhanorg/e2e-agents",
3
- "version": "1.3.2",
3
+ "version": "1.5.0",
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",