@aiready/cli 0.14.26 → 0.15.1

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.js CHANGED
@@ -25,8 +25,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
25
25
 
26
26
  // src/cli.ts
27
27
  var import_commander = require("commander");
28
- var import_fs8 = require("fs");
29
- var import_path7 = require("path");
28
+ var import_fs9 = require("fs");
29
+ var import_path8 = require("path");
30
30
  var import_url = require("url");
31
31
 
32
32
  // src/commands/scan.ts
@@ -471,7 +471,8 @@ function getProfileTools(profile) {
471
471
  return [
472
472
  import_core5.ToolName.AiSignalClarity,
473
473
  import_core5.ToolName.AgentGrounding,
474
- import_core5.ToolName.TestabilityIndex
474
+ import_core5.ToolName.TestabilityIndex,
475
+ import_core5.ToolName.ContractEnforcement
475
476
  ];
476
477
  case "cost":
477
478
  return [import_core5.ToolName.PatternDetect, import_core5.ToolName.ContextAnalyzer];
@@ -481,7 +482,8 @@ function getProfileTools(profile) {
481
482
  import_core5.ToolName.NamingConsistency,
482
483
  import_core5.ToolName.ContextAnalyzer,
483
484
  import_core5.ToolName.PatternDetect,
484
- import_core5.ToolName.ChangeAmplification
485
+ import_core5.ToolName.ChangeAmplification,
486
+ import_core5.ToolName.ContractEnforcement
485
487
  ];
486
488
  case "ui":
487
489
  return [
@@ -492,7 +494,11 @@ function getProfileTools(profile) {
492
494
  import_core5.ToolName.AiSignalClarity
493
495
  ];
494
496
  case "security":
495
- return [import_core5.ToolName.NamingConsistency, import_core5.ToolName.TestabilityIndex];
497
+ return [
498
+ import_core5.ToolName.NamingConsistency,
499
+ import_core5.ToolName.TestabilityIndex,
500
+ import_core5.ToolName.ContractEnforcement
501
+ ];
496
502
  case "onboarding":
497
503
  return [
498
504
  import_core5.ToolName.ContextAnalyzer,
@@ -544,7 +550,8 @@ var SCAN_DEFAULTS = {
544
550
  "testability-index",
545
551
  "doc-drift",
546
552
  "dependency-health",
547
- "change-amplification"
553
+ "change-amplification",
554
+ "contract-enforcement"
548
555
  ],
549
556
  include: void 0,
550
557
  exclude: void 0,
@@ -602,6 +609,7 @@ var TOOL_PACKAGE_MAP = {
602
609
  [import_core7.ToolName.DocDrift]: "@aiready/doc-drift",
603
610
  [import_core7.ToolName.DependencyHealth]: "@aiready/deps",
604
611
  [import_core7.ToolName.ChangeAmplification]: "@aiready/change-amplification",
612
+ [import_core7.ToolName.ContractEnforcement]: "@aiready/contract-enforcement",
605
613
  // Aliases handled by registry
606
614
  patterns: "@aiready/pattern-detect",
607
615
  duplicates: "@aiready/pattern-detect",
@@ -612,7 +620,8 @@ var TOOL_PACKAGE_MAP = {
612
620
  grounding: "@aiready/agent-grounding",
613
621
  testability: "@aiready/testability",
614
622
  "deps-health": "@aiready/deps",
615
- "change-amp": "@aiready/change-amplification"
623
+ "change-amp": "@aiready/change-amplification",
624
+ contract: "@aiready/contract-enforcement"
616
625
  };
617
626
  var UnifiedOrchestrator = class {
618
627
  /**
@@ -761,7 +770,8 @@ var UnifiedOrchestrator = class {
761
770
  "testability-index": ["testabilityIndex", "testability"],
762
771
  "doc-drift": ["docDrift"],
763
772
  "dependency-health": ["dependencyHealth", "deps"],
764
- "change-amplification": ["changeAmplification"]
773
+ "change-amplification": ["changeAmplification"],
774
+ "contract-enforcement": ["contractEnforcement", "contract"]
765
775
  };
766
776
  for (const [kebabKey, aliases] of Object.entries(keyMappings)) {
767
777
  if (result[kebabKey]) {
@@ -1075,6 +1085,28 @@ async function scanAction(directory, options) {
1075
1085
  finalOptions,
1076
1086
  results
1077
1087
  );
1088
+ const isCI = options.ci ?? process.env.CI === "true";
1089
+ if (!isCI) {
1090
+ console.log(
1091
+ import_chalk6.default.dim(
1092
+ "\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"
1093
+ )
1094
+ );
1095
+ console.log(import_chalk6.default.bold("\u{1F4C8} Want to see the full interactive report?"));
1096
+ console.log(
1097
+ import_chalk6.default.cyan(
1098
+ ` Upload this report to: ${import_chalk6.default.bold("https://platform.getaiready.dev")}`
1099
+ )
1100
+ );
1101
+ console.log(
1102
+ import_chalk6.default.dim(" Or run: ") + import_chalk6.default.white(`aiready upload ${outputPath}`)
1103
+ );
1104
+ console.log(
1105
+ import_chalk6.default.dim(
1106
+ "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
1107
+ )
1108
+ );
1109
+ }
1078
1110
  } catch (error) {
1079
1111
  (0, import_core10.handleCLIError)(error, "Analysis");
1080
1112
  }
@@ -2063,8 +2095,79 @@ async function testabilityAction(directory, options) {
2063
2095
  // src/commands/change-amplification.ts
2064
2096
  var import_cli = require("@aiready/change-amplification/dist/cli.js");
2065
2097
 
2066
- // src/commands/bug.ts
2098
+ // src/commands/contract-enforcement.ts
2067
2099
  var import_chalk16 = __toESM(require("chalk"));
2100
+ async function contractEnforcementAction(directory, options) {
2101
+ return await executeToolAction(directory, options, {
2102
+ toolName: "contract-enforcement",
2103
+ label: "Contract enforcement analysis",
2104
+ emoji: "\u{1F6E1}\uFE0F",
2105
+ defaults: {
2106
+ minChainDepth: 3,
2107
+ include: void 0,
2108
+ exclude: void 0,
2109
+ output: { format: "console", file: void 0 }
2110
+ },
2111
+ getCliOptions: (opts) => ({
2112
+ minChainDepth: opts.minChainDepth ? parseInt(opts.minChainDepth, 10) : void 0
2113
+ }),
2114
+ importTool: async () => {
2115
+ const tool = await import("@aiready/contract-enforcement");
2116
+ return {
2117
+ analyze: tool.analyzeContractEnforcement,
2118
+ generateSummary: (report) => report.summary,
2119
+ calculateScore: tool.calculateContractEnforcementScore
2120
+ };
2121
+ },
2122
+ renderConsole: ({ results, summary, score }) => {
2123
+ renderToolHeader(
2124
+ "Contract Enforcement",
2125
+ "\u{1F6E1}\uFE0F",
2126
+ score?.score || 0,
2127
+ summary.rating
2128
+ );
2129
+ const rawData = results.rawData || results;
2130
+ console.log(
2131
+ import_chalk16.default.dim(
2132
+ ` Patterns: ${summary.totalDefensivePatterns} (${summary.defensiveDensity}/kLOC) | ${summary.sourceFiles} files scanned`
2133
+ )
2134
+ );
2135
+ const dims = summary.dimensions;
2136
+ if (dims) {
2137
+ const entries = [
2138
+ ["Type Escape Hatches", dims.typeEscapeHatchScore],
2139
+ ["Fallback Cascades", dims.fallbackCascadeScore],
2140
+ ["Error Transparency", dims.errorTransparencyScore],
2141
+ ["Boundary Validation", dims.boundaryValidationScore]
2142
+ ];
2143
+ for (const [name, val] of entries) {
2144
+ const color = val >= 80 ? import_chalk16.default.green : val >= 60 ? import_chalk16.default.yellow : import_chalk16.default.red;
2145
+ console.log(import_chalk16.default.dim(` ${name}: ${color(val + "/100")}`));
2146
+ }
2147
+ }
2148
+ if (summary.totalDefensivePatterns > 0 && rawData["as-any"] !== void 0) {
2149
+ const breakdown = [
2150
+ rawData["as-any"] && `as-any: ${rawData["as-any"]}`,
2151
+ rawData["as-unknown"] && `as-unknown: ${rawData["as-unknown"]}`,
2152
+ rawData["deep-optional-chain"] && `deep-?.: ${rawData["deep-optional-chain"]}`,
2153
+ rawData["nullish-literal-default"] && `?? literal: ${rawData["nullish-literal-default"]}`,
2154
+ rawData["swallowed-error"] && `swallowed-error: ${rawData["swallowed-error"]}`,
2155
+ rawData["env-fallback"] && `env-fallback: ${rawData["env-fallback"]}`,
2156
+ rawData["unnecessary-guard"] && `guard-clause: ${rawData["unnecessary-guard"]}`,
2157
+ rawData["any-parameter"] && `any-param: ${rawData["any-parameter"]}`,
2158
+ rawData["any-return"] && `any-return: ${rawData["any-return"]}`
2159
+ ].filter(Boolean).join(" | ");
2160
+ console.log(import_chalk16.default.dim(` ${breakdown}`));
2161
+ }
2162
+ if (score) {
2163
+ renderToolScoreFooter(score);
2164
+ }
2165
+ }
2166
+ });
2167
+ }
2168
+
2169
+ // src/commands/bug.ts
2170
+ var import_chalk17 = __toESM(require("chalk"));
2068
2171
  var import_child_process2 = require("child_process");
2069
2172
  async function bugAction(message, options) {
2070
2173
  const repoUrl = "https://github.com/caopengau/aiready-cli";
@@ -2082,35 +2185,35 @@ Generated via AIReady CLI 'bug' command.
2082
2185
  Type: ${type}
2083
2186
  `.trim();
2084
2187
  if (options.submit) {
2085
- console.log(import_chalk16.default.blue("\u{1F680} Submitting issue via GitHub CLI...\n"));
2188
+ console.log(import_chalk17.default.blue("\u{1F680} Submitting issue via GitHub CLI...\n"));
2086
2189
  try {
2087
2190
  (0, import_child_process2.execSync)("gh auth status", { stdio: "ignore" });
2088
2191
  const command = `gh issue create --repo ${repoSlug} --title ${JSON.stringify(title)} --body ${JSON.stringify(body)} --label ${label}`;
2089
2192
  const output = (0, import_child_process2.execSync)(command, { encoding: "utf8" }).trim();
2090
- console.log(import_chalk16.default.green("\u2705 Issue Created Successfully!"));
2091
- console.log(import_chalk16.default.cyan(output));
2193
+ console.log(import_chalk17.default.green("\u2705 Issue Created Successfully!"));
2194
+ console.log(import_chalk17.default.cyan(output));
2092
2195
  return;
2093
2196
  } catch {
2094
- console.error(import_chalk16.default.red("\n\u274C Failed to submit via gh CLI."));
2197
+ console.error(import_chalk17.default.red("\n\u274C Failed to submit via gh CLI."));
2095
2198
  console.log(
2096
- import_chalk16.default.yellow(
2199
+ import_chalk17.default.yellow(
2097
2200
  ' Make sure gh is installed and run "gh auth login".\n'
2098
2201
  )
2099
2202
  );
2100
- console.log(import_chalk16.default.dim(" Falling back to URL generation..."));
2203
+ console.log(import_chalk17.default.dim(" Falling back to URL generation..."));
2101
2204
  }
2102
2205
  }
2103
2206
  const template = type === "bug" ? "bug_report.md" : type === "feature" ? "feature_request.md" : "new_metric_idea.md";
2104
2207
  const fullUrl = `${repoUrl}/issues/new?title=${encodeURIComponent(title)}&body=${encodeURIComponent(body)}&labels=${label}&template=${template}`;
2105
- console.log(import_chalk16.default.green("\u{1F680} Issue Draft Prepared!\n"));
2106
- console.log(import_chalk16.default.bold("Title: ") + title);
2107
- console.log(import_chalk16.default.bold("Type: ") + type);
2108
- console.log(import_chalk16.default.bold("\nClick the link below to submit this issue:"));
2109
- console.log(import_chalk16.default.cyan(fullUrl));
2110
- console.log(import_chalk16.default.bold("\n\u{1F916} [FOR AI AGENTS]:"));
2111
- console.log(import_chalk16.default.dim(" You have successfully prepared a report."));
2208
+ console.log(import_chalk17.default.green("\u{1F680} Issue Draft Prepared!\n"));
2209
+ console.log(import_chalk17.default.bold("Title: ") + title);
2210
+ console.log(import_chalk17.default.bold("Type: ") + type);
2211
+ console.log(import_chalk17.default.bold("\nClick the link below to submit this issue:"));
2212
+ console.log(import_chalk17.default.cyan(fullUrl));
2213
+ console.log(import_chalk17.default.bold("\n\u{1F916} [FOR AI AGENTS]:"));
2214
+ console.log(import_chalk17.default.dim(" You have successfully prepared a report."));
2112
2215
  console.log(
2113
- import_chalk16.default.dim(
2216
+ import_chalk17.default.dim(
2114
2217
  " Please present the URL above to the user so they can finalize the submission."
2115
2218
  )
2116
2219
  );
@@ -2119,14 +2222,14 @@ Type: ${type}
2119
2222
  const bugUrl = `${repoUrl}/issues/new?template=bug_report.md`;
2120
2223
  const featureUrl = `${repoUrl}/issues/new?template=feature_request.md`;
2121
2224
  const metricUrl = `${repoUrl}/issues/new?template=new_metric_idea.md`;
2122
- console.log(import_chalk16.default.blue("\u{1F4AC} Feedback & Bug Reports\n"));
2123
- console.log(` Report a Bug: ${import_chalk16.default.cyan(bugUrl)}`);
2124
- console.log(` Request a Feature: ${import_chalk16.default.cyan(featureUrl)}`);
2125
- console.log(` Suggest a Metric: ${import_chalk16.default.cyan(metricUrl)}`);
2126
- console.log(import_chalk16.default.bold("\n\u{1F916} [FOR AI AGENTS]:"));
2127
- console.log(import_chalk16.default.dim(" To prepare a specific report, run:"));
2225
+ console.log(import_chalk17.default.blue("\u{1F4AC} Feedback & Bug Reports\n"));
2226
+ console.log(` Report a Bug: ${import_chalk17.default.cyan(bugUrl)}`);
2227
+ console.log(` Request a Feature: ${import_chalk17.default.cyan(featureUrl)}`);
2228
+ console.log(` Suggest a Metric: ${import_chalk17.default.cyan(metricUrl)}`);
2229
+ console.log(import_chalk17.default.bold("\n\u{1F916} [FOR AI AGENTS]:"));
2230
+ console.log(import_chalk17.default.dim(" To prepare a specific report, run:"));
2128
2231
  console.log(
2129
- import_chalk16.default.cyan(
2232
+ import_chalk17.default.cyan(
2130
2233
  ' aiready bug "your description here" --type bug|feature|metric'
2131
2234
  )
2132
2235
  );
@@ -2139,14 +2242,105 @@ EXAMPLES:
2139
2242
  $ aiready bug "Fix typo in scan output" --submit # Submit directly via gh CLI
2140
2243
  `;
2141
2244
 
2245
+ // src/commands/remediate.ts
2246
+ var import_chalk18 = __toESM(require("chalk"));
2247
+ var import_path7 = require("path");
2248
+ var import_fs8 = require("fs");
2249
+ var import_core18 = require("@aiready/core");
2250
+ async function remediateAction(directory, options) {
2251
+ const resolvedDir = (0, import_path7.resolve)(process.cwd(), directory || ".");
2252
+ const serverUrl = options.server || "https://platform.getaiready.dev";
2253
+ (0, import_core18.printTerminalHeader)("AIREADY REMEDIATION SWARM");
2254
+ console.log(import_chalk18.default.cyan("\u{1F916} Initializing local remediation agent..."));
2255
+ let reportPath = options.report;
2256
+ if (!reportPath) {
2257
+ const aireadyDir = (0, import_path7.resolve)(resolvedDir, ".aiready");
2258
+ if ((0, import_fs8.existsSync)(aireadyDir)) {
2259
+ const files = (0, import_fs8.readdirSync)(aireadyDir).filter((f) => f.startsWith("aiready-report-") && f.endsWith(".json")).sort().reverse();
2260
+ if (files.length > 0) {
2261
+ reportPath = (0, import_path7.resolve)(aireadyDir, files[0]);
2262
+ console.log(import_chalk18.default.dim(`\u{1F4C2} Using latest report: ${files[0]}`));
2263
+ }
2264
+ }
2265
+ }
2266
+ if (!reportPath || !(0, import_fs8.existsSync)(reportPath)) {
2267
+ console.log(import_chalk18.default.yellow("\n\u26A0\uFE0F No AIReady report found."));
2268
+ console.log(
2269
+ import_chalk18.default.dim(
2270
+ " Remediation requires a recent scan report to identify issues."
2271
+ )
2272
+ );
2273
+ console.log(import_chalk18.default.white(` Run ${import_chalk18.default.bold("aiready scan")} first.
2274
+ `));
2275
+ return;
2276
+ }
2277
+ console.log(import_chalk18.default.green("\n\u2705 Analysis data loaded."));
2278
+ console.log(import_chalk18.default.bold("\n\u{1F680} Remediation Strategy:"));
2279
+ if (options.tool === "patterns" || !options.tool) {
2280
+ console.log(
2281
+ import_chalk18.default.white(
2282
+ ` \u2022 ${import_chalk18.default.bold("Pattern Consolidation")}: Suggested refactors for 95%+ similar code blocks.`
2283
+ )
2284
+ );
2285
+ }
2286
+ if (options.tool === "consistency" || !options.tool) {
2287
+ console.log(
2288
+ import_chalk18.default.white(
2289
+ ` \u2022 ${import_chalk18.default.bold("Naming Alignment")}: Automated TSDoc generation and constant extraction.`
2290
+ )
2291
+ );
2292
+ }
2293
+ if (options.tool === "context" || !options.tool) {
2294
+ console.log(
2295
+ import_chalk18.default.white(
2296
+ ` \u2022 ${import_chalk18.default.bold("Context Optimization")}: Barrel file cleanup and import flattening.`
2297
+ )
2298
+ );
2299
+ }
2300
+ console.log(
2301
+ import_chalk18.default.dim(
2302
+ "\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"
2303
+ )
2304
+ );
2305
+ console.log(import_chalk18.default.bold("\u2728 Use the Platform Swarm for Automated Fixes"));
2306
+ console.log(
2307
+ import_chalk18.default.cyan(` The high-performance Remediation Swarm is available at:`)
2308
+ );
2309
+ console.log(import_chalk18.default.white(` ${import_chalk18.default.bold(`${serverUrl}/remediate`)}`));
2310
+ console.log(
2311
+ import_chalk18.default.dim(
2312
+ "\n The swarm uses specialized agents to safely refactor your code,"
2313
+ )
2314
+ );
2315
+ console.log(
2316
+ import_chalk18.default.dim(" ensuring every change improves your AI-readiness score.")
2317
+ );
2318
+ console.log(
2319
+ import_chalk18.default.dim(
2320
+ "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
2321
+ )
2322
+ );
2323
+ console.log(
2324
+ import_chalk18.default.dim(
2325
+ '\n\u{1F4A1} Next Version: Local "aiready fix" command for minor documentation issues.'
2326
+ )
2327
+ );
2328
+ }
2329
+ var REMEDIATE_HELP_TEXT = `
2330
+ EXAMPLES:
2331
+ $ aiready remediate # See remediation options for latest report
2332
+ $ aiready remediate --tool patterns # Focus on pattern consolidation
2333
+ $ aiready remediate --report ./custom-report.json
2334
+ `;
2335
+
2142
2336
  // src/cli.ts
2143
2337
  var import_meta = {};
2144
2338
  var getDirname = () => {
2145
2339
  if (typeof __dirname !== "undefined") return __dirname;
2146
- return (0, import_path7.dirname)((0, import_url.fileURLToPath)(import_meta.url));
2340
+ return (0, import_path8.dirname)((0, import_url.fileURLToPath)(import_meta.url));
2147
2341
  };
2148
2342
  var packageJson = JSON.parse(
2149
- (0, import_fs8.readFileSync)((0, import_path7.join)(getDirname(), "../package.json"), "utf8")
2343
+ (0, import_fs9.readFileSync)((0, import_path8.join)(getDirname(), "../package.json"), "utf8")
2150
2344
  );
2151
2345
  var program = new import_commander.Command();
2152
2346
  program.name("aiready").description("AIReady - Assess and improve AI-readiness of codebases").version(packageJson.version).addHelpText(
@@ -2290,9 +2484,19 @@ program.command("change-amplification").description("Analyze graph metrics for c
2290
2484
  program.command("testability").description("Analyze test coverage and AI readiness").argument("[directory]", "Directory to analyze", ".").option("--min-coverage <ratio>", "Minimum acceptable coverage ratio", "0.3").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)").action(async (directory, options) => {
2291
2485
  await testabilityAction(directory, options);
2292
2486
  });
2487
+ program.command("contract").description("Analyze structural contract enforcement and defensive coding").argument("[directory]", "Directory to analyze", ".").option(
2488
+ "--min-chain-depth <depth>",
2489
+ "Minimum optional chain depth to flag",
2490
+ "3"
2491
+ ).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)").action(async (directory, options) => {
2492
+ await contractEnforcementAction(directory, options);
2493
+ });
2293
2494
  program.command("upload").description("Upload an AIReady report JSON to the platform").argument("<file>", "Report JSON file to upload").option("--api-key <key>", "Platform API key").option("--repo-id <id>", "Platform repository ID (optional)").option("--server <url>", "Custom platform URL").addHelpText("after", UPLOAD_HELP_TEXT).action(async (file, options) => {
2294
2495
  await uploadAction(file, options);
2295
2496
  });
2497
+ program.command("remediate").description("Suggest AI-ready refactors based on a scan report").argument("[directory]", "Directory to remediate", ".").option("-r, --report <path>", "AIReady report JSON file").option("-t, --tool <name>", "Filter by tool: patterns, context, consistency").option("--server <url>", "Custom platform URL").addHelpText("after", REMEDIATE_HELP_TEXT).action(async (directory, options) => {
2498
+ await remediateAction(directory, options);
2499
+ });
2296
2500
  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").option("--submit", "Submit the issue directly using the GitHub CLI (gh)").addHelpText("after", BUG_HELP_TEXT).action(async (message, options) => {
2297
2501
  await bugAction(message, options);
2298
2502
  });