@yasserkhanorg/e2e-agents 1.1.0 → 1.1.2

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.
@@ -1 +1 @@
1
- {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/agent/git.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,eAAe;IAC5B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,YAAY,GAAG,QAAQ,CAAC;CAC1C;AAED,MAAM,WAAW,gBAAgB;IAC7B,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAChC;AA8CD,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,eAAe,CAuC3G"}
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/agent/git.ts"],"names":[],"mappings":"AAqGA,MAAM,WAAW,eAAe;IAC5B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,YAAY,GAAG,QAAQ,CAAC;CAC1C;AAED,MAAM,WAAW,gBAAgB;IAC7B,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAChC;AA8CD,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,eAAe,CA2C3G"}
package/dist/agent/git.js CHANGED
@@ -5,6 +5,89 @@ Object.defineProperty(exports, "__esModule", { value: true });
5
5
  exports.getChangedFiles = getChangedFiles;
6
6
  const child_process_1 = require("child_process");
7
7
  const utils_js_1 = require("./utils.js");
8
+ // Directories that contain CI/tooling/docs — never relevant to impact analysis.
9
+ const IGNORED_DIR_SEGMENTS = [
10
+ '.github',
11
+ '.claude',
12
+ '.vscode',
13
+ '.idea',
14
+ 'node_modules',
15
+ ];
16
+ // Exact filenames (basename) that are never relevant.
17
+ const IGNORED_BASENAMES = new Set([
18
+ 'package.json',
19
+ 'package-lock.json',
20
+ '.gitignore',
21
+ '.prettierignore',
22
+ '.prettierrc',
23
+ '.eslintrc',
24
+ '.eslintrc.js',
25
+ '.eslintrc.json',
26
+ '.editorconfig',
27
+ '.npmrc',
28
+ '.mcp.json',
29
+ 'CHANGELOG.md',
30
+ 'README.md',
31
+ 'LICENSE',
32
+ 'LICENSE.txt',
33
+ 'tsconfig.json',
34
+ 'jest.config.js',
35
+ 'jest.config.ts',
36
+ 'babel.config.js',
37
+ ]);
38
+ // Extensions that are never source code.
39
+ const IGNORED_EXTENSIONS = new Set([
40
+ '.md',
41
+ '.txt',
42
+ '.lock',
43
+ '.png', '.jpg', '.jpeg', '.gif', '.svg', '.ico',
44
+ '.woff', '.woff2', '.ttf', '.eot',
45
+ ]);
46
+ // File patterns that indicate test/spec files (not production code).
47
+ const TEST_FILE_PATTERNS = [
48
+ /\.spec\.[tj]sx?$/,
49
+ /\.test\.[tj]sx?$/,
50
+ /_test\.go$/,
51
+ /\.stories\.[tj]sx?$/,
52
+ ];
53
+ // Config file patterns that are not production source code.
54
+ const CONFIG_FILE_PATTERNS = [
55
+ /\.config\.[tj]sx?$/,
56
+ /\.config\.json$/,
57
+ /\.config\.js$/,
58
+ ];
59
+ function isRelevantFile(file) {
60
+ const segments = file.split('/');
61
+ const basename = segments[segments.length - 1] || file;
62
+ if (IGNORED_BASENAMES.has(basename)) {
63
+ return false;
64
+ }
65
+ for (const seg of segments) {
66
+ if (IGNORED_DIR_SEGMENTS.includes(seg)) {
67
+ return false;
68
+ }
69
+ }
70
+ const dotIdx = basename.lastIndexOf('.');
71
+ if (dotIdx > 0) {
72
+ const ext = basename.slice(dotIdx).toLowerCase();
73
+ if (IGNORED_EXTENSIONS.has(ext)) {
74
+ return false;
75
+ }
76
+ }
77
+ // Filter test/spec files — they don't impact production features
78
+ for (const pattern of TEST_FILE_PATTERNS) {
79
+ if (pattern.test(basename)) {
80
+ return false;
81
+ }
82
+ }
83
+ // Filter config files
84
+ for (const pattern of CONFIG_FILE_PATTERNS) {
85
+ if (pattern.test(basename)) {
86
+ return false;
87
+ }
88
+ }
89
+ return true;
90
+ }
8
91
  function runGitRaw(args, cwd) {
9
92
  const result = (0, child_process_1.spawnSync)('git', args, {
10
93
  cwd,
@@ -66,23 +149,26 @@ function getChangedFiles(appRoot, since, options) {
66
149
  baseStrategy = 'merge-base';
67
150
  }
68
151
  }
69
- const diffFiles = runGit(['diff', '--name-only', `${baseRef}..HEAD`, '--', '.'], appRoot);
152
+ // Get repo root so we capture ALL changed files (including server/, webapp/, etc.)
153
+ // not just files under the appRoot subdirectory.
154
+ const repoRoot = runGitRaw(['rev-parse', '--show-toplevel'], appRoot)?.trim() || appRoot;
155
+ const diffFiles = runGit(['diff', '--name-only', `${baseRef}..HEAD`], repoRoot);
70
156
  if (!diffFiles) {
71
157
  return { files: [], error: 'git diff failed' };
72
158
  }
73
159
  diffFiles.forEach((file) => files.add(file));
74
160
  if (options?.includeUncommitted) {
75
- const staged = runGit(['diff', '--name-only', '--cached', '--', '.'], appRoot) || [];
161
+ const staged = runGit(['diff', '--name-only', '--cached'], repoRoot) || [];
76
162
  staged.forEach((file) => files.add(file));
77
- const unstaged = runGit(['diff', '--name-only', '--', '.'], appRoot) || [];
163
+ const unstaged = runGit(['diff', '--name-only'], repoRoot) || [];
78
164
  unstaged.forEach((file) => files.add(file));
79
- const statusOutput = runGitRaw(['status', '--porcelain', '--', '.'], appRoot);
165
+ const statusOutput = runGitRaw(['status', '--porcelain'], repoRoot);
80
166
  if (statusOutput) {
81
167
  const statusLines = statusOutput.split('\n').filter(Boolean);
82
168
  parseStatusLines(statusLines).forEach((file) => files.add(file));
83
169
  }
84
170
  }
85
- return { files: Array.from(files), baseRef, baseStrategy };
171
+ return { files: Array.from(files).filter(isRelevantFile), baseRef, baseStrategy };
86
172
  }
87
173
  catch {
88
174
  return { files: [], error: 'git diff failed' };
@@ -2,6 +2,89 @@
2
2
  // See LICENSE.txt for license information.
3
3
  import { spawnSync } from 'child_process';
4
4
  import { normalizePath } from './utils.js';
5
+ // Directories that contain CI/tooling/docs — never relevant to impact analysis.
6
+ const IGNORED_DIR_SEGMENTS = [
7
+ '.github',
8
+ '.claude',
9
+ '.vscode',
10
+ '.idea',
11
+ 'node_modules',
12
+ ];
13
+ // Exact filenames (basename) that are never relevant.
14
+ const IGNORED_BASENAMES = new Set([
15
+ 'package.json',
16
+ 'package-lock.json',
17
+ '.gitignore',
18
+ '.prettierignore',
19
+ '.prettierrc',
20
+ '.eslintrc',
21
+ '.eslintrc.js',
22
+ '.eslintrc.json',
23
+ '.editorconfig',
24
+ '.npmrc',
25
+ '.mcp.json',
26
+ 'CHANGELOG.md',
27
+ 'README.md',
28
+ 'LICENSE',
29
+ 'LICENSE.txt',
30
+ 'tsconfig.json',
31
+ 'jest.config.js',
32
+ 'jest.config.ts',
33
+ 'babel.config.js',
34
+ ]);
35
+ // Extensions that are never source code.
36
+ const IGNORED_EXTENSIONS = new Set([
37
+ '.md',
38
+ '.txt',
39
+ '.lock',
40
+ '.png', '.jpg', '.jpeg', '.gif', '.svg', '.ico',
41
+ '.woff', '.woff2', '.ttf', '.eot',
42
+ ]);
43
+ // File patterns that indicate test/spec files (not production code).
44
+ const TEST_FILE_PATTERNS = [
45
+ /\.spec\.[tj]sx?$/,
46
+ /\.test\.[tj]sx?$/,
47
+ /_test\.go$/,
48
+ /\.stories\.[tj]sx?$/,
49
+ ];
50
+ // Config file patterns that are not production source code.
51
+ const CONFIG_FILE_PATTERNS = [
52
+ /\.config\.[tj]sx?$/,
53
+ /\.config\.json$/,
54
+ /\.config\.js$/,
55
+ ];
56
+ function isRelevantFile(file) {
57
+ const segments = file.split('/');
58
+ const basename = segments[segments.length - 1] || file;
59
+ if (IGNORED_BASENAMES.has(basename)) {
60
+ return false;
61
+ }
62
+ for (const seg of segments) {
63
+ if (IGNORED_DIR_SEGMENTS.includes(seg)) {
64
+ return false;
65
+ }
66
+ }
67
+ const dotIdx = basename.lastIndexOf('.');
68
+ if (dotIdx > 0) {
69
+ const ext = basename.slice(dotIdx).toLowerCase();
70
+ if (IGNORED_EXTENSIONS.has(ext)) {
71
+ return false;
72
+ }
73
+ }
74
+ // Filter test/spec files — they don't impact production features
75
+ for (const pattern of TEST_FILE_PATTERNS) {
76
+ if (pattern.test(basename)) {
77
+ return false;
78
+ }
79
+ }
80
+ // Filter config files
81
+ for (const pattern of CONFIG_FILE_PATTERNS) {
82
+ if (pattern.test(basename)) {
83
+ return false;
84
+ }
85
+ }
86
+ return true;
87
+ }
5
88
  function runGitRaw(args, cwd) {
6
89
  const result = spawnSync('git', args, {
7
90
  cwd,
@@ -63,23 +146,26 @@ export function getChangedFiles(appRoot, since, options) {
63
146
  baseStrategy = 'merge-base';
64
147
  }
65
148
  }
66
- const diffFiles = runGit(['diff', '--name-only', `${baseRef}..HEAD`, '--', '.'], appRoot);
149
+ // Get repo root so we capture ALL changed files (including server/, webapp/, etc.)
150
+ // not just files under the appRoot subdirectory.
151
+ const repoRoot = runGitRaw(['rev-parse', '--show-toplevel'], appRoot)?.trim() || appRoot;
152
+ const diffFiles = runGit(['diff', '--name-only', `${baseRef}..HEAD`], repoRoot);
67
153
  if (!diffFiles) {
68
154
  return { files: [], error: 'git diff failed' };
69
155
  }
70
156
  diffFiles.forEach((file) => files.add(file));
71
157
  if (options?.includeUncommitted) {
72
- const staged = runGit(['diff', '--name-only', '--cached', '--', '.'], appRoot) || [];
158
+ const staged = runGit(['diff', '--name-only', '--cached'], repoRoot) || [];
73
159
  staged.forEach((file) => files.add(file));
74
- const unstaged = runGit(['diff', '--name-only', '--', '.'], appRoot) || [];
160
+ const unstaged = runGit(['diff', '--name-only'], repoRoot) || [];
75
161
  unstaged.forEach((file) => files.add(file));
76
- const statusOutput = runGitRaw(['status', '--porcelain', '--', '.'], appRoot);
162
+ const statusOutput = runGitRaw(['status', '--porcelain'], repoRoot);
77
163
  if (statusOutput) {
78
164
  const statusLines = statusOutput.split('\n').filter(Boolean);
79
165
  parseStatusLines(statusLines).forEach((file) => files.add(file));
80
166
  }
81
167
  }
82
- return { files: Array.from(files), baseRef, baseStrategy };
168
+ return { files: Array.from(files).filter(isRelevantFile), baseRef, baseStrategy };
83
169
  }
84
170
  catch {
85
171
  return { files: [], error: 'git diff failed' };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yasserkhanorg/e2e-agents",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
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",