preflight-mcp 0.7.2 → 0.7.4
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/README.md +9 -2
- package/README.zh-CN.md +1 -1
- package/dist/analysis/call-graph/adapters/base-adapter.js +193 -0
- package/dist/analysis/deep.js +4 -4
- package/dist/analysis/languages/go-analyzer.js +35 -15
- package/dist/analysis/pattern-analyzer.js +10 -0
- package/dist/analysis/scoring-config.js +118 -0
- package/dist/bundle/analysis-helpers.js +210 -0
- package/dist/bundle/cleanup.js +109 -3
- package/dist/bundle/dedup/fingerprint.js +57 -0
- package/dist/bundle/dedup/index.js +200 -0
- package/dist/bundle/deduplicator.js +318 -0
- package/dist/bundle/list.js +81 -0
- package/dist/bundle/manifest.js +129 -0
- package/dist/bundle/repo-ingest.js +210 -0
- package/dist/bundle/service.js +35 -997
- package/dist/bundle/storage.js +174 -0
- package/dist/bundle/utils.js +126 -0
- package/dist/bundle/validation.js +126 -0
- package/dist/config.js +8 -0
- package/dist/evidence/dependencyGraph.js +4 -4
- package/dist/logging/context.js +103 -0
- package/dist/logging/index.js +14 -0
- package/dist/logging/logger.js +66 -24
- package/dist/logging/types.js +30 -0
- package/dist/modal/processors/base-processor.js +2 -0
- package/dist/modal/utils/json-parser.js +1 -1
- package/dist/search/cache.js +274 -0
- package/dist/search/sqliteFts.js +48 -3
- package/dist/server/optimized-server.js +18 -2
- package/dist/server/tools/analysisTools.js +631 -0
- package/dist/server/tools/bundleTools.js +1404 -0
- package/dist/server/tools/callGraphTools.js +163 -0
- package/dist/server/tools/index.js +10 -0
- package/dist/server/tools/modalTools.js +91 -0
- package/dist/server/tools/searchTools.js +247 -0
- package/dist/server/tools/traceTools.js +231 -0
- package/dist/server/tools/types.js +5 -0
- package/dist/server.js +86 -2859
- package/dist/tools/analyzeModal.js +1 -1
- package/dist/tools/searchAndRead.js +52 -3
- package/dist/trace/suggest.js +341 -254
- package/package.json +6 -3
package/README.md
CHANGED
|
@@ -86,7 +86,7 @@ Preflight: 📄 Parsed design-spec.pdf (45 pages)
|
|
|
86
86
|
- 📖 **Auto-generated guides** — `START_HERE.md`, `AGENTS.md`, `OVERVIEW.md`
|
|
87
87
|
- ☁️ **Cloud sync** — Multi-path mirror backup for redundancy
|
|
88
88
|
- 🧠 **EDDA (Evidence-Driven Deep Analysis)** — Auto-generate auditable claims with evidence
|
|
89
|
-
- ⚡ **
|
|
89
|
+
- ⚡ **22 MCP tools + 6 prompts** — Streamlined toolkit optimized for LLM use
|
|
90
90
|
- 🧠 **Intelligent routing** — Auto-suggest tools based on task
|
|
91
91
|
- 🔗 **Call graph analysis** — Function-level dependency tracking (v0.7.2)
|
|
92
92
|
|
|
@@ -199,7 +199,7 @@ This will:
|
|
|
199
199
|
"Search for architecture diagrams in the bundle"
|
|
200
200
|
```
|
|
201
201
|
|
|
202
|
-
## Tools (
|
|
202
|
+
## Tools (22 active)
|
|
203
203
|
|
|
204
204
|
### Call Graph Tools (NEW v0.7.2)
|
|
205
205
|
|
|
@@ -426,6 +426,13 @@ Response includes:
|
|
|
426
426
|
### Analysis & Evidence
|
|
427
427
|
- `PREFLIGHT_ANALYSIS_MODE`: `none` | `quick` | `full` (default: `full`)
|
|
428
428
|
- `PREFLIGHT_AST_ENGINE`: `wasm` (default) or `native`
|
|
429
|
+
- `PREFLIGHT_DEEP_ANALYSIS_MAX_OVERVIEW_CHARS`: max chars for overview summary (default: 800)
|
|
430
|
+
- `PREFLIGHT_DEFAULT_SEARCH_CONTEXT_LINES`: context lines for search excerpts (default: 30)
|
|
431
|
+
|
|
432
|
+
### Performance Tuning
|
|
433
|
+
- `PREFLIGHT_MANIFEST_CACHE_TTL_MS`: manifest cache TTL in ms (default: 300000 = 5 min)
|
|
434
|
+
- `PREFLIGHT_MANIFEST_CACHE_MAX_SIZE`: max manifest cache entries (default: 100)
|
|
435
|
+
- `PREFLIGHT_TASK_CLEANUP_DELAY_MS`: task cleanup delay after completion (default: 60000 = 1 min)
|
|
429
436
|
|
|
430
437
|
### Built-in HTTP API
|
|
431
438
|
- `PREFLIGHT_HTTP_ENABLED`: enable/disable REST API (default: true)
|
package/README.zh-CN.md
CHANGED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base Language Adapter for Call Graph Analysis
|
|
3
|
+
*
|
|
4
|
+
* Provides common functionality for all language adapters:
|
|
5
|
+
* - File and cache management
|
|
6
|
+
* - Common utility methods
|
|
7
|
+
* - Abstract method declarations for language-specific implementations
|
|
8
|
+
*
|
|
9
|
+
* This base class was extracted to reduce code duplication across adapters.
|
|
10
|
+
*
|
|
11
|
+
* @module analysis/call-graph/adapters/base-adapter
|
|
12
|
+
*/
|
|
13
|
+
import * as fs from 'fs';
|
|
14
|
+
import * as path from 'path';
|
|
15
|
+
import { createNodeId, } from '../types.js';
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// Base Adapter Abstract Class
|
|
18
|
+
// ============================================================================
|
|
19
|
+
/**
|
|
20
|
+
* Abstract base class for language-specific call graph adapters.
|
|
21
|
+
* Provides common caching and utility functionality.
|
|
22
|
+
*/
|
|
23
|
+
export class BaseLanguageAdapter {
|
|
24
|
+
/** Project root path */
|
|
25
|
+
rootPath = '';
|
|
26
|
+
/** Cache for file contents */
|
|
27
|
+
fileCache = new Map();
|
|
28
|
+
/** Whether the adapter has been initialized */
|
|
29
|
+
initialized = false;
|
|
30
|
+
// ============================================================================
|
|
31
|
+
// Lifecycle Methods
|
|
32
|
+
// ============================================================================
|
|
33
|
+
/**
|
|
34
|
+
* Initialize the adapter with the project root path.
|
|
35
|
+
* Override in subclasses to perform language-specific initialization.
|
|
36
|
+
*/
|
|
37
|
+
async initialize(rootPath) {
|
|
38
|
+
this.rootPath = rootPath;
|
|
39
|
+
this.initialized = true;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Shutdown the adapter and clean up resources.
|
|
43
|
+
* Override in subclasses to perform language-specific cleanup.
|
|
44
|
+
*/
|
|
45
|
+
async shutdown() {
|
|
46
|
+
this.fileCache.clear();
|
|
47
|
+
this.initialized = false;
|
|
48
|
+
}
|
|
49
|
+
// ============================================================================
|
|
50
|
+
// File Support
|
|
51
|
+
// ============================================================================
|
|
52
|
+
/**
|
|
53
|
+
* Check if a file is supported by this adapter based on extension.
|
|
54
|
+
*/
|
|
55
|
+
supportsFile(filePath) {
|
|
56
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
57
|
+
return this.supportedExtensions.includes(ext);
|
|
58
|
+
}
|
|
59
|
+
// ============================================================================
|
|
60
|
+
// File Cache Management
|
|
61
|
+
// ============================================================================
|
|
62
|
+
/**
|
|
63
|
+
* Read file content with caching.
|
|
64
|
+
* Returns null if file cannot be read.
|
|
65
|
+
*/
|
|
66
|
+
readFileCached(filePath) {
|
|
67
|
+
// Check cache first
|
|
68
|
+
const cached = this.fileCache.get(filePath);
|
|
69
|
+
if (cached !== undefined) {
|
|
70
|
+
return cached;
|
|
71
|
+
}
|
|
72
|
+
// Read from disk
|
|
73
|
+
try {
|
|
74
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
75
|
+
this.fileCache.set(filePath, content);
|
|
76
|
+
return content;
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Clear the file cache, optionally for a specific file.
|
|
84
|
+
*/
|
|
85
|
+
clearCache(filePath) {
|
|
86
|
+
if (filePath) {
|
|
87
|
+
this.fileCache.delete(filePath);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
this.fileCache.clear();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Invalidate cache for files matching a pattern.
|
|
95
|
+
*/
|
|
96
|
+
invalidateCacheMatching(pattern) {
|
|
97
|
+
let cleared = 0;
|
|
98
|
+
for (const key of this.fileCache.keys()) {
|
|
99
|
+
if (pattern.test(key)) {
|
|
100
|
+
this.fileCache.delete(key);
|
|
101
|
+
cleared++;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return cleared;
|
|
105
|
+
}
|
|
106
|
+
// ============================================================================
|
|
107
|
+
// Path Utilities
|
|
108
|
+
// ============================================================================
|
|
109
|
+
/**
|
|
110
|
+
* Convert absolute path to relative path from root.
|
|
111
|
+
*/
|
|
112
|
+
toRelativePath(absolutePath) {
|
|
113
|
+
return path.relative(this.rootPath, absolutePath);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Convert relative path to absolute path from root.
|
|
117
|
+
*/
|
|
118
|
+
toAbsolutePath(relativePath) {
|
|
119
|
+
if (path.isAbsolute(relativePath)) {
|
|
120
|
+
return relativePath;
|
|
121
|
+
}
|
|
122
|
+
return path.join(this.rootPath, relativePath);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Normalize path separators to forward slashes.
|
|
126
|
+
*/
|
|
127
|
+
normalizePath(filePath) {
|
|
128
|
+
return filePath.replace(/\\/g, '/');
|
|
129
|
+
}
|
|
130
|
+
// ============================================================================
|
|
131
|
+
// Source Location Utilities
|
|
132
|
+
// ============================================================================
|
|
133
|
+
/**
|
|
134
|
+
* Create a source location object.
|
|
135
|
+
*/
|
|
136
|
+
createLocation(filePath, line, column, endLine, endColumn) {
|
|
137
|
+
return {
|
|
138
|
+
filePath,
|
|
139
|
+
line,
|
|
140
|
+
column,
|
|
141
|
+
endLine,
|
|
142
|
+
endColumn,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Generate a unique node ID for a symbol.
|
|
147
|
+
*/
|
|
148
|
+
generateNodeId(filePath, line, column, name) {
|
|
149
|
+
return createNodeId(filePath, line, column, name);
|
|
150
|
+
}
|
|
151
|
+
// ============================================================================
|
|
152
|
+
// Optional Override Points
|
|
153
|
+
// ============================================================================
|
|
154
|
+
/**
|
|
155
|
+
* Check if the adapter is ready to process requests.
|
|
156
|
+
* Override in subclasses that need async initialization.
|
|
157
|
+
*/
|
|
158
|
+
isReady() {
|
|
159
|
+
return this.initialized;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Ensure the adapter is initialized before processing requests.
|
|
163
|
+
* Throws an error if not initialized.
|
|
164
|
+
*/
|
|
165
|
+
ensureInitialized() {
|
|
166
|
+
if (!this.isReady()) {
|
|
167
|
+
throw new Error(`${this.language} adapter not initialized. Call initialize() first.`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
// ============================================================================
|
|
172
|
+
// Helper Exports
|
|
173
|
+
// ============================================================================
|
|
174
|
+
/**
|
|
175
|
+
* Common symbol kind mapping for languages that use similar conventions.
|
|
176
|
+
*/
|
|
177
|
+
export const COMMON_SYMBOL_KINDS = {
|
|
178
|
+
function: 'function',
|
|
179
|
+
method: 'method',
|
|
180
|
+
constructor: 'constructor',
|
|
181
|
+
getter: 'getter',
|
|
182
|
+
setter: 'setter',
|
|
183
|
+
class: 'class',
|
|
184
|
+
interface: 'interface',
|
|
185
|
+
module: 'module',
|
|
186
|
+
enum: 'enum',
|
|
187
|
+
};
|
|
188
|
+
/**
|
|
189
|
+
* Check if a name follows common export conventions (starts with uppercase).
|
|
190
|
+
*/
|
|
191
|
+
export function isExportedByConvention(name) {
|
|
192
|
+
return /^[A-Z]/.test(name);
|
|
193
|
+
}
|
package/dist/analysis/deep.js
CHANGED
|
@@ -7,8 +7,9 @@ import { createEmptyCoverageReport, isCoverageSufficient, } from '../types/evide
|
|
|
7
7
|
* Build a deep analysis result from individual component results.
|
|
8
8
|
* This is called by the server after gathering data from each source.
|
|
9
9
|
*/
|
|
10
|
-
export function buildDeepAnalysis(bundleId, components) {
|
|
10
|
+
export function buildDeepAnalysis(bundleId, components, options) {
|
|
11
11
|
const { tree, search, deps, traces, overviewContent, testInfo, focusPath, focusQuery, errors = [] } = components;
|
|
12
|
+
const maxOverviewChars = options?.maxOverviewChars ?? 800;
|
|
12
13
|
// Build coverage report
|
|
13
14
|
const coverageReport = createEmptyCoverageReport();
|
|
14
15
|
if (tree) {
|
|
@@ -30,9 +31,8 @@ export function buildDeepAnalysis(bundleId, components) {
|
|
|
30
31
|
const lines = overviewContent.overview.split('\n');
|
|
31
32
|
const contentLines = [];
|
|
32
33
|
let charCount = 0;
|
|
33
|
-
const MAX_CHARS = 800; // Limit to ~200 tokens
|
|
34
34
|
for (const line of lines) {
|
|
35
|
-
if (charCount >=
|
|
35
|
+
if (charCount >= maxOverviewChars)
|
|
36
36
|
break;
|
|
37
37
|
// Skip empty lines at start and title lines
|
|
38
38
|
if (contentLines.length === 0 && (line.trim() === '' || line.startsWith('#')))
|
|
@@ -42,7 +42,7 @@ export function buildDeepAnalysis(bundleId, components) {
|
|
|
42
42
|
}
|
|
43
43
|
if (contentLines.length > 0) {
|
|
44
44
|
summaryParts.push(contentLines.join('\n'));
|
|
45
|
-
if (charCount >=
|
|
45
|
+
if (charCount >= maxOverviewChars) {
|
|
46
46
|
summaryParts.push('...(truncated, see OVERVIEW.md for full content)');
|
|
47
47
|
}
|
|
48
48
|
}
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import { createModuleLogger } from '../../logging/logger.js';
|
|
13
13
|
import { extractExtensionPointsWasm, } from '../../ast/treeSitter.js';
|
|
14
|
+
import { INTERFACE_BASE_SCORE, INTERFACE_METHODS_HIGH_BONUS, INTERFACE_METHODS_LOW_BONUS, INTERFACE_EMPTY_SCORE, INTERFACE_EMBEDDING_BONUS, INTERFACE_HANDLER_BONUS, INTERFACE_PLUGIN_BONUS, CONSTRAINT_BASE_SCORE, CONSTRAINT_MEMBERS_HIGH_BONUS, CONSTRAINT_MEMBERS_LOW_BONUS, CONSTRAINT_HIGH_MEMBER_THRESHOLD, CONSTRAINT_LOW_MEMBER_THRESHOLD, MAX_SCORE, } from '../scoring-config.js';
|
|
14
15
|
const logger = createModuleLogger('go-analyzer');
|
|
15
16
|
// ============================================================================
|
|
16
17
|
// Go Analyzer Class
|
|
@@ -24,6 +25,17 @@ export class GoAnalyzer {
|
|
|
24
25
|
// Try tree-sitter first for accurate AST parsing
|
|
25
26
|
const treeSitterResult = await extractExtensionPointsWasm(filePath, content);
|
|
26
27
|
if (treeSitterResult && treeSitterResult.extensionPoints.length > 0) {
|
|
28
|
+
// Check if tree-sitter found methods in interfaces
|
|
29
|
+
const hasMethodsInInterfaces = treeSitterResult.extensionPoints.some(p => p.kind === 'interface' && p.methods && p.methods.length > 0);
|
|
30
|
+
// If tree-sitter found interfaces but no methods, fall back to regex
|
|
31
|
+
// as tree-sitter might have failed to parse the methods
|
|
32
|
+
if (!hasMethodsInInterfaces) {
|
|
33
|
+
const hasInterfaces = treeSitterResult.extensionPoints.some(p => p.kind === 'interface');
|
|
34
|
+
if (hasInterfaces) {
|
|
35
|
+
logger.debug('Tree-sitter found interfaces without methods, falling back to regex');
|
|
36
|
+
return this.analyzeContentWithRegex(content, filePath);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
27
39
|
return this.convertTreeSitterResult(treeSitterResult.extensionPoints, filePath);
|
|
28
40
|
}
|
|
29
41
|
// Fallback to regex-based parsing
|
|
@@ -434,37 +446,45 @@ export class GoAnalyzer {
|
|
|
434
446
|
}
|
|
435
447
|
return 'enum-options';
|
|
436
448
|
}
|
|
449
|
+
/**
|
|
450
|
+
* Calculate extensibility score for a Go interface.
|
|
451
|
+
* See src/analysis/scoring-config.ts for scoring constant documentation.
|
|
452
|
+
*/
|
|
437
453
|
scoreInterface(iface) {
|
|
438
|
-
let score =
|
|
454
|
+
let score = INTERFACE_BASE_SCORE;
|
|
439
455
|
// More methods = more extensible
|
|
440
456
|
if (iface.methods.length >= 3)
|
|
441
|
-
score +=
|
|
457
|
+
score += INTERFACE_METHODS_HIGH_BONUS;
|
|
442
458
|
else if (iface.methods.length >= 1)
|
|
443
|
-
score +=
|
|
444
|
-
// Empty interface (any) is very extensible
|
|
459
|
+
score += INTERFACE_METHODS_LOW_BONUS;
|
|
460
|
+
// Empty interface (any) is very extensible but too generic
|
|
445
461
|
if (iface.methods.length === 0 && iface.embedded.length === 0) {
|
|
446
|
-
score =
|
|
462
|
+
score = INTERFACE_EMPTY_SCORE;
|
|
447
463
|
}
|
|
448
464
|
// Embedding other interfaces suggests composition pattern
|
|
449
465
|
if (iface.embedded.length > 0)
|
|
450
|
-
score +=
|
|
466
|
+
score += INTERFACE_EMBEDDING_BONUS;
|
|
451
467
|
// Common extension patterns
|
|
452
468
|
const nameLower = iface.name.toLowerCase();
|
|
453
469
|
if (nameLower.includes('handler') || nameLower.includes('processor')) {
|
|
454
|
-
score +=
|
|
470
|
+
score += INTERFACE_HANDLER_BONUS;
|
|
455
471
|
}
|
|
456
472
|
if (nameLower.includes('plugin') || nameLower.includes('provider')) {
|
|
457
|
-
score +=
|
|
473
|
+
score += INTERFACE_PLUGIN_BONUS;
|
|
458
474
|
}
|
|
459
|
-
return Math.min(score,
|
|
475
|
+
return Math.min(score, MAX_SCORE);
|
|
460
476
|
}
|
|
477
|
+
/**
|
|
478
|
+
* Calculate extensibility score for a Go type constraint.
|
|
479
|
+
* See src/analysis/scoring-config.ts for scoring constant documentation.
|
|
480
|
+
*/
|
|
461
481
|
scoreConstraint(memberCount) {
|
|
462
|
-
let score =
|
|
463
|
-
if (memberCount >=
|
|
464
|
-
score +=
|
|
465
|
-
else if (memberCount >=
|
|
466
|
-
score +=
|
|
467
|
-
return Math.min(score,
|
|
482
|
+
let score = CONSTRAINT_BASE_SCORE;
|
|
483
|
+
if (memberCount >= CONSTRAINT_HIGH_MEMBER_THRESHOLD)
|
|
484
|
+
score += CONSTRAINT_MEMBERS_HIGH_BONUS;
|
|
485
|
+
else if (memberCount >= CONSTRAINT_LOW_MEMBER_THRESHOLD)
|
|
486
|
+
score += CONSTRAINT_MEMBERS_LOW_BONUS;
|
|
487
|
+
return Math.min(score, MAX_SCORE);
|
|
468
488
|
}
|
|
469
489
|
}
|
|
470
490
|
// ============================================================================
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import * as fs from 'node:fs/promises';
|
|
12
12
|
import { createModuleLogger } from '../logging/logger.js';
|
|
13
|
+
import { getConfig } from '../config.js';
|
|
13
14
|
const logger = createModuleLogger('pattern-analyzer');
|
|
14
15
|
/**
|
|
15
16
|
* Design hint patterns to detect.
|
|
@@ -70,8 +71,13 @@ const INTERFACE_EXTENSION_PATTERNS = [
|
|
|
70
71
|
* Analyzer for design patterns and comments in source code.
|
|
71
72
|
*/
|
|
72
73
|
export class PatternAnalyzer {
|
|
74
|
+
strictMode;
|
|
75
|
+
constructor(options) {
|
|
76
|
+
this.strictMode = options?.strictMode ?? getConfig().strictMode;
|
|
77
|
+
}
|
|
73
78
|
/**
|
|
74
79
|
* Analyze a file for design hints.
|
|
80
|
+
* In strict mode, errors are thrown instead of being logged and returning empty results.
|
|
75
81
|
*/
|
|
76
82
|
async analyzeFile(filePath, content) {
|
|
77
83
|
const results = [];
|
|
@@ -101,6 +107,10 @@ export class PatternAnalyzer {
|
|
|
101
107
|
}
|
|
102
108
|
catch (error) {
|
|
103
109
|
logger.error(`Failed to analyze ${filePath}`, error instanceof Error ? error : undefined);
|
|
110
|
+
// In strict mode, propagate errors instead of returning empty results
|
|
111
|
+
if (this.strictMode) {
|
|
112
|
+
throw error;
|
|
113
|
+
}
|
|
104
114
|
return [];
|
|
105
115
|
}
|
|
106
116
|
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scoring Configuration Constants
|
|
3
|
+
*
|
|
4
|
+
* This file contains all scoring-related constants used in static analysis.
|
|
5
|
+
* Centralizing these values makes them easier to tune and document.
|
|
6
|
+
*
|
|
7
|
+
* @module analysis/scoring-config
|
|
8
|
+
*/
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// Interface Scoring (Go Analyzer)
|
|
11
|
+
// ============================================================================
|
|
12
|
+
/**
|
|
13
|
+
* Base score for exported interfaces.
|
|
14
|
+
* Starting point before applying bonuses.
|
|
15
|
+
*/
|
|
16
|
+
export const INTERFACE_BASE_SCORE = 60;
|
|
17
|
+
/**
|
|
18
|
+
* Score bonus for interfaces with 3+ methods.
|
|
19
|
+
* More methods typically indicate more extensible APIs.
|
|
20
|
+
*/
|
|
21
|
+
export const INTERFACE_METHODS_HIGH_BONUS = 15;
|
|
22
|
+
/**
|
|
23
|
+
* Score bonus for interfaces with 1-2 methods.
|
|
24
|
+
* Moderate extensibility indication.
|
|
25
|
+
*/
|
|
26
|
+
export const INTERFACE_METHODS_LOW_BONUS = 10;
|
|
27
|
+
/**
|
|
28
|
+
* Score for empty interfaces (any type).
|
|
29
|
+
* Lower than base because they're too generic.
|
|
30
|
+
*/
|
|
31
|
+
export const INTERFACE_EMPTY_SCORE = 50;
|
|
32
|
+
/**
|
|
33
|
+
* Score bonus for interfaces embedding other interfaces.
|
|
34
|
+
* Suggests composition pattern usage.
|
|
35
|
+
*/
|
|
36
|
+
export const INTERFACE_EMBEDDING_BONUS = 10;
|
|
37
|
+
/**
|
|
38
|
+
* Score bonus for handler/processor named interfaces.
|
|
39
|
+
* Common extensibility patterns.
|
|
40
|
+
*/
|
|
41
|
+
export const INTERFACE_HANDLER_BONUS = 15;
|
|
42
|
+
/**
|
|
43
|
+
* Score bonus for plugin/provider named interfaces.
|
|
44
|
+
* Strong extensibility indication.
|
|
45
|
+
*/
|
|
46
|
+
export const INTERFACE_PLUGIN_BONUS = 20;
|
|
47
|
+
// ============================================================================
|
|
48
|
+
// Type Constraint Scoring (Go Analyzer)
|
|
49
|
+
// ============================================================================
|
|
50
|
+
/**
|
|
51
|
+
* Base score for type constraints.
|
|
52
|
+
*/
|
|
53
|
+
export const CONSTRAINT_BASE_SCORE = 50;
|
|
54
|
+
/**
|
|
55
|
+
* Score bonus for constraints with 5+ members.
|
|
56
|
+
* More members indicate more comprehensive type bounds.
|
|
57
|
+
*/
|
|
58
|
+
export const CONSTRAINT_MEMBERS_HIGH_BONUS = 20;
|
|
59
|
+
/**
|
|
60
|
+
* Score bonus for constraints with 3-4 members.
|
|
61
|
+
*/
|
|
62
|
+
export const CONSTRAINT_MEMBERS_LOW_BONUS = 10;
|
|
63
|
+
/**
|
|
64
|
+
* Member count threshold for high bonus.
|
|
65
|
+
*/
|
|
66
|
+
export const CONSTRAINT_HIGH_MEMBER_THRESHOLD = 5;
|
|
67
|
+
/**
|
|
68
|
+
* Member count threshold for low bonus.
|
|
69
|
+
*/
|
|
70
|
+
export const CONSTRAINT_LOW_MEMBER_THRESHOLD = 3;
|
|
71
|
+
// ============================================================================
|
|
72
|
+
// General Scoring Limits
|
|
73
|
+
// ============================================================================
|
|
74
|
+
/**
|
|
75
|
+
* Maximum possible score for any item.
|
|
76
|
+
*/
|
|
77
|
+
export const MAX_SCORE = 100;
|
|
78
|
+
/**
|
|
79
|
+
* Minimum score threshold for including items in results.
|
|
80
|
+
*/
|
|
81
|
+
export const MIN_SCORE_THRESHOLD = 0;
|
|
82
|
+
// ============================================================================
|
|
83
|
+
// TypeScript/JavaScript Scoring (for future use)
|
|
84
|
+
// ============================================================================
|
|
85
|
+
/**
|
|
86
|
+
* Base score for exported TypeScript interfaces.
|
|
87
|
+
*/
|
|
88
|
+
export const TS_INTERFACE_BASE_SCORE = 60;
|
|
89
|
+
/**
|
|
90
|
+
* Base score for exported TypeScript types.
|
|
91
|
+
*/
|
|
92
|
+
export const TS_TYPE_BASE_SCORE = 50;
|
|
93
|
+
/**
|
|
94
|
+
* Score bonus for discriminated unions.
|
|
95
|
+
*/
|
|
96
|
+
export const TS_DISCRIMINATED_UNION_BONUS = 25;
|
|
97
|
+
// ============================================================================
|
|
98
|
+
// Python Scoring (for future use)
|
|
99
|
+
// ============================================================================
|
|
100
|
+
/**
|
|
101
|
+
* Base score for Python ABC classes.
|
|
102
|
+
*/
|
|
103
|
+
export const PY_ABC_BASE_SCORE = 60;
|
|
104
|
+
/**
|
|
105
|
+
* Base score for Python Protocol classes.
|
|
106
|
+
*/
|
|
107
|
+
export const PY_PROTOCOL_BASE_SCORE = 65;
|
|
108
|
+
// ============================================================================
|
|
109
|
+
// Rust Scoring (for future use)
|
|
110
|
+
// ============================================================================
|
|
111
|
+
/**
|
|
112
|
+
* Base score for Rust traits.
|
|
113
|
+
*/
|
|
114
|
+
export const RUST_TRAIT_BASE_SCORE = 60;
|
|
115
|
+
/**
|
|
116
|
+
* Score bonus for traits with default implementations.
|
|
117
|
+
*/
|
|
118
|
+
export const RUST_TRAIT_DEFAULT_IMPL_BONUS = 10;
|