@aiready/cli 0.15.6 → 0.15.8

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.
@@ -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 || results;
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
- if (baseOptions.tools.includes(import_core6.ToolName.PatternDetect) || baseOptions.tools.includes("patterns")) {
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
- finalOptions.toolConfigs?.[import_core6.ToolName.PatternDetect] ?? {}
553
+ toolConfigs?.[import_core6.ToolName.PatternDetect] ?? {}
552
554
  );
553
555
  if (!finalOptions.toolConfigs) finalOptions.toolConfigs = {};
554
- finalOptions.toolConfigs[import_core6.ToolName.PatternDetect] = {
556
+ const configs = finalOptions.toolConfigs;
557
+ configs[import_core6.ToolName.PatternDetect] = {
555
558
  ...patternSmartDefaults,
556
- ...finalOptions.toolConfigs[import_core6.ToolName.PatternDetect]
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(toolOptions, options.tools[provider.id]);
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
- return (0, import_core8.calculateOverallScore)(toolScores, options, void 0);
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.
@@ -1156,7 +1175,7 @@ function defineScanCommand(program2) {
1156
1175
  ).option(
1157
1176
  "--exclude <patterns>",
1158
1177
  "File patterns to exclude (comma-separated)"
1159
- ).option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").option("--score", "Calculate and display AI Readiness Score (0-100)").option("--no-score", "Disable calculating AI Readiness Score").option("--weights <weights>", "Custom scoring weights").option(
1178
+ ).option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").option("--score", "Calculate and display AI Readiness Score (0-100)", true).option("--no-score", "Disable calculating AI Readiness Score").option("--weights <weights>", "Custom scoring weights").option(
1160
1179
  "--threshold <score>",
1161
1180
  "Fail CI/CD if score below threshold (0-100)"
1162
1181
  ).option(
@@ -1491,7 +1510,7 @@ function definePatternsCommand(program2) {
1491
1510
  ).option(
1492
1511
  "--exclude <patterns>",
1493
1512
  "File patterns to exclude (comma-separated)"
1494
- ).option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").option("--score", "Calculate and display AI Readiness Score (0-100)").option("--no-score", "Disable calculating AI Readiness Score").addHelpText("after", PATTERNS_HELP_TEXT).action(async (directory, options) => {
1513
+ ).option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").option("--score", "Calculate and display AI Readiness Score (0-100)", true).option("--no-score", "Disable calculating AI Readiness Score").addHelpText("after", PATTERNS_HELP_TEXT).action(async (directory, options) => {
1495
1514
  await patternsAction(directory, options);
1496
1515
  });
1497
1516
  }
@@ -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 { analyzePatterns, generateSummary, calculatePatternScore } = await import("@aiready/pattern-detect");
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(`\u{1F4C1} Files analyzed: ${import_chalk9.default.bold(results.length)}`)
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: tool.calculateContractEnforcementScore
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 }) => {
@@ -2464,7 +2517,7 @@ program.command("change-amplification").description("Analyze graph metrics for c
2464
2517
  "-o, --output <format>",
2465
2518
  "Output format: console, json",
2466
2519
  CLI_CONSTANTS.FORMATS.CONSOLE
2467
- ).option(CLI_CONSTANTS.OPTIONS.OUTPUT_FILE, "Output file path (for json)").action(async (directory, options) => {
2520
+ ).option(CLI_CONSTANTS.OPTIONS.OUTPUT_FILE, "Output file path (for json)").option("--score", "Calculate and display AI Readiness Score (0-100)", true).option("--no-score", "Disable calculating AI Readiness Score").action(async (directory, options) => {
2468
2521
  await (0, import_cli.changeAmplificationAction)(directory, options);
2469
2522
  });
2470
2523
  program.command("testability").description("Analyze test coverage and AI readiness").argument(
@@ -2485,7 +2538,7 @@ program.command("testability").description("Analyze test coverage and AI readine
2485
2538
  "-o, --output <format>",
2486
2539
  "Output format: console, json",
2487
2540
  CLI_CONSTANTS.FORMATS.CONSOLE
2488
- ).option(CLI_CONSTANTS.OPTIONS.OUTPUT_FILE, "Output file path (for json)").action(async (directory, options) => {
2541
+ ).option(CLI_CONSTANTS.OPTIONS.OUTPUT_FILE, "Output file path (for json)").option("--score", "Calculate and display AI Readiness Score (0-100)", true).option("--no-score", "Disable calculating AI Readiness Score").action(async (directory, options) => {
2489
2542
  await testabilityAction(directory, options);
2490
2543
  });
2491
2544
  program.command("contract").description("Analyze structural contract enforcement and defensive coding").argument(
@@ -2506,7 +2559,7 @@ program.command("contract").description("Analyze structural contract enforcement
2506
2559
  "-o, --output <format>",
2507
2560
  "Output format: console, json",
2508
2561
  CLI_CONSTANTS.FORMATS.CONSOLE
2509
- ).option(CLI_CONSTANTS.OPTIONS.OUTPUT_FILE, "Output file path (for json)").action(async (directory, options) => {
2562
+ ).option(CLI_CONSTANTS.OPTIONS.OUTPUT_FILE, "Output file path (for json)").option("--score", "Calculate and display AI Readiness Score (0-100)", true).option("--no-score", "Disable calculating AI Readiness Score").action(async (directory, options) => {
2510
2563
  await contractEnforcementAction(directory, options);
2511
2564
  });
2512
2565
  program.command("upload").description("Upload an AIReady report JSON to the platform").argument("<file>", "Report JSON file to upload").option(CLI_CONSTANTS.OPTIONS.API_KEY, "Platform API key").option(CLI_CONSTANTS.OPTIONS.REPO_ID, "Platform repository ID (optional)").option(CLI_CONSTANTS.OPTIONS.SERVER, "Custom platform URL").addHelpText("after", UPLOAD_HELP_TEXT).action(async (file, options) => {
package/dist/cli.mjs CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  __require,
4
4
  analyzeUnified,
5
5
  scoreUnified
6
- } from "./chunk-HX6H3VOE.mjs";
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 || results;
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
- if (baseOptions.tools.includes(ToolName2.PatternDetect) || baseOptions.tools.includes("patterns")) {
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
- finalOptions.toolConfigs?.[ToolName2.PatternDetect] ?? {}
558
+ toolConfigs?.[ToolName2.PatternDetect] ?? {}
557
559
  );
558
560
  if (!finalOptions.toolConfigs) finalOptions.toolConfigs = {};
559
- finalOptions.toolConfigs[ToolName2.PatternDetect] = {
561
+ const configs = finalOptions.toolConfigs;
562
+ configs[ToolName2.PatternDetect] = {
560
563
  ...patternSmartDefaults,
561
- ...finalOptions.toolConfigs[ToolName2.PatternDetect]
564
+ ...configs[ToolName2.PatternDetect]
562
565
  };
563
566
  }
564
567
  return finalOptions;
@@ -862,7 +865,7 @@ function defineScanCommand(program2) {
862
865
  ).option(
863
866
  "--exclude <patterns>",
864
867
  "File patterns to exclude (comma-separated)"
865
- ).option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").option("--score", "Calculate and display AI Readiness Score (0-100)").option("--no-score", "Disable calculating AI Readiness Score").option("--weights <weights>", "Custom scoring weights").option(
868
+ ).option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").option("--score", "Calculate and display AI Readiness Score (0-100)", true).option("--no-score", "Disable calculating AI Readiness Score").option("--weights <weights>", "Custom scoring weights").option(
866
869
  "--threshold <score>",
867
870
  "Fail CI/CD if score below threshold (0-100)"
868
871
  ).option(
@@ -1200,7 +1203,7 @@ function definePatternsCommand(program2) {
1200
1203
  ).option(
1201
1204
  "--exclude <patterns>",
1202
1205
  "File patterns to exclude (comma-separated)"
1203
- ).option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").option("--score", "Calculate and display AI Readiness Score (0-100)").option("--no-score", "Disable calculating AI Readiness Score").addHelpText("after", PATTERNS_HELP_TEXT).action(async (directory, options) => {
1206
+ ).option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").option("--score", "Calculate and display AI Readiness Score (0-100)", true).option("--no-score", "Disable calculating AI Readiness Score").addHelpText("after", PATTERNS_HELP_TEXT).action(async (directory, options) => {
1204
1207
  await patternsAction(directory, options);
1205
1208
  });
1206
1209
  }
@@ -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 { analyzePatterns, generateSummary, calculatePatternScore } = await import("@aiready/pattern-detect");
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(`\u{1F4C1} Files analyzed: ${chalk9.bold(results.length)}`)
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: tool.calculateContractEnforcementScore
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 }) => {
@@ -2172,7 +2209,7 @@ program.command("change-amplification").description("Analyze graph metrics for c
2172
2209
  "-o, --output <format>",
2173
2210
  "Output format: console, json",
2174
2211
  CLI_CONSTANTS.FORMATS.CONSOLE
2175
- ).option(CLI_CONSTANTS.OPTIONS.OUTPUT_FILE, "Output file path (for json)").action(async (directory, options) => {
2212
+ ).option(CLI_CONSTANTS.OPTIONS.OUTPUT_FILE, "Output file path (for json)").option("--score", "Calculate and display AI Readiness Score (0-100)", true).option("--no-score", "Disable calculating AI Readiness Score").action(async (directory, options) => {
2176
2213
  await changeAmplificationAction(directory, options);
2177
2214
  });
2178
2215
  program.command("testability").description("Analyze test coverage and AI readiness").argument(
@@ -2193,7 +2230,7 @@ program.command("testability").description("Analyze test coverage and AI readine
2193
2230
  "-o, --output <format>",
2194
2231
  "Output format: console, json",
2195
2232
  CLI_CONSTANTS.FORMATS.CONSOLE
2196
- ).option(CLI_CONSTANTS.OPTIONS.OUTPUT_FILE, "Output file path (for json)").action(async (directory, options) => {
2233
+ ).option(CLI_CONSTANTS.OPTIONS.OUTPUT_FILE, "Output file path (for json)").option("--score", "Calculate and display AI Readiness Score (0-100)", true).option("--no-score", "Disable calculating AI Readiness Score").action(async (directory, options) => {
2197
2234
  await testabilityAction(directory, options);
2198
2235
  });
2199
2236
  program.command("contract").description("Analyze structural contract enforcement and defensive coding").argument(
@@ -2214,7 +2251,7 @@ program.command("contract").description("Analyze structural contract enforcement
2214
2251
  "-o, --output <format>",
2215
2252
  "Output format: console, json",
2216
2253
  CLI_CONSTANTS.FORMATS.CONSOLE
2217
- ).option(CLI_CONSTANTS.OPTIONS.OUTPUT_FILE, "Output file path (for json)").action(async (directory, options) => {
2254
+ ).option(CLI_CONSTANTS.OPTIONS.OUTPUT_FILE, "Output file path (for json)").option("--score", "Calculate and display AI Readiness Score (0-100)", true).option("--no-score", "Disable calculating AI Readiness Score").action(async (directory, options) => {
2218
2255
  await contractEnforcementAction(directory, options);
2219
2256
  });
2220
2257
  program.command("upload").description("Upload an AIReady report JSON to the platform").argument("<file>", "Report JSON file to upload").option(CLI_CONSTANTS.OPTIONS.API_KEY, "Platform API key").option(CLI_CONSTANTS.OPTIONS.REPO_ID, "Platform repository ID (optional)").option(CLI_CONSTANTS.OPTIONS.SERVER, "Custom platform URL").addHelpText("after", UPLOAD_HELP_TEXT).action(async (file, options) => {
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(toolOptions, options.tools[provider.id]);
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
- return (0, import_core2.calculateOverallScore)(toolScores, options, void 0);
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
@@ -5,7 +5,7 @@ import {
5
5
  analyzeUnified,
6
6
  generateUnifiedSummary,
7
7
  scoreUnified
8
- } from "./chunk-HX6H3VOE.mjs";
8
+ } from "./chunk-OLJA25SP.mjs";
9
9
  export {
10
10
  ScoringOrchestrator,
11
11
  TOOL_PACKAGE_MAP,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiready/cli",
3
- "version": "0.15.6",
3
+ "version": "0.15.8",
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.5",
28
- "@aiready/consistency": "0.21.5",
29
- "@aiready/context-analyzer": "0.22.5",
30
- "@aiready/deps": "0.14.5",
31
- "@aiready/core": "0.24.5",
32
- "@aiready/doc-drift": "0.14.5",
33
- "@aiready/change-amplification": "0.14.5",
34
- "@aiready/pattern-detect": "0.17.5",
35
- "@aiready/ai-signal-clarity": "0.14.7",
36
- "@aiready/testability": "0.7.5",
37
- "@aiready/visualizer": "0.7.5",
38
- "@aiready/contract-enforcement": "0.2.5"
27
+ "@aiready/agent-grounding": "0.14.6",
28
+ "@aiready/consistency": "0.21.6",
29
+ "@aiready/context-analyzer": "0.22.6",
30
+ "@aiready/core": "0.24.6",
31
+ "@aiready/deps": "0.14.6",
32
+ "@aiready/contract-enforcement": "0.2.6",
33
+ "@aiready/change-amplification": "0.14.6",
34
+ "@aiready/doc-drift": "0.14.6",
35
+ "@aiready/ai-signal-clarity": "0.14.8",
36
+ "@aiready/testability": "0.7.6",
37
+ "@aiready/visualizer": "0.7.6",
38
+ "@aiready/pattern-detect": "0.17.6"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@types/node": "^24.0.0",