@aiready/core 0.7.9 → 0.7.10
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/index.d.mts +129 -1
- package/dist/index.d.ts +129 -1
- package/dist/index.js +164 -0
- package/dist/index.mjs +154 -0
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -34,9 +34,12 @@ interface AIReadyConfig {
|
|
|
34
34
|
scan?: {
|
|
35
35
|
include?: string[];
|
|
36
36
|
exclude?: string[];
|
|
37
|
+
tools?: string[];
|
|
37
38
|
};
|
|
38
39
|
tools?: {
|
|
39
40
|
'pattern-detect'?: {
|
|
41
|
+
enabled?: boolean;
|
|
42
|
+
scoreWeight?: number;
|
|
40
43
|
minSimilarity?: number;
|
|
41
44
|
minLines?: number;
|
|
42
45
|
batchSize?: number;
|
|
@@ -47,6 +50,8 @@ interface AIReadyConfig {
|
|
|
47
50
|
maxResults?: number;
|
|
48
51
|
};
|
|
49
52
|
'context-analyzer'?: {
|
|
53
|
+
enabled?: boolean;
|
|
54
|
+
scoreWeight?: number;
|
|
50
55
|
maxDepth?: number;
|
|
51
56
|
maxContextBudget?: number;
|
|
52
57
|
minCohesion?: number;
|
|
@@ -59,10 +64,23 @@ interface AIReadyConfig {
|
|
|
59
64
|
pathDomainMap?: Record<string, string>;
|
|
60
65
|
};
|
|
61
66
|
'consistency'?: {
|
|
67
|
+
enabled?: boolean;
|
|
68
|
+
scoreWeight?: number;
|
|
62
69
|
acceptedAbbreviations?: string[];
|
|
63
70
|
shortWords?: string[];
|
|
64
71
|
disableChecks?: ('single-letter' | 'abbreviation' | 'convention-mix' | 'unclear' | 'poor-naming')[];
|
|
65
72
|
};
|
|
73
|
+
[toolName: string]: {
|
|
74
|
+
enabled?: boolean;
|
|
75
|
+
scoreWeight?: number;
|
|
76
|
+
[key: string]: any;
|
|
77
|
+
} | undefined;
|
|
78
|
+
};
|
|
79
|
+
scoring?: {
|
|
80
|
+
threshold?: number;
|
|
81
|
+
showBreakdown?: boolean;
|
|
82
|
+
compareBaseline?: string;
|
|
83
|
+
saveTo?: string;
|
|
66
84
|
};
|
|
67
85
|
output?: {
|
|
68
86
|
format?: 'console' | 'json' | 'html';
|
|
@@ -196,4 +214,114 @@ declare function handleCLIError(error: unknown, commandName: string): never;
|
|
|
196
214
|
*/
|
|
197
215
|
declare function getElapsedTime(startTime: number): string;
|
|
198
216
|
|
|
199
|
-
|
|
217
|
+
/**
|
|
218
|
+
* AI Readiness Scoring System
|
|
219
|
+
*
|
|
220
|
+
* Provides dynamic, composable scoring across multiple analysis tools.
|
|
221
|
+
* Each tool contributes a 0-100 score with configurable weights.
|
|
222
|
+
*/
|
|
223
|
+
interface ToolScoringOutput {
|
|
224
|
+
/** Unique tool identifier (e.g., "pattern-detect") */
|
|
225
|
+
toolName: string;
|
|
226
|
+
/** Normalized 0-100 score for this tool */
|
|
227
|
+
score: number;
|
|
228
|
+
/** Raw metrics used to calculate the score */
|
|
229
|
+
rawMetrics: Record<string, any>;
|
|
230
|
+
/** Factors that influenced the score */
|
|
231
|
+
factors: Array<{
|
|
232
|
+
name: string;
|
|
233
|
+
impact: number;
|
|
234
|
+
description: string;
|
|
235
|
+
}>;
|
|
236
|
+
/** Actionable recommendations with estimated impact */
|
|
237
|
+
recommendations: Array<{
|
|
238
|
+
action: string;
|
|
239
|
+
estimatedImpact: number;
|
|
240
|
+
priority: 'high' | 'medium' | 'low';
|
|
241
|
+
}>;
|
|
242
|
+
}
|
|
243
|
+
interface ScoringResult {
|
|
244
|
+
/** Overall AI Readiness Score (0-100) */
|
|
245
|
+
overall: number;
|
|
246
|
+
/** Rating category */
|
|
247
|
+
rating: 'Excellent' | 'Good' | 'Fair' | 'Needs Work' | 'Critical';
|
|
248
|
+
/** Timestamp of score calculation */
|
|
249
|
+
timestamp: string;
|
|
250
|
+
/** Tools that contributed to this score */
|
|
251
|
+
toolsUsed: string[];
|
|
252
|
+
/** Breakdown by tool */
|
|
253
|
+
breakdown: ToolScoringOutput[];
|
|
254
|
+
/** Calculation details */
|
|
255
|
+
calculation: {
|
|
256
|
+
formula: string;
|
|
257
|
+
weights: Record<string, number>;
|
|
258
|
+
normalized: string;
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
interface ScoringConfig {
|
|
262
|
+
/** Minimum passing score (exit code 1 if below) */
|
|
263
|
+
threshold?: number;
|
|
264
|
+
/** Show detailed breakdown in output */
|
|
265
|
+
showBreakdown?: boolean;
|
|
266
|
+
/** Path to baseline JSON for comparison */
|
|
267
|
+
compareBaseline?: string;
|
|
268
|
+
/** Auto-save score to this path */
|
|
269
|
+
saveTo?: string;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Default weights for known tools.
|
|
273
|
+
* New tools get weight of 10 if not specified.
|
|
274
|
+
*/
|
|
275
|
+
declare const DEFAULT_TOOL_WEIGHTS: Record<string, number>;
|
|
276
|
+
/**
|
|
277
|
+
* Tool name normalization map (shorthand -> full name)
|
|
278
|
+
*/
|
|
279
|
+
declare const TOOL_NAME_MAP: Record<string, string>;
|
|
280
|
+
/**
|
|
281
|
+
* Normalize tool name from shorthand to full name
|
|
282
|
+
*/
|
|
283
|
+
declare function normalizeToolName(shortName: string): string;
|
|
284
|
+
/**
|
|
285
|
+
* Get tool weight with fallback priority:
|
|
286
|
+
* 1. CLI override
|
|
287
|
+
* 2. Tool config scoreWeight
|
|
288
|
+
* 3. Default weight
|
|
289
|
+
* 4. 10 (for unknown tools)
|
|
290
|
+
*/
|
|
291
|
+
declare function getToolWeight(toolName: string, toolConfig?: {
|
|
292
|
+
scoreWeight?: number;
|
|
293
|
+
}, cliOverride?: number): number;
|
|
294
|
+
/**
|
|
295
|
+
* Parse weight string from CLI (e.g., "patterns:50,context:30")
|
|
296
|
+
*/
|
|
297
|
+
declare function parseWeightString(weightStr?: string): Map<string, number>;
|
|
298
|
+
/**
|
|
299
|
+
* Calculate overall AI Readiness Score from multiple tool scores.
|
|
300
|
+
*
|
|
301
|
+
* Formula: Σ(tool_score × tool_weight) / Σ(active_tool_weights)
|
|
302
|
+
*
|
|
303
|
+
* This allows dynamic composition - score adjusts automatically
|
|
304
|
+
* based on which tools actually ran.
|
|
305
|
+
*/
|
|
306
|
+
declare function calculateOverallScore(toolOutputs: Map<string, ToolScoringOutput>, config?: any, cliWeights?: Map<string, number>): ScoringResult;
|
|
307
|
+
/**
|
|
308
|
+
* Convert numeric score to rating category
|
|
309
|
+
*/
|
|
310
|
+
declare function getRating(score: number): ScoringResult['rating'];
|
|
311
|
+
/**
|
|
312
|
+
* Get rating emoji and color for display
|
|
313
|
+
*/
|
|
314
|
+
declare function getRatingDisplay(rating: ScoringResult['rating']): {
|
|
315
|
+
emoji: string;
|
|
316
|
+
color: string;
|
|
317
|
+
};
|
|
318
|
+
/**
|
|
319
|
+
* Format score for display with rating
|
|
320
|
+
*/
|
|
321
|
+
declare function formatScore(result: ScoringResult): string;
|
|
322
|
+
/**
|
|
323
|
+
* Format individual tool score for display
|
|
324
|
+
*/
|
|
325
|
+
declare function formatToolScore(output: ToolScoringOutput): string;
|
|
326
|
+
|
|
327
|
+
export { type AIReadyConfig, type ASTNode, type AnalysisResult, type CLIOptions, DEFAULT_EXCLUDE, DEFAULT_TOOL_WEIGHTS, type ExportWithImports, type FileImport, type Issue, type IssueType, type Location, type Metrics, type Report, type ScanOptions, type ScoringConfig, type ScoringResult, TOOL_NAME_MAP, type ToolScoringOutput, calculateImportSimilarity, calculateOverallScore, estimateTokens, extractFunctions, extractImports, formatScore, formatToolScore, getElapsedTime, getFileExtension, getRating, getRatingDisplay, getToolWeight, handleCLIError, handleJSONOutput, isSourceFile, loadConfig, loadMergedConfig, mergeConfigWithDefaults, normalizeToolName, parseCode, parseFileExports, parseWeightString, readFileContent, resolveOutputPath, scanFiles };
|
package/dist/index.d.ts
CHANGED
|
@@ -34,9 +34,12 @@ interface AIReadyConfig {
|
|
|
34
34
|
scan?: {
|
|
35
35
|
include?: string[];
|
|
36
36
|
exclude?: string[];
|
|
37
|
+
tools?: string[];
|
|
37
38
|
};
|
|
38
39
|
tools?: {
|
|
39
40
|
'pattern-detect'?: {
|
|
41
|
+
enabled?: boolean;
|
|
42
|
+
scoreWeight?: number;
|
|
40
43
|
minSimilarity?: number;
|
|
41
44
|
minLines?: number;
|
|
42
45
|
batchSize?: number;
|
|
@@ -47,6 +50,8 @@ interface AIReadyConfig {
|
|
|
47
50
|
maxResults?: number;
|
|
48
51
|
};
|
|
49
52
|
'context-analyzer'?: {
|
|
53
|
+
enabled?: boolean;
|
|
54
|
+
scoreWeight?: number;
|
|
50
55
|
maxDepth?: number;
|
|
51
56
|
maxContextBudget?: number;
|
|
52
57
|
minCohesion?: number;
|
|
@@ -59,10 +64,23 @@ interface AIReadyConfig {
|
|
|
59
64
|
pathDomainMap?: Record<string, string>;
|
|
60
65
|
};
|
|
61
66
|
'consistency'?: {
|
|
67
|
+
enabled?: boolean;
|
|
68
|
+
scoreWeight?: number;
|
|
62
69
|
acceptedAbbreviations?: string[];
|
|
63
70
|
shortWords?: string[];
|
|
64
71
|
disableChecks?: ('single-letter' | 'abbreviation' | 'convention-mix' | 'unclear' | 'poor-naming')[];
|
|
65
72
|
};
|
|
73
|
+
[toolName: string]: {
|
|
74
|
+
enabled?: boolean;
|
|
75
|
+
scoreWeight?: number;
|
|
76
|
+
[key: string]: any;
|
|
77
|
+
} | undefined;
|
|
78
|
+
};
|
|
79
|
+
scoring?: {
|
|
80
|
+
threshold?: number;
|
|
81
|
+
showBreakdown?: boolean;
|
|
82
|
+
compareBaseline?: string;
|
|
83
|
+
saveTo?: string;
|
|
66
84
|
};
|
|
67
85
|
output?: {
|
|
68
86
|
format?: 'console' | 'json' | 'html';
|
|
@@ -196,4 +214,114 @@ declare function handleCLIError(error: unknown, commandName: string): never;
|
|
|
196
214
|
*/
|
|
197
215
|
declare function getElapsedTime(startTime: number): string;
|
|
198
216
|
|
|
199
|
-
|
|
217
|
+
/**
|
|
218
|
+
* AI Readiness Scoring System
|
|
219
|
+
*
|
|
220
|
+
* Provides dynamic, composable scoring across multiple analysis tools.
|
|
221
|
+
* Each tool contributes a 0-100 score with configurable weights.
|
|
222
|
+
*/
|
|
223
|
+
interface ToolScoringOutput {
|
|
224
|
+
/** Unique tool identifier (e.g., "pattern-detect") */
|
|
225
|
+
toolName: string;
|
|
226
|
+
/** Normalized 0-100 score for this tool */
|
|
227
|
+
score: number;
|
|
228
|
+
/** Raw metrics used to calculate the score */
|
|
229
|
+
rawMetrics: Record<string, any>;
|
|
230
|
+
/** Factors that influenced the score */
|
|
231
|
+
factors: Array<{
|
|
232
|
+
name: string;
|
|
233
|
+
impact: number;
|
|
234
|
+
description: string;
|
|
235
|
+
}>;
|
|
236
|
+
/** Actionable recommendations with estimated impact */
|
|
237
|
+
recommendations: Array<{
|
|
238
|
+
action: string;
|
|
239
|
+
estimatedImpact: number;
|
|
240
|
+
priority: 'high' | 'medium' | 'low';
|
|
241
|
+
}>;
|
|
242
|
+
}
|
|
243
|
+
interface ScoringResult {
|
|
244
|
+
/** Overall AI Readiness Score (0-100) */
|
|
245
|
+
overall: number;
|
|
246
|
+
/** Rating category */
|
|
247
|
+
rating: 'Excellent' | 'Good' | 'Fair' | 'Needs Work' | 'Critical';
|
|
248
|
+
/** Timestamp of score calculation */
|
|
249
|
+
timestamp: string;
|
|
250
|
+
/** Tools that contributed to this score */
|
|
251
|
+
toolsUsed: string[];
|
|
252
|
+
/** Breakdown by tool */
|
|
253
|
+
breakdown: ToolScoringOutput[];
|
|
254
|
+
/** Calculation details */
|
|
255
|
+
calculation: {
|
|
256
|
+
formula: string;
|
|
257
|
+
weights: Record<string, number>;
|
|
258
|
+
normalized: string;
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
interface ScoringConfig {
|
|
262
|
+
/** Minimum passing score (exit code 1 if below) */
|
|
263
|
+
threshold?: number;
|
|
264
|
+
/** Show detailed breakdown in output */
|
|
265
|
+
showBreakdown?: boolean;
|
|
266
|
+
/** Path to baseline JSON for comparison */
|
|
267
|
+
compareBaseline?: string;
|
|
268
|
+
/** Auto-save score to this path */
|
|
269
|
+
saveTo?: string;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Default weights for known tools.
|
|
273
|
+
* New tools get weight of 10 if not specified.
|
|
274
|
+
*/
|
|
275
|
+
declare const DEFAULT_TOOL_WEIGHTS: Record<string, number>;
|
|
276
|
+
/**
|
|
277
|
+
* Tool name normalization map (shorthand -> full name)
|
|
278
|
+
*/
|
|
279
|
+
declare const TOOL_NAME_MAP: Record<string, string>;
|
|
280
|
+
/**
|
|
281
|
+
* Normalize tool name from shorthand to full name
|
|
282
|
+
*/
|
|
283
|
+
declare function normalizeToolName(shortName: string): string;
|
|
284
|
+
/**
|
|
285
|
+
* Get tool weight with fallback priority:
|
|
286
|
+
* 1. CLI override
|
|
287
|
+
* 2. Tool config scoreWeight
|
|
288
|
+
* 3. Default weight
|
|
289
|
+
* 4. 10 (for unknown tools)
|
|
290
|
+
*/
|
|
291
|
+
declare function getToolWeight(toolName: string, toolConfig?: {
|
|
292
|
+
scoreWeight?: number;
|
|
293
|
+
}, cliOverride?: number): number;
|
|
294
|
+
/**
|
|
295
|
+
* Parse weight string from CLI (e.g., "patterns:50,context:30")
|
|
296
|
+
*/
|
|
297
|
+
declare function parseWeightString(weightStr?: string): Map<string, number>;
|
|
298
|
+
/**
|
|
299
|
+
* Calculate overall AI Readiness Score from multiple tool scores.
|
|
300
|
+
*
|
|
301
|
+
* Formula: Σ(tool_score × tool_weight) / Σ(active_tool_weights)
|
|
302
|
+
*
|
|
303
|
+
* This allows dynamic composition - score adjusts automatically
|
|
304
|
+
* based on which tools actually ran.
|
|
305
|
+
*/
|
|
306
|
+
declare function calculateOverallScore(toolOutputs: Map<string, ToolScoringOutput>, config?: any, cliWeights?: Map<string, number>): ScoringResult;
|
|
307
|
+
/**
|
|
308
|
+
* Convert numeric score to rating category
|
|
309
|
+
*/
|
|
310
|
+
declare function getRating(score: number): ScoringResult['rating'];
|
|
311
|
+
/**
|
|
312
|
+
* Get rating emoji and color for display
|
|
313
|
+
*/
|
|
314
|
+
declare function getRatingDisplay(rating: ScoringResult['rating']): {
|
|
315
|
+
emoji: string;
|
|
316
|
+
color: string;
|
|
317
|
+
};
|
|
318
|
+
/**
|
|
319
|
+
* Format score for display with rating
|
|
320
|
+
*/
|
|
321
|
+
declare function formatScore(result: ScoringResult): string;
|
|
322
|
+
/**
|
|
323
|
+
* Format individual tool score for display
|
|
324
|
+
*/
|
|
325
|
+
declare function formatToolScore(output: ToolScoringOutput): string;
|
|
326
|
+
|
|
327
|
+
export { type AIReadyConfig, type ASTNode, type AnalysisResult, type CLIOptions, DEFAULT_EXCLUDE, DEFAULT_TOOL_WEIGHTS, type ExportWithImports, type FileImport, type Issue, type IssueType, type Location, type Metrics, type Report, type ScanOptions, type ScoringConfig, type ScoringResult, TOOL_NAME_MAP, type ToolScoringOutput, calculateImportSimilarity, calculateOverallScore, estimateTokens, extractFunctions, extractImports, formatScore, formatToolScore, getElapsedTime, getFileExtension, getRating, getRatingDisplay, getToolWeight, handleCLIError, handleJSONOutput, isSourceFile, loadConfig, loadMergedConfig, mergeConfigWithDefaults, normalizeToolName, parseCode, parseFileExports, parseWeightString, readFileContent, resolveOutputPath, scanFiles };
|
package/dist/index.js
CHANGED
|
@@ -21,20 +21,30 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
DEFAULT_EXCLUDE: () => DEFAULT_EXCLUDE,
|
|
24
|
+
DEFAULT_TOOL_WEIGHTS: () => DEFAULT_TOOL_WEIGHTS,
|
|
25
|
+
TOOL_NAME_MAP: () => TOOL_NAME_MAP,
|
|
24
26
|
calculateImportSimilarity: () => calculateImportSimilarity,
|
|
27
|
+
calculateOverallScore: () => calculateOverallScore,
|
|
25
28
|
estimateTokens: () => estimateTokens,
|
|
26
29
|
extractFunctions: () => extractFunctions,
|
|
27
30
|
extractImports: () => extractImports,
|
|
31
|
+
formatScore: () => formatScore,
|
|
32
|
+
formatToolScore: () => formatToolScore,
|
|
28
33
|
getElapsedTime: () => getElapsedTime,
|
|
29
34
|
getFileExtension: () => getFileExtension,
|
|
35
|
+
getRating: () => getRating,
|
|
36
|
+
getRatingDisplay: () => getRatingDisplay,
|
|
37
|
+
getToolWeight: () => getToolWeight,
|
|
30
38
|
handleCLIError: () => handleCLIError,
|
|
31
39
|
handleJSONOutput: () => handleJSONOutput,
|
|
32
40
|
isSourceFile: () => isSourceFile,
|
|
33
41
|
loadConfig: () => loadConfig,
|
|
34
42
|
loadMergedConfig: () => loadMergedConfig,
|
|
35
43
|
mergeConfigWithDefaults: () => mergeConfigWithDefaults,
|
|
44
|
+
normalizeToolName: () => normalizeToolName,
|
|
36
45
|
parseCode: () => parseCode,
|
|
37
46
|
parseFileExports: () => parseFileExports,
|
|
47
|
+
parseWeightString: () => parseWeightString,
|
|
38
48
|
readFileContent: () => readFileContent,
|
|
39
49
|
resolveOutputPath: () => resolveOutputPath,
|
|
40
50
|
scanFiles: () => scanFiles
|
|
@@ -409,23 +419,177 @@ function handleCLIError(error, commandName) {
|
|
|
409
419
|
function getElapsedTime(startTime) {
|
|
410
420
|
return ((Date.now() - startTime) / 1e3).toFixed(2);
|
|
411
421
|
}
|
|
422
|
+
|
|
423
|
+
// src/scoring.ts
|
|
424
|
+
var DEFAULT_TOOL_WEIGHTS = {
|
|
425
|
+
"pattern-detect": 40,
|
|
426
|
+
"context-analyzer": 35,
|
|
427
|
+
"consistency": 25,
|
|
428
|
+
"doc-drift": 20,
|
|
429
|
+
"deps": 15
|
|
430
|
+
};
|
|
431
|
+
var TOOL_NAME_MAP = {
|
|
432
|
+
"patterns": "pattern-detect",
|
|
433
|
+
"context": "context-analyzer",
|
|
434
|
+
"consistency": "consistency",
|
|
435
|
+
"doc-drift": "doc-drift",
|
|
436
|
+
"deps": "deps"
|
|
437
|
+
};
|
|
438
|
+
function normalizeToolName(shortName) {
|
|
439
|
+
return TOOL_NAME_MAP[shortName] || shortName;
|
|
440
|
+
}
|
|
441
|
+
function getToolWeight(toolName, toolConfig, cliOverride) {
|
|
442
|
+
if (cliOverride !== void 0) {
|
|
443
|
+
return cliOverride;
|
|
444
|
+
}
|
|
445
|
+
if (toolConfig?.scoreWeight !== void 0) {
|
|
446
|
+
return toolConfig.scoreWeight;
|
|
447
|
+
}
|
|
448
|
+
return DEFAULT_TOOL_WEIGHTS[toolName] || 10;
|
|
449
|
+
}
|
|
450
|
+
function parseWeightString(weightStr) {
|
|
451
|
+
const weights = /* @__PURE__ */ new Map();
|
|
452
|
+
if (!weightStr) {
|
|
453
|
+
return weights;
|
|
454
|
+
}
|
|
455
|
+
const pairs = weightStr.split(",");
|
|
456
|
+
for (const pair of pairs) {
|
|
457
|
+
const [toolShortName, weightStr2] = pair.split(":");
|
|
458
|
+
if (toolShortName && weightStr2) {
|
|
459
|
+
const toolName = normalizeToolName(toolShortName.trim());
|
|
460
|
+
const weight = parseInt(weightStr2.trim(), 10);
|
|
461
|
+
if (!isNaN(weight) && weight > 0) {
|
|
462
|
+
weights.set(toolName, weight);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
return weights;
|
|
467
|
+
}
|
|
468
|
+
function calculateOverallScore(toolOutputs, config, cliWeights) {
|
|
469
|
+
if (toolOutputs.size === 0) {
|
|
470
|
+
throw new Error("No tool outputs provided for scoring");
|
|
471
|
+
}
|
|
472
|
+
const weights = /* @__PURE__ */ new Map();
|
|
473
|
+
for (const [toolName] of toolOutputs.entries()) {
|
|
474
|
+
const cliWeight = cliWeights?.get(toolName);
|
|
475
|
+
const configWeight = config?.tools?.[toolName]?.scoreWeight;
|
|
476
|
+
const weight = cliWeight ?? configWeight ?? DEFAULT_TOOL_WEIGHTS[toolName] ?? 10;
|
|
477
|
+
weights.set(toolName, weight);
|
|
478
|
+
}
|
|
479
|
+
let weightedSum = 0;
|
|
480
|
+
let totalWeight = 0;
|
|
481
|
+
const breakdown = [];
|
|
482
|
+
const toolsUsed = [];
|
|
483
|
+
const calculationWeights = {};
|
|
484
|
+
for (const [toolName, output] of toolOutputs.entries()) {
|
|
485
|
+
const weight = weights.get(toolName) || 10;
|
|
486
|
+
const weightedScore = output.score * weight;
|
|
487
|
+
weightedSum += weightedScore;
|
|
488
|
+
totalWeight += weight;
|
|
489
|
+
toolsUsed.push(toolName);
|
|
490
|
+
calculationWeights[toolName] = weight;
|
|
491
|
+
breakdown.push(output);
|
|
492
|
+
}
|
|
493
|
+
const overall = Math.round(weightedSum / totalWeight);
|
|
494
|
+
const rating = getRating(overall);
|
|
495
|
+
const formulaParts = Array.from(toolOutputs.entries()).map(([name, output]) => {
|
|
496
|
+
const w = weights.get(name) || 10;
|
|
497
|
+
return `(${output.score} \xD7 ${w})`;
|
|
498
|
+
});
|
|
499
|
+
const formulaStr = `[${formulaParts.join(" + ")}] / ${totalWeight} = ${overall}`;
|
|
500
|
+
return {
|
|
501
|
+
overall,
|
|
502
|
+
rating,
|
|
503
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
504
|
+
toolsUsed,
|
|
505
|
+
breakdown,
|
|
506
|
+
calculation: {
|
|
507
|
+
formula: formulaStr,
|
|
508
|
+
weights: calculationWeights,
|
|
509
|
+
normalized: formulaStr
|
|
510
|
+
}
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
function getRating(score) {
|
|
514
|
+
if (score >= 90) return "Excellent";
|
|
515
|
+
if (score >= 75) return "Good";
|
|
516
|
+
if (score >= 60) return "Fair";
|
|
517
|
+
if (score >= 40) return "Needs Work";
|
|
518
|
+
return "Critical";
|
|
519
|
+
}
|
|
520
|
+
function getRatingDisplay(rating) {
|
|
521
|
+
switch (rating) {
|
|
522
|
+
case "Excellent":
|
|
523
|
+
return { emoji: "\u2705", color: "green" };
|
|
524
|
+
case "Good":
|
|
525
|
+
return { emoji: "\u{1F44D}", color: "blue" };
|
|
526
|
+
case "Fair":
|
|
527
|
+
return { emoji: "\u26A0\uFE0F", color: "yellow" };
|
|
528
|
+
case "Needs Work":
|
|
529
|
+
return { emoji: "\u{1F528}", color: "orange" };
|
|
530
|
+
case "Critical":
|
|
531
|
+
return { emoji: "\u274C", color: "red" };
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
function formatScore(result) {
|
|
535
|
+
const { emoji, color } = getRatingDisplay(result.rating);
|
|
536
|
+
return `${result.overall}/100 (${result.rating}) ${emoji}`;
|
|
537
|
+
}
|
|
538
|
+
function formatToolScore(output) {
|
|
539
|
+
let result = ` Score: ${output.score}/100
|
|
540
|
+
|
|
541
|
+
`;
|
|
542
|
+
if (output.factors && output.factors.length > 0) {
|
|
543
|
+
result += ` Factors:
|
|
544
|
+
`;
|
|
545
|
+
output.factors.forEach((factor) => {
|
|
546
|
+
const impactSign = factor.impact > 0 ? "+" : "";
|
|
547
|
+
result += ` \u2022 ${factor.name}: ${impactSign}${factor.impact} - ${factor.description}
|
|
548
|
+
`;
|
|
549
|
+
});
|
|
550
|
+
result += "\n";
|
|
551
|
+
}
|
|
552
|
+
if (output.recommendations && output.recommendations.length > 0) {
|
|
553
|
+
result += ` Recommendations:
|
|
554
|
+
`;
|
|
555
|
+
output.recommendations.forEach((rec, i) => {
|
|
556
|
+
const priorityIcon = rec.priority === "high" ? "\u{1F534}" : rec.priority === "medium" ? "\u{1F7E1}" : "\u{1F535}";
|
|
557
|
+
result += ` ${i + 1}. ${priorityIcon} ${rec.action}
|
|
558
|
+
`;
|
|
559
|
+
result += ` Impact: +${rec.estimatedImpact} points
|
|
560
|
+
|
|
561
|
+
`;
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
return result;
|
|
565
|
+
}
|
|
412
566
|
// Annotate the CommonJS export names for ESM import in node:
|
|
413
567
|
0 && (module.exports = {
|
|
414
568
|
DEFAULT_EXCLUDE,
|
|
569
|
+
DEFAULT_TOOL_WEIGHTS,
|
|
570
|
+
TOOL_NAME_MAP,
|
|
415
571
|
calculateImportSimilarity,
|
|
572
|
+
calculateOverallScore,
|
|
416
573
|
estimateTokens,
|
|
417
574
|
extractFunctions,
|
|
418
575
|
extractImports,
|
|
576
|
+
formatScore,
|
|
577
|
+
formatToolScore,
|
|
419
578
|
getElapsedTime,
|
|
420
579
|
getFileExtension,
|
|
580
|
+
getRating,
|
|
581
|
+
getRatingDisplay,
|
|
582
|
+
getToolWeight,
|
|
421
583
|
handleCLIError,
|
|
422
584
|
handleJSONOutput,
|
|
423
585
|
isSourceFile,
|
|
424
586
|
loadConfig,
|
|
425
587
|
loadMergedConfig,
|
|
426
588
|
mergeConfigWithDefaults,
|
|
589
|
+
normalizeToolName,
|
|
427
590
|
parseCode,
|
|
428
591
|
parseFileExports,
|
|
592
|
+
parseWeightString,
|
|
429
593
|
readFileContent,
|
|
430
594
|
resolveOutputPath,
|
|
431
595
|
scanFiles
|
package/dist/index.mjs
CHANGED
|
@@ -366,22 +366,176 @@ function handleCLIError(error, commandName) {
|
|
|
366
366
|
function getElapsedTime(startTime) {
|
|
367
367
|
return ((Date.now() - startTime) / 1e3).toFixed(2);
|
|
368
368
|
}
|
|
369
|
+
|
|
370
|
+
// src/scoring.ts
|
|
371
|
+
var DEFAULT_TOOL_WEIGHTS = {
|
|
372
|
+
"pattern-detect": 40,
|
|
373
|
+
"context-analyzer": 35,
|
|
374
|
+
"consistency": 25,
|
|
375
|
+
"doc-drift": 20,
|
|
376
|
+
"deps": 15
|
|
377
|
+
};
|
|
378
|
+
var TOOL_NAME_MAP = {
|
|
379
|
+
"patterns": "pattern-detect",
|
|
380
|
+
"context": "context-analyzer",
|
|
381
|
+
"consistency": "consistency",
|
|
382
|
+
"doc-drift": "doc-drift",
|
|
383
|
+
"deps": "deps"
|
|
384
|
+
};
|
|
385
|
+
function normalizeToolName(shortName) {
|
|
386
|
+
return TOOL_NAME_MAP[shortName] || shortName;
|
|
387
|
+
}
|
|
388
|
+
function getToolWeight(toolName, toolConfig, cliOverride) {
|
|
389
|
+
if (cliOverride !== void 0) {
|
|
390
|
+
return cliOverride;
|
|
391
|
+
}
|
|
392
|
+
if (toolConfig?.scoreWeight !== void 0) {
|
|
393
|
+
return toolConfig.scoreWeight;
|
|
394
|
+
}
|
|
395
|
+
return DEFAULT_TOOL_WEIGHTS[toolName] || 10;
|
|
396
|
+
}
|
|
397
|
+
function parseWeightString(weightStr) {
|
|
398
|
+
const weights = /* @__PURE__ */ new Map();
|
|
399
|
+
if (!weightStr) {
|
|
400
|
+
return weights;
|
|
401
|
+
}
|
|
402
|
+
const pairs = weightStr.split(",");
|
|
403
|
+
for (const pair of pairs) {
|
|
404
|
+
const [toolShortName, weightStr2] = pair.split(":");
|
|
405
|
+
if (toolShortName && weightStr2) {
|
|
406
|
+
const toolName = normalizeToolName(toolShortName.trim());
|
|
407
|
+
const weight = parseInt(weightStr2.trim(), 10);
|
|
408
|
+
if (!isNaN(weight) && weight > 0) {
|
|
409
|
+
weights.set(toolName, weight);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
return weights;
|
|
414
|
+
}
|
|
415
|
+
function calculateOverallScore(toolOutputs, config, cliWeights) {
|
|
416
|
+
if (toolOutputs.size === 0) {
|
|
417
|
+
throw new Error("No tool outputs provided for scoring");
|
|
418
|
+
}
|
|
419
|
+
const weights = /* @__PURE__ */ new Map();
|
|
420
|
+
for (const [toolName] of toolOutputs.entries()) {
|
|
421
|
+
const cliWeight = cliWeights?.get(toolName);
|
|
422
|
+
const configWeight = config?.tools?.[toolName]?.scoreWeight;
|
|
423
|
+
const weight = cliWeight ?? configWeight ?? DEFAULT_TOOL_WEIGHTS[toolName] ?? 10;
|
|
424
|
+
weights.set(toolName, weight);
|
|
425
|
+
}
|
|
426
|
+
let weightedSum = 0;
|
|
427
|
+
let totalWeight = 0;
|
|
428
|
+
const breakdown = [];
|
|
429
|
+
const toolsUsed = [];
|
|
430
|
+
const calculationWeights = {};
|
|
431
|
+
for (const [toolName, output] of toolOutputs.entries()) {
|
|
432
|
+
const weight = weights.get(toolName) || 10;
|
|
433
|
+
const weightedScore = output.score * weight;
|
|
434
|
+
weightedSum += weightedScore;
|
|
435
|
+
totalWeight += weight;
|
|
436
|
+
toolsUsed.push(toolName);
|
|
437
|
+
calculationWeights[toolName] = weight;
|
|
438
|
+
breakdown.push(output);
|
|
439
|
+
}
|
|
440
|
+
const overall = Math.round(weightedSum / totalWeight);
|
|
441
|
+
const rating = getRating(overall);
|
|
442
|
+
const formulaParts = Array.from(toolOutputs.entries()).map(([name, output]) => {
|
|
443
|
+
const w = weights.get(name) || 10;
|
|
444
|
+
return `(${output.score} \xD7 ${w})`;
|
|
445
|
+
});
|
|
446
|
+
const formulaStr = `[${formulaParts.join(" + ")}] / ${totalWeight} = ${overall}`;
|
|
447
|
+
return {
|
|
448
|
+
overall,
|
|
449
|
+
rating,
|
|
450
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
451
|
+
toolsUsed,
|
|
452
|
+
breakdown,
|
|
453
|
+
calculation: {
|
|
454
|
+
formula: formulaStr,
|
|
455
|
+
weights: calculationWeights,
|
|
456
|
+
normalized: formulaStr
|
|
457
|
+
}
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
function getRating(score) {
|
|
461
|
+
if (score >= 90) return "Excellent";
|
|
462
|
+
if (score >= 75) return "Good";
|
|
463
|
+
if (score >= 60) return "Fair";
|
|
464
|
+
if (score >= 40) return "Needs Work";
|
|
465
|
+
return "Critical";
|
|
466
|
+
}
|
|
467
|
+
function getRatingDisplay(rating) {
|
|
468
|
+
switch (rating) {
|
|
469
|
+
case "Excellent":
|
|
470
|
+
return { emoji: "\u2705", color: "green" };
|
|
471
|
+
case "Good":
|
|
472
|
+
return { emoji: "\u{1F44D}", color: "blue" };
|
|
473
|
+
case "Fair":
|
|
474
|
+
return { emoji: "\u26A0\uFE0F", color: "yellow" };
|
|
475
|
+
case "Needs Work":
|
|
476
|
+
return { emoji: "\u{1F528}", color: "orange" };
|
|
477
|
+
case "Critical":
|
|
478
|
+
return { emoji: "\u274C", color: "red" };
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
function formatScore(result) {
|
|
482
|
+
const { emoji, color } = getRatingDisplay(result.rating);
|
|
483
|
+
return `${result.overall}/100 (${result.rating}) ${emoji}`;
|
|
484
|
+
}
|
|
485
|
+
function formatToolScore(output) {
|
|
486
|
+
let result = ` Score: ${output.score}/100
|
|
487
|
+
|
|
488
|
+
`;
|
|
489
|
+
if (output.factors && output.factors.length > 0) {
|
|
490
|
+
result += ` Factors:
|
|
491
|
+
`;
|
|
492
|
+
output.factors.forEach((factor) => {
|
|
493
|
+
const impactSign = factor.impact > 0 ? "+" : "";
|
|
494
|
+
result += ` \u2022 ${factor.name}: ${impactSign}${factor.impact} - ${factor.description}
|
|
495
|
+
`;
|
|
496
|
+
});
|
|
497
|
+
result += "\n";
|
|
498
|
+
}
|
|
499
|
+
if (output.recommendations && output.recommendations.length > 0) {
|
|
500
|
+
result += ` Recommendations:
|
|
501
|
+
`;
|
|
502
|
+
output.recommendations.forEach((rec, i) => {
|
|
503
|
+
const priorityIcon = rec.priority === "high" ? "\u{1F534}" : rec.priority === "medium" ? "\u{1F7E1}" : "\u{1F535}";
|
|
504
|
+
result += ` ${i + 1}. ${priorityIcon} ${rec.action}
|
|
505
|
+
`;
|
|
506
|
+
result += ` Impact: +${rec.estimatedImpact} points
|
|
507
|
+
|
|
508
|
+
`;
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
return result;
|
|
512
|
+
}
|
|
369
513
|
export {
|
|
370
514
|
DEFAULT_EXCLUDE,
|
|
515
|
+
DEFAULT_TOOL_WEIGHTS,
|
|
516
|
+
TOOL_NAME_MAP,
|
|
371
517
|
calculateImportSimilarity,
|
|
518
|
+
calculateOverallScore,
|
|
372
519
|
estimateTokens,
|
|
373
520
|
extractFunctions,
|
|
374
521
|
extractImports,
|
|
522
|
+
formatScore,
|
|
523
|
+
formatToolScore,
|
|
375
524
|
getElapsedTime,
|
|
376
525
|
getFileExtension,
|
|
526
|
+
getRating,
|
|
527
|
+
getRatingDisplay,
|
|
528
|
+
getToolWeight,
|
|
377
529
|
handleCLIError,
|
|
378
530
|
handleJSONOutput,
|
|
379
531
|
isSourceFile,
|
|
380
532
|
loadConfig,
|
|
381
533
|
loadMergedConfig,
|
|
382
534
|
mergeConfigWithDefaults,
|
|
535
|
+
normalizeToolName,
|
|
383
536
|
parseCode,
|
|
384
537
|
parseFileExports,
|
|
538
|
+
parseWeightString,
|
|
385
539
|
readFileContent,
|
|
386
540
|
resolveOutputPath,
|
|
387
541
|
scanFiles
|