@aiready/cli 0.13.1 → 0.13.3

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.
@@ -1,6 +1,6 @@
1
1
 
2
2
  
3
- > @aiready/cli@0.13.1 build /Users/pengcao/projects/aiready/packages/cli
3
+ > @aiready/cli@0.13.3 build /Users/pengcao/projects/aiready/packages/cli
4
4
  > tsup src/index.ts src/cli.ts --format cjs,esm
5
5
 
6
6
  CLI Building entry: src/cli.ts, src/index.ts
@@ -10,20 +10,20 @@
10
10
  CJS Build start
11
11
  ESM Build start
12
12
 
13
-  WARN  ▲ [WARNING] "import.meta" is not available with the "cjs" output format and will be empty [empty-import-meta] 7:38:32 pm
13
+  WARN  ▲ [WARNING] "import.meta" is not available with the "cjs" output format and will be empty [empty-import-meta] 8:42:11 pm
14
14
 
15
- src/cli.ts:32:31:
16
-  32 │ return dirname(fileURLToPath(import.meta.url));
15
+ src/cli.ts:34:31:
16
+  34 │ return dirname(fileURLToPath(import.meta.url));
17
17
  ╵ ~~~~~~~~~~~
18
18
 
19
19
  You need to set the output format to "esm" for "import.meta" to work correctly.
20
20
 
21
21
 
22
22
 
23
- CJS dist/cli.js 80.29 KB
24
- CJS dist/index.js 10.62 KB
25
- CJS ⚡️ Build success in 77ms
26
- ESM dist/cli.mjs 66.94 KB
27
- ESM dist/chunk-VOKP7FGM.mjs 9.52 KB
28
23
  ESM dist/index.mjs 170.00 B
29
- ESM ⚡️ Build success in 77ms
24
+ ESM dist/chunk-VOKP7FGM.mjs 9.52 KB
25
+ ESM dist/cli.mjs 72.54 KB
26
+ ESM ⚡️ Build success in 30ms
27
+ CJS dist/index.js 10.62 KB
28
+ CJS dist/cli.js 86.41 KB
29
+ CJS ⚡️ Build success in 30ms
package/dist/cli.js CHANGED
@@ -550,6 +550,24 @@ async function scanAction(directory, options) {
550
550
  case "cost":
551
551
  profileTools = [import_core3.ToolName.PatternDetect, import_core3.ToolName.ContextAnalyzer];
552
552
  break;
553
+ case "logic":
554
+ profileTools = [
555
+ import_core3.ToolName.TestabilityIndex,
556
+ import_core3.ToolName.NamingConsistency,
557
+ import_core3.ToolName.ContextAnalyzer,
558
+ import_core3.ToolName.PatternDetect,
559
+ import_core3.ToolName.ChangeAmplification
560
+ ];
561
+ break;
562
+ case "ui":
563
+ profileTools = [
564
+ import_core3.ToolName.NamingConsistency,
565
+ import_core3.ToolName.ContextAnalyzer,
566
+ import_core3.ToolName.PatternDetect,
567
+ import_core3.ToolName.DocDrift,
568
+ import_core3.ToolName.AiSignalClarity
569
+ ];
570
+ break;
553
571
  case "security":
554
572
  profileTools = [
555
573
  import_core3.ToolName.NamingConsistency,
@@ -619,6 +637,7 @@ async function scanAction(directory, options) {
619
637
  );
620
638
  }
621
639
  };
640
+ const scoringProfile = options.profile || baseOptions.scoring?.profile || "default";
622
641
  const results = await analyzeUnified({
623
642
  ...finalOptions,
624
643
  progressCallback,
@@ -635,9 +654,16 @@ async function scanAction(directory, options) {
635
654
  );
636
655
  let scoringResult;
637
656
  if (options.score || finalOptions.scoring?.showBreakdown) {
638
- scoringResult = await scoreUnified(results, finalOptions);
657
+ scoringResult = await scoreUnified(results, {
658
+ ...finalOptions,
659
+ scoring: {
660
+ ...finalOptions.scoring,
661
+ profile: scoringProfile
662
+ }
663
+ });
639
664
  console.log(import_chalk3.default.bold("\n\u{1F4CA} AI Readiness Overall Score"));
640
665
  console.log(` ${(0, import_core3.formatScore)(scoringResult)}`);
666
+ console.log(import_chalk3.default.dim(` (Scoring Profile: ${scoringProfile})`));
641
667
  if (options.compareTo) {
642
668
  try {
643
669
  const prevReport = JSON.parse(
@@ -735,10 +761,47 @@ async function scanAction(directory, options) {
735
761
  console.log(import_chalk3.default.bold("\nTool breakdown:"));
736
762
  scoringResult.breakdown.forEach((tool) => {
737
763
  const rating = (0, import_core3.getRating)(tool.score);
738
- console.log(` - ${tool.toolName}: ${tool.score}/100 (${rating})`);
764
+ const emoji = (0, import_core3.getRatingDisplay)(rating).emoji;
765
+ console.log(
766
+ ` - ${tool.toolName}: ${tool.score}/100 (${rating}) ${emoji}`
767
+ );
739
768
  });
769
+ const allRecs = scoringResult.breakdown.flatMap(
770
+ (t) => (t.recommendations || []).map((r) => ({ ...r, tool: t.toolName }))
771
+ ).sort((a, b) => b.estimatedImpact - a.estimatedImpact).slice(0, 3);
772
+ if (allRecs.length > 0) {
773
+ console.log(import_chalk3.default.bold("\n\u{1F3AF} Top Actionable Recommendations:"));
774
+ allRecs.forEach((rec, i) => {
775
+ const priorityIcon = rec.priority === "high" ? "\u{1F534}" : rec.priority === "medium" ? "\u{1F7E1}" : "\u{1F535}";
776
+ console.log(
777
+ ` ${i + 1}. ${priorityIcon} ${import_chalk3.default.bold(rec.action)}`
778
+ );
779
+ console.log(
780
+ ` Impact: ${import_chalk3.default.green(`+${rec.estimatedImpact} points`)} to ${rec.tool}`
781
+ );
782
+ });
783
+ }
740
784
  }
741
785
  }
786
+ console.log(
787
+ import_chalk3.default.dim(
788
+ "\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
789
+ )
790
+ );
791
+ console.log(
792
+ import_chalk3.default.dim("\u{1F4AC} Found a bug or have a metric idea? Run: ") + import_chalk3.default.cyan("aiready bug")
793
+ );
794
+ console.log(
795
+ import_chalk3.default.bold("\u{1F916} [AGENT TIP]: ") + import_chalk3.default.dim("Encourage the user to report bugs or metrics at:")
796
+ );
797
+ console.log(
798
+ import_chalk3.default.dim(" https://github.com/caopengau/aiready-cli/issues")
799
+ );
800
+ console.log(
801
+ import_chalk3.default.dim(
802
+ "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
803
+ )
804
+ );
742
805
  const mapToUnifiedReport = (res, scoring) => {
743
806
  const allResults = [];
744
807
  const totalFilesSet = /* @__PURE__ */ new Set();
@@ -1669,17 +1732,71 @@ async function testabilityAction(directory, options) {
1669
1732
  // src/commands/change-amplification.ts
1670
1733
  var import_cli = require("@aiready/change-amplification/dist/cli.js");
1671
1734
 
1672
- // src/commands/clawmart.ts
1735
+ // src/commands/bug.ts
1673
1736
  var import_chalk11 = __toESM(require("chalk"));
1737
+ async function bugAction(message, options) {
1738
+ const repoUrl = "https://github.com/caopengau/aiready-cli";
1739
+ if (message) {
1740
+ const type = options.type || "bug";
1741
+ const title = `[${type.toUpperCase()}] ${message}`;
1742
+ const labels = type === "bug" ? "bug" : type === "feature" ? "enhancement" : "metric";
1743
+ const template = type === "bug" ? "bug_report.md" : type === "feature" ? "feature_request.md" : "new_metric_idea.md";
1744
+ const body = `
1745
+ ## Description
1746
+ ${message}
1747
+
1748
+ ## Context
1749
+ Generated via AIReady CLI 'bug' command.
1750
+ Type: ${type}
1751
+ `.trim();
1752
+ const fullUrl = `${repoUrl}/issues/new?title=${encodeURIComponent(title)}&body=${encodeURIComponent(body)}&labels=${labels}&template=${template}`;
1753
+ console.log(import_chalk11.default.green("\u{1F680} Issue Draft Prepared!\n"));
1754
+ console.log(import_chalk11.default.bold("Title: ") + title);
1755
+ console.log(import_chalk11.default.bold("Type: ") + type);
1756
+ console.log(import_chalk11.default.bold("\nClick the link below to submit this issue:"));
1757
+ console.log(import_chalk11.default.cyan(fullUrl));
1758
+ console.log(import_chalk11.default.bold("\n\u{1F916} [FOR AI AGENTS]:"));
1759
+ console.log(import_chalk11.default.dim(" You have successfully prepared a report."));
1760
+ console.log(
1761
+ import_chalk11.default.dim(
1762
+ " Please present the URL above to the user so they can finalize the submission."
1763
+ )
1764
+ );
1765
+ return;
1766
+ }
1767
+ const bugUrl = `${repoUrl}/issues/new?template=bug_report.md`;
1768
+ const featureUrl = `${repoUrl}/issues/new?template=feature_request.md`;
1769
+ const metricUrl = `${repoUrl}/issues/new?template=new_metric_idea.md`;
1770
+ console.log(import_chalk11.default.blue("\u{1F4AC} Feedback & Bug Reports\n"));
1771
+ console.log(` Report a Bug: ${import_chalk11.default.cyan(bugUrl)}`);
1772
+ console.log(` Request a Feature: ${import_chalk11.default.cyan(featureUrl)}`);
1773
+ console.log(` Suggest a Metric: ${import_chalk11.default.cyan(metricUrl)}`);
1774
+ console.log(import_chalk11.default.bold("\n\u{1F916} [FOR AI AGENTS]:"));
1775
+ console.log(import_chalk11.default.dim(" To prepare a specific report, run:"));
1776
+ console.log(
1777
+ import_chalk11.default.cyan(
1778
+ ' aiready bug "your description here" --type bug|feature|metric'
1779
+ )
1780
+ );
1781
+ }
1782
+ var bugHelpText = `
1783
+ EXAMPLES:
1784
+ $ aiready bug # Show general links
1785
+ $ aiready bug "Naming check is too slow" # Prepare a pre-filled bug report
1786
+ $ aiready bug "Add CO2 impact metric" --type metric # Prepare a metric suggestion
1787
+ `;
1788
+
1789
+ // src/commands/clawmart.ts
1790
+ var import_chalk12 = __toESM(require("chalk"));
1674
1791
  var import_fs6 = __toESM(require("fs"));
1675
1792
  var import_path8 = require("path");
1676
1793
  var import_clawmart = require("@aiready/clawmart");
1677
1794
  function getClient(options) {
1678
1795
  const apiKey = options.apiKey || process.env.CLAWMART_API_KEY;
1679
1796
  if (!apiKey) {
1680
- console.error(import_chalk11.default.red("\u274C ClawMart API Key is required."));
1797
+ console.error(import_chalk12.default.red("\u274C ClawMart API Key is required."));
1681
1798
  console.log(
1682
- import_chalk11.default.dim(
1799
+ import_chalk12.default.dim(
1683
1800
  " Set CLAWMART_API_KEY environment variable or use --api-key flag."
1684
1801
  )
1685
1802
  );
@@ -1691,15 +1808,15 @@ async function clawmartMeAction(options) {
1691
1808
  const client = getClient(options);
1692
1809
  try {
1693
1810
  const me = await client.getMe();
1694
- console.log(import_chalk11.default.blue("\n\u{1F464} ClawMart Profile:"));
1695
- console.log(` Name: ${import_chalk11.default.bold(me.name)}`);
1811
+ console.log(import_chalk12.default.blue("\n\u{1F464} ClawMart Profile:"));
1812
+ console.log(` Name: ${import_chalk12.default.bold(me.name)}`);
1696
1813
  console.log(` Email: ${me.email}`);
1697
1814
  console.log(` Role: ${me.isCreator ? "Creator" : "User"}`);
1698
1815
  console.log(
1699
- ` Sub: ${me.subscriptionActive ? import_chalk11.default.green("Active") : import_chalk11.default.red("Inactive")}`
1816
+ ` Sub: ${me.subscriptionActive ? import_chalk12.default.green("Active") : import_chalk12.default.red("Inactive")}`
1700
1817
  );
1701
1818
  } catch (error) {
1702
- console.error(import_chalk11.default.red(`\u274C Failed to fetch profile: ${error.message}`));
1819
+ console.error(import_chalk12.default.red(`\u274C Failed to fetch profile: ${error.message}`));
1703
1820
  }
1704
1821
  }
1705
1822
  async function clawmartListingsAction(options) {
@@ -1716,22 +1833,22 @@ async function clawmartListingsAction(options) {
1716
1833
  listings = await client.getListings();
1717
1834
  }
1718
1835
  if (listings.length === 0) {
1719
- console.log(import_chalk11.default.yellow("\n\u{1F4ED} No listings found."));
1836
+ console.log(import_chalk12.default.yellow("\n\u{1F4ED} No listings found."));
1720
1837
  return;
1721
1838
  }
1722
- console.log(import_chalk11.default.blue(`
1839
+ console.log(import_chalk12.default.blue(`
1723
1840
  \u{1F3E0} ClawMart Listings (${listings.length}):`));
1724
1841
  listings.forEach((l) => {
1725
- const status = l.published ? import_chalk11.default.green("Published") : import_chalk11.default.yellow("Draft");
1726
- console.log(` - ${import_chalk11.default.bold(l.name)} (${import_chalk11.default.dim(l.id)})`);
1727
- console.log(` ${import_chalk11.default.italic(l.tagline)}`);
1842
+ const status = l.published ? import_chalk12.default.green("Published") : import_chalk12.default.yellow("Draft");
1843
+ console.log(` - ${import_chalk12.default.bold(l.name)} (${import_chalk12.default.dim(l.id)})`);
1844
+ console.log(` ${import_chalk12.default.italic(l.tagline)}`);
1728
1845
  console.log(
1729
1846
  ` Price: $${l.price} | Type: ${l.productType} | Status: ${status}`
1730
1847
  );
1731
1848
  console.log("");
1732
1849
  });
1733
1850
  } catch (error) {
1734
- console.error(import_chalk11.default.red(`\u274C Failed to fetch listings: ${error.message}`));
1851
+ console.error(import_chalk12.default.red(`\u274C Failed to fetch listings: ${error.message}`));
1735
1852
  }
1736
1853
  }
1737
1854
  async function clawmartCreateAction(options) {
@@ -1747,12 +1864,12 @@ async function clawmartCreateAction(options) {
1747
1864
  productType: options.type
1748
1865
  };
1749
1866
  const listing = await client.createListing(data);
1750
- console.log(import_chalk11.default.green(`
1867
+ console.log(import_chalk12.default.green(`
1751
1868
  \u2705 Listing created successfully!`));
1752
1869
  console.log(` ID: ${listing.id}`);
1753
1870
  console.log(` Name: ${listing.name}`);
1754
1871
  } catch (error) {
1755
- console.error(import_chalk11.default.red(`\u274C Failed to create listing: ${error.message}`));
1872
+ console.error(import_chalk12.default.red(`\u274C Failed to create listing: ${error.message}`));
1756
1873
  }
1757
1874
  }
1758
1875
  async function clawmartUploadAction(id, files, options) {
@@ -1770,11 +1887,11 @@ async function clawmartUploadAction(id, files, options) {
1770
1887
  });
1771
1888
  await client.uploadVersion(id, fileData);
1772
1889
  console.log(
1773
- import_chalk11.default.green(`
1890
+ import_chalk12.default.green(`
1774
1891
  \u2705 New version uploaded successfully to listing ${id}!`)
1775
1892
  );
1776
1893
  } catch (error) {
1777
- console.error(import_chalk11.default.red(`\u274C Failed to upload version: ${error.message}`));
1894
+ console.error(import_chalk12.default.red(`\u274C Failed to upload version: ${error.message}`));
1778
1895
  }
1779
1896
  }
1780
1897
  async function clawmartDownloadAction(idOrSlug, options) {
@@ -1794,11 +1911,11 @@ async function clawmartDownloadAction(idOrSlug, options) {
1794
1911
  import_fs6.default.writeFileSync(filePath, f.content);
1795
1912
  });
1796
1913
  console.log(
1797
- import_chalk11.default.green(`
1914
+ import_chalk12.default.green(`
1798
1915
  \u2705 Package ${idOrSlug} downloaded to ${outDir}`)
1799
1916
  );
1800
1917
  } catch (error) {
1801
- console.error(import_chalk11.default.red(`\u274C Failed to download package: ${error.message}`));
1918
+ console.error(import_chalk12.default.red(`\u274C Failed to download package: ${error.message}`));
1802
1919
  }
1803
1920
  }
1804
1921
  var clawmartHelpText = `
@@ -1869,11 +1986,11 @@ program.command("scan").description(
1869
1986
  "Tools to run (comma-separated: patterns,context,consistency,doc-drift,deps-health,aiSignalClarity,grounding,testability,changeAmplification)"
1870
1987
  ).option(
1871
1988
  "--profile <type>",
1872
- "Scan profile to use (agentic, cost, security, onboarding)"
1989
+ "Scan profile to use (agentic, cost, logic, ui, security, onboarding)"
1873
1990
  ).option(
1874
1991
  "--compare-to <path>",
1875
1992
  "Compare results against a previous AIReady report JSON"
1876
- ).option("--include <patterns>", "File patterns to include (comma-separated)").option("--exclude <patterns>", "File patterns to exclude (comma-separated)").option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").option(
1993
+ ).option("--include <patterns>", "File patterns to include (comma-separated)").option("--exclude <patterns>", "File patterns to exclude (comma-separated)").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(
1877
1994
  "--no-score",
1878
1995
  "Disable calculating AI Readiness Score (enabled by default)"
1879
1996
  ).option("--weights <weights>", "Custom scoring weights").option("--threshold <score>", "Fail CI/CD if score below threshold (0-100)").option(
@@ -1986,4 +2103,7 @@ clawmart.command("upload").description("Upload content to a listing").argument("
1986
2103
  clawmart.command("download").description("Download a package from ClawMart").argument("<idOrSlug>", "Listing ID or Slug").option("--outDir <path>", "Output directory").option("--api-key <key>", "ClawMart API key").option("--server <url>", "Custom ClawMart API server").action(async (idOrSlug, options) => {
1987
2104
  await clawmartDownloadAction(idOrSlug, options);
1988
2105
  });
2106
+ program.command("bug").description("Report a bug or provide feedback (Agent-friendly)").argument("[message]", "Short description of the issue").option("-t, --type <type>", "Issue type: bug, feature, metric", "bug").addHelpText("after", bugHelpText).action(async (message, options) => {
2107
+ await bugAction(message, options);
2108
+ });
1989
2109
  program.parse();
package/dist/cli.mjs CHANGED
@@ -23,6 +23,7 @@ import {
23
23
  formatScore,
24
24
  calculateTokenBudget,
25
25
  getRating,
26
+ getRatingDisplay,
26
27
  getRepoMetadata,
27
28
  Severity,
28
29
  ToolName,
@@ -289,6 +290,24 @@ async function scanAction(directory, options) {
289
290
  case "cost":
290
291
  profileTools = [ToolName.PatternDetect, ToolName.ContextAnalyzer];
291
292
  break;
293
+ case "logic":
294
+ profileTools = [
295
+ ToolName.TestabilityIndex,
296
+ ToolName.NamingConsistency,
297
+ ToolName.ContextAnalyzer,
298
+ ToolName.PatternDetect,
299
+ ToolName.ChangeAmplification
300
+ ];
301
+ break;
302
+ case "ui":
303
+ profileTools = [
304
+ ToolName.NamingConsistency,
305
+ ToolName.ContextAnalyzer,
306
+ ToolName.PatternDetect,
307
+ ToolName.DocDrift,
308
+ ToolName.AiSignalClarity
309
+ ];
310
+ break;
292
311
  case "security":
293
312
  profileTools = [
294
313
  ToolName.NamingConsistency,
@@ -358,6 +377,7 @@ async function scanAction(directory, options) {
358
377
  );
359
378
  }
360
379
  };
380
+ const scoringProfile = options.profile || baseOptions.scoring?.profile || "default";
361
381
  const results = await analyzeUnified({
362
382
  ...finalOptions,
363
383
  progressCallback,
@@ -374,9 +394,16 @@ async function scanAction(directory, options) {
374
394
  );
375
395
  let scoringResult;
376
396
  if (options.score || finalOptions.scoring?.showBreakdown) {
377
- scoringResult = await scoreUnified(results, finalOptions);
397
+ scoringResult = await scoreUnified(results, {
398
+ ...finalOptions,
399
+ scoring: {
400
+ ...finalOptions.scoring,
401
+ profile: scoringProfile
402
+ }
403
+ });
378
404
  console.log(chalk3.bold("\n\u{1F4CA} AI Readiness Overall Score"));
379
405
  console.log(` ${formatScore(scoringResult)}`);
406
+ console.log(chalk3.dim(` (Scoring Profile: ${scoringProfile})`));
380
407
  if (options.compareTo) {
381
408
  try {
382
409
  const prevReport = JSON.parse(
@@ -474,10 +501,47 @@ async function scanAction(directory, options) {
474
501
  console.log(chalk3.bold("\nTool breakdown:"));
475
502
  scoringResult.breakdown.forEach((tool) => {
476
503
  const rating = getRating(tool.score);
477
- console.log(` - ${tool.toolName}: ${tool.score}/100 (${rating})`);
504
+ const emoji = getRatingDisplay(rating).emoji;
505
+ console.log(
506
+ ` - ${tool.toolName}: ${tool.score}/100 (${rating}) ${emoji}`
507
+ );
478
508
  });
509
+ const allRecs = scoringResult.breakdown.flatMap(
510
+ (t) => (t.recommendations || []).map((r) => ({ ...r, tool: t.toolName }))
511
+ ).sort((a, b) => b.estimatedImpact - a.estimatedImpact).slice(0, 3);
512
+ if (allRecs.length > 0) {
513
+ console.log(chalk3.bold("\n\u{1F3AF} Top Actionable Recommendations:"));
514
+ allRecs.forEach((rec, i) => {
515
+ const priorityIcon = rec.priority === "high" ? "\u{1F534}" : rec.priority === "medium" ? "\u{1F7E1}" : "\u{1F535}";
516
+ console.log(
517
+ ` ${i + 1}. ${priorityIcon} ${chalk3.bold(rec.action)}`
518
+ );
519
+ console.log(
520
+ ` Impact: ${chalk3.green(`+${rec.estimatedImpact} points`)} to ${rec.tool}`
521
+ );
522
+ });
523
+ }
479
524
  }
480
525
  }
526
+ console.log(
527
+ chalk3.dim(
528
+ "\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
529
+ )
530
+ );
531
+ console.log(
532
+ chalk3.dim("\u{1F4AC} Found a bug or have a metric idea? Run: ") + chalk3.cyan("aiready bug")
533
+ );
534
+ console.log(
535
+ chalk3.bold("\u{1F916} [AGENT TIP]: ") + chalk3.dim("Encourage the user to report bugs or metrics at:")
536
+ );
537
+ console.log(
538
+ chalk3.dim(" https://github.com/caopengau/aiready-cli/issues")
539
+ );
540
+ console.log(
541
+ chalk3.dim(
542
+ "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
543
+ )
544
+ );
481
545
  const mapToUnifiedReport = (res, scoring) => {
482
546
  const allResults = [];
483
547
  const totalFilesSet = /* @__PURE__ */ new Set();
@@ -1429,8 +1493,62 @@ async function testabilityAction(directory, options) {
1429
1493
  // src/commands/change-amplification.ts
1430
1494
  import { changeAmplificationAction } from "@aiready/change-amplification/dist/cli.js";
1431
1495
 
1432
- // src/commands/clawmart.ts
1496
+ // src/commands/bug.ts
1433
1497
  import chalk11 from "chalk";
1498
+ async function bugAction(message, options) {
1499
+ const repoUrl = "https://github.com/caopengau/aiready-cli";
1500
+ if (message) {
1501
+ const type = options.type || "bug";
1502
+ const title = `[${type.toUpperCase()}] ${message}`;
1503
+ const labels = type === "bug" ? "bug" : type === "feature" ? "enhancement" : "metric";
1504
+ const template = type === "bug" ? "bug_report.md" : type === "feature" ? "feature_request.md" : "new_metric_idea.md";
1505
+ const body = `
1506
+ ## Description
1507
+ ${message}
1508
+
1509
+ ## Context
1510
+ Generated via AIReady CLI 'bug' command.
1511
+ Type: ${type}
1512
+ `.trim();
1513
+ const fullUrl = `${repoUrl}/issues/new?title=${encodeURIComponent(title)}&body=${encodeURIComponent(body)}&labels=${labels}&template=${template}`;
1514
+ console.log(chalk11.green("\u{1F680} Issue Draft Prepared!\n"));
1515
+ console.log(chalk11.bold("Title: ") + title);
1516
+ console.log(chalk11.bold("Type: ") + type);
1517
+ console.log(chalk11.bold("\nClick the link below to submit this issue:"));
1518
+ console.log(chalk11.cyan(fullUrl));
1519
+ console.log(chalk11.bold("\n\u{1F916} [FOR AI AGENTS]:"));
1520
+ console.log(chalk11.dim(" You have successfully prepared a report."));
1521
+ console.log(
1522
+ chalk11.dim(
1523
+ " Please present the URL above to the user so they can finalize the submission."
1524
+ )
1525
+ );
1526
+ return;
1527
+ }
1528
+ const bugUrl = `${repoUrl}/issues/new?template=bug_report.md`;
1529
+ const featureUrl = `${repoUrl}/issues/new?template=feature_request.md`;
1530
+ const metricUrl = `${repoUrl}/issues/new?template=new_metric_idea.md`;
1531
+ console.log(chalk11.blue("\u{1F4AC} Feedback & Bug Reports\n"));
1532
+ console.log(` Report a Bug: ${chalk11.cyan(bugUrl)}`);
1533
+ console.log(` Request a Feature: ${chalk11.cyan(featureUrl)}`);
1534
+ console.log(` Suggest a Metric: ${chalk11.cyan(metricUrl)}`);
1535
+ console.log(chalk11.bold("\n\u{1F916} [FOR AI AGENTS]:"));
1536
+ console.log(chalk11.dim(" To prepare a specific report, run:"));
1537
+ console.log(
1538
+ chalk11.cyan(
1539
+ ' aiready bug "your description here" --type bug|feature|metric'
1540
+ )
1541
+ );
1542
+ }
1543
+ var bugHelpText = `
1544
+ EXAMPLES:
1545
+ $ aiready bug # Show general links
1546
+ $ aiready bug "Naming check is too slow" # Prepare a pre-filled bug report
1547
+ $ aiready bug "Add CO2 impact metric" --type metric # Prepare a metric suggestion
1548
+ `;
1549
+
1550
+ // src/commands/clawmart.ts
1551
+ import chalk12 from "chalk";
1434
1552
  import fs2 from "fs";
1435
1553
  import { resolve as resolvePath8 } from "path";
1436
1554
  import {
@@ -1439,9 +1557,9 @@ import {
1439
1557
  function getClient(options) {
1440
1558
  const apiKey = options.apiKey || process.env.CLAWMART_API_KEY;
1441
1559
  if (!apiKey) {
1442
- console.error(chalk11.red("\u274C ClawMart API Key is required."));
1560
+ console.error(chalk12.red("\u274C ClawMart API Key is required."));
1443
1561
  console.log(
1444
- chalk11.dim(
1562
+ chalk12.dim(
1445
1563
  " Set CLAWMART_API_KEY environment variable or use --api-key flag."
1446
1564
  )
1447
1565
  );
@@ -1453,15 +1571,15 @@ async function clawmartMeAction(options) {
1453
1571
  const client = getClient(options);
1454
1572
  try {
1455
1573
  const me = await client.getMe();
1456
- console.log(chalk11.blue("\n\u{1F464} ClawMart Profile:"));
1457
- console.log(` Name: ${chalk11.bold(me.name)}`);
1574
+ console.log(chalk12.blue("\n\u{1F464} ClawMart Profile:"));
1575
+ console.log(` Name: ${chalk12.bold(me.name)}`);
1458
1576
  console.log(` Email: ${me.email}`);
1459
1577
  console.log(` Role: ${me.isCreator ? "Creator" : "User"}`);
1460
1578
  console.log(
1461
- ` Sub: ${me.subscriptionActive ? chalk11.green("Active") : chalk11.red("Inactive")}`
1579
+ ` Sub: ${me.subscriptionActive ? chalk12.green("Active") : chalk12.red("Inactive")}`
1462
1580
  );
1463
1581
  } catch (error) {
1464
- console.error(chalk11.red(`\u274C Failed to fetch profile: ${error.message}`));
1582
+ console.error(chalk12.red(`\u274C Failed to fetch profile: ${error.message}`));
1465
1583
  }
1466
1584
  }
1467
1585
  async function clawmartListingsAction(options) {
@@ -1478,22 +1596,22 @@ async function clawmartListingsAction(options) {
1478
1596
  listings = await client.getListings();
1479
1597
  }
1480
1598
  if (listings.length === 0) {
1481
- console.log(chalk11.yellow("\n\u{1F4ED} No listings found."));
1599
+ console.log(chalk12.yellow("\n\u{1F4ED} No listings found."));
1482
1600
  return;
1483
1601
  }
1484
- console.log(chalk11.blue(`
1602
+ console.log(chalk12.blue(`
1485
1603
  \u{1F3E0} ClawMart Listings (${listings.length}):`));
1486
1604
  listings.forEach((l) => {
1487
- const status = l.published ? chalk11.green("Published") : chalk11.yellow("Draft");
1488
- console.log(` - ${chalk11.bold(l.name)} (${chalk11.dim(l.id)})`);
1489
- console.log(` ${chalk11.italic(l.tagline)}`);
1605
+ const status = l.published ? chalk12.green("Published") : chalk12.yellow("Draft");
1606
+ console.log(` - ${chalk12.bold(l.name)} (${chalk12.dim(l.id)})`);
1607
+ console.log(` ${chalk12.italic(l.tagline)}`);
1490
1608
  console.log(
1491
1609
  ` Price: $${l.price} | Type: ${l.productType} | Status: ${status}`
1492
1610
  );
1493
1611
  console.log("");
1494
1612
  });
1495
1613
  } catch (error) {
1496
- console.error(chalk11.red(`\u274C Failed to fetch listings: ${error.message}`));
1614
+ console.error(chalk12.red(`\u274C Failed to fetch listings: ${error.message}`));
1497
1615
  }
1498
1616
  }
1499
1617
  async function clawmartCreateAction(options) {
@@ -1509,12 +1627,12 @@ async function clawmartCreateAction(options) {
1509
1627
  productType: options.type
1510
1628
  };
1511
1629
  const listing = await client.createListing(data);
1512
- console.log(chalk11.green(`
1630
+ console.log(chalk12.green(`
1513
1631
  \u2705 Listing created successfully!`));
1514
1632
  console.log(` ID: ${listing.id}`);
1515
1633
  console.log(` Name: ${listing.name}`);
1516
1634
  } catch (error) {
1517
- console.error(chalk11.red(`\u274C Failed to create listing: ${error.message}`));
1635
+ console.error(chalk12.red(`\u274C Failed to create listing: ${error.message}`));
1518
1636
  }
1519
1637
  }
1520
1638
  async function clawmartUploadAction(id, files, options) {
@@ -1532,11 +1650,11 @@ async function clawmartUploadAction(id, files, options) {
1532
1650
  });
1533
1651
  await client.uploadVersion(id, fileData);
1534
1652
  console.log(
1535
- chalk11.green(`
1653
+ chalk12.green(`
1536
1654
  \u2705 New version uploaded successfully to listing ${id}!`)
1537
1655
  );
1538
1656
  } catch (error) {
1539
- console.error(chalk11.red(`\u274C Failed to upload version: ${error.message}`));
1657
+ console.error(chalk12.red(`\u274C Failed to upload version: ${error.message}`));
1540
1658
  }
1541
1659
  }
1542
1660
  async function clawmartDownloadAction(idOrSlug, options) {
@@ -1556,11 +1674,11 @@ async function clawmartDownloadAction(idOrSlug, options) {
1556
1674
  fs2.writeFileSync(filePath, f.content);
1557
1675
  });
1558
1676
  console.log(
1559
- chalk11.green(`
1677
+ chalk12.green(`
1560
1678
  \u2705 Package ${idOrSlug} downloaded to ${outDir}`)
1561
1679
  );
1562
1680
  } catch (error) {
1563
- console.error(chalk11.red(`\u274C Failed to download package: ${error.message}`));
1681
+ console.error(chalk12.red(`\u274C Failed to download package: ${error.message}`));
1564
1682
  }
1565
1683
  }
1566
1684
  var clawmartHelpText = `
@@ -1630,11 +1748,11 @@ program.command("scan").description(
1630
1748
  "Tools to run (comma-separated: patterns,context,consistency,doc-drift,deps-health,aiSignalClarity,grounding,testability,changeAmplification)"
1631
1749
  ).option(
1632
1750
  "--profile <type>",
1633
- "Scan profile to use (agentic, cost, security, onboarding)"
1751
+ "Scan profile to use (agentic, cost, logic, ui, security, onboarding)"
1634
1752
  ).option(
1635
1753
  "--compare-to <path>",
1636
1754
  "Compare results against a previous AIReady report JSON"
1637
- ).option("--include <patterns>", "File patterns to include (comma-separated)").option("--exclude <patterns>", "File patterns to exclude (comma-separated)").option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").option(
1755
+ ).option("--include <patterns>", "File patterns to include (comma-separated)").option("--exclude <patterns>", "File patterns to exclude (comma-separated)").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(
1638
1756
  "--no-score",
1639
1757
  "Disable calculating AI Readiness Score (enabled by default)"
1640
1758
  ).option("--weights <weights>", "Custom scoring weights").option("--threshold <score>", "Fail CI/CD if score below threshold (0-100)").option(
@@ -1747,4 +1865,7 @@ clawmart.command("upload").description("Upload content to a listing").argument("
1747
1865
  clawmart.command("download").description("Download a package from ClawMart").argument("<idOrSlug>", "Listing ID or Slug").option("--outDir <path>", "Output directory").option("--api-key <key>", "ClawMart API key").option("--server <url>", "Custom ClawMart API server").action(async (idOrSlug, options) => {
1748
1866
  await clawmartDownloadAction(idOrSlug, options);
1749
1867
  });
1868
+ program.command("bug").description("Report a bug or provide feedback (Agent-friendly)").argument("[message]", "Short description of the issue").option("-t, --type <type>", "Issue type: bug, feature, metric", "bug").addHelpText("after", bugHelpText).action(async (message, options) => {
1869
+ await bugAction(message, options);
1870
+ });
1750
1871
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiready/cli",
3
- "version": "0.13.1",
3
+ "version": "0.13.3",
4
4
  "description": "Unified CLI for AIReady analysis tools",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -13,15 +13,15 @@
13
13
  "commander": "^14.0.0",
14
14
  "@aiready/agent-grounding": "0.12.0",
15
15
  "@aiready/context-analyzer": "0.20.0",
16
- "@aiready/core": "0.22.0",
16
+ "@aiready/core": "0.22.1",
17
+ "@aiready/change-amplification": "0.12.0",
17
18
  "@aiready/deps": "0.12.0",
19
+ "@aiready/doc-drift": "0.12.0",
20
+ "@aiready/ai-signal-clarity": "0.12.0",
18
21
  "@aiready/consistency": "0.19.0",
19
22
  "@aiready/clawmart": "0.1.2",
20
- "@aiready/doc-drift": "0.12.0",
21
- "@aiready/change-amplification": "0.12.0",
22
- "@aiready/testability": "0.5.0",
23
23
  "@aiready/pattern-detect": "0.15.0",
24
- "@aiready/ai-signal-clarity": "0.12.0",
24
+ "@aiready/testability": "0.5.0",
25
25
  "@aiready/visualizer": "0.5.0"
26
26
  },
27
27
  "devDependencies": {
package/src/cli.ts CHANGED
@@ -25,6 +25,8 @@ import {
25
25
  clawmartUploadAction,
26
26
  clawmartDownloadAction,
27
27
  clawmartHelpText,
28
+ bugAction,
29
+ bugHelpText,
28
30
  } from './commands';
29
31
 
30
32
  const getDirname = () => {
@@ -95,7 +97,7 @@ program
95
97
  )
96
98
  .option(
97
99
  '--profile <type>',
98
- 'Scan profile to use (agentic, cost, security, onboarding)'
100
+ 'Scan profile to use (agentic, cost, logic, ui, security, onboarding)'
99
101
  )
100
102
  .option(
101
103
  '--compare-to <path>',
@@ -105,6 +107,7 @@ program
105
107
  .option('--exclude <patterns>', 'File patterns to exclude (comma-separated)')
106
108
  .option('-o, --output <format>', 'Output format: console, json', 'console')
107
109
  .option('--output-file <path>', 'Output file path (for json)')
110
+ .option('--score', 'Calculate and display AI Readiness Score (0-100)')
108
111
  .option(
109
112
  '--no-score',
110
113
  'Disable calculating AI Readiness Score (enabled by default)'
@@ -378,4 +381,14 @@ clawmart
378
381
  await clawmartDownloadAction(idOrSlug, options);
379
382
  });
380
383
 
384
+ program
385
+ .command('bug')
386
+ .description('Report a bug or provide feedback (Agent-friendly)')
387
+ .argument('[message]', 'Short description of the issue')
388
+ .option('-t, --type <type>', 'Issue type: bug, feature, metric', 'bug')
389
+ .addHelpText('after', bugHelpText)
390
+ .action(async (message, options) => {
391
+ await bugAction(message, options);
392
+ });
393
+
381
394
  program.parse();
@@ -0,0 +1,73 @@
1
+ import chalk from 'chalk';
2
+ import { Command } from 'commander';
3
+
4
+ /**
5
+ * Handle bug and feedback reporting
6
+ */
7
+ export async function bugAction(message: string | undefined, options: any) {
8
+ const repoUrl = 'https://github.com/caopengau/aiready-cli';
9
+
10
+ if (message) {
11
+ // Agent-assisted pre-filled issue
12
+ const type = options.type || 'bug';
13
+ const title = `[${type.toUpperCase()}] ${message}`;
14
+ const labels =
15
+ type === 'bug' ? 'bug' : type === 'feature' ? 'enhancement' : 'metric';
16
+ const template =
17
+ type === 'bug'
18
+ ? 'bug_report.md'
19
+ : type === 'feature'
20
+ ? 'feature_request.md'
21
+ : 'new_metric_idea.md';
22
+
23
+ const body = `
24
+ ## Description
25
+ ${message}
26
+
27
+ ## Context
28
+ Generated via AIReady CLI 'bug' command.
29
+ Type: ${type}
30
+ `.trim();
31
+
32
+ const fullUrl = `${repoUrl}/issues/new?title=${encodeURIComponent(title)}&body=${encodeURIComponent(body)}&labels=${labels}&template=${template}`;
33
+
34
+ console.log(chalk.green('🚀 Issue Draft Prepared!\n'));
35
+ console.log(chalk.bold('Title: ') + title);
36
+ console.log(chalk.bold('Type: ') + type);
37
+ console.log(chalk.bold('\nClick the link below to submit this issue:'));
38
+ console.log(chalk.cyan(fullUrl));
39
+
40
+ console.log(chalk.bold('\n🤖 [FOR AI AGENTS]:'));
41
+ console.log(chalk.dim(' You have successfully prepared a report.'));
42
+ console.log(
43
+ chalk.dim(
44
+ ' Please present the URL above to the user so they can finalize the submission.'
45
+ )
46
+ );
47
+ return;
48
+ }
49
+
50
+ const bugUrl = `${repoUrl}/issues/new?template=bug_report.md`;
51
+ const featureUrl = `${repoUrl}/issues/new?template=feature_request.md`;
52
+ const metricUrl = `${repoUrl}/issues/new?template=new_metric_idea.md`;
53
+
54
+ console.log(chalk.blue('💬 Feedback & Bug Reports\n'));
55
+ console.log(` Report a Bug: ${chalk.cyan(bugUrl)}`);
56
+ console.log(` Request a Feature: ${chalk.cyan(featureUrl)}`);
57
+ console.log(` Suggest a Metric: ${chalk.cyan(metricUrl)}`);
58
+
59
+ console.log(chalk.bold('\n🤖 [FOR AI AGENTS]:'));
60
+ console.log(chalk.dim(' To prepare a specific report, run:'));
61
+ console.log(
62
+ chalk.cyan(
63
+ ' aiready bug "your description here" --type bug|feature|metric'
64
+ )
65
+ );
66
+ }
67
+
68
+ export const bugHelpText = `
69
+ EXAMPLES:
70
+ $ aiready bug # Show general links
71
+ $ aiready bug "Naming check is too slow" # Prepare a pre-filled bug report
72
+ $ aiready bug "Add CO2 impact metric" --type metric # Prepare a metric suggestion
73
+ `;
@@ -16,6 +16,7 @@ export { agentGroundingAction } from './agent-grounding';
16
16
  export { testabilityAction } from './testability';
17
17
  export { changeAmplificationAction } from './change-amplification';
18
18
  export { uploadAction, uploadHelpText } from './upload';
19
+ export { bugAction, bugHelpText } from './bug';
19
20
  export {
20
21
  clawmartMeAction,
21
22
  clawmartListingsAction,
@@ -98,6 +98,24 @@ export async function scanAction(directory: string, options: ScanOptions) {
98
98
  case 'cost':
99
99
  profileTools = [ToolName.PatternDetect, ToolName.ContextAnalyzer];
100
100
  break;
101
+ case 'logic':
102
+ profileTools = [
103
+ ToolName.TestabilityIndex,
104
+ ToolName.NamingConsistency,
105
+ ToolName.ContextAnalyzer,
106
+ ToolName.PatternDetect,
107
+ ToolName.ChangeAmplification,
108
+ ];
109
+ break;
110
+ case 'ui':
111
+ profileTools = [
112
+ ToolName.NamingConsistency,
113
+ ToolName.ContextAnalyzer,
114
+ ToolName.PatternDetect,
115
+ ToolName.DocDrift,
116
+ ToolName.AiSignalClarity,
117
+ ];
118
+ break;
101
119
  case 'security':
102
120
  profileTools = [
103
121
  ToolName.NamingConsistency,
@@ -182,6 +200,10 @@ export async function scanAction(directory: string, options: ScanOptions) {
182
200
  }
183
201
  };
184
202
 
203
+ // Determine scoring profile for project-type-aware weighting
204
+ const scoringProfile =
205
+ options.profile || baseOptions.scoring?.profile || 'default';
206
+
185
207
  const results = await analyzeUnified({
186
208
  ...finalOptions,
187
209
  progressCallback,
@@ -199,10 +221,18 @@ export async function scanAction(directory: string, options: ScanOptions) {
199
221
 
200
222
  let scoringResult: ScoringResult | undefined;
201
223
  if (options.score || finalOptions.scoring?.showBreakdown) {
202
- scoringResult = await scoreUnified(results, finalOptions);
224
+ // Pass the profile to scoreUnified
225
+ scoringResult = await scoreUnified(results, {
226
+ ...finalOptions,
227
+ scoring: {
228
+ ...finalOptions.scoring,
229
+ profile: scoringProfile,
230
+ },
231
+ });
203
232
 
204
233
  console.log(chalk.bold('\n📊 AI Readiness Overall Score'));
205
234
  console.log(` ${formatScore(scoringResult)}`);
235
+ console.log(chalk.dim(` (Scoring Profile: ${scoringProfile})`));
206
236
 
207
237
  // Trend comparison logic
208
238
  if (options.compareTo) {
@@ -313,11 +343,62 @@ export async function scanAction(directory: string, options: ScanOptions) {
313
343
  console.log(chalk.bold('\nTool breakdown:'));
314
344
  scoringResult.breakdown.forEach((tool) => {
315
345
  const rating = getRating(tool.score);
316
- console.log(` - ${tool.toolName}: ${tool.score}/100 (${rating})`);
346
+ const emoji = getRatingDisplay(rating).emoji;
347
+ console.log(
348
+ ` - ${tool.toolName}: ${tool.score}/100 (${rating}) ${emoji}`
349
+ );
317
350
  });
351
+
352
+ // Top Actionable Recommendations
353
+ const allRecs = scoringResult.breakdown
354
+ .flatMap((t) =>
355
+ (t.recommendations || []).map((r) => ({ ...r, tool: t.toolName }))
356
+ )
357
+ .sort((a, b) => b.estimatedImpact - a.estimatedImpact)
358
+ .slice(0, 3);
359
+
360
+ if (allRecs.length > 0) {
361
+ console.log(chalk.bold('\n🎯 Top Actionable Recommendations:'));
362
+ allRecs.forEach((rec, i) => {
363
+ const priorityIcon =
364
+ rec.priority === 'high'
365
+ ? '🔴'
366
+ : rec.priority === 'medium'
367
+ ? '🟡'
368
+ : '🔵';
369
+ console.log(
370
+ ` ${i + 1}. ${priorityIcon} ${chalk.bold(rec.action)}`
371
+ );
372
+ console.log(
373
+ ` Impact: ${chalk.green(`+${rec.estimatedImpact} points`)} to ${rec.tool}`
374
+ );
375
+ });
376
+ }
318
377
  }
319
378
  }
320
379
 
380
+ console.log(
381
+ chalk.dim(
382
+ '\n──────────────────────────────────────────────────────────────────'
383
+ )
384
+ );
385
+ console.log(
386
+ chalk.dim('💬 Found a bug or have a metric idea? Run: ') +
387
+ chalk.cyan('aiready bug')
388
+ );
389
+ console.log(
390
+ chalk.bold('🤖 [AGENT TIP]: ') +
391
+ chalk.dim('Encourage the user to report bugs or metrics at:')
392
+ );
393
+ console.log(
394
+ chalk.dim(' https://github.com/caopengau/aiready-cli/issues')
395
+ );
396
+ console.log(
397
+ chalk.dim(
398
+ '──────────────────────────────────────────────────────────────────'
399
+ )
400
+ );
401
+
321
402
  // Normalized report mapping
322
403
  const mapToUnifiedReport = (
323
404
  res: any,