@aiready/cli 0.15.6 → 0.15.7
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-5SXMJSUZ.mjs +332 -0
- package/dist/chunk-OLJA25SP.mjs +344 -0
- package/dist/cli.js +72 -19
- package/dist/cli.mjs +54 -17
- package/dist/index.js +19 -3
- package/dist/index.mjs +1 -1
- package/package.json +13 -13
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
// src/orchestrator.ts
|
|
9
|
+
import {
|
|
10
|
+
ToolRegistry,
|
|
11
|
+
ToolName,
|
|
12
|
+
initializeParsers,
|
|
13
|
+
GLOBAL_INFRA_OPTIONS,
|
|
14
|
+
COMMON_FINE_TUNING_OPTIONS
|
|
15
|
+
} from "@aiready/core";
|
|
16
|
+
var TOOL_PACKAGE_MAP = {
|
|
17
|
+
[ToolName.PatternDetect]: "@aiready/pattern-detect",
|
|
18
|
+
[ToolName.ContextAnalyzer]: "@aiready/context-analyzer",
|
|
19
|
+
[ToolName.NamingConsistency]: "@aiready/consistency",
|
|
20
|
+
[ToolName.AiSignalClarity]: "@aiready/ai-signal-clarity",
|
|
21
|
+
[ToolName.AgentGrounding]: "@aiready/agent-grounding",
|
|
22
|
+
[ToolName.TestabilityIndex]: "@aiready/testability",
|
|
23
|
+
[ToolName.DocDrift]: "@aiready/doc-drift",
|
|
24
|
+
[ToolName.DependencyHealth]: "@aiready/deps",
|
|
25
|
+
[ToolName.ChangeAmplification]: "@aiready/change-amplification",
|
|
26
|
+
[ToolName.ContractEnforcement]: "@aiready/contract-enforcement",
|
|
27
|
+
// Aliases handled by registry
|
|
28
|
+
patterns: "@aiready/pattern-detect",
|
|
29
|
+
duplicates: "@aiready/pattern-detect",
|
|
30
|
+
context: "@aiready/context-analyzer",
|
|
31
|
+
fragmentation: "@aiready/context-analyzer",
|
|
32
|
+
consistency: "@aiready/consistency",
|
|
33
|
+
"ai-signal": "@aiready/ai-signal-clarity",
|
|
34
|
+
grounding: "@aiready/agent-grounding",
|
|
35
|
+
testability: "@aiready/testability",
|
|
36
|
+
"deps-health": "@aiready/deps",
|
|
37
|
+
"change-amp": "@aiready/change-amplification",
|
|
38
|
+
contract: "@aiready/contract-enforcement"
|
|
39
|
+
};
|
|
40
|
+
var UnifiedOrchestrator = class {
|
|
41
|
+
/**
|
|
42
|
+
* Initialize orchestrator with a tool registry.
|
|
43
|
+
* Injection pattern helps with testability and AI readiness score.
|
|
44
|
+
*/
|
|
45
|
+
constructor(registry = ToolRegistry) {
|
|
46
|
+
this.registry = registry;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Deeply sanitizes a configuration object for reporting.
|
|
50
|
+
* Strips internal infrastructure keys to prevent AI context clutter.
|
|
51
|
+
*/
|
|
52
|
+
sanitizeConfig(obj) {
|
|
53
|
+
if (!obj || typeof obj !== "object" || Array.isArray(obj)) return obj;
|
|
54
|
+
const sanitized = {};
|
|
55
|
+
const infraToStrip = [
|
|
56
|
+
"rootDir",
|
|
57
|
+
"onProgress",
|
|
58
|
+
"progressCallback",
|
|
59
|
+
"streamResults",
|
|
60
|
+
"batchSize",
|
|
61
|
+
"useSmartDefaults"
|
|
62
|
+
];
|
|
63
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
64
|
+
if (infraToStrip.includes(key)) continue;
|
|
65
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
66
|
+
sanitized[key] = this.sanitizeConfig(value);
|
|
67
|
+
} else {
|
|
68
|
+
sanitized[key] = value;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return sanitized;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Performs the unified analysis.
|
|
75
|
+
*/
|
|
76
|
+
async analyze(options) {
|
|
77
|
+
await initializeParsers();
|
|
78
|
+
const startTime = Date.now();
|
|
79
|
+
const requestedTools = options.tools ?? [
|
|
80
|
+
"patterns",
|
|
81
|
+
"context",
|
|
82
|
+
"consistency"
|
|
83
|
+
];
|
|
84
|
+
const result = {
|
|
85
|
+
summary: {
|
|
86
|
+
totalIssues: 0,
|
|
87
|
+
criticalIssues: 0,
|
|
88
|
+
majorIssues: 0,
|
|
89
|
+
totalFiles: 0,
|
|
90
|
+
toolsRun: [],
|
|
91
|
+
executionTime: 0,
|
|
92
|
+
config: options,
|
|
93
|
+
toolConfigs: {}
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
for (const toolName of requestedTools) {
|
|
97
|
+
let provider = this.registry.find(toolName);
|
|
98
|
+
if (!provider) {
|
|
99
|
+
const packageName = TOOL_PACKAGE_MAP[toolName] ?? (toolName.startsWith("@aiready/") ? toolName : `@aiready/${toolName}`);
|
|
100
|
+
try {
|
|
101
|
+
await import(packageName);
|
|
102
|
+
provider = this.registry.find(toolName);
|
|
103
|
+
} catch (err) {
|
|
104
|
+
console.log(
|
|
105
|
+
`\u274C Failed to dynamically load tool ${toolName} (${packageName}):`,
|
|
106
|
+
err.message
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (!provider) {
|
|
111
|
+
console.warn(
|
|
112
|
+
`\u26A0\uFE0F Warning: Tool provider for '${toolName}' not found. Skipping.`
|
|
113
|
+
);
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
try {
|
|
117
|
+
const toolOptions = {
|
|
118
|
+
rootDir: options.rootDir
|
|
119
|
+
};
|
|
120
|
+
[...GLOBAL_INFRA_OPTIONS, ...COMMON_FINE_TUNING_OPTIONS].forEach(
|
|
121
|
+
(key) => {
|
|
122
|
+
if (key in options && key !== "toolConfigs" && key !== "tools") {
|
|
123
|
+
toolOptions[key] = options[key];
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
);
|
|
127
|
+
if (options.toolConfigs?.[provider.id]) {
|
|
128
|
+
Object.assign(toolOptions, options.toolConfigs[provider.id]);
|
|
129
|
+
} else if (options.tools && !Array.isArray(options.tools) && typeof options.tools === "object" && options.tools[provider.id]) {
|
|
130
|
+
Object.assign(
|
|
131
|
+
toolOptions,
|
|
132
|
+
options.tools[provider.id]
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
toolOptions.onProgress = (processed, total, msg) => {
|
|
136
|
+
if (options.progressCallback) {
|
|
137
|
+
options.progressCallback({
|
|
138
|
+
tool: provider.id,
|
|
139
|
+
processed,
|
|
140
|
+
total,
|
|
141
|
+
message: msg
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
const output = await provider.analyze(toolOptions);
|
|
146
|
+
if (output.metadata) {
|
|
147
|
+
output.metadata.config = this.sanitizeConfig(toolOptions);
|
|
148
|
+
}
|
|
149
|
+
if (options.progressCallback) {
|
|
150
|
+
options.progressCallback({ tool: provider.id, data: output });
|
|
151
|
+
}
|
|
152
|
+
result[provider.id] = output;
|
|
153
|
+
result.summary.toolsRun.push(provider.id);
|
|
154
|
+
const toolConfig = output.summary?.config ?? output.metadata?.config ?? toolOptions;
|
|
155
|
+
result.summary.toolConfigs[provider.id] = this.sanitizeConfig(toolConfig);
|
|
156
|
+
const toolFiles = output.summary?.totalFiles ?? output.summary?.filesAnalyzed ?? 0;
|
|
157
|
+
if (toolFiles > result.summary.totalFiles) {
|
|
158
|
+
result.summary.totalFiles = toolFiles;
|
|
159
|
+
}
|
|
160
|
+
const issueCount = output.results.reduce(
|
|
161
|
+
(sum, file) => sum + (file.issues?.length ?? 0),
|
|
162
|
+
0
|
|
163
|
+
);
|
|
164
|
+
result.summary.totalIssues += issueCount;
|
|
165
|
+
} catch (err) {
|
|
166
|
+
console.error(`\u274C Error running tool '${provider.id}':`, err);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
result.summary.config = this.sanitizeConfig({
|
|
170
|
+
scan: {
|
|
171
|
+
tools: requestedTools,
|
|
172
|
+
include: options.include,
|
|
173
|
+
exclude: options.exclude
|
|
174
|
+
},
|
|
175
|
+
tools: result.summary.toolConfigs
|
|
176
|
+
});
|
|
177
|
+
result.summary.executionTime = Date.now() - startTime;
|
|
178
|
+
this.applyLegacyKeys(result);
|
|
179
|
+
return result;
|
|
180
|
+
}
|
|
181
|
+
applyLegacyKeys(result) {
|
|
182
|
+
const keyMappings = {
|
|
183
|
+
"pattern-detect": ["patternDetect", "patterns"],
|
|
184
|
+
"context-analyzer": ["contextAnalyzer", "context"],
|
|
185
|
+
"naming-consistency": ["namingConsistency", "consistency"],
|
|
186
|
+
"ai-signal-clarity": ["aiSignalClarity"],
|
|
187
|
+
"agent-grounding": ["agentGrounding"],
|
|
188
|
+
"testability-index": ["testabilityIndex", "testability"],
|
|
189
|
+
"doc-drift": ["docDrift"],
|
|
190
|
+
"dependency-health": ["dependencyHealth", "deps"],
|
|
191
|
+
"change-amplification": ["changeAmplification"],
|
|
192
|
+
"contract-enforcement": ["contractEnforcement", "contract"]
|
|
193
|
+
};
|
|
194
|
+
for (const [kebabKey, aliases] of Object.entries(keyMappings)) {
|
|
195
|
+
if (result[kebabKey]) {
|
|
196
|
+
for (const alias of aliases) {
|
|
197
|
+
result[alias] = result[kebabKey];
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
async function analyzeUnified(options) {
|
|
204
|
+
const orchestrator = new UnifiedOrchestrator(ToolRegistry);
|
|
205
|
+
return orchestrator.analyze(options);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// src/scoring-orchestrator.ts
|
|
209
|
+
import {
|
|
210
|
+
ToolRegistry as ToolRegistry2,
|
|
211
|
+
ToolName as ToolName2,
|
|
212
|
+
calculateOverallScore,
|
|
213
|
+
calculateTokenBudget
|
|
214
|
+
} from "@aiready/core";
|
|
215
|
+
var ScoringOrchestrator = class {
|
|
216
|
+
/**
|
|
217
|
+
* Initialize scoring orchestrator with a tool registry.
|
|
218
|
+
* Injection pattern helps with testability and AI readiness score.
|
|
219
|
+
*/
|
|
220
|
+
constructor(registry = ToolRegistry2) {
|
|
221
|
+
this.registry = registry;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Calculates scores for all analyzed tools.
|
|
225
|
+
*/
|
|
226
|
+
async score(results, options) {
|
|
227
|
+
const toolScores = /* @__PURE__ */ new Map();
|
|
228
|
+
for (const toolId of results.summary.toolsRun) {
|
|
229
|
+
const provider = this.registry.get(toolId);
|
|
230
|
+
if (!provider) continue;
|
|
231
|
+
const output = results[toolId];
|
|
232
|
+
if (!output) continue;
|
|
233
|
+
try {
|
|
234
|
+
const toolScore = provider.score(output, options);
|
|
235
|
+
if (!toolScore.tokenBudget) {
|
|
236
|
+
if (toolId === ToolName2.PatternDetect && output.duplicates) {
|
|
237
|
+
const wastedTokens = output.duplicates.reduce(
|
|
238
|
+
(sum, d) => sum + (d.tokenCost ?? 0),
|
|
239
|
+
0
|
|
240
|
+
);
|
|
241
|
+
toolScore.tokenBudget = calculateTokenBudget({
|
|
242
|
+
totalContextTokens: wastedTokens * 2,
|
|
243
|
+
wastedTokens: {
|
|
244
|
+
duplication: wastedTokens,
|
|
245
|
+
fragmentation: 0,
|
|
246
|
+
chattiness: 0
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
} else if (toolId === ToolName2.ContextAnalyzer && output.summary) {
|
|
250
|
+
toolScore.tokenBudget = calculateTokenBudget({
|
|
251
|
+
totalContextTokens: output.summary.totalTokens,
|
|
252
|
+
wastedTokens: {
|
|
253
|
+
duplication: 0,
|
|
254
|
+
fragmentation: output.summary.totalPotentialSavings ?? 0,
|
|
255
|
+
chattiness: 0
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
toolScores.set(toolId, toolScore);
|
|
261
|
+
} catch (err) {
|
|
262
|
+
console.error(`\u274C Error scoring tool '${toolId}':`, err);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
if (toolScores.size === 0) {
|
|
266
|
+
return this.emptyScoringResult();
|
|
267
|
+
}
|
|
268
|
+
return calculateOverallScore(toolScores, options, void 0);
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Generate human-readable summary of unified results.
|
|
272
|
+
*/
|
|
273
|
+
generateSummary(result) {
|
|
274
|
+
const { summary } = result;
|
|
275
|
+
let output = `\u{1F680} AIReady Analysis Complete
|
|
276
|
+
|
|
277
|
+
`;
|
|
278
|
+
output += `\u{1F4CA} Summary:
|
|
279
|
+
`;
|
|
280
|
+
output += ` Tools run: ${summary.toolsRun.join(", ")}
|
|
281
|
+
`;
|
|
282
|
+
output += ` Total issues found: ${summary.totalIssues}
|
|
283
|
+
`;
|
|
284
|
+
output += ` Execution time: ${(summary.executionTime / 1e3).toFixed(2)}s
|
|
285
|
+
|
|
286
|
+
`;
|
|
287
|
+
for (const provider of this.registry.getAll()) {
|
|
288
|
+
const toolResult = result[provider.id];
|
|
289
|
+
if (toolResult) {
|
|
290
|
+
const issueCount = toolResult.results.reduce(
|
|
291
|
+
(sum, r) => sum + (r.issues?.length ?? 0),
|
|
292
|
+
0
|
|
293
|
+
);
|
|
294
|
+
output += `\u2022 ${provider.id}: ${issueCount} issues
|
|
295
|
+
`;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
return output;
|
|
299
|
+
}
|
|
300
|
+
emptyScoringResult() {
|
|
301
|
+
return {
|
|
302
|
+
overall: 0,
|
|
303
|
+
rating: "Critical",
|
|
304
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
305
|
+
toolsUsed: [],
|
|
306
|
+
breakdown: [],
|
|
307
|
+
calculation: {
|
|
308
|
+
formula: "0 / 0 = 0",
|
|
309
|
+
weights: {},
|
|
310
|
+
normalized: "0 / 0 = 0"
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
async function scoreUnified(results, options) {
|
|
316
|
+
const orchestrator = new ScoringOrchestrator(ToolRegistry2);
|
|
317
|
+
return orchestrator.score(results, options);
|
|
318
|
+
}
|
|
319
|
+
function generateUnifiedSummary(result) {
|
|
320
|
+
const orchestrator = new ScoringOrchestrator(ToolRegistry2);
|
|
321
|
+
return orchestrator.generateSummary(result);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
export {
|
|
325
|
+
__require,
|
|
326
|
+
TOOL_PACKAGE_MAP,
|
|
327
|
+
UnifiedOrchestrator,
|
|
328
|
+
analyzeUnified,
|
|
329
|
+
ScoringOrchestrator,
|
|
330
|
+
scoreUnified,
|
|
331
|
+
generateUnifiedSummary
|
|
332
|
+
};
|
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
// src/orchestrator.ts
|
|
9
|
+
import {
|
|
10
|
+
ToolRegistry,
|
|
11
|
+
ToolName,
|
|
12
|
+
initializeParsers,
|
|
13
|
+
GLOBAL_INFRA_OPTIONS,
|
|
14
|
+
COMMON_FINE_TUNING_OPTIONS
|
|
15
|
+
} from "@aiready/core";
|
|
16
|
+
var TOOL_PACKAGE_MAP = {
|
|
17
|
+
[ToolName.PatternDetect]: "@aiready/pattern-detect",
|
|
18
|
+
[ToolName.ContextAnalyzer]: "@aiready/context-analyzer",
|
|
19
|
+
[ToolName.NamingConsistency]: "@aiready/consistency",
|
|
20
|
+
[ToolName.AiSignalClarity]: "@aiready/ai-signal-clarity",
|
|
21
|
+
[ToolName.AgentGrounding]: "@aiready/agent-grounding",
|
|
22
|
+
[ToolName.TestabilityIndex]: "@aiready/testability",
|
|
23
|
+
[ToolName.DocDrift]: "@aiready/doc-drift",
|
|
24
|
+
[ToolName.DependencyHealth]: "@aiready/deps",
|
|
25
|
+
[ToolName.ChangeAmplification]: "@aiready/change-amplification",
|
|
26
|
+
[ToolName.ContractEnforcement]: "@aiready/contract-enforcement",
|
|
27
|
+
// Aliases handled by registry
|
|
28
|
+
patterns: "@aiready/pattern-detect",
|
|
29
|
+
duplicates: "@aiready/pattern-detect",
|
|
30
|
+
context: "@aiready/context-analyzer",
|
|
31
|
+
fragmentation: "@aiready/context-analyzer",
|
|
32
|
+
consistency: "@aiready/consistency",
|
|
33
|
+
"ai-signal": "@aiready/ai-signal-clarity",
|
|
34
|
+
grounding: "@aiready/agent-grounding",
|
|
35
|
+
testability: "@aiready/testability",
|
|
36
|
+
"deps-health": "@aiready/deps",
|
|
37
|
+
"change-amp": "@aiready/change-amplification",
|
|
38
|
+
contract: "@aiready/contract-enforcement"
|
|
39
|
+
};
|
|
40
|
+
var UnifiedOrchestrator = class {
|
|
41
|
+
/**
|
|
42
|
+
* Initialize orchestrator with a tool registry.
|
|
43
|
+
* Injection pattern helps with testability and AI readiness score.
|
|
44
|
+
*/
|
|
45
|
+
constructor(registry = ToolRegistry) {
|
|
46
|
+
this.registry = registry;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Deeply sanitizes a configuration object for reporting.
|
|
50
|
+
* Strips internal infrastructure keys to prevent AI context clutter.
|
|
51
|
+
*/
|
|
52
|
+
sanitizeConfig(obj) {
|
|
53
|
+
if (!obj || typeof obj !== "object" || Array.isArray(obj)) return obj;
|
|
54
|
+
const sanitized = {};
|
|
55
|
+
const infraToStrip = [
|
|
56
|
+
"rootDir",
|
|
57
|
+
"onProgress",
|
|
58
|
+
"progressCallback",
|
|
59
|
+
"streamResults",
|
|
60
|
+
"batchSize",
|
|
61
|
+
"useSmartDefaults"
|
|
62
|
+
];
|
|
63
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
64
|
+
if (infraToStrip.includes(key)) continue;
|
|
65
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
66
|
+
sanitized[key] = this.sanitizeConfig(value);
|
|
67
|
+
} else {
|
|
68
|
+
sanitized[key] = value;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return sanitized;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Performs the unified analysis.
|
|
75
|
+
*/
|
|
76
|
+
async analyze(options) {
|
|
77
|
+
await initializeParsers();
|
|
78
|
+
const startTime = Date.now();
|
|
79
|
+
const requestedTools = options.tools ?? [
|
|
80
|
+
"patterns",
|
|
81
|
+
"context",
|
|
82
|
+
"consistency"
|
|
83
|
+
];
|
|
84
|
+
const result = {
|
|
85
|
+
summary: {
|
|
86
|
+
totalIssues: 0,
|
|
87
|
+
criticalIssues: 0,
|
|
88
|
+
majorIssues: 0,
|
|
89
|
+
totalFiles: 0,
|
|
90
|
+
toolsRun: [],
|
|
91
|
+
executionTime: 0,
|
|
92
|
+
config: options,
|
|
93
|
+
toolConfigs: {}
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
for (const toolName of requestedTools) {
|
|
97
|
+
let provider = this.registry.find(toolName);
|
|
98
|
+
if (!provider) {
|
|
99
|
+
const packageName = TOOL_PACKAGE_MAP[toolName] ?? (toolName.startsWith("@aiready/") ? toolName : `@aiready/${toolName}`);
|
|
100
|
+
try {
|
|
101
|
+
await import(packageName);
|
|
102
|
+
provider = this.registry.find(toolName);
|
|
103
|
+
} catch (err) {
|
|
104
|
+
console.log(
|
|
105
|
+
`\u274C Failed to dynamically load tool ${toolName} (${packageName}):`,
|
|
106
|
+
err.message
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (!provider) {
|
|
111
|
+
console.warn(
|
|
112
|
+
`\u26A0\uFE0F Warning: Tool provider for '${toolName}' not found. Skipping.`
|
|
113
|
+
);
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
try {
|
|
117
|
+
const toolOptions = {
|
|
118
|
+
rootDir: options.rootDir
|
|
119
|
+
};
|
|
120
|
+
[...GLOBAL_INFRA_OPTIONS, ...COMMON_FINE_TUNING_OPTIONS].forEach(
|
|
121
|
+
(key) => {
|
|
122
|
+
if (key in options && key !== "toolConfigs" && key !== "tools") {
|
|
123
|
+
toolOptions[key] = options[key];
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
);
|
|
127
|
+
if (options.toolConfigs?.[provider.id]) {
|
|
128
|
+
Object.assign(toolOptions, options.toolConfigs[provider.id]);
|
|
129
|
+
} else if (options.tools && !Array.isArray(options.tools) && typeof options.tools === "object" && options.tools[provider.id]) {
|
|
130
|
+
Object.assign(
|
|
131
|
+
toolOptions,
|
|
132
|
+
options.tools[provider.id]
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
toolOptions.onProgress = (processed, total, msg) => {
|
|
136
|
+
if (options.progressCallback) {
|
|
137
|
+
options.progressCallback({
|
|
138
|
+
tool: provider.id,
|
|
139
|
+
processed,
|
|
140
|
+
total,
|
|
141
|
+
message: msg
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
const output = await provider.analyze(toolOptions);
|
|
146
|
+
if (output.metadata) {
|
|
147
|
+
output.metadata.config = this.sanitizeConfig(toolOptions);
|
|
148
|
+
}
|
|
149
|
+
if (options.progressCallback) {
|
|
150
|
+
options.progressCallback({ tool: provider.id, data: output });
|
|
151
|
+
}
|
|
152
|
+
result[provider.id] = output;
|
|
153
|
+
result.summary.toolsRun.push(provider.id);
|
|
154
|
+
const toolConfig = output.summary?.config ?? output.metadata?.config ?? toolOptions;
|
|
155
|
+
result.summary.toolConfigs[provider.id] = this.sanitizeConfig(toolConfig);
|
|
156
|
+
const toolFiles = output.summary?.totalFiles ?? output.summary?.filesAnalyzed ?? 0;
|
|
157
|
+
if (toolFiles > result.summary.totalFiles) {
|
|
158
|
+
result.summary.totalFiles = toolFiles;
|
|
159
|
+
}
|
|
160
|
+
const issueCount = output.results.reduce(
|
|
161
|
+
(sum, file) => sum + (file.issues?.length ?? 0),
|
|
162
|
+
0
|
|
163
|
+
);
|
|
164
|
+
result.summary.totalIssues += issueCount;
|
|
165
|
+
} catch (err) {
|
|
166
|
+
console.error(`\u274C Error running tool '${provider.id}':`, err);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
result.summary.config = this.sanitizeConfig({
|
|
170
|
+
scan: {
|
|
171
|
+
tools: requestedTools,
|
|
172
|
+
include: options.include,
|
|
173
|
+
exclude: options.exclude
|
|
174
|
+
},
|
|
175
|
+
tools: result.summary.toolConfigs
|
|
176
|
+
});
|
|
177
|
+
result.summary.executionTime = Date.now() - startTime;
|
|
178
|
+
this.applyLegacyKeys(result);
|
|
179
|
+
return result;
|
|
180
|
+
}
|
|
181
|
+
applyLegacyKeys(result) {
|
|
182
|
+
const keyMappings = {
|
|
183
|
+
"pattern-detect": ["patternDetect", "patterns"],
|
|
184
|
+
"context-analyzer": ["contextAnalyzer", "context"],
|
|
185
|
+
"naming-consistency": ["namingConsistency", "consistency"],
|
|
186
|
+
"ai-signal-clarity": ["aiSignalClarity"],
|
|
187
|
+
"agent-grounding": ["agentGrounding"],
|
|
188
|
+
"testability-index": ["testabilityIndex", "testability"],
|
|
189
|
+
"doc-drift": ["docDrift"],
|
|
190
|
+
"dependency-health": ["dependencyHealth", "deps"],
|
|
191
|
+
"change-amplification": ["changeAmplification"],
|
|
192
|
+
"contract-enforcement": ["contractEnforcement", "contract"]
|
|
193
|
+
};
|
|
194
|
+
for (const [kebabKey, aliases] of Object.entries(keyMappings)) {
|
|
195
|
+
if (result[kebabKey]) {
|
|
196
|
+
for (const alias of aliases) {
|
|
197
|
+
result[alias] = result[kebabKey];
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
async function analyzeUnified(options) {
|
|
204
|
+
const orchestrator = new UnifiedOrchestrator(ToolRegistry);
|
|
205
|
+
return orchestrator.analyze(options);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// src/scoring-orchestrator.ts
|
|
209
|
+
import {
|
|
210
|
+
ToolRegistry as ToolRegistry2,
|
|
211
|
+
ToolName as ToolName2,
|
|
212
|
+
calculateOverallScore,
|
|
213
|
+
calculateTokenBudget
|
|
214
|
+
} from "@aiready/core";
|
|
215
|
+
var ScoringOrchestrator = class {
|
|
216
|
+
/**
|
|
217
|
+
* Initialize scoring orchestrator with a tool registry.
|
|
218
|
+
* Injection pattern helps with testability and AI readiness score.
|
|
219
|
+
*/
|
|
220
|
+
constructor(registry = ToolRegistry2) {
|
|
221
|
+
this.registry = registry;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Calculates scores for all analyzed tools.
|
|
225
|
+
*/
|
|
226
|
+
async score(results, options) {
|
|
227
|
+
const toolScores = /* @__PURE__ */ new Map();
|
|
228
|
+
for (const toolId of results.summary.toolsRun) {
|
|
229
|
+
const provider = this.registry.get(toolId);
|
|
230
|
+
if (!provider) continue;
|
|
231
|
+
const output = results[toolId];
|
|
232
|
+
if (!output) continue;
|
|
233
|
+
try {
|
|
234
|
+
const toolScore = provider.score(output, options);
|
|
235
|
+
if (!toolScore.tokenBudget) {
|
|
236
|
+
if (toolId === ToolName2.PatternDetect && output.duplicates) {
|
|
237
|
+
const wastedTokens = output.duplicates.reduce(
|
|
238
|
+
(sum, d) => sum + (d.tokenCost ?? 0),
|
|
239
|
+
0
|
|
240
|
+
);
|
|
241
|
+
toolScore.tokenBudget = calculateTokenBudget({
|
|
242
|
+
totalContextTokens: wastedTokens * 2,
|
|
243
|
+
wastedTokens: {
|
|
244
|
+
duplication: wastedTokens,
|
|
245
|
+
fragmentation: 0,
|
|
246
|
+
chattiness: 0
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
} else if (toolId === ToolName2.ContextAnalyzer && output.summary) {
|
|
250
|
+
toolScore.tokenBudget = calculateTokenBudget({
|
|
251
|
+
totalContextTokens: output.summary.totalTokens,
|
|
252
|
+
wastedTokens: {
|
|
253
|
+
duplication: 0,
|
|
254
|
+
fragmentation: output.summary.totalPotentialSavings ?? 0,
|
|
255
|
+
chattiness: 0
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
toolScores.set(toolId, toolScore);
|
|
261
|
+
} catch (err) {
|
|
262
|
+
console.error(`\u274C Error scoring tool '${toolId}':`, err);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
if (toolScores.size === 0) {
|
|
266
|
+
return this.emptyScoringResult();
|
|
267
|
+
}
|
|
268
|
+
const scoringConfig = {
|
|
269
|
+
profile: options.profile,
|
|
270
|
+
threshold: options.threshold,
|
|
271
|
+
showBreakdown: options.scoring?.showBreakdown,
|
|
272
|
+
compareBaseline: options.compareTo,
|
|
273
|
+
tools: options.toolConfigs ? Object.fromEntries(
|
|
274
|
+
Object.entries(options.toolConfigs).map(([k, v]) => [
|
|
275
|
+
k,
|
|
276
|
+
v
|
|
277
|
+
])
|
|
278
|
+
) : void 0
|
|
279
|
+
};
|
|
280
|
+
return calculateOverallScore(toolScores, scoringConfig, void 0);
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Generate human-readable summary of unified results.
|
|
284
|
+
*/
|
|
285
|
+
generateSummary(result) {
|
|
286
|
+
const { summary } = result;
|
|
287
|
+
let output = `\u{1F680} AIReady Analysis Complete
|
|
288
|
+
|
|
289
|
+
`;
|
|
290
|
+
output += `\u{1F4CA} Summary:
|
|
291
|
+
`;
|
|
292
|
+
output += ` Tools run: ${summary.toolsRun.join(", ")}
|
|
293
|
+
`;
|
|
294
|
+
output += ` Total issues found: ${summary.totalIssues}
|
|
295
|
+
`;
|
|
296
|
+
output += ` Execution time: ${(summary.executionTime / 1e3).toFixed(2)}s
|
|
297
|
+
|
|
298
|
+
`;
|
|
299
|
+
for (const provider of this.registry.getAll()) {
|
|
300
|
+
const toolResult = result[provider.id];
|
|
301
|
+
if (toolResult) {
|
|
302
|
+
const issueCount = toolResult.results.reduce(
|
|
303
|
+
(sum, r) => sum + (r.issues?.length ?? 0),
|
|
304
|
+
0
|
|
305
|
+
);
|
|
306
|
+
output += `\u2022 ${provider.id}: ${issueCount} issues
|
|
307
|
+
`;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
return output;
|
|
311
|
+
}
|
|
312
|
+
emptyScoringResult() {
|
|
313
|
+
return {
|
|
314
|
+
overall: 0,
|
|
315
|
+
rating: "Critical",
|
|
316
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
317
|
+
toolsUsed: [],
|
|
318
|
+
breakdown: [],
|
|
319
|
+
calculation: {
|
|
320
|
+
formula: "0 / 0 = 0",
|
|
321
|
+
weights: {},
|
|
322
|
+
normalized: "0 / 0 = 0"
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
};
|
|
327
|
+
async function scoreUnified(results, options) {
|
|
328
|
+
const orchestrator = new ScoringOrchestrator(ToolRegistry2);
|
|
329
|
+
return orchestrator.score(results, options);
|
|
330
|
+
}
|
|
331
|
+
function generateUnifiedSummary(result) {
|
|
332
|
+
const orchestrator = new ScoringOrchestrator(ToolRegistry2);
|
|
333
|
+
return orchestrator.generateSummary(result);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
export {
|
|
337
|
+
__require,
|
|
338
|
+
TOOL_PACKAGE_MAP,
|
|
339
|
+
UnifiedOrchestrator,
|
|
340
|
+
analyzeUnified,
|
|
341
|
+
ScoringOrchestrator,
|
|
342
|
+
scoreUnified,
|
|
343
|
+
generateUnifiedSummary
|
|
344
|
+
};
|
package/dist/cli.js
CHANGED
|
@@ -398,7 +398,7 @@ async function executeToolAction(directory, options, config) {
|
|
|
398
398
|
let toolScore;
|
|
399
399
|
if ((options.score || finalOptions.score) && calculateScore) {
|
|
400
400
|
const resultsAny = results;
|
|
401
|
-
const scoreData = resultsAny.duplicates || resultsAny.issues ||
|
|
401
|
+
const scoreData = resultsAny.duplicates || resultsAny.issues || resultsAny;
|
|
402
402
|
const filesCount = resultsAny.length || resultsAny.summary?.filesAnalyzed || resultsAny.summary?.totalFiles;
|
|
403
403
|
toolScore = calculateScore(scoreData, filesCount);
|
|
404
404
|
}
|
|
@@ -544,16 +544,19 @@ async function resolveScanConfig(resolvedDir, options) {
|
|
|
544
544
|
cliOverrides
|
|
545
545
|
);
|
|
546
546
|
const finalOptions = { ...baseOptions };
|
|
547
|
-
|
|
547
|
+
const tools = baseOptions.tools;
|
|
548
|
+
if (tools?.includes(import_core6.ToolName.PatternDetect) || tools?.includes("patterns")) {
|
|
548
549
|
const { getSmartDefaults } = await import("@aiready/pattern-detect");
|
|
550
|
+
const toolConfigs = finalOptions.toolConfigs;
|
|
549
551
|
const patternSmartDefaults = await getSmartDefaults(
|
|
550
552
|
resolvedDir,
|
|
551
|
-
|
|
553
|
+
toolConfigs?.[import_core6.ToolName.PatternDetect] ?? {}
|
|
552
554
|
);
|
|
553
555
|
if (!finalOptions.toolConfigs) finalOptions.toolConfigs = {};
|
|
554
|
-
finalOptions.toolConfigs
|
|
556
|
+
const configs = finalOptions.toolConfigs;
|
|
557
|
+
configs[import_core6.ToolName.PatternDetect] = {
|
|
555
558
|
...patternSmartDefaults,
|
|
556
|
-
...
|
|
559
|
+
...configs[import_core6.ToolName.PatternDetect]
|
|
557
560
|
};
|
|
558
561
|
}
|
|
559
562
|
return finalOptions;
|
|
@@ -600,7 +603,8 @@ var UnifiedOrchestrator = class {
|
|
|
600
603
|
this.registry = registry;
|
|
601
604
|
}
|
|
602
605
|
/**
|
|
603
|
-
* Deeply sanitizes a configuration object.
|
|
606
|
+
* Deeply sanitizes a configuration object for reporting.
|
|
607
|
+
* Strips internal infrastructure keys to prevent AI context clutter.
|
|
604
608
|
*/
|
|
605
609
|
sanitizeConfig(obj) {
|
|
606
610
|
if (!obj || typeof obj !== "object" || Array.isArray(obj)) return obj;
|
|
@@ -680,7 +684,10 @@ var UnifiedOrchestrator = class {
|
|
|
680
684
|
if (options.toolConfigs?.[provider.id]) {
|
|
681
685
|
Object.assign(toolOptions, options.toolConfigs[provider.id]);
|
|
682
686
|
} else if (options.tools && !Array.isArray(options.tools) && typeof options.tools === "object" && options.tools[provider.id]) {
|
|
683
|
-
Object.assign(
|
|
687
|
+
Object.assign(
|
|
688
|
+
toolOptions,
|
|
689
|
+
options.tools[provider.id]
|
|
690
|
+
);
|
|
684
691
|
}
|
|
685
692
|
toolOptions.onProgress = (processed, total, msg) => {
|
|
686
693
|
if (options.progressCallback) {
|
|
@@ -810,7 +817,19 @@ var ScoringOrchestrator = class {
|
|
|
810
817
|
if (toolScores.size === 0) {
|
|
811
818
|
return this.emptyScoringResult();
|
|
812
819
|
}
|
|
813
|
-
|
|
820
|
+
const scoringConfig = {
|
|
821
|
+
profile: options.profile,
|
|
822
|
+
threshold: options.threshold,
|
|
823
|
+
showBreakdown: options.scoring?.showBreakdown,
|
|
824
|
+
compareBaseline: options.compareTo,
|
|
825
|
+
tools: options.toolConfigs ? Object.fromEntries(
|
|
826
|
+
Object.entries(options.toolConfigs).map(([k, v]) => [
|
|
827
|
+
k,
|
|
828
|
+
v
|
|
829
|
+
])
|
|
830
|
+
) : void 0
|
|
831
|
+
};
|
|
832
|
+
return (0, import_core8.calculateOverallScore)(toolScores, scoringConfig, void 0);
|
|
814
833
|
}
|
|
815
834
|
/**
|
|
816
835
|
* Generate human-readable summary of unified results.
|
|
@@ -1501,6 +1520,7 @@ async function patternsAction(directory, options) {
|
|
|
1501
1520
|
label: "Pattern analysis",
|
|
1502
1521
|
emoji: "\u{1F50D}",
|
|
1503
1522
|
defaults: {
|
|
1523
|
+
rootDir: "",
|
|
1504
1524
|
useSmartDefaults: !options.fullScan,
|
|
1505
1525
|
include: void 0,
|
|
1506
1526
|
exclude: void 0,
|
|
@@ -1515,18 +1535,24 @@ async function patternsAction(directory, options) {
|
|
|
1515
1535
|
minSharedTokens: opts.minSharedTokens ? parseInt(opts.minSharedTokens) : void 0
|
|
1516
1536
|
}),
|
|
1517
1537
|
importTool: async () => {
|
|
1518
|
-
const {
|
|
1538
|
+
const {
|
|
1539
|
+
analyzePatterns,
|
|
1540
|
+
generateSummary: rawGenerateSummary,
|
|
1541
|
+
calculatePatternScore
|
|
1542
|
+
} = await import("@aiready/pattern-detect");
|
|
1519
1543
|
return {
|
|
1520
1544
|
analyze: analyzePatterns,
|
|
1521
|
-
generateSummary,
|
|
1522
|
-
calculateScore: calculatePatternScore
|
|
1545
|
+
generateSummary: (results) => rawGenerateSummary(results.results),
|
|
1546
|
+
calculateScore: (data, resultsCount) => calculatePatternScore(data, resultsCount ?? 0)
|
|
1523
1547
|
};
|
|
1524
1548
|
},
|
|
1525
1549
|
renderConsole: ({ results, summary, elapsedTime, score }) => {
|
|
1526
1550
|
const duplicates = results.duplicates || [];
|
|
1527
1551
|
(0, import_core13.printTerminalHeader)("PATTERN ANALYSIS SUMMARY");
|
|
1528
1552
|
console.log(
|
|
1529
|
-
import_chalk9.default.white(
|
|
1553
|
+
import_chalk9.default.white(
|
|
1554
|
+
`\u{1F4C1} Files analyzed: ${import_chalk9.default.bold(results.files?.length || 0)}`
|
|
1555
|
+
)
|
|
1530
1556
|
);
|
|
1531
1557
|
console.log(
|
|
1532
1558
|
import_chalk9.default.yellow(
|
|
@@ -1599,6 +1625,7 @@ async function contextAction(directory, options) {
|
|
|
1599
1625
|
label: "Context analysis",
|
|
1600
1626
|
emoji: "\u{1F9E9}",
|
|
1601
1627
|
defaults: {
|
|
1628
|
+
rootDir: "",
|
|
1602
1629
|
maxDepth: 5,
|
|
1603
1630
|
maxContextBudget: 1e4,
|
|
1604
1631
|
include: void 0,
|
|
@@ -1614,7 +1641,7 @@ async function contextAction(directory, options) {
|
|
|
1614
1641
|
return {
|
|
1615
1642
|
analyze: analyzeContext,
|
|
1616
1643
|
generateSummary,
|
|
1617
|
-
calculateScore: calculateContextScore
|
|
1644
|
+
calculateScore: (data, _resultsCount) => calculateContextScore(data)
|
|
1618
1645
|
};
|
|
1619
1646
|
},
|
|
1620
1647
|
renderConsole: ({ results: _results, summary, elapsedTime, score }) => {
|
|
@@ -1687,6 +1714,7 @@ async function consistencyAction(directory, options) {
|
|
|
1687
1714
|
label: "Consistency analysis",
|
|
1688
1715
|
emoji: "\u{1F4CF}",
|
|
1689
1716
|
defaults: {
|
|
1717
|
+
rootDir: "",
|
|
1690
1718
|
checkNaming: options.naming !== false,
|
|
1691
1719
|
checkPatterns: options.patterns !== false,
|
|
1692
1720
|
minSeverity: options.minSeverity || "info",
|
|
@@ -1707,7 +1735,7 @@ async function consistencyAction(directory, options) {
|
|
|
1707
1735
|
return report;
|
|
1708
1736
|
},
|
|
1709
1737
|
generateSummary,
|
|
1710
|
-
calculateScore: calculateConsistencyScore
|
|
1738
|
+
calculateScore: (data, resultsCount) => calculateConsistencyScore(data, resultsCount ?? 0)
|
|
1711
1739
|
};
|
|
1712
1740
|
},
|
|
1713
1741
|
renderConsole: ({ results: report, summary, elapsedTime, score }) => {
|
|
@@ -2022,10 +2050,10 @@ async function testabilityAction(directory, options) {
|
|
|
2022
2050
|
label: "Testability analysis",
|
|
2023
2051
|
emoji: "\u{1F9EA}",
|
|
2024
2052
|
defaults: {
|
|
2053
|
+
rootDir: "",
|
|
2025
2054
|
minCoverageRatio: 0.3,
|
|
2026
2055
|
include: void 0,
|
|
2027
|
-
exclude: void 0
|
|
2028
|
-
output: { format: "console", file: void 0 }
|
|
2056
|
+
exclude: void 0
|
|
2029
2057
|
},
|
|
2030
2058
|
getCliOptions: (opts) => ({
|
|
2031
2059
|
minCoverageRatio: opts.minCoverage ? parseFloat(opts.minCoverage) : void 0
|
|
@@ -2072,10 +2100,10 @@ async function contractEnforcementAction(directory, options) {
|
|
|
2072
2100
|
label: "Contract enforcement analysis",
|
|
2073
2101
|
emoji: "\u{1F6E1}\uFE0F",
|
|
2074
2102
|
defaults: {
|
|
2103
|
+
rootDir: "",
|
|
2075
2104
|
minChainDepth: 3,
|
|
2076
2105
|
include: void 0,
|
|
2077
|
-
exclude: void 0
|
|
2078
|
-
output: { format: "console", file: void 0 }
|
|
2106
|
+
exclude: void 0
|
|
2079
2107
|
},
|
|
2080
2108
|
getCliOptions: (opts) => ({
|
|
2081
2109
|
minChainDepth: opts.minChainDepth ? parseInt(opts.minChainDepth, 10) : void 0
|
|
@@ -2085,7 +2113,32 @@ async function contractEnforcementAction(directory, options) {
|
|
|
2085
2113
|
return {
|
|
2086
2114
|
analyze: tool.analyzeContractEnforcement,
|
|
2087
2115
|
generateSummary: (report) => report.summary,
|
|
2088
|
-
calculateScore:
|
|
2116
|
+
calculateScore: (data, resultsCount) => {
|
|
2117
|
+
const result = tool.calculateContractEnforcementScore(
|
|
2118
|
+
data,
|
|
2119
|
+
resultsCount ?? 0,
|
|
2120
|
+
resultsCount ?? 0
|
|
2121
|
+
);
|
|
2122
|
+
return {
|
|
2123
|
+
toolName: "contract-enforcement",
|
|
2124
|
+
score: result.score,
|
|
2125
|
+
rawMetrics: result.dimensions || {},
|
|
2126
|
+
factors: (result.recommendations || []).map(
|
|
2127
|
+
(rec, i) => ({
|
|
2128
|
+
name: `Recommendation ${i + 1}`,
|
|
2129
|
+
impact: 0,
|
|
2130
|
+
description: rec
|
|
2131
|
+
})
|
|
2132
|
+
),
|
|
2133
|
+
recommendations: (result.recommendations || []).map(
|
|
2134
|
+
(rec) => ({
|
|
2135
|
+
action: rec,
|
|
2136
|
+
estimatedImpact: 5,
|
|
2137
|
+
priority: "medium"
|
|
2138
|
+
})
|
|
2139
|
+
)
|
|
2140
|
+
};
|
|
2141
|
+
}
|
|
2089
2142
|
};
|
|
2090
2143
|
},
|
|
2091
2144
|
renderConsole: ({ results, summary, score }) => {
|
package/dist/cli.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
__require,
|
|
4
4
|
analyzeUnified,
|
|
5
5
|
scoreUnified
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-OLJA25SP.mjs";
|
|
7
7
|
|
|
8
8
|
// src/cli.ts
|
|
9
9
|
import { Command } from "commander";
|
|
@@ -403,7 +403,7 @@ async function executeToolAction(directory, options, config) {
|
|
|
403
403
|
let toolScore;
|
|
404
404
|
if ((options.score || finalOptions.score) && calculateScore) {
|
|
405
405
|
const resultsAny = results;
|
|
406
|
-
const scoreData = resultsAny.duplicates || resultsAny.issues ||
|
|
406
|
+
const scoreData = resultsAny.duplicates || resultsAny.issues || resultsAny;
|
|
407
407
|
const filesCount = resultsAny.length || resultsAny.summary?.filesAnalyzed || resultsAny.summary?.totalFiles;
|
|
408
408
|
toolScore = calculateScore(scoreData, filesCount);
|
|
409
409
|
}
|
|
@@ -549,16 +549,19 @@ async function resolveScanConfig(resolvedDir, options) {
|
|
|
549
549
|
cliOverrides
|
|
550
550
|
);
|
|
551
551
|
const finalOptions = { ...baseOptions };
|
|
552
|
-
|
|
552
|
+
const tools = baseOptions.tools;
|
|
553
|
+
if (tools?.includes(ToolName2.PatternDetect) || tools?.includes("patterns")) {
|
|
553
554
|
const { getSmartDefaults } = await import("@aiready/pattern-detect");
|
|
555
|
+
const toolConfigs = finalOptions.toolConfigs;
|
|
554
556
|
const patternSmartDefaults = await getSmartDefaults(
|
|
555
557
|
resolvedDir,
|
|
556
|
-
|
|
558
|
+
toolConfigs?.[ToolName2.PatternDetect] ?? {}
|
|
557
559
|
);
|
|
558
560
|
if (!finalOptions.toolConfigs) finalOptions.toolConfigs = {};
|
|
559
|
-
finalOptions.toolConfigs
|
|
561
|
+
const configs = finalOptions.toolConfigs;
|
|
562
|
+
configs[ToolName2.PatternDetect] = {
|
|
560
563
|
...patternSmartDefaults,
|
|
561
|
-
...
|
|
564
|
+
...configs[ToolName2.PatternDetect]
|
|
562
565
|
};
|
|
563
566
|
}
|
|
564
567
|
return finalOptions;
|
|
@@ -1210,6 +1213,7 @@ async function patternsAction(directory, options) {
|
|
|
1210
1213
|
label: "Pattern analysis",
|
|
1211
1214
|
emoji: "\u{1F50D}",
|
|
1212
1215
|
defaults: {
|
|
1216
|
+
rootDir: "",
|
|
1213
1217
|
useSmartDefaults: !options.fullScan,
|
|
1214
1218
|
include: void 0,
|
|
1215
1219
|
exclude: void 0,
|
|
@@ -1224,18 +1228,24 @@ async function patternsAction(directory, options) {
|
|
|
1224
1228
|
minSharedTokens: opts.minSharedTokens ? parseInt(opts.minSharedTokens) : void 0
|
|
1225
1229
|
}),
|
|
1226
1230
|
importTool: async () => {
|
|
1227
|
-
const {
|
|
1231
|
+
const {
|
|
1232
|
+
analyzePatterns,
|
|
1233
|
+
generateSummary: rawGenerateSummary,
|
|
1234
|
+
calculatePatternScore
|
|
1235
|
+
} = await import("@aiready/pattern-detect");
|
|
1228
1236
|
return {
|
|
1229
1237
|
analyze: analyzePatterns,
|
|
1230
|
-
generateSummary,
|
|
1231
|
-
calculateScore: calculatePatternScore
|
|
1238
|
+
generateSummary: (results) => rawGenerateSummary(results.results),
|
|
1239
|
+
calculateScore: (data, resultsCount) => calculatePatternScore(data, resultsCount ?? 0)
|
|
1232
1240
|
};
|
|
1233
1241
|
},
|
|
1234
1242
|
renderConsole: ({ results, summary, elapsedTime, score }) => {
|
|
1235
1243
|
const duplicates = results.duplicates || [];
|
|
1236
1244
|
printTerminalHeader("PATTERN ANALYSIS SUMMARY");
|
|
1237
1245
|
console.log(
|
|
1238
|
-
chalk9.white(
|
|
1246
|
+
chalk9.white(
|
|
1247
|
+
`\u{1F4C1} Files analyzed: ${chalk9.bold(results.files?.length || 0)}`
|
|
1248
|
+
)
|
|
1239
1249
|
);
|
|
1240
1250
|
console.log(
|
|
1241
1251
|
chalk9.yellow(
|
|
@@ -1308,6 +1318,7 @@ async function contextAction(directory, options) {
|
|
|
1308
1318
|
label: "Context analysis",
|
|
1309
1319
|
emoji: "\u{1F9E9}",
|
|
1310
1320
|
defaults: {
|
|
1321
|
+
rootDir: "",
|
|
1311
1322
|
maxDepth: 5,
|
|
1312
1323
|
maxContextBudget: 1e4,
|
|
1313
1324
|
include: void 0,
|
|
@@ -1323,7 +1334,7 @@ async function contextAction(directory, options) {
|
|
|
1323
1334
|
return {
|
|
1324
1335
|
analyze: analyzeContext,
|
|
1325
1336
|
generateSummary,
|
|
1326
|
-
calculateScore: calculateContextScore
|
|
1337
|
+
calculateScore: (data, _resultsCount) => calculateContextScore(data)
|
|
1327
1338
|
};
|
|
1328
1339
|
},
|
|
1329
1340
|
renderConsole: ({ results: _results, summary, elapsedTime, score }) => {
|
|
@@ -1396,6 +1407,7 @@ async function consistencyAction(directory, options) {
|
|
|
1396
1407
|
label: "Consistency analysis",
|
|
1397
1408
|
emoji: "\u{1F4CF}",
|
|
1398
1409
|
defaults: {
|
|
1410
|
+
rootDir: "",
|
|
1399
1411
|
checkNaming: options.naming !== false,
|
|
1400
1412
|
checkPatterns: options.patterns !== false,
|
|
1401
1413
|
minSeverity: options.minSeverity || "info",
|
|
@@ -1416,7 +1428,7 @@ async function consistencyAction(directory, options) {
|
|
|
1416
1428
|
return report;
|
|
1417
1429
|
},
|
|
1418
1430
|
generateSummary,
|
|
1419
|
-
calculateScore: calculateConsistencyScore
|
|
1431
|
+
calculateScore: (data, resultsCount) => calculateConsistencyScore(data, resultsCount ?? 0)
|
|
1420
1432
|
};
|
|
1421
1433
|
},
|
|
1422
1434
|
renderConsole: ({ results: report, summary, elapsedTime, score }) => {
|
|
@@ -1731,10 +1743,10 @@ async function testabilityAction(directory, options) {
|
|
|
1731
1743
|
label: "Testability analysis",
|
|
1732
1744
|
emoji: "\u{1F9EA}",
|
|
1733
1745
|
defaults: {
|
|
1746
|
+
rootDir: "",
|
|
1734
1747
|
minCoverageRatio: 0.3,
|
|
1735
1748
|
include: void 0,
|
|
1736
|
-
exclude: void 0
|
|
1737
|
-
output: { format: "console", file: void 0 }
|
|
1749
|
+
exclude: void 0
|
|
1738
1750
|
},
|
|
1739
1751
|
getCliOptions: (opts) => ({
|
|
1740
1752
|
minCoverageRatio: opts.minCoverage ? parseFloat(opts.minCoverage) : void 0
|
|
@@ -1781,10 +1793,10 @@ async function contractEnforcementAction(directory, options) {
|
|
|
1781
1793
|
label: "Contract enforcement analysis",
|
|
1782
1794
|
emoji: "\u{1F6E1}\uFE0F",
|
|
1783
1795
|
defaults: {
|
|
1796
|
+
rootDir: "",
|
|
1784
1797
|
minChainDepth: 3,
|
|
1785
1798
|
include: void 0,
|
|
1786
|
-
exclude: void 0
|
|
1787
|
-
output: { format: "console", file: void 0 }
|
|
1799
|
+
exclude: void 0
|
|
1788
1800
|
},
|
|
1789
1801
|
getCliOptions: (opts) => ({
|
|
1790
1802
|
minChainDepth: opts.minChainDepth ? parseInt(opts.minChainDepth, 10) : void 0
|
|
@@ -1794,7 +1806,32 @@ async function contractEnforcementAction(directory, options) {
|
|
|
1794
1806
|
return {
|
|
1795
1807
|
analyze: tool.analyzeContractEnforcement,
|
|
1796
1808
|
generateSummary: (report) => report.summary,
|
|
1797
|
-
calculateScore:
|
|
1809
|
+
calculateScore: (data, resultsCount) => {
|
|
1810
|
+
const result = tool.calculateContractEnforcementScore(
|
|
1811
|
+
data,
|
|
1812
|
+
resultsCount ?? 0,
|
|
1813
|
+
resultsCount ?? 0
|
|
1814
|
+
);
|
|
1815
|
+
return {
|
|
1816
|
+
toolName: "contract-enforcement",
|
|
1817
|
+
score: result.score,
|
|
1818
|
+
rawMetrics: result.dimensions || {},
|
|
1819
|
+
factors: (result.recommendations || []).map(
|
|
1820
|
+
(rec, i) => ({
|
|
1821
|
+
name: `Recommendation ${i + 1}`,
|
|
1822
|
+
impact: 0,
|
|
1823
|
+
description: rec
|
|
1824
|
+
})
|
|
1825
|
+
),
|
|
1826
|
+
recommendations: (result.recommendations || []).map(
|
|
1827
|
+
(rec) => ({
|
|
1828
|
+
action: rec,
|
|
1829
|
+
estimatedImpact: 5,
|
|
1830
|
+
priority: "medium"
|
|
1831
|
+
})
|
|
1832
|
+
)
|
|
1833
|
+
};
|
|
1834
|
+
}
|
|
1798
1835
|
};
|
|
1799
1836
|
},
|
|
1800
1837
|
renderConsole: ({ results, summary, score }) => {
|
package/dist/index.js
CHANGED
|
@@ -64,7 +64,8 @@ var UnifiedOrchestrator = class {
|
|
|
64
64
|
this.registry = registry;
|
|
65
65
|
}
|
|
66
66
|
/**
|
|
67
|
-
* Deeply sanitizes a configuration object.
|
|
67
|
+
* Deeply sanitizes a configuration object for reporting.
|
|
68
|
+
* Strips internal infrastructure keys to prevent AI context clutter.
|
|
68
69
|
*/
|
|
69
70
|
sanitizeConfig(obj) {
|
|
70
71
|
if (!obj || typeof obj !== "object" || Array.isArray(obj)) return obj;
|
|
@@ -144,7 +145,10 @@ var UnifiedOrchestrator = class {
|
|
|
144
145
|
if (options.toolConfigs?.[provider.id]) {
|
|
145
146
|
Object.assign(toolOptions, options.toolConfigs[provider.id]);
|
|
146
147
|
} else if (options.tools && !Array.isArray(options.tools) && typeof options.tools === "object" && options.tools[provider.id]) {
|
|
147
|
-
Object.assign(
|
|
148
|
+
Object.assign(
|
|
149
|
+
toolOptions,
|
|
150
|
+
options.tools[provider.id]
|
|
151
|
+
);
|
|
148
152
|
}
|
|
149
153
|
toolOptions.onProgress = (processed, total, msg) => {
|
|
150
154
|
if (options.progressCallback) {
|
|
@@ -274,7 +278,19 @@ var ScoringOrchestrator = class {
|
|
|
274
278
|
if (toolScores.size === 0) {
|
|
275
279
|
return this.emptyScoringResult();
|
|
276
280
|
}
|
|
277
|
-
|
|
281
|
+
const scoringConfig = {
|
|
282
|
+
profile: options.profile,
|
|
283
|
+
threshold: options.threshold,
|
|
284
|
+
showBreakdown: options.scoring?.showBreakdown,
|
|
285
|
+
compareBaseline: options.compareTo,
|
|
286
|
+
tools: options.toolConfigs ? Object.fromEntries(
|
|
287
|
+
Object.entries(options.toolConfigs).map(([k, v]) => [
|
|
288
|
+
k,
|
|
289
|
+
v
|
|
290
|
+
])
|
|
291
|
+
) : void 0
|
|
292
|
+
};
|
|
293
|
+
return (0, import_core2.calculateOverallScore)(toolScores, scoringConfig, void 0);
|
|
278
294
|
}
|
|
279
295
|
/**
|
|
280
296
|
* Generate human-readable summary of unified results.
|
package/dist/index.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aiready/cli",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.7",
|
|
4
4
|
"description": "The unified CLI for Agentic Readiness. Optimize codebases for AI agents like Cursor, Windsurf, and Claude. Detect semantic duplicates, analyze context fragmentation, and improve agentic leverage.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -24,18 +24,18 @@
|
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"chalk": "^5.3.0",
|
|
26
26
|
"commander": "^14.0.0",
|
|
27
|
-
"@aiready/agent-grounding": "0.14.
|
|
28
|
-
"@aiready/consistency": "0.21.
|
|
29
|
-
"@aiready/
|
|
30
|
-
"@aiready/
|
|
31
|
-
"@aiready/
|
|
32
|
-
"@aiready/
|
|
33
|
-
"@aiready/change-amplification": "0.14.
|
|
34
|
-
"@aiready/
|
|
35
|
-
"@aiready/
|
|
36
|
-
"@aiready/testability": "0.7.
|
|
37
|
-
"@aiready/visualizer": "0.7.
|
|
38
|
-
"@aiready/
|
|
27
|
+
"@aiready/agent-grounding": "0.14.6",
|
|
28
|
+
"@aiready/consistency": "0.21.6",
|
|
29
|
+
"@aiready/core": "0.24.6",
|
|
30
|
+
"@aiready/context-analyzer": "0.22.6",
|
|
31
|
+
"@aiready/doc-drift": "0.14.6",
|
|
32
|
+
"@aiready/deps": "0.14.6",
|
|
33
|
+
"@aiready/change-amplification": "0.14.6",
|
|
34
|
+
"@aiready/contract-enforcement": "0.2.6",
|
|
35
|
+
"@aiready/pattern-detect": "0.17.6",
|
|
36
|
+
"@aiready/testability": "0.7.6",
|
|
37
|
+
"@aiready/visualizer": "0.7.6",
|
|
38
|
+
"@aiready/ai-signal-clarity": "0.14.8"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/node": "^24.0.0",
|