@aiready/core 0.19.5 → 0.21.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.
- package/dist/chunk-YCA4FTEK.mjs +582 -0
- package/dist/client.d.mts +21 -4
- package/dist/client.d.ts +21 -4
- package/dist/client.js +12 -3
- package/dist/client.mjs +3 -1
- package/dist/index.d.mts +54 -3
- package/dist/index.d.ts +54 -3
- package/dist/index.js +110 -12
- package/dist/index.mjs +100 -10
- package/package.json +1 -1
|
@@ -0,0 +1,582 @@
|
|
|
1
|
+
// src/types/schema.ts
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
var Severity = /* @__PURE__ */ ((Severity2) => {
|
|
4
|
+
Severity2["Critical"] = "critical";
|
|
5
|
+
Severity2["Major"] = "major";
|
|
6
|
+
Severity2["Minor"] = "minor";
|
|
7
|
+
Severity2["Info"] = "info";
|
|
8
|
+
return Severity2;
|
|
9
|
+
})(Severity || {});
|
|
10
|
+
var SeveritySchema = z.nativeEnum(Severity);
|
|
11
|
+
var ToolName = /* @__PURE__ */ ((ToolName2) => {
|
|
12
|
+
ToolName2["PatternDetect"] = "pattern-detect";
|
|
13
|
+
ToolName2["ContextAnalyzer"] = "context-analyzer";
|
|
14
|
+
ToolName2["NamingConsistency"] = "naming-consistency";
|
|
15
|
+
ToolName2["AiSignalClarity"] = "ai-signal-clarity";
|
|
16
|
+
ToolName2["AgentGrounding"] = "agent-grounding";
|
|
17
|
+
ToolName2["TestabilityIndex"] = "testability-index";
|
|
18
|
+
ToolName2["DocDrift"] = "doc-drift";
|
|
19
|
+
ToolName2["DependencyHealth"] = "dependency-health";
|
|
20
|
+
ToolName2["ChangeAmplification"] = "change-amplification";
|
|
21
|
+
ToolName2["CognitiveLoad"] = "cognitive-load";
|
|
22
|
+
ToolName2["PatternEntropy"] = "pattern-entropy";
|
|
23
|
+
ToolName2["ConceptCohesion"] = "concept-cohesion";
|
|
24
|
+
ToolName2["SemanticDistance"] = "semantic-distance";
|
|
25
|
+
return ToolName2;
|
|
26
|
+
})(ToolName || {});
|
|
27
|
+
var ToolNameSchema = z.nativeEnum(ToolName);
|
|
28
|
+
var FRIENDLY_TOOL_NAMES = {
|
|
29
|
+
["pattern-detect" /* PatternDetect */]: "Semantic Duplicates",
|
|
30
|
+
["context-analyzer" /* ContextAnalyzer */]: "Context Fragmentation",
|
|
31
|
+
["naming-consistency" /* NamingConsistency */]: "Naming Consistency",
|
|
32
|
+
["ai-signal-clarity" /* AiSignalClarity */]: "AI Signal Clarity",
|
|
33
|
+
["agent-grounding" /* AgentGrounding */]: "Agent Grounding",
|
|
34
|
+
["testability-index" /* TestabilityIndex */]: "Testability Index",
|
|
35
|
+
["doc-drift" /* DocDrift */]: "Documentation Health",
|
|
36
|
+
["dependency-health" /* DependencyHealth */]: "Dependency Health",
|
|
37
|
+
["change-amplification" /* ChangeAmplification */]: "Change Amplification",
|
|
38
|
+
["cognitive-load" /* CognitiveLoad */]: "Cognitive Load",
|
|
39
|
+
["pattern-entropy" /* PatternEntropy */]: "Pattern Entropy",
|
|
40
|
+
["concept-cohesion" /* ConceptCohesion */]: "Concept Cohesion",
|
|
41
|
+
["semantic-distance" /* SemanticDistance */]: "Semantic Distance"
|
|
42
|
+
};
|
|
43
|
+
var IssueType = /* @__PURE__ */ ((IssueType2) => {
|
|
44
|
+
IssueType2["DuplicatePattern"] = "duplicate-pattern";
|
|
45
|
+
IssueType2["PatternInconsistency"] = "pattern-inconsistency";
|
|
46
|
+
IssueType2["ContextFragmentation"] = "context-fragmentation";
|
|
47
|
+
IssueType2["DependencyHealth"] = "dependency-health";
|
|
48
|
+
IssueType2["CircularDependency"] = "circular-dependency";
|
|
49
|
+
IssueType2["DocDrift"] = "doc-drift";
|
|
50
|
+
IssueType2["NamingInconsistency"] = "naming-inconsistency";
|
|
51
|
+
IssueType2["NamingQuality"] = "naming-quality";
|
|
52
|
+
IssueType2["ArchitectureInconsistency"] = "architecture-inconsistency";
|
|
53
|
+
IssueType2["DeadCode"] = "dead-code";
|
|
54
|
+
IssueType2["MissingTypes"] = "missing-types";
|
|
55
|
+
IssueType2["MagicLiteral"] = "magic-literal";
|
|
56
|
+
IssueType2["BooleanTrap"] = "boolean-trap";
|
|
57
|
+
IssueType2["AiSignalClarity"] = "ai-signal-clarity";
|
|
58
|
+
IssueType2["LowTestability"] = "low-testability";
|
|
59
|
+
IssueType2["AgentNavigationFailure"] = "agent-navigation-failure";
|
|
60
|
+
IssueType2["AmbiguousApi"] = "ambiguous-api";
|
|
61
|
+
IssueType2["ChangeAmplification"] = "change-amplification";
|
|
62
|
+
return IssueType2;
|
|
63
|
+
})(IssueType || {});
|
|
64
|
+
var IssueTypeSchema = z.nativeEnum(IssueType);
|
|
65
|
+
var AnalysisStatus = /* @__PURE__ */ ((AnalysisStatus2) => {
|
|
66
|
+
AnalysisStatus2["Processing"] = "processing";
|
|
67
|
+
AnalysisStatus2["Completed"] = "completed";
|
|
68
|
+
AnalysisStatus2["Failed"] = "failed";
|
|
69
|
+
return AnalysisStatus2;
|
|
70
|
+
})(AnalysisStatus || {});
|
|
71
|
+
var AnalysisStatusSchema = z.nativeEnum(AnalysisStatus);
|
|
72
|
+
var ModelTier = /* @__PURE__ */ ((ModelTier2) => {
|
|
73
|
+
ModelTier2["Compact"] = "compact";
|
|
74
|
+
ModelTier2["Standard"] = "standard";
|
|
75
|
+
ModelTier2["Extended"] = "extended";
|
|
76
|
+
ModelTier2["Frontier"] = "frontier";
|
|
77
|
+
return ModelTier2;
|
|
78
|
+
})(ModelTier || {});
|
|
79
|
+
var ModelTierSchema = z.nativeEnum(ModelTier);
|
|
80
|
+
var LocationSchema = z.object({
|
|
81
|
+
file: z.string(),
|
|
82
|
+
line: z.number(),
|
|
83
|
+
column: z.number().optional(),
|
|
84
|
+
endLine: z.number().optional(),
|
|
85
|
+
endColumn: z.number().optional()
|
|
86
|
+
});
|
|
87
|
+
var IssueSchema = z.object({
|
|
88
|
+
type: IssueTypeSchema,
|
|
89
|
+
severity: SeveritySchema,
|
|
90
|
+
message: z.string(),
|
|
91
|
+
location: LocationSchema,
|
|
92
|
+
suggestion: z.string().optional()
|
|
93
|
+
});
|
|
94
|
+
var MetricsSchema = z.object({
|
|
95
|
+
tokenCost: z.number().optional(),
|
|
96
|
+
complexityScore: z.number().optional(),
|
|
97
|
+
consistencyScore: z.number().optional(),
|
|
98
|
+
docFreshnessScore: z.number().optional(),
|
|
99
|
+
// AI agent readiness metrics (v0.12+)
|
|
100
|
+
aiSignalClarityScore: z.number().optional(),
|
|
101
|
+
agentGroundingScore: z.number().optional(),
|
|
102
|
+
testabilityScore: z.number().optional(),
|
|
103
|
+
docDriftScore: z.number().optional(),
|
|
104
|
+
dependencyHealthScore: z.number().optional(),
|
|
105
|
+
modelContextTier: ModelTierSchema.optional(),
|
|
106
|
+
// Business value metrics
|
|
107
|
+
estimatedMonthlyCost: z.number().optional(),
|
|
108
|
+
estimatedDeveloperHours: z.number().optional(),
|
|
109
|
+
comprehensionDifficultyIndex: z.number().optional(),
|
|
110
|
+
// Extended metrics for specific spokes
|
|
111
|
+
totalSymbols: z.number().optional(),
|
|
112
|
+
totalExports: z.number().optional()
|
|
113
|
+
});
|
|
114
|
+
var AnalysisResultSchema = z.object({
|
|
115
|
+
fileName: z.string(),
|
|
116
|
+
issues: z.array(IssueSchema),
|
|
117
|
+
metrics: MetricsSchema
|
|
118
|
+
});
|
|
119
|
+
var SpokeSummarySchema = z.object({
|
|
120
|
+
totalFiles: z.number().optional(),
|
|
121
|
+
totalIssues: z.number().optional(),
|
|
122
|
+
criticalIssues: z.number().optional(),
|
|
123
|
+
majorIssues: z.number().optional(),
|
|
124
|
+
score: z.number().optional()
|
|
125
|
+
}).catchall(z.any());
|
|
126
|
+
var SpokeOutputSchema = z.object({
|
|
127
|
+
results: z.array(AnalysisResultSchema),
|
|
128
|
+
summary: SpokeSummarySchema,
|
|
129
|
+
metadata: z.object({
|
|
130
|
+
toolName: z.string(),
|
|
131
|
+
version: z.string().optional(),
|
|
132
|
+
timestamp: z.string().optional()
|
|
133
|
+
}).catchall(z.any()).optional()
|
|
134
|
+
});
|
|
135
|
+
var UnifiedReportSchema = z.object({
|
|
136
|
+
summary: z.object({
|
|
137
|
+
totalFiles: z.number(),
|
|
138
|
+
totalIssues: z.number(),
|
|
139
|
+
criticalIssues: z.number(),
|
|
140
|
+
majorIssues: z.number()
|
|
141
|
+
}),
|
|
142
|
+
results: z.array(AnalysisResultSchema),
|
|
143
|
+
scoring: z.object({
|
|
144
|
+
overall: z.number(),
|
|
145
|
+
rating: z.string(),
|
|
146
|
+
timestamp: z.string(),
|
|
147
|
+
breakdown: z.array(
|
|
148
|
+
z.object({
|
|
149
|
+
toolName: z.union([ToolNameSchema, z.string()]),
|
|
150
|
+
score: z.number()
|
|
151
|
+
}).catchall(z.any())
|
|
152
|
+
)
|
|
153
|
+
}).optional()
|
|
154
|
+
}).catchall(z.any());
|
|
155
|
+
|
|
156
|
+
// src/types/language.ts
|
|
157
|
+
var Language = /* @__PURE__ */ ((Language2) => {
|
|
158
|
+
Language2["TypeScript"] = "typescript";
|
|
159
|
+
Language2["JavaScript"] = "javascript";
|
|
160
|
+
Language2["Python"] = "python";
|
|
161
|
+
Language2["Java"] = "java";
|
|
162
|
+
Language2["Go"] = "go";
|
|
163
|
+
Language2["Rust"] = "rust";
|
|
164
|
+
Language2["CSharp"] = "csharp";
|
|
165
|
+
return Language2;
|
|
166
|
+
})(Language || {});
|
|
167
|
+
var LANGUAGE_EXTENSIONS = {
|
|
168
|
+
".ts": "typescript" /* TypeScript */,
|
|
169
|
+
".tsx": "typescript" /* TypeScript */,
|
|
170
|
+
".js": "javascript" /* JavaScript */,
|
|
171
|
+
".jsx": "javascript" /* JavaScript */,
|
|
172
|
+
".py": "python" /* Python */,
|
|
173
|
+
".java": "java" /* Java */,
|
|
174
|
+
".go": "go" /* Go */,
|
|
175
|
+
".rs": "rust" /* Rust */,
|
|
176
|
+
".cs": "csharp" /* CSharp */
|
|
177
|
+
};
|
|
178
|
+
var ParseError = class extends Error {
|
|
179
|
+
constructor(message, filePath, loc) {
|
|
180
|
+
super(message);
|
|
181
|
+
this.filePath = filePath;
|
|
182
|
+
this.loc = loc;
|
|
183
|
+
this.name = "ParseError";
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
// src/scoring.ts
|
|
188
|
+
var DEFAULT_TOOL_WEIGHTS = {
|
|
189
|
+
["pattern-detect" /* PatternDetect */]: 22,
|
|
190
|
+
["context-analyzer" /* ContextAnalyzer */]: 19,
|
|
191
|
+
["naming-consistency" /* NamingConsistency */]: 14,
|
|
192
|
+
["ai-signal-clarity" /* AiSignalClarity */]: 11,
|
|
193
|
+
["agent-grounding" /* AgentGrounding */]: 10,
|
|
194
|
+
["testability-index" /* TestabilityIndex */]: 10,
|
|
195
|
+
["doc-drift" /* DocDrift */]: 8,
|
|
196
|
+
["dependency-health" /* DependencyHealth */]: 6,
|
|
197
|
+
["change-amplification" /* ChangeAmplification */]: 8
|
|
198
|
+
};
|
|
199
|
+
var TOOL_NAME_MAP = {
|
|
200
|
+
patterns: "pattern-detect" /* PatternDetect */,
|
|
201
|
+
"pattern-detect": "pattern-detect" /* PatternDetect */,
|
|
202
|
+
context: "context-analyzer" /* ContextAnalyzer */,
|
|
203
|
+
"context-analyzer": "context-analyzer" /* ContextAnalyzer */,
|
|
204
|
+
consistency: "naming-consistency" /* NamingConsistency */,
|
|
205
|
+
"naming-consistency": "naming-consistency" /* NamingConsistency */,
|
|
206
|
+
"ai-signal": "ai-signal-clarity" /* AiSignalClarity */,
|
|
207
|
+
"ai-signal-clarity": "ai-signal-clarity" /* AiSignalClarity */,
|
|
208
|
+
grounding: "agent-grounding" /* AgentGrounding */,
|
|
209
|
+
"agent-grounding": "agent-grounding" /* AgentGrounding */,
|
|
210
|
+
testability: "testability-index" /* TestabilityIndex */,
|
|
211
|
+
"testability-index": "testability-index" /* TestabilityIndex */,
|
|
212
|
+
"doc-drift": "doc-drift" /* DocDrift */,
|
|
213
|
+
"deps-health": "dependency-health" /* DependencyHealth */,
|
|
214
|
+
"dependency-health": "dependency-health" /* DependencyHealth */,
|
|
215
|
+
"change-amp": "change-amplification" /* ChangeAmplification */,
|
|
216
|
+
"change-amplification": "change-amplification" /* ChangeAmplification */
|
|
217
|
+
};
|
|
218
|
+
var CONTEXT_TIER_THRESHOLDS = {
|
|
219
|
+
compact: { idealTokens: 3e3, criticalTokens: 1e4, idealDepth: 4 },
|
|
220
|
+
standard: { idealTokens: 5e3, criticalTokens: 15e3, idealDepth: 5 },
|
|
221
|
+
extended: { idealTokens: 15e3, criticalTokens: 5e4, idealDepth: 7 },
|
|
222
|
+
frontier: { idealTokens: 5e4, criticalTokens: 15e4, idealDepth: 10 }
|
|
223
|
+
};
|
|
224
|
+
var SIZE_ADJUSTED_THRESHOLDS = {
|
|
225
|
+
xs: 80,
|
|
226
|
+
// < 50 files
|
|
227
|
+
small: 75,
|
|
228
|
+
// 50-200 files
|
|
229
|
+
medium: 70,
|
|
230
|
+
// 200-500 files
|
|
231
|
+
large: 65,
|
|
232
|
+
// 500-2000 files
|
|
233
|
+
enterprise: 58
|
|
234
|
+
// 2000+ files
|
|
235
|
+
};
|
|
236
|
+
function getProjectSizeTier(fileCount) {
|
|
237
|
+
if (fileCount < 50) return "xs";
|
|
238
|
+
if (fileCount < 200) return "small";
|
|
239
|
+
if (fileCount < 500) return "medium";
|
|
240
|
+
if (fileCount < 2e3) return "large";
|
|
241
|
+
return "enterprise";
|
|
242
|
+
}
|
|
243
|
+
function getRecommendedThreshold(fileCount, modelTier = "standard") {
|
|
244
|
+
const sizeTier = getProjectSizeTier(fileCount);
|
|
245
|
+
const base = SIZE_ADJUSTED_THRESHOLDS[sizeTier];
|
|
246
|
+
const modelBonus = modelTier === "frontier" ? -3 : modelTier === "extended" ? -2 : 0;
|
|
247
|
+
return base + modelBonus;
|
|
248
|
+
}
|
|
249
|
+
function normalizeToolName(shortName) {
|
|
250
|
+
return TOOL_NAME_MAP[shortName.toLowerCase()] || shortName;
|
|
251
|
+
}
|
|
252
|
+
function getToolWeight(toolName, toolConfig, cliOverride) {
|
|
253
|
+
if (cliOverride !== void 0) return cliOverride;
|
|
254
|
+
if (toolConfig?.scoreWeight !== void 0) return toolConfig.scoreWeight;
|
|
255
|
+
return DEFAULT_TOOL_WEIGHTS[toolName] || 5;
|
|
256
|
+
}
|
|
257
|
+
function parseWeightString(weightStr) {
|
|
258
|
+
const weights = /* @__PURE__ */ new Map();
|
|
259
|
+
if (!weightStr) return weights;
|
|
260
|
+
const pairs = weightStr.split(",");
|
|
261
|
+
for (const pair of pairs) {
|
|
262
|
+
const [toolShortName, weightStr2] = pair.split(":");
|
|
263
|
+
if (toolShortName && weightStr2) {
|
|
264
|
+
const toolName = normalizeToolName(toolShortName.trim());
|
|
265
|
+
const weight = parseInt(weightStr2.trim(), 10);
|
|
266
|
+
if (!isNaN(weight) && weight > 0) {
|
|
267
|
+
weights.set(toolName, weight);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return weights;
|
|
272
|
+
}
|
|
273
|
+
function calculateOverallScore(toolOutputs, config, cliWeights) {
|
|
274
|
+
if (toolOutputs.size === 0) {
|
|
275
|
+
throw new Error("No tool outputs provided for scoring");
|
|
276
|
+
}
|
|
277
|
+
const weights = /* @__PURE__ */ new Map();
|
|
278
|
+
for (const [toolName] of toolOutputs.entries()) {
|
|
279
|
+
const cliWeight = cliWeights?.get(toolName);
|
|
280
|
+
const configWeight = config?.tools?.[toolName]?.scoreWeight;
|
|
281
|
+
const weight = cliWeight ?? configWeight ?? DEFAULT_TOOL_WEIGHTS[toolName] ?? 5;
|
|
282
|
+
weights.set(toolName, weight);
|
|
283
|
+
}
|
|
284
|
+
let weightedSum = 0;
|
|
285
|
+
let totalWeight = 0;
|
|
286
|
+
const breakdown = [];
|
|
287
|
+
const toolsUsed = [];
|
|
288
|
+
const calculationWeights = {};
|
|
289
|
+
for (const [toolName, output] of toolOutputs.entries()) {
|
|
290
|
+
const weight = weights.get(toolName) || 5;
|
|
291
|
+
weightedSum += output.score * weight;
|
|
292
|
+
totalWeight += weight;
|
|
293
|
+
toolsUsed.push(toolName);
|
|
294
|
+
calculationWeights[toolName] = weight;
|
|
295
|
+
breakdown.push(output);
|
|
296
|
+
}
|
|
297
|
+
const overall = Math.round(weightedSum / totalWeight);
|
|
298
|
+
const rating = getRating(overall);
|
|
299
|
+
const formulaParts = Array.from(toolOutputs.entries()).map(
|
|
300
|
+
([name, output]) => {
|
|
301
|
+
const w = weights.get(name) || 5;
|
|
302
|
+
return `(${output.score} \xD7 ${w})`;
|
|
303
|
+
}
|
|
304
|
+
);
|
|
305
|
+
const formulaStr = `[${formulaParts.join(" + ")}] / ${totalWeight} = ${overall}`;
|
|
306
|
+
return {
|
|
307
|
+
overall,
|
|
308
|
+
rating,
|
|
309
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
310
|
+
toolsUsed,
|
|
311
|
+
breakdown,
|
|
312
|
+
calculation: {
|
|
313
|
+
formula: formulaStr,
|
|
314
|
+
weights: calculationWeights,
|
|
315
|
+
normalized: formulaStr
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
function getRating(score) {
|
|
320
|
+
if (score >= 90) return "Excellent";
|
|
321
|
+
if (score >= 75) return "Good";
|
|
322
|
+
if (score >= 60) return "Fair";
|
|
323
|
+
if (score >= 40) return "Needs Work";
|
|
324
|
+
return "Critical";
|
|
325
|
+
}
|
|
326
|
+
function getRatingWithContext(score, fileCount, modelTier = "standard") {
|
|
327
|
+
const threshold = getRecommendedThreshold(fileCount, modelTier);
|
|
328
|
+
const normalized = score - threshold + 70;
|
|
329
|
+
return getRating(normalized);
|
|
330
|
+
}
|
|
331
|
+
function getRatingDisplay(rating) {
|
|
332
|
+
switch (rating) {
|
|
333
|
+
case "Excellent":
|
|
334
|
+
return { emoji: "\u2705", color: "green" };
|
|
335
|
+
case "Good":
|
|
336
|
+
return { emoji: "\u{1F44D}", color: "blue" };
|
|
337
|
+
case "Fair":
|
|
338
|
+
return { emoji: "\u26A0\uFE0F", color: "yellow" };
|
|
339
|
+
case "Needs Work":
|
|
340
|
+
return { emoji: "\u{1F528}", color: "orange" };
|
|
341
|
+
case "Critical":
|
|
342
|
+
return { emoji: "\u274C", color: "red" };
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
function formatScore(result) {
|
|
346
|
+
const { emoji } = getRatingDisplay(result.rating);
|
|
347
|
+
return `${result.overall}/100 (${result.rating}) ${emoji}`;
|
|
348
|
+
}
|
|
349
|
+
function formatToolScore(output) {
|
|
350
|
+
let result = ` Score: ${output.score}/100
|
|
351
|
+
|
|
352
|
+
`;
|
|
353
|
+
if (output.factors && output.factors.length > 0) {
|
|
354
|
+
result += ` Factors:
|
|
355
|
+
`;
|
|
356
|
+
output.factors.forEach((factor) => {
|
|
357
|
+
const impactSign = factor.impact > 0 ? "+" : "";
|
|
358
|
+
result += ` \u2022 ${factor.name}: ${impactSign}${factor.impact} - ${factor.description}
|
|
359
|
+
`;
|
|
360
|
+
});
|
|
361
|
+
result += "\n";
|
|
362
|
+
}
|
|
363
|
+
if (output.recommendations && output.recommendations.length > 0) {
|
|
364
|
+
result += ` Recommendations:
|
|
365
|
+
`;
|
|
366
|
+
output.recommendations.forEach((rec, i) => {
|
|
367
|
+
const priorityIcon = rec.priority === "high" ? "\u{1F534}" : rec.priority === "medium" ? "\u{1F7E1}" : "\u{1F535}";
|
|
368
|
+
result += ` ${i + 1}. ${priorityIcon} ${rec.action}
|
|
369
|
+
`;
|
|
370
|
+
result += ` Impact: +${rec.estimatedImpact} points
|
|
371
|
+
|
|
372
|
+
`;
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
return result;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// src/utils/visualization.ts
|
|
379
|
+
function generateHTML(graph) {
|
|
380
|
+
const payload = JSON.stringify(graph, null, 2);
|
|
381
|
+
return `<!doctype html>
|
|
382
|
+
<html>
|
|
383
|
+
<head>
|
|
384
|
+
<meta charset="utf-8" />
|
|
385
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
386
|
+
<title>AIReady Visualization</title>
|
|
387
|
+
<style>
|
|
388
|
+
html,body { height: 100%; margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #0f172a; color: #e2e8f0 }
|
|
389
|
+
#container { display:flex; height:100vh }
|
|
390
|
+
#panel { width: 320px; padding: 16px; background: #071130; box-shadow: -2px 0 8px rgba(0,0,0,0.3); overflow:auto }
|
|
391
|
+
#canvasWrap { flex:1; display:flex; align-items:center; justify-content:center }
|
|
392
|
+
canvas { background: #0b1220; border-radius:8px }
|
|
393
|
+
.stat { margin-bottom:12px }
|
|
394
|
+
</style>
|
|
395
|
+
</head>
|
|
396
|
+
<body>
|
|
397
|
+
<div id="container">
|
|
398
|
+
<div id="canvasWrap"><canvas id="canvas" width="1200" height="800"></canvas></div>
|
|
399
|
+
<div id="panel">
|
|
400
|
+
<h2>AIReady Visualization</h2>
|
|
401
|
+
<div class="stat"><strong>Files:</strong> <span id="stat-files"></span></div>
|
|
402
|
+
<div class="stat"><strong>Dependencies:</strong> <span id="stat-deps"></span></div>
|
|
403
|
+
<div class="stat"><strong>Legend</strong></div>
|
|
404
|
+
<div style="font-size:13px;line-height:1.3;color:#cbd5e1;margin-top:8px">
|
|
405
|
+
<div style="margin-bottom:8px"><span style="display:inline-block;width:12px;height:12px;background:#ff4d4f;margin-right:8px;border:1px solid rgba(255,255,255,0.06)"></span><strong>Critical</strong>: highest severity issues.</div>
|
|
406
|
+
<div style="margin-bottom:8px"><span style="display:inline-block;width:12px;height:12px;background:#ff9900;margin-right:8px;border:1px solid rgba(255,255,255,0.06)"></span><strong>Major</strong>: important issues.</div>
|
|
407
|
+
<div style="margin-bottom:8px"><span style="display:inline-block;width:12px;height:12px;background:#ffd666;margin-right:8px;border:1px solid rgba(255,255,255,0.06)"></span><strong>Minor</strong>: low priority issues.</div>
|
|
408
|
+
<div style="margin-bottom:8px"><span style="display:inline-block;width:12px;height:12px;background:#91d5ff;margin-right:8px;border:1px solid rgba(255,255,255,0.06)"></span><strong>Info</strong>: informational notes.</div>
|
|
409
|
+
<div style="margin-top:10px;color:#94a3b8"><strong>Node size</strong>: larger = higher token cost, more issues or dependency weight.</div>
|
|
410
|
+
<div style="margin-top:6px;color:#94a3b8"><strong>Proximity</strong>: nodes that are spatially close are more contextually related; relatedness is represented by distance and size rather than explicit edges.</div>
|
|
411
|
+
<div style="margin-top:6px;color:#94a3b8"><strong>Edge colors</strong>: <span style="color:#fb7e81">Similarity</span>, <span style="color:#84c1ff">Dependency</span>, <span style="color:#ffa500">Reference</span>, default <span style="color:#334155">Other</span>.</div>
|
|
412
|
+
</div>
|
|
413
|
+
</div>
|
|
414
|
+
</div>
|
|
415
|
+
|
|
416
|
+
<script>
|
|
417
|
+
const graphData = ${payload};
|
|
418
|
+
document.getElementById('stat-files').textContent = graphData.metadata.totalFiles;
|
|
419
|
+
document.getElementById('stat-deps').textContent = graphData.metadata.totalDependencies;
|
|
420
|
+
|
|
421
|
+
const canvas = document.getElementById('canvas');
|
|
422
|
+
const ctx = canvas.getContext('2d');
|
|
423
|
+
|
|
424
|
+
const nodes = graphData.nodes.map((n, i) => ({
|
|
425
|
+
...n,
|
|
426
|
+
x: canvas.width / 2 + Math.cos(i / graphData.nodes.length * Math.PI * 2) * (Math.min(canvas.width, canvas.height) / 3),
|
|
427
|
+
y: canvas.height / 2 + Math.sin(i / graphData.nodes.length * Math.PI * 2) * (Math.min(canvas.width, canvas.height) / 3),
|
|
428
|
+
}));
|
|
429
|
+
|
|
430
|
+
function draw() {
|
|
431
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
432
|
+
|
|
433
|
+
graphData.edges.forEach(edge => {
|
|
434
|
+
const s = nodes.find(n => n.id === edge.source);
|
|
435
|
+
const t = nodes.find(n => n.id === edge.target);
|
|
436
|
+
if (!s || !t) return;
|
|
437
|
+
if (edge.type === 'related') return;
|
|
438
|
+
if (edge.type === 'similarity') {
|
|
439
|
+
ctx.strokeStyle = '#fb7e81';
|
|
440
|
+
ctx.lineWidth = 1.2;
|
|
441
|
+
} else if (edge.type === 'dependency') {
|
|
442
|
+
ctx.strokeStyle = '#84c1ff';
|
|
443
|
+
ctx.lineWidth = 1.0;
|
|
444
|
+
} else if (edge.type === 'reference') {
|
|
445
|
+
ctx.strokeStyle = '#ffa500';
|
|
446
|
+
ctx.lineWidth = 0.9;
|
|
447
|
+
} else {
|
|
448
|
+
ctx.strokeStyle = '#334155';
|
|
449
|
+
ctx.lineWidth = 0.8;
|
|
450
|
+
}
|
|
451
|
+
ctx.beginPath();
|
|
452
|
+
ctx.moveTo(s.x, s.y);
|
|
453
|
+
ctx.lineTo(t.x, t.y);
|
|
454
|
+
ctx.stroke();
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
const groups = {};
|
|
458
|
+
nodes.forEach(n => {
|
|
459
|
+
const g = n.group || '__default';
|
|
460
|
+
if (!groups[g]) groups[g] = { minX: n.x, minY: n.y, maxX: n.x, maxY: n.y };
|
|
461
|
+
groups[g].minX = Math.min(groups[g].minX, n.x);
|
|
462
|
+
groups[g].minY = Math.min(groups[g].minY, n.y);
|
|
463
|
+
groups[g].maxX = Math.max(groups[g].maxX, n.x);
|
|
464
|
+
groups[g].maxY = Math.max(groups[g].maxY, n.y);
|
|
465
|
+
});
|
|
466
|
+
|
|
467
|
+
const groupRelations = {};
|
|
468
|
+
graphData.edges.forEach(edge => {
|
|
469
|
+
const sNode = nodes.find(n => n.id === edge.source);
|
|
470
|
+
const tNode = nodes.find(n => n.id === edge.target);
|
|
471
|
+
if (!sNode || !tNode) return;
|
|
472
|
+
const g1 = sNode.group || '__default';
|
|
473
|
+
const g2 = tNode.group || '__default';
|
|
474
|
+
if (g1 === g2) return;
|
|
475
|
+
const key = g1 < g2 ? g1 + '::' + g2 : g2 + '::' + g1;
|
|
476
|
+
groupRelations[key] = (groupRelations[key] || 0) + 1;
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
Object.keys(groupRelations).forEach(k => {
|
|
480
|
+
const count = groupRelations[k];
|
|
481
|
+
const [ga, gb] = k.split('::');
|
|
482
|
+
if (!groups[ga] || !groups[gb]) return;
|
|
483
|
+
const ax = (groups[ga].minX + groups[ga].maxX) / 2;
|
|
484
|
+
const ay = (groups[ga].minY + groups[ga].maxY) / 2;
|
|
485
|
+
const bx = (groups[gb].minX + groups[gb].maxX) / 2;
|
|
486
|
+
const by = (groups[gb].minY + groups[gb].maxY) / 2;
|
|
487
|
+
ctx.beginPath();
|
|
488
|
+
ctx.strokeStyle = 'rgba(148,163,184,0.25)';
|
|
489
|
+
ctx.lineWidth = Math.min(6, 0.6 + Math.sqrt(count));
|
|
490
|
+
ctx.moveTo(ax, ay);
|
|
491
|
+
ctx.lineTo(bx, by);
|
|
492
|
+
ctx.stroke();
|
|
493
|
+
});
|
|
494
|
+
|
|
495
|
+
Object.keys(groups).forEach(g => {
|
|
496
|
+
if (g === '__default') return;
|
|
497
|
+
const box = groups[g];
|
|
498
|
+
const pad = 16;
|
|
499
|
+
const x = box.minX - pad;
|
|
500
|
+
const y = box.minY - pad;
|
|
501
|
+
const w = (box.maxX - box.minX) + pad * 2;
|
|
502
|
+
const h = (box.maxY - box.minY) + pad * 2;
|
|
503
|
+
ctx.save();
|
|
504
|
+
ctx.fillStyle = 'rgba(30,64,175,0.04)';
|
|
505
|
+
ctx.strokeStyle = 'rgba(30,64,175,0.12)';
|
|
506
|
+
ctx.lineWidth = 1.2;
|
|
507
|
+
const r = 8;
|
|
508
|
+
ctx.beginPath();
|
|
509
|
+
ctx.moveTo(x + r, y);
|
|
510
|
+
ctx.arcTo(x + w, y, x + w, y + h, r);
|
|
511
|
+
ctx.arcTo(x + w, y + h, x, y + h, r);
|
|
512
|
+
ctx.arcTo(x, y + h, x, y, r);
|
|
513
|
+
ctx.arcTo(x, y, x + w, y, r);
|
|
514
|
+
ctx.closePath();
|
|
515
|
+
ctx.fill();
|
|
516
|
+
ctx.stroke();
|
|
517
|
+
ctx.restore();
|
|
518
|
+
ctx.fillStyle = '#94a3b8';
|
|
519
|
+
ctx.font = '11px sans-serif';
|
|
520
|
+
ctx.fillText(g, x + 8, y + 14);
|
|
521
|
+
});
|
|
522
|
+
|
|
523
|
+
nodes.forEach(n => {
|
|
524
|
+
const sizeVal = (n.size || n.value || 1);
|
|
525
|
+
const r = 6 + (sizeVal / 2);
|
|
526
|
+
ctx.beginPath();
|
|
527
|
+
ctx.fillStyle = n.color || '#60a5fa';
|
|
528
|
+
ctx.arc(n.x, n.y, r, 0, Math.PI * 2);
|
|
529
|
+
ctx.fill();
|
|
530
|
+
|
|
531
|
+
ctx.fillStyle = '#e2e8f0';
|
|
532
|
+
ctx.font = '11px sans-serif';
|
|
533
|
+
ctx.textAlign = 'center';
|
|
534
|
+
ctx.fillText(n.label || n.id.split('/').slice(-1)[0], n.x, n.y + r + 12);
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
draw();
|
|
539
|
+
</script>
|
|
540
|
+
</body>
|
|
541
|
+
</html>`;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
export {
|
|
545
|
+
Severity,
|
|
546
|
+
SeveritySchema,
|
|
547
|
+
ToolName,
|
|
548
|
+
ToolNameSchema,
|
|
549
|
+
FRIENDLY_TOOL_NAMES,
|
|
550
|
+
IssueType,
|
|
551
|
+
IssueTypeSchema,
|
|
552
|
+
AnalysisStatus,
|
|
553
|
+
AnalysisStatusSchema,
|
|
554
|
+
ModelTier,
|
|
555
|
+
ModelTierSchema,
|
|
556
|
+
LocationSchema,
|
|
557
|
+
IssueSchema,
|
|
558
|
+
MetricsSchema,
|
|
559
|
+
AnalysisResultSchema,
|
|
560
|
+
SpokeSummarySchema,
|
|
561
|
+
SpokeOutputSchema,
|
|
562
|
+
UnifiedReportSchema,
|
|
563
|
+
Language,
|
|
564
|
+
LANGUAGE_EXTENSIONS,
|
|
565
|
+
ParseError,
|
|
566
|
+
DEFAULT_TOOL_WEIGHTS,
|
|
567
|
+
TOOL_NAME_MAP,
|
|
568
|
+
CONTEXT_TIER_THRESHOLDS,
|
|
569
|
+
SIZE_ADJUSTED_THRESHOLDS,
|
|
570
|
+
getProjectSizeTier,
|
|
571
|
+
getRecommendedThreshold,
|
|
572
|
+
normalizeToolName,
|
|
573
|
+
getToolWeight,
|
|
574
|
+
parseWeightString,
|
|
575
|
+
calculateOverallScore,
|
|
576
|
+
getRating,
|
|
577
|
+
getRatingWithContext,
|
|
578
|
+
getRatingDisplay,
|
|
579
|
+
formatScore,
|
|
580
|
+
formatToolScore,
|
|
581
|
+
generateHTML
|
|
582
|
+
};
|
package/dist/client.d.mts
CHANGED
|
@@ -163,6 +163,17 @@ declare const AnalysisResultSchema: z.ZodObject<{
|
|
|
163
163
|
}, z.core.$strip>;
|
|
164
164
|
}, z.core.$strip>;
|
|
165
165
|
type AnalysisResult = z.infer<typeof AnalysisResultSchema>;
|
|
166
|
+
/**
|
|
167
|
+
* Standard spoke tool summary schema.
|
|
168
|
+
*/
|
|
169
|
+
declare const SpokeSummarySchema: z.ZodObject<{
|
|
170
|
+
totalFiles: z.ZodOptional<z.ZodNumber>;
|
|
171
|
+
totalIssues: z.ZodOptional<z.ZodNumber>;
|
|
172
|
+
criticalIssues: z.ZodOptional<z.ZodNumber>;
|
|
173
|
+
majorIssues: z.ZodOptional<z.ZodNumber>;
|
|
174
|
+
score: z.ZodOptional<z.ZodNumber>;
|
|
175
|
+
}, z.core.$catchall<z.ZodAny>>;
|
|
176
|
+
type SpokeSummary = z.infer<typeof SpokeSummarySchema>;
|
|
166
177
|
/**
|
|
167
178
|
* Standard spoke tool output contract.
|
|
168
179
|
*/
|
|
@@ -200,11 +211,17 @@ declare const SpokeOutputSchema: z.ZodObject<{
|
|
|
200
211
|
totalExports: z.ZodOptional<z.ZodNumber>;
|
|
201
212
|
}, z.core.$strip>;
|
|
202
213
|
}, z.core.$strip>>;
|
|
203
|
-
summary: z.
|
|
214
|
+
summary: z.ZodObject<{
|
|
215
|
+
totalFiles: z.ZodOptional<z.ZodNumber>;
|
|
216
|
+
totalIssues: z.ZodOptional<z.ZodNumber>;
|
|
217
|
+
criticalIssues: z.ZodOptional<z.ZodNumber>;
|
|
218
|
+
majorIssues: z.ZodOptional<z.ZodNumber>;
|
|
219
|
+
score: z.ZodOptional<z.ZodNumber>;
|
|
220
|
+
}, z.core.$catchall<z.ZodAny>>;
|
|
204
221
|
metadata: z.ZodOptional<z.ZodObject<{
|
|
205
222
|
toolName: z.ZodString;
|
|
206
|
-
version: z.ZodString
|
|
207
|
-
timestamp: z.ZodString
|
|
223
|
+
version: z.ZodOptional<z.ZodString>;
|
|
224
|
+
timestamp: z.ZodOptional<z.ZodString>;
|
|
208
225
|
}, z.core.$catchall<z.ZodAny>>>;
|
|
209
226
|
}, z.core.$strip>;
|
|
210
227
|
type SpokeOutput = z.infer<typeof SpokeOutputSchema>;
|
|
@@ -862,4 +879,4 @@ declare function formatToolScore(output: ToolScoringOutput): string;
|
|
|
862
879
|
*/
|
|
863
880
|
declare function generateHTML(graph: GraphData): string;
|
|
864
881
|
|
|
865
|
-
export { type AIReadyConfig, type AcceptancePrediction, type AnalysisResult, AnalysisResultSchema, AnalysisStatus, AnalysisStatusSchema, type BusinessReport, CONTEXT_TIER_THRESHOLDS, type CommonASTNode, type ComprehensionDifficulty, type CostConfig, DEFAULT_TOOL_WEIGHTS, type ExportInfo, FRIENDLY_TOOL_NAMES, type GraphData, type GraphEdge, type GraphIssueSeverity, type GraphMetadata, type GraphNode, type ImportInfo, type Issue, IssueSchema, IssueType, IssueTypeSchema, LANGUAGE_EXTENSIONS, Language, type LanguageConfig, type LanguageParser, type Location, LocationSchema, type Metrics, MetricsSchema, type ModelContextTier, ModelTier, ModelTierSchema, type NamingConvention, ParseError, type ParseResult, type ParseStatistics, type ProductivityImpact, type Report, SIZE_ADJUSTED_THRESHOLDS, type ScanOptions, type ScoringConfig, type ScoringResult, Severity, SeveritySchema, type SourceLocation, type SourceRange, type SpokeOutput, SpokeOutputSchema, TOOL_NAME_MAP, type TechnicalValueChain, type TechnicalValueChainSummary, type TokenBudget, ToolName, ToolNameSchema, type ToolScoringOutput, type UnifiedReport, UnifiedReportSchema, calculateOverallScore, formatScore, formatToolScore, generateHTML, getProjectSizeTier, getRating, getRatingDisplay, getRatingWithContext, getRecommendedThreshold, getToolWeight, normalizeToolName, parseWeightString };
|
|
882
|
+
export { type AIReadyConfig, type AcceptancePrediction, type AnalysisResult, AnalysisResultSchema, AnalysisStatus, AnalysisStatusSchema, type BusinessReport, CONTEXT_TIER_THRESHOLDS, type CommonASTNode, type ComprehensionDifficulty, type CostConfig, DEFAULT_TOOL_WEIGHTS, type ExportInfo, FRIENDLY_TOOL_NAMES, type GraphData, type GraphEdge, type GraphIssueSeverity, type GraphMetadata, type GraphNode, type ImportInfo, type Issue, IssueSchema, IssueType, IssueTypeSchema, LANGUAGE_EXTENSIONS, Language, type LanguageConfig, type LanguageParser, type Location, LocationSchema, type Metrics, MetricsSchema, type ModelContextTier, ModelTier, ModelTierSchema, type NamingConvention, ParseError, type ParseResult, type ParseStatistics, type ProductivityImpact, type Report, SIZE_ADJUSTED_THRESHOLDS, type ScanOptions, type ScoringConfig, type ScoringResult, Severity, SeveritySchema, type SourceLocation, type SourceRange, type SpokeOutput, SpokeOutputSchema, type SpokeSummary, SpokeSummarySchema, TOOL_NAME_MAP, type TechnicalValueChain, type TechnicalValueChainSummary, type TokenBudget, ToolName, ToolNameSchema, type ToolScoringOutput, type UnifiedReport, UnifiedReportSchema, calculateOverallScore, formatScore, formatToolScore, generateHTML, getProjectSizeTier, getRating, getRatingDisplay, getRatingWithContext, getRecommendedThreshold, getToolWeight, normalizeToolName, parseWeightString };
|
package/dist/client.d.ts
CHANGED
|
@@ -163,6 +163,17 @@ declare const AnalysisResultSchema: z.ZodObject<{
|
|
|
163
163
|
}, z.core.$strip>;
|
|
164
164
|
}, z.core.$strip>;
|
|
165
165
|
type AnalysisResult = z.infer<typeof AnalysisResultSchema>;
|
|
166
|
+
/**
|
|
167
|
+
* Standard spoke tool summary schema.
|
|
168
|
+
*/
|
|
169
|
+
declare const SpokeSummarySchema: z.ZodObject<{
|
|
170
|
+
totalFiles: z.ZodOptional<z.ZodNumber>;
|
|
171
|
+
totalIssues: z.ZodOptional<z.ZodNumber>;
|
|
172
|
+
criticalIssues: z.ZodOptional<z.ZodNumber>;
|
|
173
|
+
majorIssues: z.ZodOptional<z.ZodNumber>;
|
|
174
|
+
score: z.ZodOptional<z.ZodNumber>;
|
|
175
|
+
}, z.core.$catchall<z.ZodAny>>;
|
|
176
|
+
type SpokeSummary = z.infer<typeof SpokeSummarySchema>;
|
|
166
177
|
/**
|
|
167
178
|
* Standard spoke tool output contract.
|
|
168
179
|
*/
|
|
@@ -200,11 +211,17 @@ declare const SpokeOutputSchema: z.ZodObject<{
|
|
|
200
211
|
totalExports: z.ZodOptional<z.ZodNumber>;
|
|
201
212
|
}, z.core.$strip>;
|
|
202
213
|
}, z.core.$strip>>;
|
|
203
|
-
summary: z.
|
|
214
|
+
summary: z.ZodObject<{
|
|
215
|
+
totalFiles: z.ZodOptional<z.ZodNumber>;
|
|
216
|
+
totalIssues: z.ZodOptional<z.ZodNumber>;
|
|
217
|
+
criticalIssues: z.ZodOptional<z.ZodNumber>;
|
|
218
|
+
majorIssues: z.ZodOptional<z.ZodNumber>;
|
|
219
|
+
score: z.ZodOptional<z.ZodNumber>;
|
|
220
|
+
}, z.core.$catchall<z.ZodAny>>;
|
|
204
221
|
metadata: z.ZodOptional<z.ZodObject<{
|
|
205
222
|
toolName: z.ZodString;
|
|
206
|
-
version: z.ZodString
|
|
207
|
-
timestamp: z.ZodString
|
|
223
|
+
version: z.ZodOptional<z.ZodString>;
|
|
224
|
+
timestamp: z.ZodOptional<z.ZodString>;
|
|
208
225
|
}, z.core.$catchall<z.ZodAny>>>;
|
|
209
226
|
}, z.core.$strip>;
|
|
210
227
|
type SpokeOutput = z.infer<typeof SpokeOutputSchema>;
|
|
@@ -862,4 +879,4 @@ declare function formatToolScore(output: ToolScoringOutput): string;
|
|
|
862
879
|
*/
|
|
863
880
|
declare function generateHTML(graph: GraphData): string;
|
|
864
881
|
|
|
865
|
-
export { type AIReadyConfig, type AcceptancePrediction, type AnalysisResult, AnalysisResultSchema, AnalysisStatus, AnalysisStatusSchema, type BusinessReport, CONTEXT_TIER_THRESHOLDS, type CommonASTNode, type ComprehensionDifficulty, type CostConfig, DEFAULT_TOOL_WEIGHTS, type ExportInfo, FRIENDLY_TOOL_NAMES, type GraphData, type GraphEdge, type GraphIssueSeverity, type GraphMetadata, type GraphNode, type ImportInfo, type Issue, IssueSchema, IssueType, IssueTypeSchema, LANGUAGE_EXTENSIONS, Language, type LanguageConfig, type LanguageParser, type Location, LocationSchema, type Metrics, MetricsSchema, type ModelContextTier, ModelTier, ModelTierSchema, type NamingConvention, ParseError, type ParseResult, type ParseStatistics, type ProductivityImpact, type Report, SIZE_ADJUSTED_THRESHOLDS, type ScanOptions, type ScoringConfig, type ScoringResult, Severity, SeveritySchema, type SourceLocation, type SourceRange, type SpokeOutput, SpokeOutputSchema, TOOL_NAME_MAP, type TechnicalValueChain, type TechnicalValueChainSummary, type TokenBudget, ToolName, ToolNameSchema, type ToolScoringOutput, type UnifiedReport, UnifiedReportSchema, calculateOverallScore, formatScore, formatToolScore, generateHTML, getProjectSizeTier, getRating, getRatingDisplay, getRatingWithContext, getRecommendedThreshold, getToolWeight, normalizeToolName, parseWeightString };
|
|
882
|
+
export { type AIReadyConfig, type AcceptancePrediction, type AnalysisResult, AnalysisResultSchema, AnalysisStatus, AnalysisStatusSchema, type BusinessReport, CONTEXT_TIER_THRESHOLDS, type CommonASTNode, type ComprehensionDifficulty, type CostConfig, DEFAULT_TOOL_WEIGHTS, type ExportInfo, FRIENDLY_TOOL_NAMES, type GraphData, type GraphEdge, type GraphIssueSeverity, type GraphMetadata, type GraphNode, type ImportInfo, type Issue, IssueSchema, IssueType, IssueTypeSchema, LANGUAGE_EXTENSIONS, Language, type LanguageConfig, type LanguageParser, type Location, LocationSchema, type Metrics, MetricsSchema, type ModelContextTier, ModelTier, ModelTierSchema, type NamingConvention, ParseError, type ParseResult, type ParseStatistics, type ProductivityImpact, type Report, SIZE_ADJUSTED_THRESHOLDS, type ScanOptions, type ScoringConfig, type ScoringResult, Severity, SeveritySchema, type SourceLocation, type SourceRange, type SpokeOutput, SpokeOutputSchema, type SpokeSummary, SpokeSummarySchema, TOOL_NAME_MAP, type TechnicalValueChain, type TechnicalValueChainSummary, type TokenBudget, ToolName, ToolNameSchema, type ToolScoringOutput, type UnifiedReport, UnifiedReportSchema, calculateOverallScore, formatScore, formatToolScore, generateHTML, getProjectSizeTier, getRating, getRatingDisplay, getRatingWithContext, getRecommendedThreshold, getToolWeight, normalizeToolName, parseWeightString };
|
package/dist/client.js
CHANGED
|
@@ -40,6 +40,7 @@ __export(client_exports, {
|
|
|
40
40
|
Severity: () => Severity,
|
|
41
41
|
SeveritySchema: () => SeveritySchema,
|
|
42
42
|
SpokeOutputSchema: () => SpokeOutputSchema,
|
|
43
|
+
SpokeSummarySchema: () => SpokeSummarySchema,
|
|
43
44
|
TOOL_NAME_MAP: () => TOOL_NAME_MAP,
|
|
44
45
|
ToolName: () => ToolName,
|
|
45
46
|
ToolNameSchema: () => ToolNameSchema,
|
|
@@ -177,13 +178,20 @@ var AnalysisResultSchema = import_zod.z.object({
|
|
|
177
178
|
issues: import_zod.z.array(IssueSchema),
|
|
178
179
|
metrics: MetricsSchema
|
|
179
180
|
});
|
|
181
|
+
var SpokeSummarySchema = import_zod.z.object({
|
|
182
|
+
totalFiles: import_zod.z.number().optional(),
|
|
183
|
+
totalIssues: import_zod.z.number().optional(),
|
|
184
|
+
criticalIssues: import_zod.z.number().optional(),
|
|
185
|
+
majorIssues: import_zod.z.number().optional(),
|
|
186
|
+
score: import_zod.z.number().optional()
|
|
187
|
+
}).catchall(import_zod.z.any());
|
|
180
188
|
var SpokeOutputSchema = import_zod.z.object({
|
|
181
189
|
results: import_zod.z.array(AnalysisResultSchema),
|
|
182
|
-
summary:
|
|
190
|
+
summary: SpokeSummarySchema,
|
|
183
191
|
metadata: import_zod.z.object({
|
|
184
192
|
toolName: import_zod.z.string(),
|
|
185
|
-
version: import_zod.z.string(),
|
|
186
|
-
timestamp: import_zod.z.string()
|
|
193
|
+
version: import_zod.z.string().optional(),
|
|
194
|
+
timestamp: import_zod.z.string().optional()
|
|
187
195
|
}).catchall(import_zod.z.any()).optional()
|
|
188
196
|
});
|
|
189
197
|
var UnifiedReportSchema = import_zod.z.object({
|
|
@@ -616,6 +624,7 @@ function generateHTML(graph) {
|
|
|
616
624
|
Severity,
|
|
617
625
|
SeveritySchema,
|
|
618
626
|
SpokeOutputSchema,
|
|
627
|
+
SpokeSummarySchema,
|
|
619
628
|
TOOL_NAME_MAP,
|
|
620
629
|
ToolName,
|
|
621
630
|
ToolNameSchema,
|
package/dist/client.mjs
CHANGED
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
Severity,
|
|
20
20
|
SeveritySchema,
|
|
21
21
|
SpokeOutputSchema,
|
|
22
|
+
SpokeSummarySchema,
|
|
22
23
|
TOOL_NAME_MAP,
|
|
23
24
|
ToolName,
|
|
24
25
|
ToolNameSchema,
|
|
@@ -35,7 +36,7 @@ import {
|
|
|
35
36
|
getToolWeight,
|
|
36
37
|
normalizeToolName,
|
|
37
38
|
parseWeightString
|
|
38
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-YCA4FTEK.mjs";
|
|
39
40
|
export {
|
|
40
41
|
AnalysisResultSchema,
|
|
41
42
|
AnalysisStatus,
|
|
@@ -57,6 +58,7 @@ export {
|
|
|
57
58
|
Severity,
|
|
58
59
|
SeveritySchema,
|
|
59
60
|
SpokeOutputSchema,
|
|
61
|
+
SpokeSummarySchema,
|
|
60
62
|
TOOL_NAME_MAP,
|
|
61
63
|
ToolName,
|
|
62
64
|
ToolNameSchema,
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ScanOptions, AIReadyConfig, ModelContextTier, CostConfig, TokenBudget, ProductivityImpact,
|
|
2
|
-
export { AnalysisResult, AnalysisResultSchema, AnalysisStatus, AnalysisStatusSchema, BusinessReport, CONTEXT_TIER_THRESHOLDS, CommonASTNode, DEFAULT_TOOL_WEIGHTS, ExportInfo, FRIENDLY_TOOL_NAMES, GraphData, GraphEdge, GraphIssueSeverity, GraphMetadata, GraphNode, ImportInfo, Issue, IssueSchema, IssueType, IssueTypeSchema, LANGUAGE_EXTENSIONS, LanguageConfig, Location, LocationSchema, Metrics, MetricsSchema, ModelTier, ModelTierSchema, ParseError, ParseStatistics, Report, SIZE_ADJUSTED_THRESHOLDS, ScoringConfig, ScoringResult, Severity, SeveritySchema, SourceLocation, SourceRange,
|
|
1
|
+
import { ToolName, ScanOptions, SpokeOutput, ToolScoringOutput, AIReadyConfig, ModelContextTier, CostConfig, TokenBudget, ProductivityImpact, AcceptancePrediction, ComprehensionDifficulty, TechnicalValueChainSummary, TechnicalValueChain, LanguageParser, Language, ParseResult, NamingConvention } from './client.mjs';
|
|
2
|
+
export { AnalysisResult, AnalysisResultSchema, AnalysisStatus, AnalysisStatusSchema, BusinessReport, CONTEXT_TIER_THRESHOLDS, CommonASTNode, DEFAULT_TOOL_WEIGHTS, ExportInfo, FRIENDLY_TOOL_NAMES, GraphData, GraphEdge, GraphIssueSeverity, GraphMetadata, GraphNode, ImportInfo, Issue, IssueSchema, IssueType, IssueTypeSchema, LANGUAGE_EXTENSIONS, LanguageConfig, Location, LocationSchema, Metrics, MetricsSchema, ModelTier, ModelTierSchema, ParseError, ParseStatistics, Report, SIZE_ADJUSTED_THRESHOLDS, ScoringConfig, ScoringResult, Severity, SeveritySchema, SourceLocation, SourceRange, SpokeOutputSchema, SpokeSummary, SpokeSummarySchema, TOOL_NAME_MAP, ToolNameSchema, UnifiedReport, UnifiedReportSchema, calculateOverallScore, formatScore, formatToolScore, generateHTML, getProjectSizeTier, getRating, getRatingDisplay, getRatingWithContext, getRecommendedThreshold, getToolWeight, normalizeToolName, parseWeightString } from './client.mjs';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -8,6 +8,22 @@ import { z } from 'zod';
|
|
|
8
8
|
* changes in spokes don't break the CLI, Platform, or Visualizer.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Tool Provider Interface
|
|
13
|
+
* Every AIReady spoke must implement this interface to be integrated into the CLI registry.
|
|
14
|
+
*/
|
|
15
|
+
interface ToolProvider {
|
|
16
|
+
/** Canonical tool ID */
|
|
17
|
+
id: ToolName;
|
|
18
|
+
/** CLI aliases/shorthand for this tool */
|
|
19
|
+
alias: string[];
|
|
20
|
+
/** Primary analysis logic */
|
|
21
|
+
analyze: (options: ScanOptions) => Promise<SpokeOutput>;
|
|
22
|
+
/** Scoring logic for this tool's output */
|
|
23
|
+
score: (output: SpokeOutput, options: ScanOptions) => ToolScoringOutput;
|
|
24
|
+
/** Optional weight override for this tool */
|
|
25
|
+
defaultWeight?: number;
|
|
26
|
+
}
|
|
11
27
|
/**
|
|
12
28
|
* Validation utility to ensure a spoke's output matches the expected contract.
|
|
13
29
|
* Used in spoke tests to catch breakages early.
|
|
@@ -25,6 +41,41 @@ declare function validateWithSchema<T>(schema: z.ZodSchema<T>, data: any): {
|
|
|
25
41
|
errors?: string[];
|
|
26
42
|
};
|
|
27
43
|
|
|
44
|
+
/**
|
|
45
|
+
* AIReady Tool Registry
|
|
46
|
+
*
|
|
47
|
+
* Central registry for all analysis tools. Decouples the CLI from
|
|
48
|
+
* individual tool packages and allows for easier extension.
|
|
49
|
+
*/
|
|
50
|
+
declare class ToolRegistry {
|
|
51
|
+
private static getProviders;
|
|
52
|
+
static instanceId: number;
|
|
53
|
+
/**
|
|
54
|
+
* Register a new tool provider.
|
|
55
|
+
*/
|
|
56
|
+
static register(provider: ToolProvider): void;
|
|
57
|
+
/**
|
|
58
|
+
* Get a provider by its canonical ID.
|
|
59
|
+
*/
|
|
60
|
+
static get(id: ToolName): ToolProvider | undefined;
|
|
61
|
+
/**
|
|
62
|
+
* Get a provider by name or alias.
|
|
63
|
+
*/
|
|
64
|
+
static find(nameOrAlias: string): ToolProvider | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* Get all registered tool providers.
|
|
67
|
+
*/
|
|
68
|
+
static getAll(): ToolProvider[];
|
|
69
|
+
/**
|
|
70
|
+
* Get all available tool IDs from the ToolName enum.
|
|
71
|
+
*/
|
|
72
|
+
static getAvailableIds(): ToolName[];
|
|
73
|
+
/**
|
|
74
|
+
* Clear the registry (primarily for testing).
|
|
75
|
+
*/
|
|
76
|
+
static clear(): void;
|
|
77
|
+
}
|
|
78
|
+
|
|
28
79
|
declare const DEFAULT_EXCLUDE: string[];
|
|
29
80
|
declare const VAGUE_FILE_NAMES: Set<string>;
|
|
30
81
|
/**
|
|
@@ -800,4 +851,4 @@ declare function getRepoMetadata(directory: string): {
|
|
|
800
851
|
author?: string;
|
|
801
852
|
};
|
|
802
853
|
|
|
803
|
-
export { AIReadyConfig, type ASTNode, AcceptancePrediction, type AgentGroundingScore, type AiSignalClarity, type AiSignalClaritySignal, type CLIOptions, type ChangeAmplificationScore, type CognitiveLoad, ComprehensionDifficulty, type ConceptCohesion, CostConfig, DEFAULT_COST_CONFIG, DEFAULT_EXCLUDE, type DependencyHealthScore, type DocDriftRisk, type ExportWithImports, type FileImport, type FileWithDomain, type KnowledgeConcentrationRisk, Language, LanguageParser, type LoadFactor, MODEL_PRICING_PRESETS, ModelContextTier, type ModelPricingPreset, NamingConvention, ParseResult, ParserFactory, type PatternEntropy, ProductivityImpact, PythonParser, SEVERITY_TIME_ESTIMATES, ScanOptions, type ScoreHistoryEntry, type ScoreTrend, type SemanticDistance, type TechnicalDebtInterest, TechnicalValueChain, TechnicalValueChainSummary, type TestabilityIndex, TokenBudget, ToolScoringOutput, TypeScriptParser, VAGUE_FILE_NAMES, calculateAgentGrounding, calculateAiSignalClarity, calculateBusinessROI, calculateChangeAmplification, calculateCognitiveLoad, calculateComprehensionDifficulty, calculateConceptCohesion, calculateDebtInterest, calculateDependencyHealth, calculateDocDrift, calculateExtendedFutureProofScore, calculateFutureProofScore, calculateImportSimilarity, calculateKnowledgeConcentration, calculateMonthlyCost, calculatePatternEntropy, calculateProductivityImpact, calculateSemanticDistance, calculateTechnicalValueChain, calculateTestabilityIndex, calculateTokenBudget, clearHistory, estimateCostFromBudget, estimateTokens, exportHistory, extractFunctions, extractImports, formatAcceptanceRate, formatCost, formatHours, generateValueChain, getElapsedTime, getFileCommitTimestamps, getFileExtension, getHistorySummary, getLineRangeLastModifiedCached, getModelPreset, getParser, getRepoMetadata, getSafetyIcon, getScoreBar, getSeverityColor, getSupportedLanguages, handleCLIError, handleJSONOutput, isFileSupported, isSourceFile, loadConfig, loadMergedConfig, loadScoreHistory, mergeConfigWithDefaults, parseCode, parseFileExports, predictAcceptanceRate, readFileContent, resolveOutputPath, saveScoreEntry, scanEntries, scanFiles, validateSpokeOutput, validateWithSchema };
|
|
854
|
+
export { AIReadyConfig, type ASTNode, AcceptancePrediction, type AgentGroundingScore, type AiSignalClarity, type AiSignalClaritySignal, type CLIOptions, type ChangeAmplificationScore, type CognitiveLoad, ComprehensionDifficulty, type ConceptCohesion, CostConfig, DEFAULT_COST_CONFIG, DEFAULT_EXCLUDE, type DependencyHealthScore, type DocDriftRisk, type ExportWithImports, type FileImport, type FileWithDomain, type KnowledgeConcentrationRisk, Language, LanguageParser, type LoadFactor, MODEL_PRICING_PRESETS, ModelContextTier, type ModelPricingPreset, NamingConvention, ParseResult, ParserFactory, type PatternEntropy, ProductivityImpact, PythonParser, SEVERITY_TIME_ESTIMATES, ScanOptions, type ScoreHistoryEntry, type ScoreTrend, type SemanticDistance, SpokeOutput, type TechnicalDebtInterest, TechnicalValueChain, TechnicalValueChainSummary, type TestabilityIndex, TokenBudget, ToolName, type ToolProvider, ToolRegistry, ToolScoringOutput, TypeScriptParser, VAGUE_FILE_NAMES, calculateAgentGrounding, calculateAiSignalClarity, calculateBusinessROI, calculateChangeAmplification, calculateCognitiveLoad, calculateComprehensionDifficulty, calculateConceptCohesion, calculateDebtInterest, calculateDependencyHealth, calculateDocDrift, calculateExtendedFutureProofScore, calculateFutureProofScore, calculateImportSimilarity, calculateKnowledgeConcentration, calculateMonthlyCost, calculatePatternEntropy, calculateProductivityImpact, calculateSemanticDistance, calculateTechnicalValueChain, calculateTestabilityIndex, calculateTokenBudget, clearHistory, estimateCostFromBudget, estimateTokens, exportHistory, extractFunctions, extractImports, formatAcceptanceRate, formatCost, formatHours, generateValueChain, getElapsedTime, getFileCommitTimestamps, getFileExtension, getHistorySummary, getLineRangeLastModifiedCached, getModelPreset, getParser, getRepoMetadata, getSafetyIcon, getScoreBar, getSeverityColor, getSupportedLanguages, handleCLIError, handleJSONOutput, isFileSupported, isSourceFile, loadConfig, loadMergedConfig, loadScoreHistory, mergeConfigWithDefaults, parseCode, parseFileExports, predictAcceptanceRate, readFileContent, resolveOutputPath, saveScoreEntry, scanEntries, scanFiles, validateSpokeOutput, validateWithSchema };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ScanOptions, AIReadyConfig, ModelContextTier, CostConfig, TokenBudget, ProductivityImpact,
|
|
2
|
-
export { AnalysisResult, AnalysisResultSchema, AnalysisStatus, AnalysisStatusSchema, BusinessReport, CONTEXT_TIER_THRESHOLDS, CommonASTNode, DEFAULT_TOOL_WEIGHTS, ExportInfo, FRIENDLY_TOOL_NAMES, GraphData, GraphEdge, GraphIssueSeverity, GraphMetadata, GraphNode, ImportInfo, Issue, IssueSchema, IssueType, IssueTypeSchema, LANGUAGE_EXTENSIONS, LanguageConfig, Location, LocationSchema, Metrics, MetricsSchema, ModelTier, ModelTierSchema, ParseError, ParseStatistics, Report, SIZE_ADJUSTED_THRESHOLDS, ScoringConfig, ScoringResult, Severity, SeveritySchema, SourceLocation, SourceRange,
|
|
1
|
+
import { ToolName, ScanOptions, SpokeOutput, ToolScoringOutput, AIReadyConfig, ModelContextTier, CostConfig, TokenBudget, ProductivityImpact, AcceptancePrediction, ComprehensionDifficulty, TechnicalValueChainSummary, TechnicalValueChain, LanguageParser, Language, ParseResult, NamingConvention } from './client.js';
|
|
2
|
+
export { AnalysisResult, AnalysisResultSchema, AnalysisStatus, AnalysisStatusSchema, BusinessReport, CONTEXT_TIER_THRESHOLDS, CommonASTNode, DEFAULT_TOOL_WEIGHTS, ExportInfo, FRIENDLY_TOOL_NAMES, GraphData, GraphEdge, GraphIssueSeverity, GraphMetadata, GraphNode, ImportInfo, Issue, IssueSchema, IssueType, IssueTypeSchema, LANGUAGE_EXTENSIONS, LanguageConfig, Location, LocationSchema, Metrics, MetricsSchema, ModelTier, ModelTierSchema, ParseError, ParseStatistics, Report, SIZE_ADJUSTED_THRESHOLDS, ScoringConfig, ScoringResult, Severity, SeveritySchema, SourceLocation, SourceRange, SpokeOutputSchema, SpokeSummary, SpokeSummarySchema, TOOL_NAME_MAP, ToolNameSchema, UnifiedReport, UnifiedReportSchema, calculateOverallScore, formatScore, formatToolScore, generateHTML, getProjectSizeTier, getRating, getRatingDisplay, getRatingWithContext, getRecommendedThreshold, getToolWeight, normalizeToolName, parseWeightString } from './client.js';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -8,6 +8,22 @@ import { z } from 'zod';
|
|
|
8
8
|
* changes in spokes don't break the CLI, Platform, or Visualizer.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Tool Provider Interface
|
|
13
|
+
* Every AIReady spoke must implement this interface to be integrated into the CLI registry.
|
|
14
|
+
*/
|
|
15
|
+
interface ToolProvider {
|
|
16
|
+
/** Canonical tool ID */
|
|
17
|
+
id: ToolName;
|
|
18
|
+
/** CLI aliases/shorthand for this tool */
|
|
19
|
+
alias: string[];
|
|
20
|
+
/** Primary analysis logic */
|
|
21
|
+
analyze: (options: ScanOptions) => Promise<SpokeOutput>;
|
|
22
|
+
/** Scoring logic for this tool's output */
|
|
23
|
+
score: (output: SpokeOutput, options: ScanOptions) => ToolScoringOutput;
|
|
24
|
+
/** Optional weight override for this tool */
|
|
25
|
+
defaultWeight?: number;
|
|
26
|
+
}
|
|
11
27
|
/**
|
|
12
28
|
* Validation utility to ensure a spoke's output matches the expected contract.
|
|
13
29
|
* Used in spoke tests to catch breakages early.
|
|
@@ -25,6 +41,41 @@ declare function validateWithSchema<T>(schema: z.ZodSchema<T>, data: any): {
|
|
|
25
41
|
errors?: string[];
|
|
26
42
|
};
|
|
27
43
|
|
|
44
|
+
/**
|
|
45
|
+
* AIReady Tool Registry
|
|
46
|
+
*
|
|
47
|
+
* Central registry for all analysis tools. Decouples the CLI from
|
|
48
|
+
* individual tool packages and allows for easier extension.
|
|
49
|
+
*/
|
|
50
|
+
declare class ToolRegistry {
|
|
51
|
+
private static getProviders;
|
|
52
|
+
static instanceId: number;
|
|
53
|
+
/**
|
|
54
|
+
* Register a new tool provider.
|
|
55
|
+
*/
|
|
56
|
+
static register(provider: ToolProvider): void;
|
|
57
|
+
/**
|
|
58
|
+
* Get a provider by its canonical ID.
|
|
59
|
+
*/
|
|
60
|
+
static get(id: ToolName): ToolProvider | undefined;
|
|
61
|
+
/**
|
|
62
|
+
* Get a provider by name or alias.
|
|
63
|
+
*/
|
|
64
|
+
static find(nameOrAlias: string): ToolProvider | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* Get all registered tool providers.
|
|
67
|
+
*/
|
|
68
|
+
static getAll(): ToolProvider[];
|
|
69
|
+
/**
|
|
70
|
+
* Get all available tool IDs from the ToolName enum.
|
|
71
|
+
*/
|
|
72
|
+
static getAvailableIds(): ToolName[];
|
|
73
|
+
/**
|
|
74
|
+
* Clear the registry (primarily for testing).
|
|
75
|
+
*/
|
|
76
|
+
static clear(): void;
|
|
77
|
+
}
|
|
78
|
+
|
|
28
79
|
declare const DEFAULT_EXCLUDE: string[];
|
|
29
80
|
declare const VAGUE_FILE_NAMES: Set<string>;
|
|
30
81
|
/**
|
|
@@ -800,4 +851,4 @@ declare function getRepoMetadata(directory: string): {
|
|
|
800
851
|
author?: string;
|
|
801
852
|
};
|
|
802
853
|
|
|
803
|
-
export { AIReadyConfig, type ASTNode, AcceptancePrediction, type AgentGroundingScore, type AiSignalClarity, type AiSignalClaritySignal, type CLIOptions, type ChangeAmplificationScore, type CognitiveLoad, ComprehensionDifficulty, type ConceptCohesion, CostConfig, DEFAULT_COST_CONFIG, DEFAULT_EXCLUDE, type DependencyHealthScore, type DocDriftRisk, type ExportWithImports, type FileImport, type FileWithDomain, type KnowledgeConcentrationRisk, Language, LanguageParser, type LoadFactor, MODEL_PRICING_PRESETS, ModelContextTier, type ModelPricingPreset, NamingConvention, ParseResult, ParserFactory, type PatternEntropy, ProductivityImpact, PythonParser, SEVERITY_TIME_ESTIMATES, ScanOptions, type ScoreHistoryEntry, type ScoreTrend, type SemanticDistance, type TechnicalDebtInterest, TechnicalValueChain, TechnicalValueChainSummary, type TestabilityIndex, TokenBudget, ToolScoringOutput, TypeScriptParser, VAGUE_FILE_NAMES, calculateAgentGrounding, calculateAiSignalClarity, calculateBusinessROI, calculateChangeAmplification, calculateCognitiveLoad, calculateComprehensionDifficulty, calculateConceptCohesion, calculateDebtInterest, calculateDependencyHealth, calculateDocDrift, calculateExtendedFutureProofScore, calculateFutureProofScore, calculateImportSimilarity, calculateKnowledgeConcentration, calculateMonthlyCost, calculatePatternEntropy, calculateProductivityImpact, calculateSemanticDistance, calculateTechnicalValueChain, calculateTestabilityIndex, calculateTokenBudget, clearHistory, estimateCostFromBudget, estimateTokens, exportHistory, extractFunctions, extractImports, formatAcceptanceRate, formatCost, formatHours, generateValueChain, getElapsedTime, getFileCommitTimestamps, getFileExtension, getHistorySummary, getLineRangeLastModifiedCached, getModelPreset, getParser, getRepoMetadata, getSafetyIcon, getScoreBar, getSeverityColor, getSupportedLanguages, handleCLIError, handleJSONOutput, isFileSupported, isSourceFile, loadConfig, loadMergedConfig, loadScoreHistory, mergeConfigWithDefaults, parseCode, parseFileExports, predictAcceptanceRate, readFileContent, resolveOutputPath, saveScoreEntry, scanEntries, scanFiles, validateSpokeOutput, validateWithSchema };
|
|
854
|
+
export { AIReadyConfig, type ASTNode, AcceptancePrediction, type AgentGroundingScore, type AiSignalClarity, type AiSignalClaritySignal, type CLIOptions, type ChangeAmplificationScore, type CognitiveLoad, ComprehensionDifficulty, type ConceptCohesion, CostConfig, DEFAULT_COST_CONFIG, DEFAULT_EXCLUDE, type DependencyHealthScore, type DocDriftRisk, type ExportWithImports, type FileImport, type FileWithDomain, type KnowledgeConcentrationRisk, Language, LanguageParser, type LoadFactor, MODEL_PRICING_PRESETS, ModelContextTier, type ModelPricingPreset, NamingConvention, ParseResult, ParserFactory, type PatternEntropy, ProductivityImpact, PythonParser, SEVERITY_TIME_ESTIMATES, ScanOptions, type ScoreHistoryEntry, type ScoreTrend, type SemanticDistance, SpokeOutput, type TechnicalDebtInterest, TechnicalValueChain, TechnicalValueChainSummary, type TestabilityIndex, TokenBudget, ToolName, type ToolProvider, ToolRegistry, ToolScoringOutput, TypeScriptParser, VAGUE_FILE_NAMES, calculateAgentGrounding, calculateAiSignalClarity, calculateBusinessROI, calculateChangeAmplification, calculateCognitiveLoad, calculateComprehensionDifficulty, calculateConceptCohesion, calculateDebtInterest, calculateDependencyHealth, calculateDocDrift, calculateExtendedFutureProofScore, calculateFutureProofScore, calculateImportSimilarity, calculateKnowledgeConcentration, calculateMonthlyCost, calculatePatternEntropy, calculateProductivityImpact, calculateSemanticDistance, calculateTechnicalValueChain, calculateTestabilityIndex, calculateTokenBudget, clearHistory, estimateCostFromBudget, estimateTokens, exportHistory, extractFunctions, extractImports, formatAcceptanceRate, formatCost, formatHours, generateValueChain, getElapsedTime, getFileCommitTimestamps, getFileExtension, getHistorySummary, getLineRangeLastModifiedCached, getModelPreset, getParser, getRepoMetadata, getSafetyIcon, getScoreBar, getSeverityColor, getSupportedLanguages, handleCLIError, handleJSONOutput, isFileSupported, isSourceFile, loadConfig, loadMergedConfig, loadScoreHistory, mergeConfigWithDefaults, parseCode, parseFileExports, predictAcceptanceRate, readFileContent, resolveOutputPath, saveScoreEntry, scanEntries, scanFiles, validateSpokeOutput, validateWithSchema };
|
package/dist/index.js
CHANGED
|
@@ -56,9 +56,11 @@ __export(index_exports, {
|
|
|
56
56
|
Severity: () => Severity,
|
|
57
57
|
SeveritySchema: () => SeveritySchema,
|
|
58
58
|
SpokeOutputSchema: () => SpokeOutputSchema,
|
|
59
|
+
SpokeSummarySchema: () => SpokeSummarySchema,
|
|
59
60
|
TOOL_NAME_MAP: () => TOOL_NAME_MAP,
|
|
60
61
|
ToolName: () => ToolName,
|
|
61
62
|
ToolNameSchema: () => ToolNameSchema,
|
|
63
|
+
ToolRegistry: () => ToolRegistry,
|
|
62
64
|
TypeScriptParser: () => TypeScriptParser,
|
|
63
65
|
UnifiedReportSchema: () => UnifiedReportSchema,
|
|
64
66
|
VAGUE_FILE_NAMES: () => VAGUE_FILE_NAMES,
|
|
@@ -256,13 +258,20 @@ var AnalysisResultSchema = import_zod.z.object({
|
|
|
256
258
|
issues: import_zod.z.array(IssueSchema),
|
|
257
259
|
metrics: MetricsSchema
|
|
258
260
|
});
|
|
261
|
+
var SpokeSummarySchema = import_zod.z.object({
|
|
262
|
+
totalFiles: import_zod.z.number().optional(),
|
|
263
|
+
totalIssues: import_zod.z.number().optional(),
|
|
264
|
+
criticalIssues: import_zod.z.number().optional(),
|
|
265
|
+
majorIssues: import_zod.z.number().optional(),
|
|
266
|
+
score: import_zod.z.number().optional()
|
|
267
|
+
}).catchall(import_zod.z.any());
|
|
259
268
|
var SpokeOutputSchema = import_zod.z.object({
|
|
260
269
|
results: import_zod.z.array(AnalysisResultSchema),
|
|
261
|
-
summary:
|
|
270
|
+
summary: SpokeSummarySchema,
|
|
262
271
|
metadata: import_zod.z.object({
|
|
263
272
|
toolName: import_zod.z.string(),
|
|
264
|
-
version: import_zod.z.string(),
|
|
265
|
-
timestamp: import_zod.z.string()
|
|
273
|
+
version: import_zod.z.string().optional(),
|
|
274
|
+
timestamp: import_zod.z.string().optional()
|
|
266
275
|
}).catchall(import_zod.z.any()).optional()
|
|
267
276
|
});
|
|
268
277
|
var UnifiedReportSchema = import_zod.z.object({
|
|
@@ -375,6 +384,65 @@ function validateWithSchema(schema, data) {
|
|
|
375
384
|
};
|
|
376
385
|
}
|
|
377
386
|
|
|
387
|
+
// src/registry.ts
|
|
388
|
+
var ToolRegistry = class {
|
|
389
|
+
static getProviders() {
|
|
390
|
+
const g = globalThis;
|
|
391
|
+
if (!g.__AIRE_TOOL_REGISTRY__) {
|
|
392
|
+
g.__AIRE_TOOL_REGISTRY__ = /* @__PURE__ */ new Map();
|
|
393
|
+
}
|
|
394
|
+
return g.__AIRE_TOOL_REGISTRY__;
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Register a new tool provider.
|
|
398
|
+
*/
|
|
399
|
+
static register(provider) {
|
|
400
|
+
console.log(
|
|
401
|
+
`[ToolRegistry#${this.instanceId}] Registering tool: ${provider.id} (${provider.alias.join(", ")})`
|
|
402
|
+
);
|
|
403
|
+
this.getProviders().set(provider.id, provider);
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Get a provider by its canonical ID.
|
|
407
|
+
*/
|
|
408
|
+
static get(id) {
|
|
409
|
+
return this.getProviders().get(id);
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Get a provider by name or alias.
|
|
413
|
+
*/
|
|
414
|
+
static find(nameOrAlias) {
|
|
415
|
+
const providers = this.getProviders();
|
|
416
|
+
const exact = providers.get(nameOrAlias);
|
|
417
|
+
if (exact) return exact;
|
|
418
|
+
for (const p of providers.values()) {
|
|
419
|
+
if (p.alias.includes(nameOrAlias)) return p;
|
|
420
|
+
}
|
|
421
|
+
return void 0;
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Get all registered tool providers.
|
|
425
|
+
*/
|
|
426
|
+
static getAll() {
|
|
427
|
+
return Array.from(this.getProviders().values());
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Get all available tool IDs from the ToolName enum.
|
|
431
|
+
*/
|
|
432
|
+
static getAvailableIds() {
|
|
433
|
+
return Object.values(ToolName).filter(
|
|
434
|
+
(v) => typeof v === "string"
|
|
435
|
+
);
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Clear the registry (primarily for testing).
|
|
439
|
+
*/
|
|
440
|
+
static clear() {
|
|
441
|
+
this.getProviders().clear();
|
|
442
|
+
}
|
|
443
|
+
};
|
|
444
|
+
ToolRegistry.instanceId = globalThis.Math.random();
|
|
445
|
+
|
|
378
446
|
// src/utils/file-scanner.ts
|
|
379
447
|
var import_glob = require("glob");
|
|
380
448
|
var import_promises = require("fs/promises");
|
|
@@ -467,7 +535,13 @@ async function scanFiles(options) {
|
|
|
467
535
|
ignoreFromFile = [];
|
|
468
536
|
}
|
|
469
537
|
}
|
|
470
|
-
const TEST_PATTERNS = [
|
|
538
|
+
const TEST_PATTERNS = [
|
|
539
|
+
"**/*.test.*",
|
|
540
|
+
"**/*.spec.*",
|
|
541
|
+
"**/__tests__/**",
|
|
542
|
+
"**/test/**",
|
|
543
|
+
"**/tests/**"
|
|
544
|
+
];
|
|
471
545
|
const baseExclude = options.includeTests ? DEFAULT_EXCLUDE.filter((p) => !TEST_PATTERNS.includes(p)) : DEFAULT_EXCLUDE;
|
|
472
546
|
const finalExclude = [
|
|
473
547
|
.../* @__PURE__ */ new Set([...exclude || [], ...ignoreFromFile, ...baseExclude])
|
|
@@ -488,12 +562,19 @@ async function scanFiles(options) {
|
|
|
488
562
|
for (const gitignorePath of gitignoreFiles) {
|
|
489
563
|
const gitTxt = await (0, import_promises.readFile)(gitignorePath, "utf-8");
|
|
490
564
|
const gitignoreDir = (0, import_path.dirname)(gitignorePath);
|
|
491
|
-
const relativePrefix = (0, import_path.relative)(rootDir || ".", gitignoreDir).replace(
|
|
565
|
+
const relativePrefix = (0, import_path.relative)(rootDir || ".", gitignoreDir).replace(
|
|
566
|
+
/\\/g,
|
|
567
|
+
"/"
|
|
568
|
+
);
|
|
492
569
|
const patterns = gitTxt.split(/\r?\n/).map((s) => s.trim()).filter(Boolean).filter((l) => !l.startsWith("#"));
|
|
493
570
|
if (relativePrefix === "." || relativePrefix === "") {
|
|
494
571
|
ig.add(patterns);
|
|
495
572
|
} else {
|
|
496
|
-
ig.add(
|
|
573
|
+
ig.add(
|
|
574
|
+
patterns.map(
|
|
575
|
+
(p) => p.startsWith("/") ? `${relativePrefix}${p}` : `${relativePrefix}/**/${p}`
|
|
576
|
+
)
|
|
577
|
+
);
|
|
497
578
|
}
|
|
498
579
|
}
|
|
499
580
|
const filtered = files.filter((f) => {
|
|
@@ -521,9 +602,17 @@ async function scanEntries(options) {
|
|
|
521
602
|
ignoreFromFile = [];
|
|
522
603
|
}
|
|
523
604
|
}
|
|
524
|
-
const TEST_PATTERNS = [
|
|
605
|
+
const TEST_PATTERNS = [
|
|
606
|
+
"**/*.test.*",
|
|
607
|
+
"**/*.spec.*",
|
|
608
|
+
"**/__tests__/**",
|
|
609
|
+
"**/test/**",
|
|
610
|
+
"**/tests/**"
|
|
611
|
+
];
|
|
525
612
|
const baseExclude = includeTests ? DEFAULT_EXCLUDE.filter((p) => !TEST_PATTERNS.includes(p)) : DEFAULT_EXCLUDE;
|
|
526
|
-
const finalExclude = [
|
|
613
|
+
const finalExclude = [
|
|
614
|
+
.../* @__PURE__ */ new Set([...exclude || [], ...ignoreFromFile, ...baseExclude])
|
|
615
|
+
];
|
|
527
616
|
const dirs = await (0, import_glob.glob)("**/", {
|
|
528
617
|
cwd: rootDir,
|
|
529
618
|
ignore: finalExclude,
|
|
@@ -539,16 +628,23 @@ async function scanEntries(options) {
|
|
|
539
628
|
for (const gitignorePath of gitignoreFiles) {
|
|
540
629
|
const gitTxt = await (0, import_promises.readFile)(gitignorePath, "utf-8");
|
|
541
630
|
const gitignoreDir = (0, import_path.dirname)(gitignorePath);
|
|
542
|
-
const relativePrefix = (0, import_path.relative)(rootDir || ".", gitignoreDir).replace(
|
|
631
|
+
const relativePrefix = (0, import_path.relative)(rootDir || ".", gitignoreDir).replace(
|
|
632
|
+
/\\/g,
|
|
633
|
+
"/"
|
|
634
|
+
);
|
|
543
635
|
const patterns = gitTxt.split(/\r?\n/).map((s) => s.trim()).filter(Boolean).filter((l) => !l.startsWith("#"));
|
|
544
636
|
if (relativePrefix === "." || relativePrefix === "") {
|
|
545
637
|
ig.add(patterns);
|
|
546
638
|
} else {
|
|
547
|
-
ig.add(
|
|
639
|
+
ig.add(
|
|
640
|
+
patterns.map(
|
|
641
|
+
(p) => p.startsWith("/") ? `${relativePrefix}${p}` : `${relativePrefix}/**/${p}`
|
|
642
|
+
)
|
|
643
|
+
);
|
|
548
644
|
}
|
|
549
645
|
}
|
|
550
646
|
const filteredDirs = dirs.filter((d) => {
|
|
551
|
-
|
|
647
|
+
const rel = (0, import_path.relative)(rootDir || ".", d).replace(/\\/g, "/").replace(/\/$/, "");
|
|
552
648
|
if (rel === "") return true;
|
|
553
649
|
return !ig.ignores(rel);
|
|
554
650
|
});
|
|
@@ -2844,7 +2940,7 @@ function calculateChangeAmplification(params) {
|
|
|
2844
2940
|
const hotspots = files.map((f) => ({ ...f, amplificationFactor: f.fanOut + f.fanIn * 0.5 })).sort((a, b) => b.amplificationFactor - a.amplificationFactor);
|
|
2845
2941
|
const maxAmplification = hotspots[0].amplificationFactor;
|
|
2846
2942
|
const avgAmplification = hotspots.reduce((sum, h) => sum + h.amplificationFactor, 0) / hotspots.length;
|
|
2847
|
-
|
|
2943
|
+
const score = Math.max(
|
|
2848
2944
|
0,
|
|
2849
2945
|
Math.min(
|
|
2850
2946
|
100,
|
|
@@ -3190,9 +3286,11 @@ function getRepoMetadata(directory) {
|
|
|
3190
3286
|
Severity,
|
|
3191
3287
|
SeveritySchema,
|
|
3192
3288
|
SpokeOutputSchema,
|
|
3289
|
+
SpokeSummarySchema,
|
|
3193
3290
|
TOOL_NAME_MAP,
|
|
3194
3291
|
ToolName,
|
|
3195
3292
|
ToolNameSchema,
|
|
3293
|
+
ToolRegistry,
|
|
3196
3294
|
TypeScriptParser,
|
|
3197
3295
|
UnifiedReportSchema,
|
|
3198
3296
|
VAGUE_FILE_NAMES,
|
package/dist/index.mjs
CHANGED
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
Severity,
|
|
20
20
|
SeveritySchema,
|
|
21
21
|
SpokeOutputSchema,
|
|
22
|
+
SpokeSummarySchema,
|
|
22
23
|
TOOL_NAME_MAP,
|
|
23
24
|
ToolName,
|
|
24
25
|
ToolNameSchema,
|
|
@@ -35,7 +36,7 @@ import {
|
|
|
35
36
|
getToolWeight,
|
|
36
37
|
normalizeToolName,
|
|
37
38
|
parseWeightString
|
|
38
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-YCA4FTEK.mjs";
|
|
39
40
|
|
|
40
41
|
// src/types/contract.ts
|
|
41
42
|
function validateSpokeOutput(toolName, output) {
|
|
@@ -95,6 +96,65 @@ function validateWithSchema(schema, data) {
|
|
|
95
96
|
};
|
|
96
97
|
}
|
|
97
98
|
|
|
99
|
+
// src/registry.ts
|
|
100
|
+
var ToolRegistry = class {
|
|
101
|
+
static getProviders() {
|
|
102
|
+
const g = globalThis;
|
|
103
|
+
if (!g.__AIRE_TOOL_REGISTRY__) {
|
|
104
|
+
g.__AIRE_TOOL_REGISTRY__ = /* @__PURE__ */ new Map();
|
|
105
|
+
}
|
|
106
|
+
return g.__AIRE_TOOL_REGISTRY__;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Register a new tool provider.
|
|
110
|
+
*/
|
|
111
|
+
static register(provider) {
|
|
112
|
+
console.log(
|
|
113
|
+
`[ToolRegistry#${this.instanceId}] Registering tool: ${provider.id} (${provider.alias.join(", ")})`
|
|
114
|
+
);
|
|
115
|
+
this.getProviders().set(provider.id, provider);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Get a provider by its canonical ID.
|
|
119
|
+
*/
|
|
120
|
+
static get(id) {
|
|
121
|
+
return this.getProviders().get(id);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Get a provider by name or alias.
|
|
125
|
+
*/
|
|
126
|
+
static find(nameOrAlias) {
|
|
127
|
+
const providers = this.getProviders();
|
|
128
|
+
const exact = providers.get(nameOrAlias);
|
|
129
|
+
if (exact) return exact;
|
|
130
|
+
for (const p of providers.values()) {
|
|
131
|
+
if (p.alias.includes(nameOrAlias)) return p;
|
|
132
|
+
}
|
|
133
|
+
return void 0;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Get all registered tool providers.
|
|
137
|
+
*/
|
|
138
|
+
static getAll() {
|
|
139
|
+
return Array.from(this.getProviders().values());
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Get all available tool IDs from the ToolName enum.
|
|
143
|
+
*/
|
|
144
|
+
static getAvailableIds() {
|
|
145
|
+
return Object.values(ToolName).filter(
|
|
146
|
+
(v) => typeof v === "string"
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Clear the registry (primarily for testing).
|
|
151
|
+
*/
|
|
152
|
+
static clear() {
|
|
153
|
+
this.getProviders().clear();
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
ToolRegistry.instanceId = globalThis.Math.random();
|
|
157
|
+
|
|
98
158
|
// src/utils/file-scanner.ts
|
|
99
159
|
import { glob } from "glob";
|
|
100
160
|
import { readFile } from "fs/promises";
|
|
@@ -187,7 +247,13 @@ async function scanFiles(options) {
|
|
|
187
247
|
ignoreFromFile = [];
|
|
188
248
|
}
|
|
189
249
|
}
|
|
190
|
-
const TEST_PATTERNS = [
|
|
250
|
+
const TEST_PATTERNS = [
|
|
251
|
+
"**/*.test.*",
|
|
252
|
+
"**/*.spec.*",
|
|
253
|
+
"**/__tests__/**",
|
|
254
|
+
"**/test/**",
|
|
255
|
+
"**/tests/**"
|
|
256
|
+
];
|
|
191
257
|
const baseExclude = options.includeTests ? DEFAULT_EXCLUDE.filter((p) => !TEST_PATTERNS.includes(p)) : DEFAULT_EXCLUDE;
|
|
192
258
|
const finalExclude = [
|
|
193
259
|
.../* @__PURE__ */ new Set([...exclude || [], ...ignoreFromFile, ...baseExclude])
|
|
@@ -208,12 +274,19 @@ async function scanFiles(options) {
|
|
|
208
274
|
for (const gitignorePath of gitignoreFiles) {
|
|
209
275
|
const gitTxt = await readFile(gitignorePath, "utf-8");
|
|
210
276
|
const gitignoreDir = dirname(gitignorePath);
|
|
211
|
-
const relativePrefix = relative(rootDir || ".", gitignoreDir).replace(
|
|
277
|
+
const relativePrefix = relative(rootDir || ".", gitignoreDir).replace(
|
|
278
|
+
/\\/g,
|
|
279
|
+
"/"
|
|
280
|
+
);
|
|
212
281
|
const patterns = gitTxt.split(/\r?\n/).map((s) => s.trim()).filter(Boolean).filter((l) => !l.startsWith("#"));
|
|
213
282
|
if (relativePrefix === "." || relativePrefix === "") {
|
|
214
283
|
ig.add(patterns);
|
|
215
284
|
} else {
|
|
216
|
-
ig.add(
|
|
285
|
+
ig.add(
|
|
286
|
+
patterns.map(
|
|
287
|
+
(p) => p.startsWith("/") ? `${relativePrefix}${p}` : `${relativePrefix}/**/${p}`
|
|
288
|
+
)
|
|
289
|
+
);
|
|
217
290
|
}
|
|
218
291
|
}
|
|
219
292
|
const filtered = files.filter((f) => {
|
|
@@ -241,9 +314,17 @@ async function scanEntries(options) {
|
|
|
241
314
|
ignoreFromFile = [];
|
|
242
315
|
}
|
|
243
316
|
}
|
|
244
|
-
const TEST_PATTERNS = [
|
|
317
|
+
const TEST_PATTERNS = [
|
|
318
|
+
"**/*.test.*",
|
|
319
|
+
"**/*.spec.*",
|
|
320
|
+
"**/__tests__/**",
|
|
321
|
+
"**/test/**",
|
|
322
|
+
"**/tests/**"
|
|
323
|
+
];
|
|
245
324
|
const baseExclude = includeTests ? DEFAULT_EXCLUDE.filter((p) => !TEST_PATTERNS.includes(p)) : DEFAULT_EXCLUDE;
|
|
246
|
-
const finalExclude = [
|
|
325
|
+
const finalExclude = [
|
|
326
|
+
.../* @__PURE__ */ new Set([...exclude || [], ...ignoreFromFile, ...baseExclude])
|
|
327
|
+
];
|
|
247
328
|
const dirs = await glob("**/", {
|
|
248
329
|
cwd: rootDir,
|
|
249
330
|
ignore: finalExclude,
|
|
@@ -259,16 +340,23 @@ async function scanEntries(options) {
|
|
|
259
340
|
for (const gitignorePath of gitignoreFiles) {
|
|
260
341
|
const gitTxt = await readFile(gitignorePath, "utf-8");
|
|
261
342
|
const gitignoreDir = dirname(gitignorePath);
|
|
262
|
-
const relativePrefix = relative(rootDir || ".", gitignoreDir).replace(
|
|
343
|
+
const relativePrefix = relative(rootDir || ".", gitignoreDir).replace(
|
|
344
|
+
/\\/g,
|
|
345
|
+
"/"
|
|
346
|
+
);
|
|
263
347
|
const patterns = gitTxt.split(/\r?\n/).map((s) => s.trim()).filter(Boolean).filter((l) => !l.startsWith("#"));
|
|
264
348
|
if (relativePrefix === "." || relativePrefix === "") {
|
|
265
349
|
ig.add(patterns);
|
|
266
350
|
} else {
|
|
267
|
-
ig.add(
|
|
351
|
+
ig.add(
|
|
352
|
+
patterns.map(
|
|
353
|
+
(p) => p.startsWith("/") ? `${relativePrefix}${p}` : `${relativePrefix}/**/${p}`
|
|
354
|
+
)
|
|
355
|
+
);
|
|
268
356
|
}
|
|
269
357
|
}
|
|
270
358
|
const filteredDirs = dirs.filter((d) => {
|
|
271
|
-
|
|
359
|
+
const rel = relative(rootDir || ".", d).replace(/\\/g, "/").replace(/\/$/, "");
|
|
272
360
|
if (rel === "") return true;
|
|
273
361
|
return !ig.ignores(rel);
|
|
274
362
|
});
|
|
@@ -2207,7 +2295,7 @@ function calculateChangeAmplification(params) {
|
|
|
2207
2295
|
const hotspots = files.map((f) => ({ ...f, amplificationFactor: f.fanOut + f.fanIn * 0.5 })).sort((a, b) => b.amplificationFactor - a.amplificationFactor);
|
|
2208
2296
|
const maxAmplification = hotspots[0].amplificationFactor;
|
|
2209
2297
|
const avgAmplification = hotspots.reduce((sum, h) => sum + h.amplificationFactor, 0) / hotspots.length;
|
|
2210
|
-
|
|
2298
|
+
const score = Math.max(
|
|
2211
2299
|
0,
|
|
2212
2300
|
Math.min(
|
|
2213
2301
|
100,
|
|
@@ -2552,9 +2640,11 @@ export {
|
|
|
2552
2640
|
Severity,
|
|
2553
2641
|
SeveritySchema,
|
|
2554
2642
|
SpokeOutputSchema,
|
|
2643
|
+
SpokeSummarySchema,
|
|
2555
2644
|
TOOL_NAME_MAP,
|
|
2556
2645
|
ToolName,
|
|
2557
2646
|
ToolNameSchema,
|
|
2647
|
+
ToolRegistry,
|
|
2558
2648
|
TypeScriptParser,
|
|
2559
2649
|
UnifiedReportSchema,
|
|
2560
2650
|
VAGUE_FILE_NAMES,
|