gitnexus 1.6.11-rc.31 → 1.6.11-rc.32

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.
@@ -29,8 +29,12 @@ export interface EntryPointScoreResult {
29
29
  */
30
30
  export declare function calculateEntryPointScore(name: string, language: SupportedLanguages, isExported: boolean, callerCount: number, calleeCount: number, filePath?: string): EntryPointScoreResult;
31
31
  /**
32
- * Check if a file path is a test file (should be excluded from entry points)
33
- * Covers common test file patterns across all supported languages
32
+ * Check if a file path is a test file (should be excluded from entry points).
33
+ *
34
+ * Delegates to the shared predicate in `utils/test-file-path.ts`. This used to be
35
+ * a second, hand-maintained copy that had drifted from the one backing the MCP
36
+ * `includeTests` flag — see that module's header. Re-exported under this name so
37
+ * existing importers are unaffected.
34
38
  */
35
39
  export declare function isTestFile(filePath: string): boolean;
36
40
  /**
@@ -11,6 +11,7 @@
11
11
  */
12
12
  import { detectFrameworkFromPath } from './framework-detection.js';
13
13
  import { providers } from './languages/index.js';
14
+ import { isTestFilePath } from './utils/test-file-path.js';
14
15
  // ============================================================================
15
16
  // NAME PATTERNS
16
17
  // ============================================================================
@@ -127,52 +128,15 @@ export function calculateEntryPointScore(name, language, isExported, callerCount
127
128
  // HELPER FUNCTIONS
128
129
  // ============================================================================
129
130
  /**
130
- * Check if a file path is a test file (should be excluded from entry points)
131
- * Covers common test file patterns across all supported languages
131
+ * Check if a file path is a test file (should be excluded from entry points).
132
+ *
133
+ * Delegates to the shared predicate in `utils/test-file-path.ts`. This used to be
134
+ * a second, hand-maintained copy that had drifted from the one backing the MCP
135
+ * `includeTests` flag — see that module's header. Re-exported under this name so
136
+ * existing importers are unaffected.
132
137
  */
133
138
  export function isTestFile(filePath) {
134
- const p = filePath.toLowerCase().replace(/\\/g, '/');
135
- return (
136
- // JavaScript/TypeScript test patterns
137
- p.includes('.test.') ||
138
- p.includes('.spec.') ||
139
- p.includes('__tests__/') ||
140
- p.includes('__mocks__/') ||
141
- // Generic test folders
142
- p.includes('/test/') ||
143
- p.includes('/tests/') ||
144
- p.includes('/testing/') ||
145
- // Python test patterns
146
- p.endsWith('_test.py') ||
147
- p.includes('/test_') ||
148
- // Go test patterns
149
- p.endsWith('_test.go') ||
150
- // Java test patterns
151
- p.includes('/src/test/') ||
152
- // Rust test patterns (inline tests are different, but test files)
153
- p.includes('/tests/') ||
154
- // Swift/iOS test patterns
155
- p.endsWith('tests.swift') ||
156
- p.endsWith('test.swift') ||
157
- p.includes('uitests/') ||
158
- // C# test patterns
159
- p.endsWith('tests.cs') ||
160
- p.endsWith('test.cs') ||
161
- p.includes('.tests/') ||
162
- p.includes('.test/') ||
163
- p.includes('.integrationtests/') ||
164
- p.includes('.unittests/') ||
165
- p.includes('/testproject/') ||
166
- // PHP/Laravel test patterns
167
- p.endsWith('test.php') ||
168
- p.endsWith('spec.php') ||
169
- p.includes('/tests/feature/') ||
170
- p.includes('/tests/unit/') ||
171
- // Ruby test patterns
172
- p.endsWith('_spec.rb') ||
173
- p.endsWith('_test.rb') ||
174
- p.includes('/spec/') ||
175
- p.includes('/test/fixtures/'));
139
+ return isTestFilePath(filePath);
176
140
  }
177
141
  /**
178
142
  * Check if a file path is likely a utility/helper file
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Test-file path classification — the single source of truth.
3
+ *
4
+ * WHY THIS MODULE EXISTS
5
+ *
6
+ * Two independent copies of this predicate existed and had drifted apart:
7
+ *
8
+ * - `core/ingestion/entry-point-scoring.ts` `isTestFile` — excludes test
9
+ * files from process entry-point detection.
10
+ * - `mcp/local/local-backend.ts` `isTestFilePath` — backs the
11
+ * `includeTests` flag on `impact` / `trace` / `context`.
12
+ *
13
+ * They answered "is this a test file?" differently, so the same path could be a
14
+ * test in one code path and not the other. The MCP copy recognized no C#, Java,
15
+ * or Swift test convention at all, meaning `includeTests: false` silently failed
16
+ * to filter them; the scoring copy missed `/conftest.` (it already matched
17
+ * `/test/`, so `/test/fixtures/` was never a scoring gap).
18
+ *
19
+ * The duplication was not gratuitous: `entry-point-scoring.ts` imports the
20
+ * language-provider registry, and #2802 deliberately cut that closure out of MCP
21
+ * server startup. Importing it back into `local-backend.ts` would reintroduce
22
+ * that cost. So the shared predicate lives here instead, with NO imports — pure
23
+ * string matching — and both callers delegate to it.
24
+ *
25
+ * Keep it dependency-free. Anything imported here lands in MCP startup.
26
+ */
27
+ /** Absent / empty paths are not test paths. */
28
+ export declare function isTestFilePath(filePath: string | null | undefined): boolean;
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Test-file path classification — the single source of truth.
3
+ *
4
+ * WHY THIS MODULE EXISTS
5
+ *
6
+ * Two independent copies of this predicate existed and had drifted apart:
7
+ *
8
+ * - `core/ingestion/entry-point-scoring.ts` `isTestFile` — excludes test
9
+ * files from process entry-point detection.
10
+ * - `mcp/local/local-backend.ts` `isTestFilePath` — backs the
11
+ * `includeTests` flag on `impact` / `trace` / `context`.
12
+ *
13
+ * They answered "is this a test file?" differently, so the same path could be a
14
+ * test in one code path and not the other. The MCP copy recognized no C#, Java,
15
+ * or Swift test convention at all, meaning `includeTests: false` silently failed
16
+ * to filter them; the scoring copy missed `/conftest.` (it already matched
17
+ * `/test/`, so `/test/fixtures/` was never a scoring gap).
18
+ *
19
+ * The duplication was not gratuitous: `entry-point-scoring.ts` imports the
20
+ * language-provider registry, and #2802 deliberately cut that closure out of MCP
21
+ * server startup. Importing it back into `local-backend.ts` would reintroduce
22
+ * that cost. So the shared predicate lives here instead, with NO imports — pure
23
+ * string matching — and both callers delegate to it.
24
+ *
25
+ * Keep it dependency-free. Anything imported here lands in MCP startup.
26
+ */
27
+ /**
28
+ * Lowercase forward-slash path substrings. Directory needles include a leading
29
+ * slash so they match path components after the caller slash-prefixes relative
30
+ * paths. `/test/` already covers Maven `src/test` and `/test/fixtures/`;
31
+ * `/tests/` covers Laravel `tests/Feature` and `/tests/fixtures/`.
32
+ */
33
+ const TEST_PATH_SUBSTRINGS = [
34
+ '.test.',
35
+ '.spec.',
36
+ '__tests__/',
37
+ '__mocks__/',
38
+ '/test/',
39
+ '/tests/',
40
+ '/testing/',
41
+ '/spec/',
42
+ '/test_',
43
+ '/conftest.',
44
+ '/uitests/',
45
+ '.tests/',
46
+ '.test/',
47
+ '.integrationtests/',
48
+ '.unittests/',
49
+ '/testproject/',
50
+ ];
51
+ /** Case-insensitive suffixes that already include a delimiter (`_test.py`, not `test.py`). */
52
+ const TEST_PATH_DELIMITED_SUFFIXES = [
53
+ '_test.py',
54
+ '_test.go',
55
+ '_spec.rb',
56
+ '_test.rb',
57
+ ];
58
+ /**
59
+ * Case-sensitive `Test`/`Tests`/`Spec` suffixes. Lowercasing first would also
60
+ * match production names such as `Contest.swift` and `Latest.php`.
61
+ */
62
+ const TEST_PATH_CASED_SUFFIXES = [
63
+ 'Tests.swift',
64
+ 'Test.swift',
65
+ 'Tests.cs',
66
+ 'Test.cs',
67
+ 'Test.php',
68
+ 'Spec.php',
69
+ ];
70
+ /** Absent / empty paths are not test paths. */
71
+ export function isTestFilePath(filePath) {
72
+ if (!filePath)
73
+ return false;
74
+ const slashed = filePath.replace(/\\/g, '/');
75
+ const prefixed = slashed.startsWith('/') ? slashed : `/${slashed}`;
76
+ const lower = prefixed.toLowerCase();
77
+ if (TEST_PATH_SUBSTRINGS.some((needle) => lower.includes(needle)))
78
+ return true;
79
+ if (TEST_PATH_DELIMITED_SUFFIXES.some((suffix) => lower.endsWith(suffix)))
80
+ return true;
81
+ // Xcode `{Product}UITests` targets. Slash-anchored `/uitests/` does not match
82
+ // `MyAppUITests`; an unanchored `uitests/` substring also matches `fruitests`.
83
+ if (prefixed.split('/').some((seg) => seg.endsWith('UITests')))
84
+ return true;
85
+ const basename = prefixed.slice(prefixed.lastIndexOf('/') + 1);
86
+ return TEST_PATH_CASED_SUFFIXES.some((suffix) => basename.endsWith(suffix));
87
+ }
@@ -5,14 +5,12 @@
5
5
  * Supports multiple indexed repositories via a global registry.
6
6
  * LadybugDB connections are opened lazily per repo on first query.
7
7
  */
8
+ import { isTestFilePath } from '../../core/ingestion/utils/test-file-path.js';
8
9
  import { type RegistryEntry, type BranchSummary } from '../../storage/repo-manager.js';
9
10
  import { GroupService } from '../../core/group/service.js';
10
11
  import { type StalenessInfo } from '../../core/git-staleness.js';
11
- /**
12
- * Quick test-file detection for filtering impact results.
13
- * Matches common test file patterns across all supported languages.
14
- */
15
- export declare function isTestFilePath(filePath: string | null | undefined): boolean;
12
+ /** Shared predicate; re-exported so MCP importers keep the old public name. */
13
+ export { isTestFilePath };
16
14
  /** Valid LadybugDB node labels for safe Cypher query construction */
17
15
  export declare const VALID_NODE_LABELS: Set<string>;
18
16
  /** Valid relation types for impact analysis filtering */
@@ -859,4 +857,3 @@ export declare class LocalBackend {
859
857
  queryProcessDetail(name: string, repoName?: string): Promise<any>;
860
858
  disconnect(): Promise<void>;
861
859
  }
862
- export {};
@@ -19,6 +19,7 @@ import { LBUG_ID_PROBE_BATCH_SIZE, LBUG_QUERY_BATCH_SIZE } from '../../core/lbug
19
19
  import { chunk, mapConcurrent } from '../../lib/utils.js';
20
20
  import { pathSuffixOf } from './path-predicate.js';
21
21
  import { toOneBasedLine } from '../../core/ingestion/utils/line-base.js';
22
+ import { isTestFilePath } from '../../core/ingestion/utils/test-file-path.js';
22
23
  import { isWalCorruptionError, WAL_RECOVERY_SUGGESTION } from '../../core/lbug/lbug-config.js';
23
24
  // Embedding imports are lazy (dynamic import) to avoid loading onnxruntime-node
24
25
  // at MCP server startup — crashes on unsupported Node ABI versions (#89)
@@ -190,30 +191,8 @@ function normalizeToolParams(method, params) {
190
191
  }
191
192
  // AI context generation is CLI-only (gitnexus analyze)
192
193
  // import { generateAIContextFiles } from '../../cli/ai-context.js';
193
- /**
194
- * Quick test-file detection for filtering impact results.
195
- * Matches common test file patterns across all supported languages.
196
- */
197
- export function isTestFilePath(filePath) {
198
- if (!filePath)
199
- return false;
200
- const p = filePath.toLowerCase().replace(/\\/g, '/');
201
- return (p.includes('.test.') ||
202
- p.includes('.spec.') ||
203
- p.includes('__tests__/') ||
204
- p.includes('__mocks__/') ||
205
- p.includes('/test/') ||
206
- p.includes('/tests/') ||
207
- p.includes('/testing/') ||
208
- p.includes('/fixtures/') ||
209
- p.endsWith('_test.go') ||
210
- p.endsWith('_test.py') ||
211
- p.endsWith('_spec.rb') ||
212
- p.endsWith('_test.rb') ||
213
- p.includes('/spec/') ||
214
- p.includes('/test_') ||
215
- p.includes('/conftest.'));
216
- }
194
+ /** Shared predicate; re-exported so MCP importers keep the old public name. */
195
+ export { isTestFilePath };
217
196
  /** Valid LadybugDB node labels for safe Cypher query construction */
218
197
  export const VALID_NODE_LABELS = new Set([
219
198
  'File',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gitnexus",
3
- "version": "1.6.11-rc.31",
3
+ "version": "1.6.11-rc.32",
4
4
  "description": "Graph-powered code intelligence for AI agents. Index any codebase, query via MCP or CLI.",
5
5
  "author": "Abhigyan Patwari",
6
6
  "license": "PolyForm-Noncommercial-1.0.0",