@yasserkhanorg/e2e-agents 1.6.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/commands/train.d.ts.map +1 -1
- package/dist/cli/commands/train.js +96 -48
- package/dist/cli/parse_args.d.ts.map +1 -1
- package/dist/cli/parse_args.js +2 -0
- package/dist/cli/types.d.ts +2 -0
- package/dist/cli/types.d.ts.map +1 -1
- package/dist/esm/cli/commands/train.js +96 -48
- package/dist/esm/cli/parse_args.js +2 -0
- package/dist/esm/logger.js +29 -2
- package/dist/esm/pipeline/orchestrator.js +17 -3
- package/dist/esm/training/enricher.js +11 -4
- package/dist/esm/training/scanner.js +167 -12
- package/dist/esm/training/validator.js +58 -2
- package/dist/logger.d.ts +9 -0
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +29 -2
- package/dist/pipeline/orchestrator.d.ts.map +1 -1
- package/dist/pipeline/orchestrator.js +17 -3
- package/dist/training/enricher.d.ts.map +1 -1
- package/dist/training/enricher.js +11 -4
- package/dist/training/scanner.d.ts +15 -2
- package/dist/training/scanner.d.ts.map +1 -1
- package/dist/training/scanner.js +169 -12
- package/dist/training/types.d.ts +4 -0
- package/dist/training/types.d.ts.map +1 -1
- package/dist/training/validator.d.ts +5 -0
- package/dist/training/validator.d.ts.map +1 -1
- package/dist/training/validator.js +59 -2
- package/package.json +1 -1
|
@@ -12,7 +12,20 @@ export declare function discoverTestDirs(projectRoot: string): DiscoveredDir[];
|
|
|
12
12
|
*
|
|
13
13
|
* Each domain becomes a candidate family with precise serverPaths.
|
|
14
14
|
*/
|
|
15
|
-
export declare function discoverServerDerivedFamilies(serverRoot: string):
|
|
15
|
+
export declare function discoverServerDerivedFamilies(serverRoot: string): {
|
|
16
|
+
multiTierFamilies: ScannedFamily[];
|
|
17
|
+
singleTierFamilies: ScannedFamily[];
|
|
18
|
+
};
|
|
16
19
|
export declare function discoverTestDerivedFamilies(testsRoot: string): ScannedFamily[];
|
|
17
|
-
|
|
20
|
+
/**
|
|
21
|
+
* Discover test library paths (page objects, helpers) organized by feature.
|
|
22
|
+
* Walks well-known test lib directories and maps subdirectories to family IDs.
|
|
23
|
+
*/
|
|
24
|
+
export declare function discoverTestLibPaths(testsRoot: string): Map<string, string[]>;
|
|
25
|
+
/**
|
|
26
|
+
* Discover files in well-known directories (types, utils) whose basename
|
|
27
|
+
* maps directly to a family ID.
|
|
28
|
+
*/
|
|
29
|
+
export declare function discoverNameMatchedPaths(appPath: string, gitRepoRoot?: string): Map<string, string[]>;
|
|
30
|
+
export declare function scanProject(projectRoot: string, testsRoot?: string, serverRoot?: string, gitRepoRoot?: string): ScanResult;
|
|
18
31
|
//# sourceMappingURL=scanner.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../src/training/scanner.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAC,aAAa,EAAE,aAAa,EAAkB,UAAU,EAAC,MAAM,YAAY,CAAC;AAgJzF,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,aAAa,EAAE,CA+BvE;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,aAAa,EAAE,CA6DrE;AAuLD;;;;;;;;;;GAUG;AACH,wBAAgB,6BAA6B,CAAC,UAAU,EAAE,MAAM,GAAG,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../src/training/scanner.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAC,aAAa,EAAE,aAAa,EAAkB,UAAU,EAAC,MAAM,YAAY,CAAC;AAgJzF,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,aAAa,EAAE,CA+BvE;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,aAAa,EAAE,CA6DrE;AAuLD;;;;;;;;;;GAUG;AACH,wBAAgB,6BAA6B,CAAC,UAAU,EAAE,MAAM,GAAG;IAAC,iBAAiB,EAAE,aAAa,EAAE,CAAC;IAAC,kBAAkB,EAAE,aAAa,EAAE,CAAA;CAAC,CAgI3I;AAED,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,EAAE,CAiG9E;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAmC7E;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CACpC,OAAO,EAAE,MAAM,EACf,WAAW,CAAC,EAAE,MAAM,GACrB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAmDvB;AAED,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,UAAU,CA0L1H"}
|
package/dist/training/scanner.js
CHANGED
|
@@ -6,6 +6,8 @@ exports.discoverSourceDirs = discoverSourceDirs;
|
|
|
6
6
|
exports.discoverTestDirs = discoverTestDirs;
|
|
7
7
|
exports.discoverServerDerivedFamilies = discoverServerDerivedFamilies;
|
|
8
8
|
exports.discoverTestDerivedFamilies = discoverTestDerivedFamilies;
|
|
9
|
+
exports.discoverTestLibPaths = discoverTestLibPaths;
|
|
10
|
+
exports.discoverNameMatchedPaths = discoverNameMatchedPaths;
|
|
9
11
|
exports.scanProject = scanProject;
|
|
10
12
|
const fs_1 = require("fs");
|
|
11
13
|
const path_1 = require("path");
|
|
@@ -520,15 +522,15 @@ function discoverServerDerivedFamilies(serverRoot) {
|
|
|
520
522
|
}
|
|
521
523
|
}
|
|
522
524
|
// Build families from grouped domains.
|
|
523
|
-
//
|
|
524
|
-
|
|
525
|
+
// Multi-tier families (≥2 tiers) can be new families.
|
|
526
|
+
// Single-tier families can only merge into existing families.
|
|
527
|
+
const multiTierFamilies = [];
|
|
528
|
+
const singleTierFamilies = [];
|
|
525
529
|
for (const [domain, paths] of familyPaths) {
|
|
526
530
|
if (paths.size === 0)
|
|
527
531
|
continue;
|
|
528
532
|
const tierCount = familyTiers.get(domain)?.size ?? 0;
|
|
529
|
-
|
|
530
|
-
continue; // Skip single-tier domains (likely infrastructure)
|
|
531
|
-
families.push({
|
|
533
|
+
const family = {
|
|
532
534
|
id: domain,
|
|
533
535
|
routes: [`/${domain.replace(/_/g, '-')}`],
|
|
534
536
|
webappPaths: [],
|
|
@@ -538,9 +540,15 @@ function discoverServerDerivedFamilies(serverRoot) {
|
|
|
538
540
|
tags: [],
|
|
539
541
|
features: [],
|
|
540
542
|
routesGuessed: true,
|
|
541
|
-
}
|
|
543
|
+
};
|
|
544
|
+
if (tierCount >= 2) {
|
|
545
|
+
multiTierFamilies.push(family);
|
|
546
|
+
}
|
|
547
|
+
else {
|
|
548
|
+
singleTierFamilies.push(family);
|
|
549
|
+
}
|
|
542
550
|
}
|
|
543
|
-
return
|
|
551
|
+
return { multiTierFamilies, singleTierFamilies };
|
|
544
552
|
}
|
|
545
553
|
function discoverTestDerivedFamilies(testsRoot) {
|
|
546
554
|
const resolved = (0, path_1.resolve)(testsRoot);
|
|
@@ -627,7 +635,113 @@ function discoverTestDerivedFamilies(testsRoot) {
|
|
|
627
635
|
}
|
|
628
636
|
return Array.from(familyMap.values());
|
|
629
637
|
}
|
|
630
|
-
|
|
638
|
+
/**
|
|
639
|
+
* Discover test library paths (page objects, helpers) organized by feature.
|
|
640
|
+
* Walks well-known test lib directories and maps subdirectories to family IDs.
|
|
641
|
+
*/
|
|
642
|
+
function discoverTestLibPaths(testsRoot) {
|
|
643
|
+
const resolved = (0, path_1.resolve)(testsRoot);
|
|
644
|
+
const result = new Map();
|
|
645
|
+
const libDirs = [
|
|
646
|
+
'lib/src/ui/components',
|
|
647
|
+
'lib/src/ui/pages',
|
|
648
|
+
'lib/src/server',
|
|
649
|
+
];
|
|
650
|
+
for (const libDir of libDirs) {
|
|
651
|
+
const fullDir = (0, path_1.join)(resolved, libDir);
|
|
652
|
+
if (!(0, fs_1.existsSync)(fullDir))
|
|
653
|
+
continue;
|
|
654
|
+
let entries;
|
|
655
|
+
try {
|
|
656
|
+
entries = (0, fs_1.readdirSync)(fullDir);
|
|
657
|
+
}
|
|
658
|
+
catch {
|
|
659
|
+
continue;
|
|
660
|
+
}
|
|
661
|
+
for (const entry of entries) {
|
|
662
|
+
if (isSkipped(entry))
|
|
663
|
+
continue;
|
|
664
|
+
const fullPath = (0, path_1.join)(fullDir, entry);
|
|
665
|
+
try {
|
|
666
|
+
const stat = (0, fs_1.lstatSync)(fullPath);
|
|
667
|
+
if (stat.isSymbolicLink() || !stat.isDirectory())
|
|
668
|
+
continue;
|
|
669
|
+
}
|
|
670
|
+
catch {
|
|
671
|
+
continue;
|
|
672
|
+
}
|
|
673
|
+
const familyId = normalizeId(entry);
|
|
674
|
+
const relPath = (0, path_1.relative)(resolved, fullPath).replace(/\\/g, '/');
|
|
675
|
+
const pattern = `${relPath}/*`;
|
|
676
|
+
if (!result.has(familyId))
|
|
677
|
+
result.set(familyId, []);
|
|
678
|
+
result.get(familyId).push(pattern);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
return result;
|
|
682
|
+
}
|
|
683
|
+
/**
|
|
684
|
+
* Discover files in well-known directories (types, utils) whose basename
|
|
685
|
+
* maps directly to a family ID.
|
|
686
|
+
*/
|
|
687
|
+
function discoverNameMatchedPaths(appPath, gitRepoRoot) {
|
|
688
|
+
const result = new Map();
|
|
689
|
+
const resolvedApp = (0, path_1.resolve)(appPath);
|
|
690
|
+
const scanRoots = [
|
|
691
|
+
{ root: (0, path_1.join)(resolvedApp, 'src/utils'), base: resolvedApp },
|
|
692
|
+
{ root: (0, path_1.join)(resolvedApp, 'src/types'), base: resolvedApp },
|
|
693
|
+
];
|
|
694
|
+
// Monorepo-aware: scan platform types directory
|
|
695
|
+
if (gitRepoRoot) {
|
|
696
|
+
const resolvedGitRoot = (0, path_1.resolve)(gitRepoRoot);
|
|
697
|
+
const platformTypes = (0, path_1.join)(resolvedGitRoot, 'webapp/platform/types/src');
|
|
698
|
+
if ((0, fs_1.existsSync)(platformTypes)) {
|
|
699
|
+
scanRoots.push({ root: platformTypes, base: resolvedGitRoot });
|
|
700
|
+
}
|
|
701
|
+
const platformClient = (0, path_1.join)(resolvedGitRoot, 'webapp/platform/client/src');
|
|
702
|
+
if ((0, fs_1.existsSync)(platformClient)) {
|
|
703
|
+
scanRoots.push({ root: platformClient, base: resolvedGitRoot });
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
for (const { root, base } of scanRoots) {
|
|
707
|
+
if (!(0, fs_1.existsSync)(root))
|
|
708
|
+
continue;
|
|
709
|
+
let entries;
|
|
710
|
+
try {
|
|
711
|
+
entries = (0, fs_1.readdirSync)(root);
|
|
712
|
+
}
|
|
713
|
+
catch {
|
|
714
|
+
continue;
|
|
715
|
+
}
|
|
716
|
+
for (const entry of entries) {
|
|
717
|
+
if (entry.startsWith('.'))
|
|
718
|
+
continue;
|
|
719
|
+
const ext = entry.slice(entry.lastIndexOf('.'));
|
|
720
|
+
if (!['.ts', '.tsx', '.js', '.jsx'].includes(ext))
|
|
721
|
+
continue;
|
|
722
|
+
const fullPath = (0, path_1.join)(root, entry);
|
|
723
|
+
try {
|
|
724
|
+
const stat = (0, fs_1.lstatSync)(fullPath);
|
|
725
|
+
if (!stat.isFile() || stat.isSymbolicLink())
|
|
726
|
+
continue;
|
|
727
|
+
}
|
|
728
|
+
catch {
|
|
729
|
+
continue;
|
|
730
|
+
}
|
|
731
|
+
// Strip extension and normalize
|
|
732
|
+
const baseName = entry.slice(0, entry.lastIndexOf('.'));
|
|
733
|
+
const familyId = normalizeId(baseName);
|
|
734
|
+
if (familyId.length < 3)
|
|
735
|
+
continue;
|
|
736
|
+
const relPath = (0, path_1.relative)(base, fullPath).replace(/\\/g, '/');
|
|
737
|
+
if (!result.has(familyId))
|
|
738
|
+
result.set(familyId, []);
|
|
739
|
+
result.get(familyId).push(relPath);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
return result;
|
|
743
|
+
}
|
|
744
|
+
function scanProject(projectRoot, testsRoot, serverRoot, gitRepoRoot) {
|
|
631
745
|
const resolved = (0, path_1.resolve)(projectRoot);
|
|
632
746
|
const resolvedTestsRoot = testsRoot ? (0, path_1.resolve)(testsRoot) : resolved;
|
|
633
747
|
const sourceDirs = discoverSourceDirs(resolved);
|
|
@@ -690,9 +804,12 @@ function scanProject(projectRoot, testsRoot, serverRoot) {
|
|
|
690
804
|
// When a separate serverRoot is provided, discover families from Go source
|
|
691
805
|
// filenames across the three-tier backend (api4, app, store).
|
|
692
806
|
if (serverRoot) {
|
|
693
|
-
const
|
|
807
|
+
const { multiTierFamilies: serverMulti, singleTierFamilies: serverSingle } = discoverServerDerivedFamilies((0, path_1.resolve)(serverRoot));
|
|
694
808
|
const existingIds = new Set(families.map((f) => f.id));
|
|
695
|
-
|
|
809
|
+
// Merge ALL server families (multi + single tier) into existing families,
|
|
810
|
+
// but only add NEW families if they span ≥2 tiers.
|
|
811
|
+
const allServerFamilies = [...serverMulti, ...serverSingle];
|
|
812
|
+
for (const sf of allServerFamilies) {
|
|
696
813
|
// Try exact match, then singular/plural variants
|
|
697
814
|
let target = families.find((f) => f.id === sf.id);
|
|
698
815
|
if (!target && !sf.id.endsWith('s')) {
|
|
@@ -709,13 +826,53 @@ function scanProject(projectRoot, testsRoot, serverRoot) {
|
|
|
709
826
|
}
|
|
710
827
|
}
|
|
711
828
|
}
|
|
712
|
-
else {
|
|
713
|
-
//
|
|
829
|
+
else if (serverMulti.includes(sf)) {
|
|
830
|
+
// Only add new families if they span ≥2 tiers
|
|
714
831
|
families.push(sf);
|
|
715
832
|
existingIds.add(sf.id);
|
|
716
833
|
}
|
|
717
834
|
}
|
|
718
835
|
}
|
|
836
|
+
// Merge test library paths (page objects, helpers) into existing families
|
|
837
|
+
if (testsRoot) {
|
|
838
|
+
const testLibPaths = discoverTestLibPaths(resolvedTestsRoot);
|
|
839
|
+
for (const [libFamilyId, patterns] of testLibPaths) {
|
|
840
|
+
let target = families.find((f) => f.id === libFamilyId);
|
|
841
|
+
if (!target && !libFamilyId.endsWith('s')) {
|
|
842
|
+
target = families.find((f) => f.id === libFamilyId + 's');
|
|
843
|
+
}
|
|
844
|
+
if (!target && libFamilyId.endsWith('s')) {
|
|
845
|
+
target = families.find((f) => f.id === libFamilyId.slice(0, -1));
|
|
846
|
+
}
|
|
847
|
+
if (target) {
|
|
848
|
+
for (const p of patterns) {
|
|
849
|
+
if (!target.webappPaths.includes(p)) {
|
|
850
|
+
target.webappPaths.push(p);
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
// Merge name-matched type/util files into existing families
|
|
857
|
+
{
|
|
858
|
+
const nameMatchedPaths = discoverNameMatchedPaths(resolved, gitRepoRoot);
|
|
859
|
+
for (const [nmFamilyId, paths] of nameMatchedPaths) {
|
|
860
|
+
let target = families.find((f) => f.id === nmFamilyId);
|
|
861
|
+
if (!target && !nmFamilyId.endsWith('s')) {
|
|
862
|
+
target = families.find((f) => f.id === nmFamilyId + 's');
|
|
863
|
+
}
|
|
864
|
+
if (!target && nmFamilyId.endsWith('s')) {
|
|
865
|
+
target = families.find((f) => f.id === nmFamilyId.slice(0, -1));
|
|
866
|
+
}
|
|
867
|
+
if (target) {
|
|
868
|
+
for (const p of paths) {
|
|
869
|
+
if (!target.webappPaths.includes(p)) {
|
|
870
|
+
target.webappPaths.push(p);
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
}
|
|
719
876
|
const familyIds = new Set(families.map((f) => f.id));
|
|
720
877
|
const unmatchedSourceDirs = sourceDirs.filter((d) => !familyIds.has(normalizeId(d.familyHint)));
|
|
721
878
|
const unmatchedTestDirs = testDirs.filter((d) => !familyIds.has(normalizeId(d.familyHint)));
|
package/dist/training/types.d.ts
CHANGED
|
@@ -47,6 +47,10 @@ export interface EnrichmentResult {
|
|
|
47
47
|
tokensUsed: number;
|
|
48
48
|
costUSD: number;
|
|
49
49
|
skippedFamilies: string[];
|
|
50
|
+
/** Number of LLM requests made */
|
|
51
|
+
requestCount?: number;
|
|
52
|
+
/** Average response time per LLM request in ms */
|
|
53
|
+
avgResponseMs?: number;
|
|
50
54
|
}
|
|
51
55
|
/** A single commit's validation result */
|
|
52
56
|
export interface CommitValidation {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/training/types.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,WAAW,EAAE,mBAAmB,EAAC,MAAM,gCAAgC,CAAC;AAErF,mDAAmD;AACnD,MAAM,WAAW,aAAa;IAC1B,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,YAAY,EAAE,MAAM,CAAC;IACrB,yDAAyD;IACzD,QAAQ,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;IACnD,gFAAgF;IAChF,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,qDAAqD;AACrD,MAAM,WAAW,aAAa;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,wDAAwD;IACxD,aAAa,EAAE,OAAO,CAAC;CAC1B;AAED,+CAA+C;AAC/C,MAAM,WAAW,cAAc;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,0CAA0C;AAC1C,MAAM,WAAW,UAAU;IACvB,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,mBAAmB,EAAE,aAAa,EAAE,CAAC;IACrC,iBAAiB,EAAE,aAAa,EAAE,CAAC;IACnC,KAAK,EAAE;QACH,gBAAgB,EAAE,MAAM,CAAC;QACzB,cAAc,EAAE,MAAM,CAAC;QACvB,WAAW,EAAE,MAAM,CAAC;KACvB,CAAC;CACL;AAED,+BAA+B;AAC/B,MAAM,WAAW,gBAAgB;IAC7B,gBAAgB,EAAE,WAAW,EAAE,CAAC;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/training/types.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,WAAW,EAAE,mBAAmB,EAAC,MAAM,gCAAgC,CAAC;AAErF,mDAAmD;AACnD,MAAM,WAAW,aAAa;IAC1B,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,YAAY,EAAE,MAAM,CAAC;IACrB,yDAAyD;IACzD,QAAQ,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;IACnD,gFAAgF;IAChF,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,qDAAqD;AACrD,MAAM,WAAW,aAAa;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,wDAAwD;IACxD,aAAa,EAAE,OAAO,CAAC;CAC1B;AAED,+CAA+C;AAC/C,MAAM,WAAW,cAAc;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,0CAA0C;AAC1C,MAAM,WAAW,UAAU;IACvB,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,mBAAmB,EAAE,aAAa,EAAE,CAAC;IACrC,iBAAiB,EAAE,aAAa,EAAE,CAAC;IACnC,KAAK,EAAE;QACH,gBAAgB,EAAE,MAAM,CAAC;QACzB,cAAc,EAAE,MAAM,CAAC;QACvB,WAAW,EAAE,MAAM,CAAC;KACvB,CAAC;CACL;AAED,+BAA+B;AAC/B,MAAM,WAAW,gBAAgB;IAC7B,gBAAgB,EAAE,WAAW,EAAE,CAAC;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,kCAAkC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kDAAkD;IAClD,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,0CAA0C;AAC1C,MAAM,WAAW,gBAAgB;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,WAAW,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,gCAAgC;AAChC,MAAM,WAAW,gBAAgB;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,mBAAmB,EAAE,KAAK,CAAC;QACvB,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,eAAe,EAAE,MAAM,CAAC;KAC3B,CAAC,CAAC;CACN;AAED,4BAA4B;AAC5B,MAAM,WAAW,WAAW;IACxB,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,oCAAoC;AACpC,MAAM,WAAW,YAAY;IACzB,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,mDAAmD;IACnD,SAAS,EAAE,MAAM,CAAC;IAClB,4DAA4D;IAC5D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kDAAkD;IAClD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4CAA4C;IAC5C,MAAM,EAAE,OAAO,CAAC;IAChB,yCAAyC;IACzC,QAAQ,EAAE,OAAO,CAAC;IAClB,+CAA+C;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,sCAAsC;IACtC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,0CAA0C;IAC1C,UAAU,EAAE,MAAM,CAAC;IACnB,sCAAsC;IACtC,MAAM,EAAE,OAAO,CAAC;IAChB,2BAA2B;IAC3B,GAAG,EAAE,OAAO,CAAC;IACb,2BAA2B;IAC3B,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,uEAAuE;AACvE,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAExD"}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { RouteFamilyManifest } from '../knowledge/route_families.js';
|
|
2
2
|
import type { CommitValidation, ValidationReport } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Check if a file path matches any infrastructure glob pattern.
|
|
5
|
+
* Uses simple string matching — no external glob library needed.
|
|
6
|
+
*/
|
|
7
|
+
export declare function isInfraFile(filePath: string): boolean;
|
|
3
8
|
export declare function parseGitLog(log: string): Array<{
|
|
4
9
|
hash: string;
|
|
5
10
|
message: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/training/validator.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,gCAAgC,CAAC;AAExE,OAAO,KAAK,EAAC,gBAAgB,EAAE,gBAAgB,EAAC,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/training/validator.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,gCAAgC,CAAC;AAExE,OAAO,KAAK,EAAC,gBAAgB,EAAE,gBAAgB,EAAC,MAAM,YAAY,CAAC;AAgBnE;;;GAGG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CA6BrD;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAC,CAAC,CA6BhG;AAED,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAC,CAAC,CAgB1H;AAED,wBAAgB,cAAc,CAC1B,QAAQ,EAAE,mBAAmB,EAC7B,KAAK,EAAE,MAAM,EAAE,EACf,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GAChB,gBAAgB,CA6BlB;AAED,wBAAgB,qBAAqB,CACjC,OAAO,EAAE,gBAAgB,EAAE,EAC3B,QAAQ,EAAE,mBAAmB,GAC9B,gBAAgB,CAkDlB;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAgCvE"}
|
|
@@ -2,6 +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.isInfraFile = isInfraFile;
|
|
5
6
|
exports.parseGitLog = parseGitLog;
|
|
6
7
|
exports.getCommitFiles = getCommitFiles;
|
|
7
8
|
exports.validateCommit = validateCommit;
|
|
@@ -10,6 +11,62 @@ exports.formatValidationReport = formatValidationReport;
|
|
|
10
11
|
const child_process_1 = require("child_process");
|
|
11
12
|
const path_1 = require("path");
|
|
12
13
|
const route_families_js_1 = require("../knowledge/route_families.js");
|
|
14
|
+
/**
|
|
15
|
+
* Glob-style patterns for infrastructure / cross-cutting files that will never
|
|
16
|
+
* belong to a single route family. Excluded from coverage calculations.
|
|
17
|
+
*/
|
|
18
|
+
const INFRA_GLOBS = [
|
|
19
|
+
'Makefile', 'go.mod', 'go.sum',
|
|
20
|
+
'*.lock',
|
|
21
|
+
'**/mocks/*', '**/storetest/*', '**/testlib/*',
|
|
22
|
+
'**/i18n/*',
|
|
23
|
+
'**/.github/*', '**/scripts/*',
|
|
24
|
+
'**/docker-compose*',
|
|
25
|
+
'**/__fixtures__/*', '**/test_templates/*',
|
|
26
|
+
];
|
|
27
|
+
/**
|
|
28
|
+
* Check if a file path matches any infrastructure glob pattern.
|
|
29
|
+
* Uses simple string matching — no external glob library needed.
|
|
30
|
+
*/
|
|
31
|
+
function isInfraFile(filePath) {
|
|
32
|
+
const normalized = filePath.replace(/\\/g, '/');
|
|
33
|
+
for (const pattern of INFRA_GLOBS) {
|
|
34
|
+
if (pattern.startsWith('**/')) {
|
|
35
|
+
// Match anywhere in the path
|
|
36
|
+
const suffix = pattern.slice(3);
|
|
37
|
+
if (suffix.endsWith('/*')) {
|
|
38
|
+
// Directory match: **/mocks/* → any segment named "mocks" with a child
|
|
39
|
+
const dirName = suffix.slice(0, -2);
|
|
40
|
+
if (normalized.includes(`/${dirName}/`) || normalized.startsWith(`${dirName}/`))
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
else if (suffix.endsWith('*')) {
|
|
44
|
+
// Prefix match: **/docker-compose* → file starting with docker-compose
|
|
45
|
+
const prefix = suffix.slice(0, -1);
|
|
46
|
+
const base = normalized.split('/').pop() || '';
|
|
47
|
+
if (base.startsWith(prefix))
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
if (normalized.endsWith(`/${suffix}`) || normalized === suffix)
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
else if (pattern.startsWith('*.')) {
|
|
56
|
+
// Extension match: *.lock
|
|
57
|
+
const ext = pattern.slice(1);
|
|
58
|
+
if (normalized.endsWith(ext))
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
// Exact basename match: Makefile, go.mod, go.sum
|
|
63
|
+
const base = normalized.split('/').pop() || '';
|
|
64
|
+
if (base === pattern)
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
13
70
|
function parseGitLog(log) {
|
|
14
71
|
const commits = [];
|
|
15
72
|
let current = null;
|
|
@@ -56,10 +113,10 @@ function getCommitFiles(projectRoot, since) {
|
|
|
56
113
|
return parseGitLog(log);
|
|
57
114
|
}
|
|
58
115
|
function validateCommit(manifest, files, hash, message) {
|
|
59
|
-
// Filter out non-source files
|
|
116
|
+
// Filter out non-source files and infrastructure files
|
|
60
117
|
const sourceFiles = files.filter((f) => {
|
|
61
118
|
return !f.endsWith('.md') && !f.endsWith('.json') && !f.endsWith('.yml') && !f.endsWith('.yaml') &&
|
|
62
|
-
!f.startsWith('.') && !f.includes('node_modules/');
|
|
119
|
+
!f.startsWith('.') && !f.includes('node_modules/') && !isInfraFile(f);
|
|
63
120
|
});
|
|
64
121
|
if (sourceFiles.length === 0) {
|
|
65
122
|
return { hash, message, changedFiles: [], boundFiles: 0, unboundFiles: [], familiesHit: [] };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yasserkhanorg/e2e-agents",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.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",
|