@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.
- package/.turbo/turbo-build.log +10 -10
- package/dist/cli.js +143 -23
- package/dist/cli.mjs +144 -23
- package/package.json +6 -6
- package/src/cli.ts +14 -1
- package/src/commands/bug.ts +73 -0
- package/src/commands/index.ts +1 -0
- package/src/commands/scan.ts +83 -2
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
|
-
> @aiready/cli@0.13.
|
|
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
|
[34mCLI[39m Building entry: src/cli.ts, src/index.ts
|
|
@@ -10,20 +10,20 @@
|
|
|
10
10
|
[34mCJS[39m Build start
|
|
11
11
|
[34mESM[39m Build start
|
|
12
12
|
|
|
13
|
-
[43m[30m WARN [39m[49m [33m▲ [43;33m[[43;30mWARNING[43;33m][0m [1m"import.meta" is not available with the "cjs" output format and will be empty[0m [empty-import-meta] [
|
|
13
|
+
[43m[30m WARN [39m[49m [33m▲ [43;33m[[43;30mWARNING[43;33m][0m [1m"import.meta" is not available with the "cjs" output format and will be empty[0m [empty-import-meta] [90m8:42:11 pm[39m
|
|
14
14
|
|
|
15
|
-
src/cli.ts:
|
|
16
|
-
[37m
|
|
15
|
+
src/cli.ts:34:31:
|
|
16
|
+
[37m 34 │ return dirname(fileURLToPath([32mimport.meta[37m.url));
|
|
17
17
|
╵ [32m~~~~~~~~~~~[0m
|
|
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
|
-
[32mCJS[39m [1mdist/cli.js [22m[32m80.29 KB[39m
|
|
24
|
-
[32mCJS[39m [1mdist/index.js [22m[32m10.62 KB[39m
|
|
25
|
-
[32mCJS[39m ⚡️ Build success in 77ms
|
|
26
|
-
[32mESM[39m [1mdist/cli.mjs [22m[32m66.94 KB[39m
|
|
27
|
-
[32mESM[39m [1mdist/chunk-VOKP7FGM.mjs [22m[32m9.52 KB[39m
|
|
28
23
|
[32mESM[39m [1mdist/index.mjs [22m[32m170.00 B[39m
|
|
29
|
-
[32mESM[39m
|
|
24
|
+
[32mESM[39m [1mdist/chunk-VOKP7FGM.mjs [22m[32m9.52 KB[39m
|
|
25
|
+
[32mESM[39m [1mdist/cli.mjs [22m[32m72.54 KB[39m
|
|
26
|
+
[32mESM[39m ⚡️ Build success in 30ms
|
|
27
|
+
[32mCJS[39m [1mdist/index.js [22m[32m10.62 KB[39m
|
|
28
|
+
[32mCJS[39m [1mdist/cli.js [22m[32m86.41 KB[39m
|
|
29
|
+
[32mCJS[39m ⚡️ 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,
|
|
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
|
-
|
|
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/
|
|
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(
|
|
1797
|
+
console.error(import_chalk12.default.red("\u274C ClawMart API Key is required."));
|
|
1681
1798
|
console.log(
|
|
1682
|
-
|
|
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(
|
|
1695
|
-
console.log(` 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 ?
|
|
1816
|
+
` Sub: ${me.subscriptionActive ? import_chalk12.default.green("Active") : import_chalk12.default.red("Inactive")}`
|
|
1700
1817
|
);
|
|
1701
1818
|
} catch (error) {
|
|
1702
|
-
console.error(
|
|
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(
|
|
1836
|
+
console.log(import_chalk12.default.yellow("\n\u{1F4ED} No listings found."));
|
|
1720
1837
|
return;
|
|
1721
1838
|
}
|
|
1722
|
-
console.log(
|
|
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 ?
|
|
1726
|
-
console.log(` - ${
|
|
1727
|
-
console.log(` ${
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
-
|
|
1890
|
+
import_chalk12.default.green(`
|
|
1774
1891
|
\u2705 New version uploaded successfully to listing ${id}!`)
|
|
1775
1892
|
);
|
|
1776
1893
|
} catch (error) {
|
|
1777
|
-
console.error(
|
|
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
|
-
|
|
1914
|
+
import_chalk12.default.green(`
|
|
1798
1915
|
\u2705 Package ${idOrSlug} downloaded to ${outDir}`)
|
|
1799
1916
|
);
|
|
1800
1917
|
} catch (error) {
|
|
1801
|
-
console.error(
|
|
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,
|
|
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
|
-
|
|
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/
|
|
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(
|
|
1560
|
+
console.error(chalk12.red("\u274C ClawMart API Key is required."));
|
|
1443
1561
|
console.log(
|
|
1444
|
-
|
|
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(
|
|
1457
|
-
console.log(` 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 ?
|
|
1579
|
+
` Sub: ${me.subscriptionActive ? chalk12.green("Active") : chalk12.red("Inactive")}`
|
|
1462
1580
|
);
|
|
1463
1581
|
} catch (error) {
|
|
1464
|
-
console.error(
|
|
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(
|
|
1599
|
+
console.log(chalk12.yellow("\n\u{1F4ED} No listings found."));
|
|
1482
1600
|
return;
|
|
1483
1601
|
}
|
|
1484
|
-
console.log(
|
|
1602
|
+
console.log(chalk12.blue(`
|
|
1485
1603
|
\u{1F3E0} ClawMart Listings (${listings.length}):`));
|
|
1486
1604
|
listings.forEach((l) => {
|
|
1487
|
-
const status = l.published ?
|
|
1488
|
-
console.log(` - ${
|
|
1489
|
-
console.log(` ${
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
-
|
|
1653
|
+
chalk12.green(`
|
|
1536
1654
|
\u2705 New version uploaded successfully to listing ${id}!`)
|
|
1537
1655
|
);
|
|
1538
1656
|
} catch (error) {
|
|
1539
|
-
console.error(
|
|
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
|
-
|
|
1677
|
+
chalk12.green(`
|
|
1560
1678
|
\u2705 Package ${idOrSlug} downloaded to ${outDir}`)
|
|
1561
1679
|
);
|
|
1562
1680
|
} catch (error) {
|
|
1563
|
-
console.error(
|
|
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.
|
|
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.
|
|
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/
|
|
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
|
+
`;
|
package/src/commands/index.ts
CHANGED
|
@@ -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,
|
package/src/commands/scan.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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,
|