@aiready/cli 0.14.9 → 0.14.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.mjs CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  __require,
4
4
  analyzeUnified,
5
5
  scoreUnified
6
- } from "./chunk-VOKP7FGM.mjs";
6
+ } from "./chunk-JRRBBFYB.mjs";
7
7
 
8
8
  // src/cli.ts
9
9
  import { Command } from "commander";
@@ -134,7 +134,7 @@ import {
134
134
  function printScanSummary(results, startTime) {
135
135
  console.log(chalk2.cyan("\n=== AIReady Run Summary ==="));
136
136
  console.log(
137
- ` Total issues (all tools): ${chalk2.bold(String(results.summary.totalIssues || 0))}`
137
+ ` Total issues (all tools): ${chalk2.bold(String(results.summary.totalIssues ?? 0))}`
138
138
  );
139
139
  console.log(
140
140
  ` Execution time: ${chalk2.bold(((Date.now() - startTime) / 1e3).toFixed(2) + "s")}`
@@ -169,7 +169,7 @@ function printScoring(scoringResult, scoringProfile) {
169
169
  );
170
170
  });
171
171
  const allRecs = scoringResult.breakdown.flatMap(
172
- (t) => (t.recommendations || []).map((r) => ({ ...r, tool: t.toolName }))
172
+ (t) => (t.recommendations ?? []).map((r) => ({ ...r, tool: t.toolName }))
173
173
  ).sort((a, b) => b.estimatedImpact - a.estimatedImpact).slice(0, 3);
174
174
  if (allRecs.length > 0) {
175
175
  console.log(chalk2.bold("\n\u{1F3AF} Top Actionable Recommendations:"));
@@ -223,8 +223,8 @@ import { handleCLIError } from "@aiready/core";
223
223
  async function uploadAction(file, options) {
224
224
  const startTime = Date.now();
225
225
  const filePath = resolvePath2(process.cwd(), file);
226
- const serverUrl = options.server || process.env.AIREADY_SERVER || "https://dev.platform.getaiready.dev";
227
- const apiKey = options.apiKey || process.env.AIREADY_API_KEY;
226
+ const serverUrl = options.server ?? process.env.AIREADY_SERVER ?? "https://dev.platform.getaiready.dev";
227
+ const apiKey = options.apiKey ?? process.env.AIREADY_API_KEY;
228
228
  if (!apiKey) {
229
229
  console.error(chalk3.red("\u274C API Key is required for upload."));
230
230
  console.log(
@@ -249,7 +249,7 @@ async function uploadAction(file, options) {
249
249
  const reportContent = fs.readFileSync(filePath, "utf-8");
250
250
  const reportData = JSON.parse(reportContent);
251
251
  console.log(chalk3.dim(` Successfully parsed report JSON.`));
252
- const repoId = options.repoId || reportData.repository?.repoId;
252
+ const repoId = options.repoId ?? reportData.repository?.repoId;
253
253
  const response = await fetch(`${serverUrl}/api/analysis/upload`, {
254
254
  method: "POST",
255
255
  headers: {
@@ -268,12 +268,12 @@ async function uploadAction(file, options) {
268
268
  uploadResult = await response.json();
269
269
  } else {
270
270
  const text = await response.text();
271
- uploadResult = { error: text || response.statusText };
271
+ uploadResult = { error: text ?? response.statusText };
272
272
  }
273
273
  if (!response.ok) {
274
274
  console.error(
275
275
  chalk3.red(
276
- `\u274C Upload failed: ${uploadResult.error || response.statusText}`
276
+ `\u274C Upload failed: ${uploadResult.error ?? response.statusText}`
277
277
  )
278
278
  );
279
279
  if (contentType?.includes("text/html")) {
@@ -324,7 +324,7 @@ ENVIRONMENT VARIABLES:
324
324
  async function scanAction(directory, options) {
325
325
  console.log(chalk4.blue("\u{1F680} Starting AIReady unified analysis...\n"));
326
326
  const startTime = Date.now();
327
- const resolvedDir = resolvePath3(process.cwd(), directory || ".");
327
+ const resolvedDir = resolvePath3(process.cwd(), directory ?? ".");
328
328
  const repoMetadata = getRepoMetadata(resolvedDir);
329
329
  try {
330
330
  const defaults = {
@@ -414,7 +414,7 @@ async function scanAction(directory, options) {
414
414
  const { getSmartDefaults } = await import("@aiready/pattern-detect");
415
415
  const patternSmartDefaults = await getSmartDefaults(
416
416
  resolvedDir,
417
- finalOptions.toolConfigs?.[ToolName.PatternDetect] || {}
417
+ finalOptions.toolConfigs?.[ToolName.PatternDetect] ?? {}
418
418
  );
419
419
  if (!finalOptions.toolConfigs) finalOptions.toolConfigs = {};
420
420
  finalOptions.toolConfigs[ToolName.PatternDetect] = {
@@ -425,7 +425,7 @@ async function scanAction(directory, options) {
425
425
  console.log(chalk4.cyan("\n=== AIReady Run Preview ==="));
426
426
  console.log(
427
427
  chalk4.white("Tools to run:"),
428
- (finalOptions.tools || []).join(", ")
428
+ (finalOptions.tools ?? []).join(", ")
429
429
  );
430
430
  const progressCallback = (event) => {
431
431
  if (event.message) {
@@ -446,7 +446,7 @@ async function scanAction(directory, options) {
446
446
  );
447
447
  }
448
448
  };
449
- const scoringProfile = options.profile || baseOptions.scoring?.profile || "default";
449
+ const scoringProfile = options.profile ?? baseOptions.scoring?.profile ?? "default";
450
450
  const results = await analyzeUnified({
451
451
  ...finalOptions,
452
452
  progressCallback,
@@ -470,7 +470,7 @@ async function scanAction(directory, options) {
470
470
  const prevReport = JSON.parse(
471
471
  readFileSync2(resolvePath3(process.cwd(), options.compareTo), "utf8")
472
472
  );
473
- const prevScore = prevReport.scoring?.overall || prevReport.scoring?.score;
473
+ const prevScore = prevReport.scoring?.overall ?? prevReport.scoring?.score;
474
474
  if (typeof prevScore === "number") {
475
475
  const diff = scoringResult.overall - prevScore;
476
476
  const diffStr = diff > 0 ? `+${diff}` : String(diff);
@@ -497,17 +497,17 @@ async function scanAction(directory, options) {
497
497
  void e;
498
498
  }
499
499
  }
500
- const totalWastedDuplication = (scoringResult.breakdown || []).reduce(
501
- (sum, s) => sum + (s.tokenBudget?.wastedTokens.bySource.duplication || 0),
500
+ const totalWastedDuplication = (scoringResult.breakdown ?? []).reduce(
501
+ (sum, s) => sum + (s.tokenBudget?.wastedTokens?.bySource?.duplication ?? 0),
502
502
  0
503
503
  );
504
- const totalWastedFragmentation = (scoringResult.breakdown || []).reduce(
505
- (sum, s) => sum + (s.tokenBudget?.wastedTokens.bySource.fragmentation || 0),
504
+ const totalWastedFragmentation = (scoringResult.breakdown ?? []).reduce(
505
+ (sum, s) => sum + (s.tokenBudget?.wastedTokens?.bySource?.fragmentation ?? 0),
506
506
  0
507
507
  );
508
508
  const totalContext = Math.max(
509
- ...(scoringResult.breakdown || []).map(
510
- (s) => s.tokenBudget?.totalContextTokens || 0
509
+ ...(scoringResult.breakdown ?? []).map(
510
+ (s) => s.tokenBudget?.totalContextTokens ?? 0
511
511
  ),
512
512
  0
513
513
  );
@@ -531,7 +531,7 @@ async function scanAction(directory, options) {
531
531
  });
532
532
  }
533
533
  }
534
- const modelId = options.model || "claude-3-5-sonnet";
534
+ const modelId = options.model ?? "gpt-5.4-mini";
535
535
  const roi = (await import("@aiready/core")).calculateBusinessROI({
536
536
  tokenWaste: unifiedBudget.wastedTokens.total,
537
537
  issues: allIssues,
@@ -568,9 +568,9 @@ async function scanAction(directory, options) {
568
568
  ...mapToUnifiedReport(results, scoringResult),
569
569
  repository: repoMetadata
570
570
  };
571
- const outputFormat = options.output || finalOptions.output?.format || "console";
571
+ const outputFormat = options.output ?? finalOptions.output?.format ?? "console";
572
572
  const outputPath = resolveOutputPath(
573
- options.outputFile || finalOptions.output?.file,
573
+ options.outputFile ?? finalOptions.output?.file,
574
574
  `aiready-report-${getReportTimestamp()}.json`,
575
575
  resolvedDir
576
576
  );
@@ -597,8 +597,8 @@ async function scanAction(directory, options) {
597
597
  await warnIfGraphCapExceeded(outputData, resolvedDir);
598
598
  if (scoringResult) {
599
599
  const threshold = options.threshold ? parseInt(options.threshold) : void 0;
600
- const failOnLevel = options.failOn || "critical";
601
- const isCI = options.ci || process.env.CI === "true";
600
+ const failOnLevel = options.failOn ?? "critical";
601
+ const isCI = options.ci ?? process.env.CI === "true";
602
602
  let shouldFail = false;
603
603
  let failReason = "";
604
604
  const report = mapToUnifiedReport(results, scoringResult);
@@ -789,7 +789,7 @@ import {
789
789
  async function patternsAction(directory, options) {
790
790
  console.log(chalk6.blue("\u{1F50D} Analyzing patterns...\n"));
791
791
  const startTime = Date.now();
792
- const resolvedDir = resolvePath4(process.cwd(), directory || ".");
792
+ const resolvedDir = resolvePath4(process.cwd(), directory ?? ".");
793
793
  try {
794
794
  const useSmartDefaults = !options.fullScan;
795
795
  const defaults = {
@@ -833,8 +833,8 @@ async function patternsAction(directory, options) {
833
833
  if (options.score) {
834
834
  patternScore = calculatePatternScore(duplicates, results.length);
835
835
  }
836
- const outputFormat = options.output || finalOptions.output?.format || "console";
837
- const userOutputFile = options.outputFile || finalOptions.output?.file;
836
+ const outputFormat = options.output ?? finalOptions.output?.format ?? "console";
837
+ const userOutputFile = options.outputFile ?? finalOptions.output?.file;
838
838
  if (outputFormat === "json") {
839
839
  const outputData = {
840
840
  results,
@@ -942,7 +942,7 @@ import {
942
942
  async function contextAction(directory, options) {
943
943
  console.log(chalk7.blue("\u{1F9E0} Analyzing context costs...\n"));
944
944
  const startTime = Date.now();
945
- const resolvedDir = resolvePath5(process.cwd(), directory || ".");
945
+ const resolvedDir = resolvePath5(process.cwd(), directory ?? ".");
946
946
  try {
947
947
  const defaults = {
948
948
  maxDepth: 5,
@@ -986,8 +986,8 @@ async function contextAction(directory, options) {
986
986
  if (options.score) {
987
987
  contextScore = calculateContextScore(summary);
988
988
  }
989
- const outputFormat = options.output || finalOptions.output?.format || "console";
990
- const userOutputFile = options.outputFile || finalOptions.output?.file;
989
+ const outputFormat = options.output ?? finalOptions.output?.format ?? "console";
990
+ const userOutputFile = options.outputFile ?? finalOptions.output?.file;
991
991
  if (outputFormat === "json") {
992
992
  const outputData = {
993
993
  results,
@@ -1005,7 +1005,7 @@ async function contextAction(directory, options) {
1005
1005
  `\u2705 Results saved to ${outputPath}`
1006
1006
  );
1007
1007
  } else {
1008
- const terminalWidth = process.stdout.columns || 80;
1008
+ const terminalWidth = process.stdout.columns ?? 80;
1009
1009
  const dividerWidth = Math.min(60, terminalWidth - 2);
1010
1010
  const divider = "\u2501".repeat(dividerWidth);
1011
1011
  console.log(chalk7.cyan(divider));
@@ -1150,7 +1150,7 @@ import {
1150
1150
  async function consistencyAction(directory, options) {
1151
1151
  console.log(chalk8.blue("\u{1F50D} Analyzing consistency...\n"));
1152
1152
  const startTime = Date.now();
1153
- const resolvedDir = resolvePath6(process.cwd(), directory || ".");
1153
+ const resolvedDir = resolvePath6(process.cwd(), directory ?? ".");
1154
1154
  try {
1155
1155
  const defaults = {
1156
1156
  checkNaming: true,
@@ -1175,14 +1175,14 @@ async function consistencyAction(directory, options) {
1175
1175
  const elapsedTime = getElapsedTime3(startTime);
1176
1176
  let consistencyScore;
1177
1177
  if (options.score) {
1178
- const issues = report.results?.flatMap((r) => r.issues) || [];
1178
+ const issues = report.results?.flatMap((r) => r.issues) ?? [];
1179
1179
  consistencyScore = calculateConsistencyScore(
1180
1180
  issues,
1181
1181
  report.summary.filesAnalyzed
1182
1182
  );
1183
1183
  }
1184
- const outputFormat = options.output || finalOptions.output?.format || "console";
1185
- const userOutputFile = options.outputFile || finalOptions.output?.file;
1184
+ const outputFormat = options.output ?? finalOptions.output?.format ?? "console";
1185
+ const userOutputFile = options.outputFile ?? finalOptions.output?.file;
1186
1186
  if (outputFormat === "json") {
1187
1187
  const outputData = {
1188
1188
  ...report,
@@ -1220,7 +1220,7 @@ async function consistencyAction(directory, options) {
1220
1220
  console.log(` Naming: ${chalk8.yellow(report.summary.namingIssues)}`);
1221
1221
  console.log(` Patterns: ${chalk8.yellow(report.summary.patternIssues)}`);
1222
1222
  console.log(
1223
- ` Architecture: ${chalk8.yellow(report.summary.architectureIssues || 0)}`
1223
+ ` Architecture: ${chalk8.yellow(report.summary.architectureIssues ?? 0)}`
1224
1224
  );
1225
1225
  console.log(`Analysis Time: ${chalk8.gray(elapsedTime + "s")}
1226
1226
  `);
@@ -1319,7 +1319,7 @@ import { handleCLIError as handleCLIError6 } from "@aiready/core";
1319
1319
  import { generateHTML, findLatestReport as findLatestReport2 } from "@aiready/core";
1320
1320
  async function visualizeAction(directory, options) {
1321
1321
  try {
1322
- const dirPath = resolvePath7(process.cwd(), directory || ".");
1322
+ const dirPath = resolvePath7(process.cwd(), directory ?? ".");
1323
1323
  let reportPath = options.report ? resolvePath7(dirPath, options.report) : null;
1324
1324
  if (!reportPath || !existsSync3(reportPath)) {
1325
1325
  const latestScan = findLatestReport2(dirPath);
@@ -1365,7 +1365,7 @@ Or specify a custom report:
1365
1365
  console.log("Building graph from report...");
1366
1366
  const { GraphBuilder } = await import("@aiready/visualizer/graph");
1367
1367
  const graph = GraphBuilder.buildFromReport(report, dirPath);
1368
- let useDevMode = options.dev || false;
1368
+ let useDevMode = options.dev ?? false;
1369
1369
  let devServerStarted = false;
1370
1370
  if (useDevMode) {
1371
1371
  try {
@@ -1481,7 +1481,7 @@ Or specify a custom report:
1481
1481
  console.log("Generating HTML...");
1482
1482
  const html = generateHTML(graph);
1483
1483
  const defaultOutput = "visualization.html";
1484
- const outPath = resolvePath7(dirPath, options.output || defaultOutput);
1484
+ const outPath = resolvePath7(dirPath, options.output ?? defaultOutput);
1485
1485
  writeFileSync4(outPath, html, "utf8");
1486
1486
  console.log(chalk9.green(`\u2705 Visualization written to: ${outPath}`));
1487
1487
  if (options.open || options.serve) {
@@ -1493,7 +1493,7 @@ Or specify a custom report:
1493
1493
  const fsp = await import("fs/promises");
1494
1494
  const server = http.createServer(async (req, res) => {
1495
1495
  try {
1496
- const urlPath = req.url || "/";
1496
+ const urlPath = req.url ?? "/";
1497
1497
  if (urlPath === "/" || urlPath === "/index.html") {
1498
1498
  const content = await fsp.readFile(outPath, "utf8");
1499
1499
  res.writeHead(200, {
@@ -1631,7 +1631,7 @@ async function bugAction(message, options) {
1631
1631
  const repoUrl = "https://github.com/caopengau/aiready-cli";
1632
1632
  const repoSlug = "caopengau/aiready-cli";
1633
1633
  if (message) {
1634
- const type = options.type || "bug";
1634
+ const type = options.type ?? "bug";
1635
1635
  const title = `[${type.toUpperCase()}] ${message}`;
1636
1636
  const label = type === "bug" ? "bug" : type === "feature" ? "enhancement" : "metric";
1637
1637
  const body = `
package/dist/index.js CHANGED
@@ -84,7 +84,7 @@ function sanitizeToolConfig(config) {
84
84
  async function analyzeUnified(options) {
85
85
  await (0, import_core.initializeParsers)();
86
86
  const startTime = Date.now();
87
- const requestedTools = options.tools || [
87
+ const requestedTools = options.tools ?? [
88
88
  "patterns",
89
89
  "context",
90
90
  "consistency"
@@ -106,7 +106,7 @@ async function analyzeUnified(options) {
106
106
  for (const toolName of requestedTools) {
107
107
  let provider = import_core.ToolRegistry.find(toolName);
108
108
  if (!provider) {
109
- const packageName = TOOL_PACKAGE_MAP[toolName] || (toolName.startsWith("@aiready/") ? toolName : `@aiready/${toolName}`);
109
+ const packageName = TOOL_PACKAGE_MAP[toolName] ?? (toolName.startsWith("@aiready/") ? toolName : `@aiready/${toolName}`);
110
110
  try {
111
111
  await import(packageName);
112
112
  provider = import_core.ToolRegistry.find(toolName);
@@ -184,29 +184,15 @@ async function analyzeUnified(options) {
184
184
  } else {
185
185
  result.summary.toolConfigs[provider.id] = sanitizeToolConfig(toolOptions);
186
186
  }
187
- const toolFiles = output.summary?.totalFiles || output.summary?.filesAnalyzed || 0;
187
+ const toolFiles = output.summary?.totalFiles ?? output.summary?.filesAnalyzed ?? 0;
188
188
  if (toolFiles > result.summary.totalFiles) {
189
189
  result.summary.totalFiles = toolFiles;
190
190
  }
191
191
  const issueCount = output.results.reduce(
192
- (sum, file) => sum + (file.issues?.length || 0),
192
+ (sum, file) => sum + (file.issues?.length ?? 0),
193
193
  0
194
194
  );
195
195
  result.summary.totalIssues += issueCount;
196
- if (provider.alias && Array.isArray(provider.alias)) {
197
- for (const alias of provider.alias) {
198
- if (!result[alias]) {
199
- result[alias] = output;
200
- }
201
- }
202
- }
203
- const camelCaseId = provider.id.replace(
204
- /-([a-z])/g,
205
- (g) => g[1].toUpperCase()
206
- );
207
- if (camelCaseId !== provider.id && !result[camelCaseId]) {
208
- result[camelCaseId] = output;
209
- }
210
196
  } catch (err) {
211
197
  console.error(`\u274C Error running tool '${provider.id}':`, err);
212
198
  }
@@ -221,6 +207,24 @@ async function analyzeUnified(options) {
221
207
  tools: result.summary.toolConfigs
222
208
  });
223
209
  result.summary.executionTime = Date.now() - startTime;
210
+ const keyMappings = {
211
+ "pattern-detect": ["patternDetect", "patterns"],
212
+ "context-analyzer": ["contextAnalyzer", "context"],
213
+ "naming-consistency": ["namingConsistency", "consistency"],
214
+ "ai-signal-clarity": ["aiSignalClarity"],
215
+ "agent-grounding": ["agentGrounding"],
216
+ "testability-index": ["testabilityIndex", "testability"],
217
+ "doc-drift": ["docDrift"],
218
+ "dependency-health": ["dependencyHealth", "deps"],
219
+ "change-amplification": ["changeAmplification"]
220
+ };
221
+ for (const [kebabKey, aliases] of Object.entries(keyMappings)) {
222
+ if (result[kebabKey]) {
223
+ for (const alias of aliases) {
224
+ result[alias] = result[kebabKey];
225
+ }
226
+ }
227
+ }
224
228
  return result;
225
229
  }
226
230
  async function scoreUnified(results, options) {
@@ -235,7 +239,7 @@ async function scoreUnified(results, options) {
235
239
  if (!toolScore.tokenBudget) {
236
240
  if (toolId === import_core.ToolName.PatternDetect && output.duplicates) {
237
241
  const wastedTokens = output.duplicates.reduce(
238
- (sum, d) => sum + (d.tokenCost || 0),
242
+ (sum, d) => sum + (d.tokenCost ?? 0),
239
243
  0
240
244
  );
241
245
  toolScore.tokenBudget = (0, import_core.calculateTokenBudget)({
@@ -251,7 +255,7 @@ async function scoreUnified(results, options) {
251
255
  totalContextTokens: output.summary.totalTokens,
252
256
  wastedTokens: {
253
257
  duplication: 0,
254
- fragmentation: output.summary.totalPotentialSavings || 0,
258
+ fragmentation: output.summary.totalPotentialSavings ?? 0,
255
259
  chattiness: 0
256
260
  }
257
261
  });
@@ -296,7 +300,7 @@ function generateUnifiedSummary(result) {
296
300
  const toolResult = result[provider.id];
297
301
  if (toolResult) {
298
302
  const issueCount = toolResult.results.reduce(
299
- (sum, r) => sum + (r.issues?.length || 0),
303
+ (sum, r) => sum + (r.issues?.length ?? 0),
300
304
  0
301
305
  );
302
306
  output += `\u2022 ${provider.id}: ${issueCount} issues
package/dist/index.mjs CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  analyzeUnified,
3
3
  generateUnifiedSummary,
4
4
  scoreUnified
5
- } from "./chunk-VOKP7FGM.mjs";
5
+ } from "./chunk-JRRBBFYB.mjs";
6
6
  export {
7
7
  analyzeUnified,
8
8
  generateUnifiedSummary,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiready/cli",
3
- "version": "0.14.9",
3
+ "version": "0.14.10",
4
4
  "description": "Unified CLI for AIReady analysis tools",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -11,17 +11,17 @@
11
11
  "dependencies": {
12
12
  "chalk": "^5.3.0",
13
13
  "commander": "^14.0.0",
14
- "@aiready/agent-grounding": "0.13.6",
15
- "@aiready/consistency": "0.20.6",
16
- "@aiready/context-analyzer": "0.21.10",
17
- "@aiready/core": "0.23.7",
18
- "@aiready/deps": "0.13.6",
19
- "@aiready/change-amplification": "0.13.6",
20
- "@aiready/visualizer": "0.6.6",
21
- "@aiready/ai-signal-clarity": "0.13.7",
22
- "@aiready/pattern-detect": "0.16.6",
23
- "@aiready/testability": "0.6.6",
24
- "@aiready/doc-drift": "0.13.6"
14
+ "@aiready/agent-grounding": "0.13.7",
15
+ "@aiready/consistency": "0.20.7",
16
+ "@aiready/core": "0.23.8",
17
+ "@aiready/deps": "0.13.7",
18
+ "@aiready/context-analyzer": "0.21.11",
19
+ "@aiready/doc-drift": "0.13.7",
20
+ "@aiready/change-amplification": "0.13.7",
21
+ "@aiready/ai-signal-clarity": "0.13.8",
22
+ "@aiready/pattern-detect": "0.16.7",
23
+ "@aiready/testability": "0.6.7",
24
+ "@aiready/visualizer": "0.6.7"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@types/node": "^24.0.0",
@@ -11,7 +11,7 @@ export async function bugAction(message: string | undefined, options: any) {
11
11
 
12
12
  if (message) {
13
13
  // Agent-assisted pre-filled issue
14
- const type = options.type || 'bug';
14
+ const type = options.type ?? 'bug';
15
15
  const title = `[${type.toUpperCase()}] ${message}`;
16
16
  const label =
17
17
  type === 'bug' ? 'bug' : type === 'feature' ? 'enhancement' : 'metric';
@@ -34,7 +34,7 @@ export async function consistencyAction(
34
34
  console.log(chalk.blue('šŸ” Analyzing consistency...\n'));
35
35
 
36
36
  const startTime = Date.now();
37
- const resolvedDir = resolvePath(process.cwd(), directory || '.');
37
+ const resolvedDir = resolvePath(process.cwd(), directory ?? '.');
38
38
 
39
39
  try {
40
40
  // Define defaults
@@ -69,7 +69,7 @@ export async function consistencyAction(
69
69
  // Calculate score if requested
70
70
  let consistencyScore: ToolScoringOutput | undefined;
71
71
  if (options.score) {
72
- const issues = report.results?.flatMap((r: any) => r.issues) || [];
72
+ const issues = report.results?.flatMap((r: any) => r.issues) ?? [];
73
73
  consistencyScore = calculateConsistencyScore(
74
74
  issues,
75
75
  report.summary.filesAnalyzed
@@ -77,8 +77,8 @@ export async function consistencyAction(
77
77
  }
78
78
 
79
79
  const outputFormat =
80
- options.output || finalOptions.output?.format || 'console';
81
- const userOutputFile = options.outputFile || finalOptions.output?.file;
80
+ options.output ?? finalOptions.output?.format ?? 'console';
81
+ const userOutputFile = options.outputFile ?? finalOptions.output?.file;
82
82
 
83
83
  if (outputFormat === 'json') {
84
84
  const outputData = {
@@ -121,7 +121,7 @@ export async function consistencyAction(
121
121
  console.log(` Naming: ${chalk.yellow(report.summary.namingIssues)}`);
122
122
  console.log(` Patterns: ${chalk.yellow(report.summary.patternIssues)}`);
123
123
  console.log(
124
- ` Architecture: ${chalk.yellow(report.summary.architectureIssues || 0)}`
124
+ ` Architecture: ${chalk.yellow(report.summary.architectureIssues ?? 0)}`
125
125
  );
126
126
  console.log(`Analysis Time: ${chalk.gray(elapsedTime + 's')}\n`);
127
127
 
@@ -32,7 +32,7 @@ export async function contextAction(
32
32
  console.log(chalk.blue('🧠 Analyzing context costs...\n'));
33
33
 
34
34
  const startTime = Date.now();
35
- const resolvedDir = resolvePath(process.cwd(), directory || '.');
35
+ const resolvedDir = resolvePath(process.cwd(), directory ?? '.');
36
36
 
37
37
  try {
38
38
  // Define defaults
@@ -94,8 +94,8 @@ export async function contextAction(
94
94
  }
95
95
 
96
96
  const outputFormat =
97
- options.output || finalOptions.output?.format || 'console';
98
- const userOutputFile = options.outputFile || finalOptions.output?.file;
97
+ options.output ?? finalOptions.output?.format ?? 'console';
98
+ const userOutputFile = options.outputFile ?? finalOptions.output?.file;
99
99
 
100
100
  if (outputFormat === 'json') {
101
101
  const outputData = {
@@ -117,7 +117,7 @@ export async function contextAction(
117
117
  );
118
118
  } else {
119
119
  // Console output - format the results nicely
120
- const terminalWidth = process.stdout.columns || 80;
120
+ const terminalWidth = process.stdout.columns ?? 80;
121
121
  const dividerWidth = Math.min(60, terminalWidth - 2);
122
122
  const divider = '━'.repeat(dividerWidth);
123
123
 
@@ -35,7 +35,7 @@ export async function patternsAction(
35
35
  console.log(chalk.blue('šŸ” Analyzing patterns...\n'));
36
36
 
37
37
  const startTime = Date.now();
38
- const resolvedDir = resolvePath(process.cwd(), directory || '.');
38
+ const resolvedDir = resolvePath(process.cwd(), directory ?? '.');
39
39
 
40
40
  try {
41
41
  // Determine if smart defaults should be used
@@ -100,8 +100,8 @@ export async function patternsAction(
100
100
  }
101
101
 
102
102
  const outputFormat =
103
- options.output || finalOptions.output?.format || 'console';
104
- const userOutputFile = options.outputFile || finalOptions.output?.file;
103
+ options.output ?? finalOptions.output?.format ?? 'console';
104
+ const userOutputFile = options.outputFile ?? finalOptions.output?.file;
105
105
 
106
106
  if (outputFormat === 'json') {
107
107
  const outputData = {
@@ -16,7 +16,7 @@ import {
16
16
  export function printScanSummary(results: any, startTime: number) {
17
17
  console.log(chalk.cyan('\n=== AIReady Run Summary ==='));
18
18
  console.log(
19
- ` Total issues (all tools): ${chalk.bold(String(results.summary.totalIssues || 0))}`
19
+ ` Total issues (all tools): ${chalk.bold(String(results.summary.totalIssues ?? 0))}`
20
20
  );
21
21
  console.log(
22
22
  ` Execution time: ${chalk.bold(((Date.now() - startTime) / 1000).toFixed(2) + 's')}`
@@ -61,7 +61,7 @@ export function printScoring(
61
61
 
62
62
  if (scoringResult.breakdown) {
63
63
  console.log(chalk.bold('\nTool breakdown:'));
64
- scoringResult.breakdown.forEach((tool) => {
64
+ scoringResult.breakdown.forEach((tool: any) => {
65
65
  const rating = getRating(tool.score);
66
66
  const emoji = getRatingDisplay(rating).emoji;
67
67
  console.log(
@@ -71,15 +71,15 @@ export function printScoring(
71
71
 
72
72
  // Top Actionable Recommendations
73
73
  const allRecs = scoringResult.breakdown
74
- .flatMap((t) =>
75
- (t.recommendations || []).map((r) => ({ ...r, tool: t.toolName }))
74
+ .flatMap((t: any) =>
75
+ (t.recommendations ?? []).map((r: any) => ({ ...r, tool: t.toolName }))
76
76
  )
77
- .sort((a, b) => b.estimatedImpact - a.estimatedImpact)
77
+ .sort((a: any, b: any) => b.estimatedImpact - a.estimatedImpact)
78
78
  .slice(0, 3);
79
79
 
80
80
  if (allRecs.length > 0) {
81
81
  console.log(chalk.bold('\nšŸŽÆ Top Actionable Recommendations:'));
82
- allRecs.forEach((rec, i) => {
82
+ allRecs.forEach((rec: any, i: number) => {
83
83
  const priorityIcon =
84
84
  rec.priority === 'high'
85
85
  ? 'šŸ”“'