entkapp 5.5.0 → 5.6.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 (62) hide show
  1. package/README.md +1 -1
  2. package/bin/cli.js +2 -2
  3. package/bin/cli.mjs +175 -0
  4. package/index.cjs +18 -0
  5. package/index.mjs +51 -0
  6. package/package.json +7 -6
  7. package/src/EngineContext.mjs +428 -0
  8. package/src/Initializer.mjs +82 -0
  9. package/src/analyzers/CodeSmellAnalyzer.mjs +106 -0
  10. package/src/analyzers/OxcAnalyzer.mjs +11 -0
  11. package/src/api/HeadlessAPI.js +31 -16
  12. package/src/api/HeadlessAPI.mjs +369 -0
  13. package/src/api/PluginSDK.mjs +135 -0
  14. package/src/ast/ASTAnalyzer.js +17 -3
  15. package/src/ast/ASTAnalyzer.mjs +742 -0
  16. package/src/ast/AdvancedAnalysis.mjs +586 -0
  17. package/src/ast/BarrelParser.mjs +230 -0
  18. package/src/ast/DeadCodeDetector.js +7 -5
  19. package/src/ast/DeadCodeDetector.mjs +92 -0
  20. package/src/ast/MagicDetector.mjs +203 -0
  21. package/src/ast/OxcAnalyzer.mjs +188 -0
  22. package/src/ast/SecretScanner.mjs +374 -0
  23. package/src/healing/GitSandbox.mjs +82 -0
  24. package/src/healing/SelfHealer.mjs +48 -0
  25. package/src/index.js +37 -1
  26. package/src/index.mjs +1180 -0
  27. package/src/performance/GraphCache.mjs +108 -0
  28. package/src/performance/SupplyChainGuard.mjs +92 -0
  29. package/src/performance/WorkerPool.mjs +132 -0
  30. package/src/performance/WorkerTaskRunner.mjs +144 -0
  31. package/src/plugins/BasePlugin.mjs +240 -0
  32. package/src/plugins/PluginRegistry.mjs +203 -0
  33. package/src/plugins/ecosystems/BackendServices.mjs +197 -0
  34. package/src/plugins/ecosystems/GenericPlugins.mjs +142 -0
  35. package/src/plugins/ecosystems/ModernFrameworks.mjs +162 -0
  36. package/src/plugins/ecosystems/MorePlugins.mjs +562 -0
  37. package/src/plugins/ecosystems/NewPlugins.mjs +526 -0
  38. package/src/plugins/ecosystems/NextJsPlugin.mjs +45 -0
  39. package/src/plugins/ecosystems/PluginLoader.mjs +193 -0
  40. package/src/plugins/ecosystems/TypeScriptPlugin.mjs +56 -0
  41. package/src/plugins/ecosystems/UltimateBundle.mjs +1182 -0
  42. package/src/refractor/ImpactAnalyzer.mjs +92 -0
  43. package/src/refractor/SourceRewriter.mjs +86 -0
  44. package/src/refractor/TransactionManager.mjs +5 -0
  45. package/src/refractor/TypeIntegrity.mjs +4 -0
  46. package/src/resolution/BuildOrchestrator.mjs +46 -0
  47. package/src/resolution/CircularDetector.mjs +91 -0
  48. package/src/resolution/ConfigGenerator.mjs +83 -0
  49. package/src/resolution/ConfigLoader.mjs +94 -0
  50. package/src/resolution/DepencyResolver.mjs +66 -0
  51. package/src/resolution/DependencyFixer.mjs +88 -0
  52. package/src/resolution/DependencyProfiler.mjs +286 -0
  53. package/src/resolution/EntryPointDetector.mjs +134 -0
  54. package/src/resolution/FrameworkConfigParser.mjs +119 -0
  55. package/src/resolution/GraphAnalyzer.mjs +80 -0
  56. package/src/resolution/MigrationAnalyzer.mjs +60 -0
  57. package/src/resolution/PathMapper.mjs +82 -0
  58. package/src/resolution/TSConfigLoader.mjs +162 -0
  59. package/src/resolution/WorkSpaceGraph.mjs +183 -0
  60. package/src/resolution/WorkspaceDiagnostic.mjs +139 -0
  61. package/test.js +76 -0
  62. package/wrangler.toml +6 -0
@@ -0,0 +1,230 @@
1
+ import ts from 'typescript';
2
+ import fs from 'fs/promises';
3
+
4
+ /**
5
+ * Enterprise Wildcard Optimization & Flattening Layer for Barrel Operations
6
+ * Traces unreferenced paths through redistribution entries.
7
+ */
8
+ export class BarrelParser {
9
+ constructor(context, resolver) {
10
+ this.context = context; // Enthält globale Konfigurationen (z.B. context.entrypoints)
11
+ this.resolver = resolver;
12
+ this.cachedSpecifications = new Map();
13
+ }
14
+
15
+ /**
16
+ * Compiles the structural export layout for a specific index or barrel target.
17
+ * @param {string} filePath - Absolute path to on-disk target element
18
+ */
19
+ async parseBarrelSpecification(filePath) {
20
+ if (this.cachedSpecifications.has(filePath)) {
21
+ return this.cachedSpecifications.get(filePath);
22
+ }
23
+
24
+ const specification = {
25
+ isBarrelInstance: false,
26
+ isApplicationEntrypoint: false, // FIX: Schutzschicht für Einstiegspunkte gegen Fehldetektion
27
+ wildcardExports: new Set(), // export * from './module';
28
+ namespacedWildcardExports: new Map(), // export * as Utils from './module';
29
+ forwardedNamedExports: new Map(), // export { token as alias } from './module';
30
+ declaredLocalExports: new Set() // export const a = 1;
31
+ };
32
+
33
+ // FIX: Überprüfe, ob die aktuelle Datei als App-Einstiegspunkt deklariert ist
34
+ if (this.context && this.context.entrypoints) {
35
+ const isEntry = this.context.entrypoints.some(entry =>
36
+ this.resolver.resolveModulePath(filePath, entry) === filePath || entry === filePath
37
+ );
38
+ if (isEntry) {
39
+ specification.isApplicationEntrypoint = true;
40
+ }
41
+ }
42
+
43
+ try {
44
+ const code = await fs.readFile(filePath, 'utf8');
45
+ const sourceFile = ts.createSourceFile(filePath, code, ts.ScriptTarget.Latest, true);
46
+
47
+ this.harvestExportSignatures(sourceFile, specification);
48
+
49
+ // FIX: Eine Datei ist NUR DANN ein rein kosmetisches Barrel, wenn sie Re-Exports besitzt
50
+ // UND NICHT der geschützte Haupteinstiegspunkt (Entrypoint) der Anwendung ist!
51
+ if (!specification.isApplicationEntrypoint && (
52
+ specification.wildcardExports.size > 0 ||
53
+ specification.namespacedWildcardExports.size > 0 ||
54
+ specification.forwardedNamedExports.size > 0
55
+ )) {
56
+ specification.isBarrelInstance = true;
57
+ }
58
+
59
+ this.cachedSpecifications.set(filePath, specification);
60
+ return specification;
61
+ } catch {
62
+ return specification; // Error-State fällt auf sicheres Standard-Layout zurück
63
+ }
64
+ }
65
+
66
+ harvestExportSignatures(node, spec) {
67
+ if (!node) return;
68
+
69
+ switch (node.kind) {
70
+ case ts.SyntaxKind.ExportDeclaration: {
71
+ const targetSpecifier = node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)
72
+ ? node.moduleSpecifier.text
73
+ : null;
74
+
75
+ if (targetSpecifier) {
76
+ if (!node.exportClause) {
77
+ // Standard Wildcard Transfer: export * from './module';
78
+ spec.wildcardExports.add(targetSpecifier);
79
+ } else if (ts.isNamespaceExport(node.exportClause)) {
80
+ // Namespaced Wildcard Transfer: export * as Core from './module';
81
+ const namespaceAlias = node.exportClause.name.text;
82
+ spec.namespacedWildcardExports.set(namespaceAlias, targetSpecifier);
83
+ } else if (ts.isNamedExports(node.exportClause)) {
84
+ // Selective Re-export Forwarding: export { x, y as z } from './module';
85
+ node.exportClause.elements.forEach(element => {
86
+ const originalSymbol = element.propertyName ? element.propertyName.text : element.name.text;
87
+ const exposedAlias = element.name.text;
88
+ spec.forwardedNamedExports.set(exposedAlias, {
89
+ targetModule: targetSpecifier,
90
+ sourceSymbol: originalSymbol
91
+ });
92
+ });
93
+ }
94
+ }
95
+ break;
96
+ }
97
+
98
+ // Track items declared directly within the file boundary
99
+ case ts.SyntaxKind.FunctionDeclaration:
100
+ case ts.SyntaxKind.ClassDeclaration:
101
+ case ts.SyntaxKind.InterfaceDeclaration:
102
+ case ts.SyntaxKind.TypeAliasDeclaration:
103
+ case ts.SyntaxKind.EnumDeclaration: {
104
+ if (node.modifiers && node.modifiers.some(m => m.kind === ts.SyntaxKind.ExportKeyword)) {
105
+ if (node.name && ts.isIdentifier(node.name)) {
106
+ spec.declaredLocalExports.add(node.name.text);
107
+ }
108
+ }
109
+ break;
110
+ }
111
+
112
+ case ts.SyntaxKind.VariableStatement: {
113
+ if (node.modifiers && node.modifiers.some(m => m.kind === ts.SyntaxKind.ExportKeyword)) {
114
+ node.declarationList.declarations.forEach(decl => {
115
+ if (ts.isIdentifier(decl.name)) {
116
+ spec.declaredLocalExports.add(decl.name.text);
117
+ } else if (ts.isObjectBindingPattern(decl.name)) {
118
+ decl.name.elements.forEach(element => {
119
+ if (element.name && ts.isIdentifier(element.name)) {
120
+ spec.declaredLocalExports.add(element.name.text);
121
+ }
122
+ });
123
+ } else if (ts.isArrayBindingPattern(decl.name)) {
124
+ decl.name.elements.forEach(element => {
125
+ if (ts.isBindingElement(element) && element.name && ts.isIdentifier(element.name)) {
126
+ spec.declaredLocalExports.add(element.name.text);
127
+ }
128
+ });
129
+ }
130
+ });
131
+ }
132
+ break;
133
+ }
134
+
135
+ case ts.SyntaxKind.ExportAssignment: {
136
+ spec.declaredLocalExports.add('default');
137
+ break;
138
+ }
139
+ }
140
+
141
+ ts.forEachChild(node, child => this.harvestExportSignatures(child, spec));
142
+ }
143
+
144
+ /**
145
+ * Challenge #3 Resolution Logic. Unwraps nested redistribution links to find origin source nodes.
146
+ * @param {string} contextFilePath - Current position filename vector pointer
147
+ * @param {string} targetSymbolName - Targeted semantic variable signature name
148
+ * @param {Map} activeProjectGraph - Global active module maps directory registry
149
+ * @param {Set} [protectionStack] - Avoids cyclic validation traps inside self-referencing links
150
+ */
151
+ async determineSymbolDeclarationOrigin(contextFilePath, targetSymbolName, activeProjectGraph, protectionStack = new Set()) {
152
+ if (protectionStack.has(contextFilePath)) {
153
+ return { originFile: contextFilePath, originSymbol: targetSymbolName };
154
+ }
155
+ protectionStack.add(contextFilePath);
156
+
157
+ const spec = await this.parseBarrelSpecification(contextFilePath);
158
+ if (!spec.isBarrelInstance) {
159
+ return { originFile: contextFilePath, originSymbol: targetSymbolName };
160
+ }
161
+
162
+ // Rule A: Settle boundary immediately if local declaration matches token signature name
163
+ if (spec.declaredLocalExports.has(targetSymbolName)) {
164
+ return { originFile: contextFilePath, originSymbol: targetSymbolName };
165
+ }
166
+
167
+ // Rule B: Evaluate explicit named re-export mappings (export { A as B } from 'module')
168
+ if (spec.forwardedNamedExports.has(targetSymbolName)) {
169
+ const routingRule = spec.forwardedNamedExports.get(targetSymbolName);
170
+ const fullyResolvedPath = this.resolver.resolveModulePath(contextFilePath, routingRule.targetModule);
171
+ if (fullyResolvedPath) {
172
+ return this.determineSymbolDeclarationOrigin(fullyResolvedPath, routingRule.sourceSymbol, activeProjectGraph, protectionStack);
173
+ }
174
+ }
175
+
176
+ // Rule C: Evaluate structural namespace alias groupings (export * as name from 'module')
177
+ for (const [namespaceAlias, relativeModule] of spec.namespacedWildcardExports.entries()) {
178
+ if (targetSymbolName === namespaceAlias) {
179
+ const fullyResolvedPath = this.resolver.resolveModulePath(contextFilePath, relativeModule);
180
+ return { originFile: fullyResolvedPath, originSymbol: '*' };
181
+ }
182
+ if (targetSymbolName.startsWith(`${namespaceAlias}.`)) {
183
+ const originalSymbol = targetSymbolName.substring(namespaceAlias.length + 1);
184
+ const fullyResolvedPath = this.resolver.resolveModulePath(contextFilePath, relativeModule);
185
+ if (fullyResolvedPath) {
186
+ return this.determineSymbolDeclarationOrigin(fullyResolvedPath, originalSymbol, activeProjectGraph, protectionStack);
187
+ }
188
+ }
189
+ }
190
+
191
+ // Rule D: Sweep through anonymous star re-exports vectors (export * from 'module')
192
+ for (const relativePath of spec.wildcardExports) {
193
+ const fullyResolvedPath = this.resolver.resolveModulePath(contextFilePath, relativePath);
194
+
195
+ if (fullyResolvedPath) {
196
+ // Verbinde Graph-Kanten direkt während der Wildcard-Traversierung
197
+ const contextNode = activeProjectGraph.get(contextFilePath);
198
+ if (contextNode) {
199
+ contextNode.outgoingEdges.add(fullyResolvedPath);
200
+ const targetNode = activeProjectGraph.get(fullyResolvedPath);
201
+ if (targetNode) {
202
+ targetNode.incomingEdges.add(contextFilePath);
203
+ }
204
+ }
205
+
206
+ const continuousResolutionTrace = await this.determineSymbolDeclarationOrigin(
207
+ fullyResolvedPath,
208
+ targetSymbolName,
209
+ activeProjectGraph,
210
+ new Set(protectionStack) // Kopie verhindert geschwisterliche Branch-Blockaden
211
+ );
212
+
213
+ if (!continuousResolutionTrace) continue;
214
+ if (continuousResolutionTrace.originFile === contextFilePath) continue;
215
+
216
+ const originSpec = await this.parseBarrelSpecification(continuousResolutionTrace.originFile);
217
+ if (originSpec.declaredLocalExports.has(continuousResolutionTrace.originSymbol) ||
218
+ continuousResolutionTrace.originSymbol === '*') {
219
+ return continuousResolutionTrace;
220
+ }
221
+
222
+ if (originSpec.isBarrelInstance) {
223
+ return continuousResolutionTrace;
224
+ }
225
+ }
226
+ }
227
+
228
+ return { originFile: contextFilePath, originSymbol: targetSymbolName };
229
+ }
230
+ }
@@ -10,8 +10,10 @@ export class DeadCodeDetector {
10
10
  // Find all entry points
11
11
  const entryPoints = new Set();
12
12
  for (const [filePath, node] of graph.entries()) {
13
- // NIGHTMARE FIX: node.isEntry must be respected, and also check for library entries
14
- if (node.isEntry || node.isLibraryEntry || node.isNextJsRoute || node.isSvelteComponent || node.isAstroPage) {
13
+ // ADVANCED: Framework-agnostic entry point detection
14
+ // Respects explicit entries, side-effect files, and dynamic entry points
15
+ if (node.isEntry || node.isLibraryEntry || node.isDynamicEntry || node.hasSideEffects ||
16
+ node.isNextJsRoute || node.isSvelteComponent || node.isAstroPage) {
15
17
  entryPoints.add(filePath);
16
18
  }
17
19
  }
@@ -63,11 +65,11 @@ export class DeadCodeDetector {
63
65
  if (exportName === '*' || exportName === 'default') continue; // Skip wildcards for now
64
66
 
65
67
  let isUsed = false;
66
- // Check ALL nodes in the graph for usage of this symbol, not just those with edges
67
- // (Handles cases where edges might be missing or complex)
68
+ // ADVANCED: Global usage tracking including dynamic property access
68
69
  for (const [otherPath, otherNode] of graph.entries()) {
69
70
  if (otherNode.importedSymbols.has(`${filePath}:${exportName}`) ||
70
- otherNode.importedSymbols.has(`${filePath}:*`)) {
71
+ otherNode.importedSymbols.has(`${filePath}:*`) ||
72
+ otherNode.instantiatedIdentifiers.has(exportName)) {
71
73
  isUsed = true;
72
74
  break;
73
75
  }
@@ -0,0 +1,92 @@
1
+ export class DeadCodeDetector {
2
+ constructor(context) {
3
+ this.context = context;
4
+ }
5
+
6
+ detectDeadCode(graph) {
7
+ const deadFiles = [];
8
+ const deadExports = [];
9
+
10
+ // Find all entry points
11
+ const entryPoints = new Set();
12
+ for (const [filePath, node] of graph.entries()) {
13
+ // ADVANCED: Framework-agnostic entry point detection
14
+ // Respects explicit entries, side-effect files, and dynamic entry points
15
+ if (node.isEntry || node.isLibraryEntry || node.isDynamicEntry || node.hasSideEffects ||
16
+ node.isNextJsRoute || node.isSvelteComponent || node.isAstroPage) {
17
+ entryPoints.add(filePath);
18
+ }
19
+ }
20
+
21
+ // UPGRADE 5: Cycle-tolerant Graph Traversal.
22
+ // We use a robust recursive traversal with a visited set to handle cycles.
23
+ const usedFiles = new Set();
24
+ const visited = new Set();
25
+
26
+ const traverse = (filePath) => {
27
+ if (visited.has(filePath)) return;
28
+ visited.add(filePath);
29
+ usedFiles.add(filePath);
30
+
31
+ const node = graph.get(filePath);
32
+ if (node && node.outgoingEdges) {
33
+ for (const edge of node.outgoingEdges) {
34
+ traverse(edge);
35
+ }
36
+ }
37
+ };
38
+
39
+ for (const entry of entryPoints) {
40
+ traverse(entry);
41
+ }
42
+
43
+ // Identify dead files
44
+ for (const filePath of graph.keys()) {
45
+ if (!usedFiles.has(filePath)) {
46
+ deadFiles.push(filePath);
47
+ }
48
+ }
49
+
50
+ // Identify dead exports in used files
51
+ for (const filePath of usedFiles) {
52
+ const node = graph.get(filePath);
53
+ if (!node) continue;
54
+
55
+ // If it's an entry point, we consider its exports used (unless strictly configured otherwise)
56
+ // NIGHTMARE FIX: Even in entry points, we might want to find unused exports if they are not re-exported
57
+ if (node.isEntry && !node.isLibraryEntry) {
58
+ // If it's a main entry but not a library, its exports are usually unused
59
+ // unless it's a barrel file. Let's proceed to check usage.
60
+ } else if (node.isLibraryEntry) {
61
+ continue;
62
+ }
63
+
64
+ for (const [exportName, exportInfo] of node.internalExports.entries()) {
65
+ if (exportName === '*' || exportName === 'default') continue; // Skip wildcards for now
66
+
67
+ let isUsed = false;
68
+ // ADVANCED: Global usage tracking including dynamic property access
69
+ for (const [otherPath, otherNode] of graph.entries()) {
70
+ if (otherNode.importedSymbols.has(`${filePath}:${exportName}`) ||
71
+ otherNode.importedSymbols.has(`${filePath}:*`) ||
72
+ otherNode.instantiatedIdentifiers.has(exportName)) {
73
+ isUsed = true;
74
+ break;
75
+ }
76
+ }
77
+
78
+ // Additional check for library entries or index files
79
+ // NIGHTMARE FIX: Don't blindly protect 'index' files if they are not real entries
80
+ if (!isUsed && (node.isLibraryEntry)) {
81
+ isUsed = true;
82
+ }
83
+
84
+ if (!isUsed) {
85
+ deadExports.push({ file: filePath, symbol: exportName, line: exportInfo.start });
86
+ }
87
+ }
88
+ }
89
+
90
+ return { deadFiles, deadExports };
91
+ }
92
+ }
@@ -0,0 +1,203 @@
1
+ import path from 'path';
2
+ import fs from 'fs/promises';
3
+ import { PluginRegistry } from '../plugins/PluginRegistry.mjs';
4
+
5
+ /**
6
+ * Ecosystem Entry Point Manifest & Dynamic Framework Router Heuristic Validator
7
+ * Intercepts implicit conventions to handle cases where direct import statements are absent.
8
+ * Now refactored to use a pluggable architecture.
9
+ *
10
+ * Improvements over v1:
11
+ * - Extended config-file detection list (Biome, Oxlint, tsup, unbuild, etc.)
12
+ * - Next.js App Router conventions (page.tsx, layout.tsx, loading.tsx, error.tsx, etc.)
13
+ * - Remix conventions (route files under app/routes/)
14
+ * - SvelteKit conventions (+page.svelte, +layout.svelte, etc.)
15
+ * - Astro page/layout conventions
16
+ * - Common entry-point patterns (bin/, cli.ts, server.ts, main.ts, app.ts)
17
+ * - Test file patterns extended to cover Vitest workspace files
18
+ */
19
+ export class MagicDetector {
20
+ constructor(context) {
21
+ this.context = context;
22
+ this.registry = new PluginRegistry(context);
23
+ this.isInitialized = false;
24
+ }
25
+
26
+ async ensureInitialized(baseDir) {
27
+ if (this.isInitialized) return;
28
+ await this.registry.init(baseDir || process.cwd());
29
+ this.isInitialized = true;
30
+ }
31
+
32
+ /**
33
+ * Audits the project context to map active micro-framework ecosystems.
34
+ * @param {string} baseContextDirectory - Root file workspace context execution vector path
35
+ */
36
+ async identifyActiveProjectEcosystems(baseContextDirectory) {
37
+ await this.ensureInitialized(baseContextDirectory);
38
+ const activePlugins = await this.registry.getActivePlugins(baseContextDirectory);
39
+ const activeFrameworkFlags = activePlugins.map(p => p.name);
40
+
41
+ // Universal infrastructure overrides (testing platforms and common bundlers)
42
+ activeFrameworkFlags.push('universal-tooling-vectors');
43
+ return activeFrameworkFlags;
44
+ }
45
+
46
+ /**
47
+ * Assesses if a file path acts as an implicit route entry point.
48
+ */
49
+ async isImplicitlyRequiredByEcosystem(absolutePath, activeFrameworks, baseDir) {
50
+ await this.ensureInitialized();
51
+ const normalizedSystemPath = absolutePath.replace(/\\/g, '/');
52
+
53
+ const plugins = this.registry.getPlugins();
54
+ for (const plugin of plugins) {
55
+ if (activeFrameworks.includes(plugin.name)) {
56
+ const patterns = plugin.getRoutePatterns();
57
+ if (patterns.some(regex => regex.test(normalizedSystemPath))) {
58
+ return true;
59
+ }
60
+ }
61
+ }
62
+
63
+ // Apply baseline platform rules (Test suites, lint parameters, continuous integration files)
64
+ if (this.isCoreToolingSuiteElement(normalizedSystemPath)) {
65
+ return true;
66
+ }
67
+
68
+ return false;
69
+ }
70
+
71
+ isCoreToolingSuiteElement(normalizedPath) {
72
+ // ── Test / spec files ──────────────────────────────────────────────────────
73
+ if (/\.(test|spec|e2e|cy)\.(js|ts|tsx|jsx)$/i.test(normalizedPath)) return true;
74
+ if (/\.stories\.(js|ts|tsx|jsx)$/i.test(normalizedPath)) return true;
75
+
76
+ // ── Build / bundler config files ───────────────────────────────────────────
77
+ const configFragments = [
78
+ // Test runners
79
+ 'jest.config.', 'vitest.config.', 'vitest.workspace.',
80
+ 'playwright.config.', 'cypress.config.',
81
+ // Bundlers
82
+ 'webpack.config.', 'vite.config.', 'rollup.config.',
83
+ 'esbuild.config.', 'parcel.config.',
84
+ 'tsup.config.', 'unbuild.config.', 'pkgroll.config.',
85
+ // CSS / styling
86
+ 'tailwind.config.', 'postcss.config.', '.postcssrc.',
87
+ // Linters / formatters
88
+ '.eslintrc.', 'eslint.config.', 'prettier.config.', '.prettierrc.',
89
+ '.stylelintrc.', 'stylelint.config.',
90
+ 'biome.json', '.oxlintrc.',
91
+ // Babel / transpilation
92
+ '.babelrc.', 'babel.config.',
93
+ // Commit / git hooks
94
+ '.commitlintrc.', 'commitlint.config.',
95
+ '.lintstagedrc.', 'lint-staged.config.',
96
+ // Documentation
97
+ 'typedoc.config.', 'typedoc.json',
98
+ // Monorepo tools
99
+ 'turbo.json', 'nx.json', 'lerna.json',
100
+ // Misc tooling
101
+ 'knip.config.', 'knip.json',
102
+ 'syncpack.config.',
103
+ // Internal worker
104
+ 'WorkerTaskRunner.mjs'
105
+ ];
106
+ if (configFragments.some(f => normalizedPath.includes(f))) return true;
107
+
108
+ // ── Common application entry points ───────────────────────────────────────
109
+ const entryPatterns = [
110
+ // CLI binaries
111
+ '/bin/cli.mjs', '/bin/cli.ts', '/bin/cli.mjs',
112
+ '/bin/index.mjs', '/bin/index.ts',
113
+ // Server / app entry points (Reduced in v3.3.8 to avoid false positives in libraries)
114
+ '/src/main.ts', '/src/main.mjs',
115
+ '/src/app.ts', '/src/app.mjs',
116
+ '/src/api/HeadlessAPI.mjs', '/src/api/PluginSDK.mjs',
117
+ '/main.ts', '/main.mjs',
118
+ '/app.ts', '/app.mjs',
119
+ ];
120
+ if (entryPatterns.some(p => normalizedPath.endsWith(p))) return true;
121
+
122
+ // ── Next.js App Router conventions ────────────────────────────────────────
123
+ // Files under app/ directory with Next.js special names
124
+ if (/\/app\/(page|layout|loading|error|not-found|template|default|route|middleware)\.(js|ts|tsx|jsx)$/.test(normalizedPath)) return true;
125
+ // Next.js Pages Router
126
+ if (/\/pages\/.*\.(js|ts|tsx|jsx)$/.test(normalizedPath)) return true;
127
+ // Next.js API routes
128
+ if (/\/pages\/api\/.*\.(js|ts)$/.test(normalizedPath)) return true;
129
+ // Next.js middleware
130
+ if (/\/middleware\.(js|ts)$/.test(normalizedPath)) return true;
131
+ // Next.js config
132
+ if (/\/next\.config\.(js|ts|mjs|cjs)$/.test(normalizedPath)) return true;
133
+
134
+ // ── Remix conventions ─────────────────────────────────────────────────────
135
+ if (/\/app\/routes\/.*\.(js|ts|tsx|jsx)$/.test(normalizedPath)) return true;
136
+ if (/\/app\/root\.(js|ts|tsx|jsx)$/.test(normalizedPath)) return true;
137
+ if (/\/app\/entry\.(client|server)\.(js|ts|tsx|jsx)$/.test(normalizedPath)) return true;
138
+
139
+ // ── SvelteKit conventions ─────────────────────────────────────────────────
140
+ if (/\/\+page(\.(server|client))?\.(svelte|js|ts)$/.test(normalizedPath)) return true;
141
+ if (/\/\+layout(\.(server|client))?\.(svelte|js|ts)$/.test(normalizedPath)) return true;
142
+ if (/\/\+error\.(svelte|js|ts)$/.test(normalizedPath)) return true;
143
+ if (/\/\+server\.(js|ts)$/.test(normalizedPath)) return true;
144
+ if (/\/svelte\.config\.(js|ts|mjs)$/.test(normalizedPath)) return true;
145
+
146
+ // ── Astro conventions ─────────────────────────────────────────────────────
147
+ if (/\/src\/pages\/.*\.astro$/.test(normalizedPath)) return true;
148
+ if (/\/src\/layouts\/.*\.astro$/.test(normalizedPath)) return true;
149
+ if (/\/astro\.config\.(mjs|js|ts)$/.test(normalizedPath)) return true;
150
+
151
+ // ── Nuxt conventions ──────────────────────────────────────────────────────
152
+ if (/\/pages\/.*\.vue$/.test(normalizedPath)) return true;
153
+ if (/\/layouts\/.*\.vue$/.test(normalizedPath)) return true;
154
+ if (/\/server\/api\/.*\.(js|ts)$/.test(normalizedPath)) return true;
155
+ if (/\/nuxt\.config\.(js|ts|mjs)$/.test(normalizedPath)) return true;
156
+
157
+ // ── React / Vite entry points ─────────────────────────────────────────────
158
+ if (/\/vite\.config\.(js|ts|mjs)$/.test(normalizedPath)) return true;
159
+
160
+ // ── Angular conventions ───────────────────────────────────────────────────
161
+ if (/\/main\.(ts|js)$/.test(normalizedPath)) return true;
162
+ if (/\/app\.module\.(ts|js)$/.test(normalizedPath)) return true;
163
+ if (/\/angular\.json$/.test(normalizedPath)) return true;
164
+
165
+ // ── Expo / React Native ───────────────────────────────────────────────────
166
+ if (/\/app\/_layout\.(js|ts|tsx|jsx)$/.test(normalizedPath)) return true;
167
+ if (/\/app\/index\.(js|ts|tsx|jsx)$/.test(normalizedPath)) return true;
168
+
169
+ return false;
170
+ }
171
+
172
+ /**
173
+ * Challenge #4 Framework Overrides. Protects interface boundaries from false positive report flags.
174
+ */
175
+ async injectVirtualConsumerEdges(filePath, fileNode, activeFrameworks) {
176
+ await this.ensureInitialized();
177
+ if (!await this.isImplicitlyRequiredByEcosystem(filePath, activeFrameworks)) return;
178
+
179
+ // Retain entry point elements within memory to keep verification safe
180
+ fileNode.isEntry = true;
181
+
182
+ // Apply dynamic exports coverage metrics based on active platform contracts
183
+ const normalizedPath = filePath.replace(/\\/g, '/');
184
+ const plugins = this.registry.getPlugins();
185
+
186
+ for (const plugin of plugins) {
187
+ if (activeFrameworks.includes(plugin.name)) {
188
+ const patterns = plugin.getRoutePatterns();
189
+ const appliesToFramework = patterns.some(regex => regex.test(normalizedPath));
190
+
191
+ if (appliesToFramework) {
192
+ const contracts = plugin.getRequiredSystemContracts();
193
+ contracts.forEach(contractMethodToken => {
194
+ if (fileNode.internalExports.has(contractMethodToken)) {
195
+ // Emulate active local reference linkages to protect the export
196
+ fileNode.instantiatedIdentifiers.add(contractMethodToken);
197
+ }
198
+ });
199
+ }
200
+ }
201
+ }
202
+ }
203
+ }