#!/usr/bin/env node
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));

// src/cli.ts
var import_commander = require("commander");
var import_fs6 = require("fs");
var import_path8 = require("path");
var import_url = require("url");

// src/commands/scan.ts
var import_chalk3 = __toESM(require("chalk"));
var import_fs3 = require("fs");
var import_path3 = require("path");
var import_core3 = require("@aiready/core");

// src/index.ts
var import_core = require("@aiready/core");
var import_pattern_detect = require("@aiready/pattern-detect");
var import_context_analyzer = require("@aiready/context-analyzer");
var import_consistency = require("@aiready/consistency");
var import_ai_signal_clarity = require("@aiready/ai-signal-clarity");
var import_agent_grounding = require("@aiready/agent-grounding");
var import_testability = require("@aiready/testability");
var import_doc_drift = require("@aiready/doc-drift");
var import_deps = require("@aiready/deps");
var import_change_amplification = require("@aiready/change-amplification");
var TOOL_PACKAGE_MAP = {
  [import_core.ToolName.PatternDetect]: "@aiready/pattern-detect",
  [import_core.ToolName.ContextAnalyzer]: "@aiready/context-analyzer",
  [import_core.ToolName.NamingConsistency]: "@aiready/consistency",
  [import_core.ToolName.AiSignalClarity]: "@aiready/ai-signal-clarity",
  [import_core.ToolName.AgentGrounding]: "@aiready/agent-grounding",
  [import_core.ToolName.TestabilityIndex]: "@aiready/testability",
  [import_core.ToolName.DocDrift]: "@aiready/doc-drift",
  [import_core.ToolName.DependencyHealth]: "@aiready/deps",
  [import_core.ToolName.ChangeAmplification]: "@aiready/change-amplification",
  // Aliases handled by registry
  patterns: "@aiready/pattern-detect",
  duplicates: "@aiready/pattern-detect",
  context: "@aiready/context-analyzer",
  fragmentation: "@aiready/context-analyzer",
  consistency: "@aiready/consistency",
  "naming-consistency": "@aiready/consistency",
  "ai-signal": "@aiready/ai-signal-clarity",
  "ai-signal-clarity": "@aiready/ai-signal-clarity",
  grounding: "@aiready/agent-grounding",
  "agent-grounding": "@aiready/agent-grounding",
  testability: "@aiready/testability",
  "testability-index": "@aiready/testability",
  "doc-drift": "@aiready/doc-drift",
  "deps-health": "@aiready/deps",
  "dependency-health": "@aiready/deps",
  "change-amp": "@aiready/change-amplification",
  "change-amplification": "@aiready/change-amplification"
};
async function analyzeUnified(options) {
  const startTime = Date.now();
  const requestedTools = options.tools || [
    "patterns",
    "context",
    "consistency"
  ];
  const result = {
    summary: {
      totalIssues: 0,
      totalFiles: 0,
      toolsRun: [],
      executionTime: 0
    }
  };
  for (const toolName of requestedTools) {
    let provider = import_core.ToolRegistry.find(toolName);
    if (!provider) {
      const packageName = TOOL_PACKAGE_MAP[toolName] || (toolName.startsWith("@aiready/") ? toolName : `@aiready/${toolName}`);
      try {
        await import(packageName);
        provider = import_core.ToolRegistry.find(toolName);
        if (provider) {
          console.log(
            `\u2705 Successfully loaded tool provider: ${toolName} from ${packageName}`
          );
        } else {
          console.log(
            `\u26A0\uFE0F Loaded ${packageName} but provider ${toolName} still not found in registry.`
          );
        }
      } catch (err) {
        console.log(
          `\u274C Failed to dynamically load tool ${toolName} (${packageName}):`,
          err.message
        );
      }
    }
    if (!provider) {
      console.warn(
        `\u26A0\uFE0F  Warning: Tool provider for '${toolName}' not found. Skipping.`
      );
      continue;
    }
    try {
      const output = await provider.analyze({
        ...options,
        onProgress: (processed, total, message) => {
          if (options.progressCallback) {
            options.progressCallback({
              tool: provider.id,
              processed,
              total,
              message
            });
          }
        }
      });
      if (options.progressCallback) {
        options.progressCallback({ tool: provider.id, data: output });
      }
      result[provider.id] = output;
      result.summary.toolsRun.push(provider.id);
      const toolFiles = output.summary?.totalFiles || output.summary?.filesAnalyzed || 0;
      if (toolFiles > result.summary.totalFiles) {
        result.summary.totalFiles = toolFiles;
      }
      const issueCount = output.results.reduce(
        (sum, file) => sum + (file.issues?.length || 0),
        0
      );
      result.summary.totalIssues += issueCount;
      if (provider.alias && Array.isArray(provider.alias)) {
        for (const alias of provider.alias) {
          if (!result[alias]) {
            result[alias] = output;
          }
        }
      }
      const camelCaseId = provider.id.replace(
        /-([a-z])/g,
        (g) => g[1].toUpperCase()
      );
      if (camelCaseId !== provider.id && !result[camelCaseId]) {
        result[camelCaseId] = output;
      }
    } catch (err) {
      console.error(`\u274C Error running tool '${provider.id}':`, err);
    }
  }
  result.summary.executionTime = Date.now() - startTime;
  return result;
}
async function scoreUnified(results, options) {
  const toolScores = /* @__PURE__ */ new Map();
  for (const toolId of results.summary.toolsRun) {
    const provider = import_core.ToolRegistry.get(toolId);
    if (!provider) continue;
    const output = results[toolId];
    if (!output) continue;
    try {
      const toolScore = provider.score(output, options);
      if (!toolScore.tokenBudget) {
        if (toolId === import_core.ToolName.PatternDetect && output.duplicates) {
          const wastedTokens = output.duplicates.reduce(
            (sum, d) => sum + (d.tokenCost || 0),
            0
          );
          toolScore.tokenBudget = (0, import_core.calculateTokenBudget)({
            totalContextTokens: wastedTokens * 2,
            wastedTokens: {
              duplication: wastedTokens,
              fragmentation: 0,
              chattiness: 0
            }
          });
        } else if (toolId === import_core.ToolName.ContextAnalyzer && output.summary) {
          toolScore.tokenBudget = (0, import_core.calculateTokenBudget)({
            totalContextTokens: output.summary.totalTokens,
            wastedTokens: {
              duplication: 0,
              fragmentation: output.summary.totalPotentialSavings || 0,
              chattiness: 0
            }
          });
        }
      }
      toolScores.set(toolId, toolScore);
    } catch (err) {
      console.error(`\u274C Error scoring tool '${toolId}':`, err);
    }
  }
  if (toolScores.size === 0) {
    return {
      overall: 0,
      rating: "Critical",
      timestamp: (/* @__PURE__ */ new Date()).toISOString(),
      toolsUsed: [],
      breakdown: [],
      calculation: {
        formula: "0 / 0 = 0",
        weights: {},
        normalized: "0 / 0 = 0"
      }
    };
  }
  return (0, import_core.calculateOverallScore)(toolScores, options, void 0);
}

// src/utils/helpers.ts
var import_path = require("path");
var import_fs = require("fs");
var import_chalk = __toESM(require("chalk"));
function getReportTimestamp() {
  const now = /* @__PURE__ */ new Date();
  const pad = (n) => String(n).padStart(2, "0");
  return `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}-${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
}
function findLatestScanReport(dirPath) {
  const aireadyDir = (0, import_path.resolve)(dirPath, ".aiready");
  if (!(0, import_fs.existsSync)(aireadyDir)) {
    return null;
  }
  let files = (0, import_fs.readdirSync)(aireadyDir).filter(
    (f) => f.startsWith("aiready-report-") && f.endsWith(".json")
  );
  if (files.length === 0) {
    files = (0, import_fs.readdirSync)(aireadyDir).filter(
      (f) => f.startsWith("aiready-scan-") && f.endsWith(".json")
    );
  }
  if (files.length === 0) {
    return null;
  }
  const sortedFiles = files.map((f) => ({
    name: f,
    path: (0, import_path.resolve)(aireadyDir, f),
    mtime: (0, import_fs.statSync)((0, import_path.resolve)(aireadyDir, f)).mtime
  })).sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
  return sortedFiles[0].path;
}
async function warnIfGraphCapExceeded(report, dirPath) {
  try {
    const { loadConfig: loadConfig4 } = await import("@aiready/core");
    void loadConfig4;
    let graphConfig = { maxNodes: 400, maxEdges: 600 };
    const configPath = (0, import_path.resolve)(dirPath, "aiready.json");
    if ((0, import_fs.existsSync)(configPath)) {
      try {
        const rawConfig = JSON.parse((0, import_fs.readFileSync)(configPath, "utf8"));
        if (rawConfig.visualizer?.graph) {
          graphConfig = {
            maxNodes: rawConfig.visualizer.graph.maxNodes ?? graphConfig.maxNodes,
            maxEdges: rawConfig.visualizer.graph.maxEdges ?? graphConfig.maxEdges
          };
        }
      } catch (err) {
        void err;
      }
    }
    const nodeCount = (report.context?.length || 0) + (report.patterns?.length || 0);
    const edgeCount = report.context?.reduce((sum, ctx) => {
      const relCount = ctx.relatedFiles?.length || 0;
      const depCount = ctx.dependencies?.length || 0;
      return sum + relCount + depCount;
    }, 0) || 0;
    if (nodeCount > graphConfig.maxNodes || edgeCount > graphConfig.maxEdges) {
      console.log("");
      console.log(
        import_chalk.default.yellow(`\u26A0\uFE0F  Graph may be truncated at visualization time:`)
      );
      if (nodeCount > graphConfig.maxNodes) {
        console.log(
          import_chalk.default.dim(`   \u2022 Nodes: ${nodeCount} > limit ${graphConfig.maxNodes}`)
        );
      }
      if (edgeCount > graphConfig.maxEdges) {
        console.log(
          import_chalk.default.dim(`   \u2022 Edges: ${edgeCount} > limit ${graphConfig.maxEdges}`)
        );
      }
      console.log(import_chalk.default.dim(`   To increase limits, add to aiready.json:`));
      console.log(import_chalk.default.dim(`   {`));
      console.log(import_chalk.default.dim(`     "visualizer": {`));
      console.log(
        import_chalk.default.dim(`       "graph": { "maxNodes": 2000, "maxEdges": 5000 }`)
      );
      console.log(import_chalk.default.dim(`     }`));
      console.log(import_chalk.default.dim(`   }`));
    }
  } catch (err) {
    void err;
  }
}
function generateMarkdownReport(report, elapsedTime) {
  let markdown = `# Consistency Analysis Report

`;
  markdown += `**Generated:** ${(/* @__PURE__ */ new Date()).toISOString()}
`;
  markdown += `**Analysis Time:** ${elapsedTime}s

`;
  markdown += `## Summary

`;
  markdown += `- **Files Analyzed:** ${report.summary.filesAnalyzed}
`;
  markdown += `- **Total Issues:** ${report.summary.totalIssues}
`;
  markdown += `  - Naming: ${report.summary.namingIssues}
`;
  markdown += `  - Patterns: ${report.summary.patternIssues}

`;
  if (report.recommendations.length > 0) {
    markdown += `## Recommendations

`;
    report.recommendations.forEach((rec, i) => {
      markdown += `${i + 1}. ${rec}
`;
    });
  }
  return markdown;
}

// src/commands/upload.ts
var import_fs2 = __toESM(require("fs"));
var import_path2 = require("path");
var import_chalk2 = __toESM(require("chalk"));
var import_core2 = require("@aiready/core");
async function uploadAction(file, options) {
  const startTime = Date.now();
  const filePath = (0, import_path2.resolve)(process.cwd(), file);
  const serverUrl = options.server || process.env.AIREADY_SERVER || "https://dev.platform.getaiready.dev";
  const apiKey = options.apiKey || process.env.AIREADY_API_KEY;
  if (!apiKey) {
    console.error(import_chalk2.default.red("\u274C API Key is required for upload."));
    console.log(
      import_chalk2.default.dim(
        "   Set AIREADY_API_KEY environment variable or use --api-key flag."
      )
    );
    console.log(
      import_chalk2.default.dim(
        "   Get an API key from https://platform.getaiready.dev/dashboard"
      )
    );
    process.exit(1);
  }
  if (!import_fs2.default.existsSync(filePath)) {
    console.error(import_chalk2.default.red(`\u274C File not found: ${filePath}`));
    process.exit(1);
  }
  try {
    console.log(import_chalk2.default.blue(`\u{1F680} Uploading report to ${serverUrl}...`));
    console.log(import_chalk2.default.dim(`   Reading report from ${filePath}...`));
    const reportContent = import_fs2.default.readFileSync(filePath, "utf-8");
    const reportData = JSON.parse(reportContent);
    console.log(import_chalk2.default.dim(`   Successfully parsed report JSON.`));
    const repoId = options.repoId || reportData.repository?.repoId;
    const res = await fetch(`${serverUrl}/api/analysis/upload`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${apiKey}`
      },
      body: JSON.stringify({
        data: reportData,
        repoId
        // Might be null, server will handle mapping
      })
    });
    const contentType = res.headers.get("content-type");
    let result = {};
    if (contentType?.includes("application/json")) {
      result = await res.json();
    } else {
      const text = await res.text();
      result = { error: text || res.statusText };
    }
    if (!res.ok) {
      console.error(
        import_chalk2.default.red(`\u274C Upload failed: ${result.error || res.statusText}`)
      );
      if (contentType?.includes("text/html")) {
        console.log(
          import_chalk2.default.yellow(
            "   Note: Received an HTML response. This often indicates a redirect (e.g., to a login page) or a server error."
          )
        );
        if (result.error?.includes("Redirecting")) {
          console.log(
            import_chalk2.default.dim(
              "   Detected redirect. Check if the API endpoint requires authentication or has changed."
            )
          );
        }
      }
      if (res.status === 401) {
        console.log(
          import_chalk2.default.dim("   Hint: Your API key may be invalid or expired.")
        );
      }
      process.exit(1);
    }
    const duration = ((Date.now() - startTime) / 1e3).toFixed(2);
    console.log(import_chalk2.default.green(`
\u2705 Upload successful! (${duration}s)`));
    console.log(import_chalk2.default.cyan(`   View results: ${serverUrl}/dashboard`));
    if (result.analysis) {
      console.log(import_chalk2.default.dim(`   Analysis ID: ${result.analysis.id}`));
      console.log(import_chalk2.default.dim(`   Score: ${result.analysis.aiScore}/100`));
    }
  } catch (error) {
    (0, import_core2.handleCLIError)(error, "Upload");
  }
}
var uploadHelpText = `
EXAMPLES:
  $ aiready upload report.json --api-key ar_...
  $ aiready upload .aiready/latest.json
  $ AIREADY_API_KEY=ar_... aiready upload report.json

ENVIRONMENT VARIABLES:
  AIREADY_API_KEY    Your platform API key
  AIREADY_SERVER     Custom platform URL (default: https://dev.platform.getaiready.dev)
`;

// src/commands/scan.ts
async function scanAction(directory, options) {
  console.log(import_chalk3.default.blue("\u{1F680} Starting AIReady unified analysis...\n"));
  const startTime = Date.now();
  const resolvedDir = (0, import_path3.resolve)(process.cwd(), directory || ".");
  const repoMetadata = (0, import_core3.getRepoMetadata)(resolvedDir);
  try {
    const defaults = {
      tools: [
        "pattern-detect",
        "context-analyzer",
        "naming-consistency",
        "ai-signal-clarity",
        "agent-grounding",
        "testability-index",
        "doc-drift",
        "dependency-health",
        "change-amplification"
      ],
      include: void 0,
      exclude: void 0,
      output: {
        format: "console",
        file: void 0
      }
    };
    let profileTools = options.tools ? options.tools.split(",").map((t) => t.trim()) : void 0;
    if (options.profile) {
      switch (options.profile.toLowerCase()) {
        case "agentic":
          profileTools = [
            import_core3.ToolName.AiSignalClarity,
            import_core3.ToolName.AgentGrounding,
            import_core3.ToolName.TestabilityIndex
          ];
          break;
        case "cost":
          profileTools = [import_core3.ToolName.PatternDetect, import_core3.ToolName.ContextAnalyzer];
          break;
        case "security":
          profileTools = [
            import_core3.ToolName.NamingConsistency,
            import_core3.ToolName.TestabilityIndex
          ];
          break;
        case "onboarding":
          profileTools = [
            import_core3.ToolName.ContextAnalyzer,
            import_core3.ToolName.NamingConsistency,
            import_core3.ToolName.AgentGrounding
          ];
          break;
        default:
          console.log(
            import_chalk3.default.yellow(
              `
\u26A0\uFE0F  Unknown profile '${options.profile}'. Using defaults.`
            )
          );
      }
    }
    const cliOverrides = {
      include: options.include?.split(","),
      exclude: options.exclude?.split(",")
    };
    if (profileTools) cliOverrides.tools = profileTools;
    const baseOptions = await (0, import_core3.loadMergedConfig)(
      resolvedDir,
      defaults,
      cliOverrides
    );
    let finalOptions = { ...baseOptions };
    if (baseOptions.tools.includes(import_core3.ToolName.PatternDetect) || baseOptions.tools.includes("patterns")) {
      const { getSmartDefaults } = await import("@aiready/pattern-detect");
      const patternSmartDefaults = await getSmartDefaults(
        resolvedDir,
        baseOptions
      );
      finalOptions = {
        ...patternSmartDefaults,
        ...finalOptions,
        ...baseOptions
      };
    }
    console.log(import_chalk3.default.cyan("\n=== AIReady Run Preview ==="));
    console.log(
      import_chalk3.default.white("Tools to run:"),
      (finalOptions.tools || []).join(", ")
    );
    const progressCallback = (event) => {
      if (event.message) {
        process.stdout.write(`\r\x1B[K   [${event.tool}] ${event.message}`);
        return;
      }
      process.stdout.write("\r\x1B[K");
      console.log(import_chalk3.default.cyan(`--- ${event.tool.toUpperCase()} RESULTS ---`));
      const res = event.data;
      if (res && res.summary) {
        if (res.summary.totalIssues !== void 0)
          console.log(`  Issues found: ${import_chalk3.default.bold(res.summary.totalIssues)}`);
        if (res.summary.score !== void 0)
          console.log(`  Tool Score: ${import_chalk3.default.bold(res.summary.score)}/100`);
        if (res.summary.totalFiles !== void 0)
          console.log(
            `  Files analyzed: ${import_chalk3.default.bold(res.summary.totalFiles)}`
          );
      }
    };
    const results = await analyzeUnified({
      ...finalOptions,
      progressCallback,
      onProgress: () => {
      },
      suppressToolConfig: true
    });
    console.log(import_chalk3.default.cyan("\n=== AIReady Run Summary ==="));
    console.log(
      `  Total issues (all tools): ${import_chalk3.default.bold(String(results.summary.totalIssues || 0))}`
    );
    let scoringResult;
    if (options.score || finalOptions.scoring?.showBreakdown) {
      scoringResult = await scoreUnified(results, finalOptions);
      console.log(import_chalk3.default.bold("\n\u{1F4CA} AI Readiness Overall Score"));
      console.log(`  ${(0, import_core3.formatScore)(scoringResult)}`);
      if (options.compareTo) {
        try {
          const prevReport = JSON.parse(
            (0, import_fs3.readFileSync)((0, import_path3.resolve)(process.cwd(), options.compareTo), "utf8")
          );
          const prevScore = prevReport.scoring?.overall || prevReport.scoring?.score;
          if (typeof prevScore === "number") {
            const diff = scoringResult.overall - prevScore;
            const diffStr = diff > 0 ? `+${diff}` : String(diff);
            if (diff > 0)
              console.log(
                import_chalk3.default.green(
                  `  \u{1F4C8} Trend: ${diffStr} compared to ${options.compareTo} (${prevScore} \u2192 ${scoringResult.overall})`
                )
              );
            else if (diff < 0)
              console.log(
                import_chalk3.default.red(
                  `  \u{1F4C9} Trend: ${diffStr} compared to ${options.compareTo} (${prevScore} \u2192 ${scoringResult.overall})`
                )
              );
            else
              console.log(
                import_chalk3.default.blue(
                  `  \u2796 Trend: No change (${prevScore} \u2192 ${scoringResult.overall})`
                )
              );
          }
        } catch (e) {
          void e;
        }
      }
      const totalWastedDuplication = (scoringResult.breakdown || []).reduce(
        (sum, s) => sum + (s.tokenBudget?.wastedTokens.bySource.duplication || 0),
        0
      );
      const totalWastedFragmentation = (scoringResult.breakdown || []).reduce(
        (sum, s) => sum + (s.tokenBudget?.wastedTokens.bySource.fragmentation || 0),
        0
      );
      const totalContext = Math.max(
        ...(scoringResult.breakdown || []).map(
          (s) => s.tokenBudget?.totalContextTokens || 0
        ),
        0
      );
      if (totalContext > 0) {
        const unifiedBudget = (0, import_core3.calculateTokenBudget)({
          totalContextTokens: totalContext,
          wastedTokens: {
            duplication: totalWastedDuplication,
            fragmentation: totalWastedFragmentation,
            chattiness: 0
          }
        });
        const modelPreset = (0, import_core3.getModelPreset)(options.model || "claude-4.6");
        const costEstimate = (0, import_core3.estimateCostFromBudget)(unifiedBudget, modelPreset);
        console.log(import_chalk3.default.bold("\n\u{1F4CA} AI Token Budget Analysis"));
        console.log(
          `  Efficiency: ${(unifiedBudget.efficiencyRatio * 100).toFixed(0)}%`
        );
        console.log(
          `  Wasted Tokens: ${import_chalk3.default.red(unifiedBudget.wastedTokens.total.toLocaleString())}`
        );
        console.log(
          `  Est. Monthly Cost (${modelPreset.name}): ${import_chalk3.default.bold("$" + costEstimate.total)}`
        );
        scoringResult.tokenBudget = unifiedBudget;
        scoringResult.costEstimate = {
          model: modelPreset.name,
          ...costEstimate
        };
      }
      if (scoringResult.breakdown) {
        console.log(import_chalk3.default.bold("\nTool breakdown:"));
        scoringResult.breakdown.forEach((tool) => {
          const rating = (0, import_core3.getRating)(tool.score);
          console.log(`  - ${tool.toolName}: ${tool.score}/100 (${rating})`);
        });
      }
    }
    const mapToUnifiedReport = (res, scoring) => {
      const allResults = [];
      const totalFilesSet = /* @__PURE__ */ new Set();
      let criticalCount = 0;
      let majorCount = 0;
      res.summary.toolsRun.forEach((toolId) => {
        const spokeRes = res[toolId];
        if (!spokeRes || !spokeRes.results) return;
        spokeRes.results.forEach((r) => {
          totalFilesSet.add(r.fileName);
          allResults.push(r);
          r.issues?.forEach((i) => {
            if (i.severity === import_core3.Severity.Critical) criticalCount++;
            if (i.severity === import_core3.Severity.Major) majorCount++;
          });
        });
      });
      return {
        ...res,
        results: allResults,
        summary: {
          ...res.summary,
          totalFiles: totalFilesSet.size,
          criticalIssues: criticalCount,
          majorIssues: majorCount
        },
        scoring
      };
    };
    const outputData = {
      ...mapToUnifiedReport(results, scoringResult),
      repository: repoMetadata
    };
    const outputFormat = options.output || finalOptions.output?.format || "console";
    const outputPath = (0, import_core3.resolveOutputPath)(
      options.outputFile || finalOptions.output?.file,
      `aiready-report-${getReportTimestamp()}.json`,
      resolvedDir
    );
    if (outputFormat === "json") {
      (0, import_core3.handleJSONOutput)(
        outputData,
        outputPath,
        `\u2705 Report saved to ${outputPath}`
      );
    } else {
      try {
        (0, import_fs3.writeFileSync)(outputPath, JSON.stringify(outputData, null, 2));
        console.log(import_chalk3.default.dim(`\u2705 Report auto-persisted to ${outputPath}`));
      } catch (err) {
        void err;
      }
    }
    if (options.upload) {
      await uploadAction(outputPath, {
        apiKey: options.apiKey,
        server: options.server
      });
    }
    await warnIfGraphCapExceeded(outputData, resolvedDir);
    const isCI = options.ci || process.env.CI === "true";
    if (isCI && scoringResult) {
      const threshold = options.threshold ? parseInt(options.threshold) : void 0;
      const failOnLevel = options.failOn || "critical";
      let shouldFail = false;
      let failReason = "";
      if (threshold && scoringResult.overall < threshold) {
        shouldFail = true;
        failReason = `Score ${scoringResult.overall} < threshold ${threshold}`;
      }
      const report = mapToUnifiedReport(results, scoringResult);
      if (failOnLevel !== "none") {
        if (failOnLevel === "critical" && report.summary.criticalIssues > 0) {
          shouldFail = true;
          failReason = `Found ${report.summary.criticalIssues} critical issues`;
        } else if (failOnLevel === "major" && report.summary.criticalIssues + report.summary.majorIssues > 0) {
          shouldFail = true;
          failReason = `Found ${report.summary.criticalIssues} critical and ${report.summary.majorIssues} major issues`;
        }
      }
      if (shouldFail) {
        console.log(import_chalk3.default.red(`
\u{1F6AB} PR BLOCKED: ${failReason}`));
        process.exit(1);
      } else {
        console.log(import_chalk3.default.green("\n\u2705 PR PASSED"));
      }
    }
  } catch (error) {
    (0, import_core3.handleCLIError)(error, "Analysis");
  }
}
var scanHelpText = `...`;

// src/commands/patterns.ts
var import_chalk4 = __toESM(require("chalk"));
var import_path4 = require("path");
var import_core4 = require("@aiready/core");
async function patternsAction(directory, options) {
  console.log(import_chalk4.default.blue("\u{1F50D} Analyzing patterns...\n"));
  const startTime = Date.now();
  const resolvedDir = (0, import_path4.resolve)(process.cwd(), directory || ".");
  try {
    const useSmartDefaults = !options.fullScan;
    const defaults = {
      useSmartDefaults,
      include: void 0,
      exclude: void 0,
      output: {
        format: "console",
        file: void 0
      }
    };
    if (!useSmartDefaults) {
      defaults.minSimilarity = 0.4;
      defaults.minLines = 5;
    }
    const cliOptions = {
      minSimilarity: options.similarity ? parseFloat(options.similarity) : void 0,
      minLines: options.minLines ? parseInt(options.minLines) : void 0,
      useSmartDefaults,
      include: options.include?.split(","),
      exclude: options.exclude?.split(",")
    };
    if (options.maxCandidates) {
      cliOptions.maxCandidatesPerBlock = parseInt(options.maxCandidates);
    }
    if (options.minSharedTokens) {
      cliOptions.minSharedTokens = parseInt(options.minSharedTokens);
    }
    const finalOptions = await (0, import_core4.loadMergedConfig)(
      resolvedDir,
      defaults,
      cliOptions
    );
    const { analyzePatterns, generateSummary, calculatePatternScore } = await import("@aiready/pattern-detect");
    const { results, duplicates } = await analyzePatterns(finalOptions);
    const elapsedTime = (0, import_core4.getElapsedTime)(startTime);
    const summary = generateSummary(results);
    let patternScore;
    if (options.score) {
      patternScore = calculatePatternScore(duplicates, results.length);
    }
    const outputFormat = options.output || finalOptions.output?.format || "console";
    const userOutputFile = options.outputFile || finalOptions.output?.file;
    if (outputFormat === "json") {
      const outputData = {
        results,
        summary: { ...summary, executionTime: parseFloat(elapsedTime) },
        ...patternScore && { scoring: patternScore }
      };
      const outputPath = (0, import_core4.resolveOutputPath)(
        userOutputFile,
        `aiready-report-${getReportTimestamp()}.json`,
        resolvedDir
      );
      (0, import_core4.handleJSONOutput)(
        outputData,
        outputPath,
        `\u2705 Results saved to ${outputPath}`
      );
    } else {
      const terminalWidth = process.stdout.columns || 80;
      const dividerWidth = Math.min(60, terminalWidth - 2);
      const divider = "\u2501".repeat(dividerWidth);
      console.log(import_chalk4.default.cyan(divider));
      console.log(import_chalk4.default.bold.white("  PATTERN ANALYSIS SUMMARY"));
      console.log(import_chalk4.default.cyan(divider) + "\n");
      console.log(
        import_chalk4.default.white(`\u{1F4C1} Files analyzed: ${import_chalk4.default.bold(results.length)}`)
      );
      console.log(
        import_chalk4.default.yellow(
          `\u26A0  Duplicate patterns found: ${import_chalk4.default.bold(summary.totalPatterns)}`
        )
      );
      console.log(
        import_chalk4.default.red(
          `\u{1F4B0} Token cost (wasted): ${import_chalk4.default.bold(summary.totalTokenCost.toLocaleString())}`
        )
      );
      console.log(
        import_chalk4.default.gray(`\u23F1  Analysis time: ${import_chalk4.default.bold(elapsedTime + "s")}`)
      );
      const sortedTypes = Object.entries(summary.patternsByType || {}).filter(([, count]) => count > 0).sort(([, a], [, b]) => b - a);
      if (sortedTypes.length > 0) {
        console.log(import_chalk4.default.cyan("\n" + divider));
        console.log(import_chalk4.default.bold.white("  PATTERNS BY TYPE"));
        console.log(import_chalk4.default.cyan(divider) + "\n");
        sortedTypes.forEach(([type, count]) => {
          console.log(`  ${import_chalk4.default.white(type.padEnd(15))} ${import_chalk4.default.bold(count)}`);
        });
      }
      if (summary.totalPatterns > 0 && duplicates.length > 0) {
        console.log(import_chalk4.default.cyan("\n" + divider));
        console.log(import_chalk4.default.bold.white("  TOP DUPLICATE PATTERNS"));
        console.log(import_chalk4.default.cyan(divider) + "\n");
        const topDuplicates = [...duplicates].sort((a, b) => b.similarity - a.similarity).slice(0, 10);
        topDuplicates.forEach((dup) => {
          const severity = dup.similarity > 0.95 ? "CRITICAL" : dup.similarity > 0.9 ? "HIGH" : "MEDIUM";
          const severityIcon = dup.similarity > 0.95 ? "\u{1F534}" : dup.similarity > 0.9 ? "\u{1F7E1}" : "\u{1F535}";
          const file1Name = dup.file1.split("/").pop() || dup.file1;
          const file2Name = dup.file2.split("/").pop() || dup.file2;
          console.log(
            `${severityIcon} ${severity}: ${import_chalk4.default.bold(file1Name)} \u2194 ${import_chalk4.default.bold(file2Name)}`
          );
          console.log(
            `   Similarity: ${import_chalk4.default.bold(Math.round(dup.similarity * 100) + "%")} | Wasted: ${import_chalk4.default.bold(dup.tokenCost.toLocaleString())} tokens each`
          );
          console.log(
            `   Lines: ${import_chalk4.default.cyan(dup.line1 + "-" + dup.endLine1)} \u2194 ${import_chalk4.default.cyan(dup.line2 + "-" + dup.endLine2)}
`
          );
        });
      } else {
        console.log(
          import_chalk4.default.green("\n\u2728 Great! No duplicate patterns detected.\n")
        );
      }
      if (patternScore) {
        console.log(import_chalk4.default.cyan(divider));
        console.log(import_chalk4.default.bold.white("  AI READINESS SCORE (Patterns)"));
        console.log(import_chalk4.default.cyan(divider) + "\n");
        console.log((0, import_core4.formatToolScore)(patternScore));
        console.log();
      }
    }
  } catch (error) {
    (0, import_core4.handleCLIError)(error, "Pattern analysis");
  }
}
var patternsHelpText = `
EXAMPLES:
  $ aiready patterns                                 # Default analysis
  $ aiready patterns --similarity 0.6               # Stricter matching
  $ aiready patterns --min-lines 10                 # Larger patterns only
`;

// src/commands/context.ts
var import_chalk5 = __toESM(require("chalk"));
var import_path5 = require("path");
var import_core5 = require("@aiready/core");
async function contextAction(directory, options) {
  console.log(import_chalk5.default.blue("\u{1F9E0} Analyzing context costs...\n"));
  const startTime = Date.now();
  const resolvedDir = (0, import_path5.resolve)(process.cwd(), directory || ".");
  try {
    const defaults = {
      maxDepth: 5,
      maxContextBudget: 1e4,
      include: void 0,
      exclude: void 0,
      output: {
        format: "console",
        file: void 0
      }
    };
    const baseOptions = await (0, import_core5.loadMergedConfig)(resolvedDir, defaults, {
      maxDepth: options.maxDepth ? parseInt(options.maxDepth) : void 0,
      maxContextBudget: options.maxContext ? parseInt(options.maxContext) : void 0,
      include: options.include?.split(","),
      exclude: options.exclude?.split(",")
    });
    let finalOptions = { ...baseOptions };
    const { getSmartDefaults } = await import("@aiready/context-analyzer");
    const contextSmartDefaults = await getSmartDefaults(
      resolvedDir,
      baseOptions
    );
    finalOptions = { ...contextSmartDefaults, ...finalOptions };
    console.log("\u{1F4CB} Configuration:");
    console.log(`   Max depth: ${finalOptions.maxDepth}`);
    console.log(`   Max context budget: ${finalOptions.maxContextBudget}`);
    console.log(
      `   Min cohesion: ${(finalOptions.minCohesion * 100).toFixed(1)}%`
    );
    console.log(
      `   Max fragmentation: ${(finalOptions.maxFragmentation * 100).toFixed(1)}%`
    );
    console.log(`   Analysis focus: ${finalOptions.focus}`);
    console.log("");
    const { analyzeContext, generateSummary, calculateContextScore } = await import("@aiready/context-analyzer");
    const results = await analyzeContext(finalOptions);
    const elapsedTime = (0, import_core5.getElapsedTime)(startTime);
    const summary = generateSummary(results);
    let contextScore;
    if (options.score) {
      contextScore = calculateContextScore(summary);
    }
    const outputFormat = options.output || finalOptions.output?.format || "console";
    const userOutputFile = options.outputFile || finalOptions.output?.file;
    if (outputFormat === "json") {
      const outputData = {
        results,
        summary: { ...summary, executionTime: parseFloat(elapsedTime) },
        ...contextScore && { scoring: contextScore }
      };
      const outputPath = (0, import_core5.resolveOutputPath)(
        userOutputFile,
        `aiready-report-${getReportTimestamp()}.json`,
        resolvedDir
      );
      (0, import_core5.handleJSONOutput)(
        outputData,
        outputPath,
        `\u2705 Results saved to ${outputPath}`
      );
    } else {
      const terminalWidth = process.stdout.columns || 80;
      const dividerWidth = Math.min(60, terminalWidth - 2);
      const divider = "\u2501".repeat(dividerWidth);
      console.log(import_chalk5.default.cyan(divider));
      console.log(import_chalk5.default.bold.white("  CONTEXT ANALYSIS SUMMARY"));
      console.log(import_chalk5.default.cyan(divider) + "\n");
      console.log(
        import_chalk5.default.white(`\u{1F4C1} Files analyzed: ${import_chalk5.default.bold(summary.totalFiles)}`)
      );
      console.log(
        import_chalk5.default.white(
          `\u{1F4CA} Total tokens: ${import_chalk5.default.bold(summary.totalTokens.toLocaleString())}`
        )
      );
      console.log(
        import_chalk5.default.yellow(
          `\u{1F4B0} Avg context budget: ${import_chalk5.default.bold(summary.avgContextBudget.toFixed(0))} tokens/file`
        )
      );
      console.log(
        import_chalk5.default.white(`\u23F1  Analysis time: ${import_chalk5.default.bold(elapsedTime + "s")}
`)
      );
      const totalIssues = summary.criticalIssues + summary.majorIssues + summary.minorIssues;
      if (totalIssues > 0) {
        console.log(import_chalk5.default.bold("\u26A0\uFE0F  Issues Found:\n"));
        if (summary.criticalIssues > 0) {
          console.log(
            import_chalk5.default.red(`   \u{1F534} Critical: ${import_chalk5.default.bold(summary.criticalIssues)}`)
          );
        }
        if (summary.majorIssues > 0) {
          console.log(
            import_chalk5.default.yellow(`   \u{1F7E1} Major: ${import_chalk5.default.bold(summary.majorIssues)}`)
          );
        }
        if (summary.minorIssues > 0) {
          console.log(
            import_chalk5.default.blue(`   \u{1F535} Minor: ${import_chalk5.default.bold(summary.minorIssues)}`)
          );
        }
        console.log(
          import_chalk5.default.green(
            `
   \u{1F4A1} Potential savings: ${import_chalk5.default.bold(summary.totalPotentialSavings.toLocaleString())} tokens
`
          )
        );
      } else {
        console.log(import_chalk5.default.green("\u2705 No significant issues found!\n"));
      }
      if (summary.deepFiles.length > 0) {
        console.log(import_chalk5.default.bold("\u{1F4CF} Deep Import Chains:\n"));
        console.log(
          import_chalk5.default.gray(`   Average depth: ${summary.avgImportDepth.toFixed(1)}`)
        );
        console.log(
          import_chalk5.default.gray(`   Maximum depth: ${summary.maxImportDepth}
`)
        );
        summary.deepFiles.slice(0, 10).forEach((item) => {
          const fileName = item.file.split("/").slice(-2).join("/");
          console.log(
            `   ${import_chalk5.default.cyan("\u2192")} ${import_chalk5.default.white(fileName)} ${import_chalk5.default.dim(`(depth: ${item.depth})`)}`
          );
        });
        console.log();
      }
      if (summary.fragmentedModules.length > 0) {
        console.log(import_chalk5.default.bold("\u{1F9E9} Fragmented Modules:\n"));
        console.log(
          import_chalk5.default.gray(
            `   Average fragmentation: ${(summary.avgFragmentation * 100).toFixed(0)}%
`
          )
        );
        summary.fragmentedModules.slice(0, 10).forEach((module2) => {
          console.log(
            `   ${import_chalk5.default.yellow("\u25CF")} ${import_chalk5.default.white(module2.domain)} - ${import_chalk5.default.dim(`${module2.files.length} files, ${(module2.fragmentationScore * 100).toFixed(0)}% scattered`)}`
          );
          console.log(
            import_chalk5.default.dim(
              `     Token cost: ${module2.totalTokens.toLocaleString()}, Cohesion: ${(module2.avgCohesion * 100).toFixed(0)}%`
            )
          );
        });
        console.log();
      }
      if (summary.lowCohesionFiles.length > 0) {
        console.log(import_chalk5.default.bold("\u{1F500} Low Cohesion Files:\n"));
        console.log(
          import_chalk5.default.gray(
            `   Average cohesion: ${(summary.avgCohesion * 100).toFixed(0)}%
`
          )
        );
        summary.lowCohesionFiles.slice(0, 10).forEach((item) => {
          const fileName = item.file.split("/").slice(-2).join("/");
          const scorePercent = (item.score * 100).toFixed(0);
          const color = item.score < 0.4 ? import_chalk5.default.red : import_chalk5.default.yellow;
          console.log(
            `   ${color("\u25CB")} ${import_chalk5.default.white(fileName)} ${import_chalk5.default.dim(`(${scorePercent}% cohesion)`)}`
          );
        });
        console.log();
      }
      if (summary.topExpensiveFiles.length > 0) {
        console.log(import_chalk5.default.bold("\u{1F4B8} Most Expensive Files (Context Budget):\n"));
        summary.topExpensiveFiles.slice(0, 10).forEach((item) => {
          const fileName = item.file.split("/").slice(-2).join("/");
          const severityColor = item.severity === "critical" ? import_chalk5.default.red : item.severity === "major" ? import_chalk5.default.yellow : import_chalk5.default.blue;
          console.log(
            `   ${severityColor("\u25CF")} ${import_chalk5.default.white(fileName)} ${import_chalk5.default.dim(`(${item.contextBudget.toLocaleString()} tokens)`)}`
          );
        });
        console.log();
      }
      if (contextScore) {
        console.log(import_chalk5.default.cyan(divider));
        console.log(import_chalk5.default.bold.white("  AI READINESS SCORE (Context)"));
        console.log(import_chalk5.default.cyan(divider) + "\n");
        console.log((0, import_core5.formatToolScore)(contextScore));
        console.log();
      }
    }
  } catch (error) {
    (0, import_core5.handleCLIError)(error, "Context analysis");
  }
}

// src/commands/consistency.ts
var import_chalk6 = __toESM(require("chalk"));
var import_fs4 = require("fs");
var import_path6 = require("path");
var import_core6 = require("@aiready/core");
async function consistencyAction(directory, options) {
  console.log(import_chalk6.default.blue("\u{1F50D} Analyzing consistency...\n"));
  const startTime = Date.now();
  const resolvedDir = (0, import_path6.resolve)(process.cwd(), directory || ".");
  try {
    const defaults = {
      checkNaming: true,
      checkPatterns: true,
      minSeverity: "info",
      include: void 0,
      exclude: void 0,
      output: {
        format: "console",
        file: void 0
      }
    };
    const finalOptions = await (0, import_core6.loadMergedConfig)(resolvedDir, defaults, {
      checkNaming: options.naming !== false,
      checkPatterns: options.patterns !== false,
      minSeverity: options.minSeverity,
      include: options.include?.split(","),
      exclude: options.exclude?.split(",")
    });
    const { analyzeConsistency, calculateConsistencyScore } = await import("@aiready/consistency");
    const report = await analyzeConsistency(finalOptions);
    const elapsedTime = (0, import_core6.getElapsedTime)(startTime);
    let consistencyScore;
    if (options.score) {
      const issues = report.results?.flatMap((r) => r.issues) || [];
      consistencyScore = calculateConsistencyScore(
        issues,
        report.summary.filesAnalyzed
      );
    }
    const outputFormat = options.output || finalOptions.output?.format || "console";
    const userOutputFile = options.outputFile || finalOptions.output?.file;
    if (outputFormat === "json") {
      const outputData = {
        ...report,
        summary: {
          ...report.summary,
          executionTime: parseFloat(elapsedTime)
        },
        ...consistencyScore && { scoring: consistencyScore }
      };
      const outputPath = (0, import_core6.resolveOutputPath)(
        userOutputFile,
        `aiready-report-${getReportTimestamp()}.json`,
        resolvedDir
      );
      (0, import_core6.handleJSONOutput)(
        outputData,
        outputPath,
        `\u2705 Results saved to ${outputPath}`
      );
    } else if (outputFormat === "markdown") {
      const markdown = generateMarkdownReport(report, elapsedTime);
      const outputPath = (0, import_core6.resolveOutputPath)(
        userOutputFile,
        `aiready-report-${getReportTimestamp()}.md`,
        resolvedDir
      );
      (0, import_fs4.writeFileSync)(outputPath, markdown);
      console.log(import_chalk6.default.green(`\u2705 Report saved to ${outputPath}`));
    } else {
      console.log(import_chalk6.default.bold("\n\u{1F4CA} Summary\n"));
      console.log(
        `Files Analyzed: ${import_chalk6.default.cyan(report.summary.filesAnalyzed)}`
      );
      console.log(`Total Issues: ${import_chalk6.default.yellow(report.summary.totalIssues)}`);
      console.log(`  Naming: ${import_chalk6.default.yellow(report.summary.namingIssues)}`);
      console.log(`  Patterns: ${import_chalk6.default.yellow(report.summary.patternIssues)}`);
      console.log(
        `  Architecture: ${import_chalk6.default.yellow(report.summary.architectureIssues || 0)}`
      );
      console.log(`Analysis Time: ${import_chalk6.default.gray(elapsedTime + "s")}
`);
      if (report.summary.totalIssues === 0) {
        console.log(
          import_chalk6.default.green(
            "\u2728 No consistency issues found! Your codebase is well-maintained.\n"
          )
        );
      } else {
        const namingResults = report.results.filter(
          (r) => r.issues.some((i) => i.category === "naming")
        );
        const patternResults = report.results.filter(
          (r) => r.issues.some((i) => i.category === "patterns")
        );
        if (namingResults.length > 0) {
          console.log(import_chalk6.default.bold("\u{1F3F7}\uFE0F  Naming Issues\n"));
          let shown = 0;
          for (const result of namingResults) {
            if (shown >= 5) break;
            for (const issue of result.issues) {
              if (shown >= 5) break;
              const severityColor = issue.severity === "critical" ? import_chalk6.default.red : issue.severity === "major" ? import_chalk6.default.yellow : issue.severity === "minor" ? import_chalk6.default.blue : import_chalk6.default.gray;
              console.log(
                `${severityColor(issue.severity.toUpperCase())} ${import_chalk6.default.dim(`${issue.location.file}:${issue.location.line}`)}`
              );
              console.log(`  ${issue.message}`);
              if (issue.suggestion) {
                console.log(
                  `  ${import_chalk6.default.dim("\u2192")} ${import_chalk6.default.italic(issue.suggestion)}`
                );
              }
              console.log();
              shown++;
            }
          }
          const remaining = namingResults.reduce((sum, r) => sum + r.issues.length, 0) - shown;
          if (remaining > 0) {
            console.log(import_chalk6.default.dim(`  ... and ${remaining} more issues
`));
          }
        }
        if (patternResults.length > 0) {
          console.log(import_chalk6.default.bold("\u{1F504} Pattern Issues\n"));
          let shown = 0;
          for (const result of patternResults) {
            if (shown >= 5) break;
            for (const issue of result.issues) {
              if (shown >= 5) break;
              const severityColor = issue.severity === "critical" ? import_chalk6.default.red : issue.severity === "major" ? import_chalk6.default.yellow : issue.severity === "minor" ? import_chalk6.default.blue : import_chalk6.default.gray;
              console.log(
                `${severityColor(issue.severity.toUpperCase())} ${import_chalk6.default.dim(`${issue.location.file}:${issue.location.line}`)}`
              );
              console.log(`  ${issue.message}`);
              if (issue.suggestion) {
                console.log(
                  `  ${import_chalk6.default.dim("\u2192")} ${import_chalk6.default.italic(issue.suggestion)}`
                );
              }
              console.log();
              shown++;
            }
          }
          const remaining = patternResults.reduce((sum, r) => sum + r.issues.length, 0) - shown;
          if (remaining > 0) {
            console.log(import_chalk6.default.dim(`  ... and ${remaining} more issues
`));
          }
        }
        if (report.recommendations.length > 0) {
          console.log(import_chalk6.default.bold("\u{1F4A1} Recommendations\n"));
          report.recommendations.forEach((rec, i) => {
            console.log(`${i + 1}. ${rec}`);
          });
          console.log();
        }
      }
      if (consistencyScore) {
        console.log(import_chalk6.default.bold("\n\u{1F4CA} AI Readiness Score (Consistency)\n"));
        console.log((0, import_core6.formatToolScore)(consistencyScore));
        console.log();
      }
    }
  } catch (error) {
    (0, import_core6.handleCLIError)(error, "Consistency analysis");
  }
}

// src/commands/visualize.ts
var import_chalk7 = __toESM(require("chalk"));
var import_fs5 = require("fs");
var import_path7 = require("path");
var import_child_process = require("child_process");
var import_core7 = require("@aiready/core");
var import_core8 = require("@aiready/core");
async function visualizeAction(directory, options) {
  try {
    const dirPath = (0, import_path7.resolve)(process.cwd(), directory || ".");
    let reportPath = options.report ? (0, import_path7.resolve)(dirPath, options.report) : null;
    if (!reportPath || !(0, import_fs5.existsSync)(reportPath)) {
      const latestScan = findLatestScanReport(dirPath);
      if (latestScan) {
        reportPath = latestScan;
        console.log(
          import_chalk7.default.dim(`Found latest report: ${latestScan.split("/").pop()}`)
        );
      } else {
        console.error(import_chalk7.default.red("\u274C No AI readiness report found"));
        console.log(
          import_chalk7.default.dim(
            `
Generate a report with:
  aiready scan --output json

Or specify a custom report:
  aiready visualise --report <path-to-report.json>`
          )
        );
        return;
      }
    }
    const raw = (0, import_fs5.readFileSync)(reportPath, "utf8");
    const report = JSON.parse(raw);
    const configPath = (0, import_path7.resolve)(dirPath, "aiready.json");
    let graphConfig = { maxNodes: 400, maxEdges: 600 };
    if ((0, import_fs5.existsSync)(configPath)) {
      try {
        const rawConfig = JSON.parse((0, import_fs5.readFileSync)(configPath, "utf8"));
        if (rawConfig.visualizer?.graph) {
          graphConfig = {
            maxNodes: rawConfig.visualizer.graph.maxNodes ?? graphConfig.maxNodes,
            maxEdges: rawConfig.visualizer.graph.maxEdges ?? graphConfig.maxEdges
          };
        }
      } catch (e) {
        void e;
      }
    }
    const envVisualizerConfig = JSON.stringify(graphConfig);
    process.env.AIREADY_VISUALIZER_CONFIG = envVisualizerConfig;
    console.log("Building graph from report...");
    const { GraphBuilder } = await import("@aiready/visualizer/graph");
    const graph = GraphBuilder.buildFromReport(report, dirPath);
    let useDevMode = options.dev || false;
    let devServerStarted = false;
    if (useDevMode) {
      try {
        const localWebDir = (0, import_path7.resolve)(dirPath, "packages/visualizer");
        let webDir = "";
        let visualizerAvailable = false;
        if ((0, import_fs5.existsSync)(localWebDir)) {
          webDir = localWebDir;
          visualizerAvailable = true;
        } else {
          const nodemodulesLocations = [
            (0, import_path7.resolve)(dirPath, "node_modules", "@aiready", "visualizer"),
            (0, import_path7.resolve)(
              process.cwd(),
              "node_modules",
              "@aiready",
              "visualizer"
            )
          ];
          let currentDir = dirPath;
          while (currentDir !== "/" && currentDir !== ".") {
            nodemodulesLocations.push(
              (0, import_path7.resolve)(currentDir, "node_modules", "@aiready", "visualizer")
            );
            const parent = (0, import_path7.resolve)(currentDir, "..");
            if (parent === currentDir) break;
            currentDir = parent;
          }
          for (const location of nodemodulesLocations) {
            if ((0, import_fs5.existsSync)(location) && (0, import_fs5.existsSync)((0, import_path7.resolve)(location, "package.json"))) {
              webDir = location;
              visualizerAvailable = true;
              break;
            }
          }
          if (!visualizerAvailable) {
            try {
              const vizPkgPath = require.resolve("@aiready/visualizer/package.json");
              webDir = (0, import_path7.resolve)(vizPkgPath, "..");
              visualizerAvailable = true;
            } catch (err) {
              void err;
            }
          }
        }
        const webViteConfigExists = webDir && (0, import_fs5.existsSync)((0, import_path7.resolve)(webDir, "web", "vite.config.ts"));
        if (visualizerAvailable && webViteConfigExists) {
          const spawnCwd = webDir;
          const { watch } = await import("fs");
          const copyReportToViz = () => {
            try {
              const destPath = (0, import_path7.resolve)(spawnCwd, "web", "report-data.json");
              (0, import_fs5.copyFileSync)(reportPath, destPath);
              console.log(`\u{1F4CB} Report synced to ${destPath}`);
            } catch (e) {
              console.error("Failed to sync report:", e);
            }
          };
          copyReportToViz();
          let watchTimeout = null;
          const reportWatcher = watch(reportPath, () => {
            if (watchTimeout) clearTimeout(watchTimeout);
            watchTimeout = setTimeout(copyReportToViz, 100);
          });
          const envForSpawn = {
            ...process.env,
            AIREADY_REPORT_PATH: reportPath,
            AIREADY_VISUALIZER_CONFIG: envVisualizerConfig
          };
          const vite = (0, import_child_process.spawn)("pnpm", ["run", "dev:web"], {
            cwd: spawnCwd,
            stdio: "inherit",
            shell: true,
            env: envForSpawn
          });
          const onExit = () => {
            try {
              reportWatcher.close();
            } catch (err) {
              void err;
            }
            try {
              vite.kill();
            } catch (err) {
              void err;
            }
            process.exit(0);
          };
          process.on("SIGINT", onExit);
          process.on("SIGTERM", onExit);
          devServerStarted = true;
          void devServerStarted;
          return;
        } else {
          console.log(
            import_chalk7.default.yellow(
              "\u26A0\uFE0F  Dev server not available (requires local @aiready/visualizer with web assets)."
            )
          );
          console.log(
            import_chalk7.default.cyan("   Falling back to static HTML generation...\n")
          );
          useDevMode = false;
        }
      } catch (err) {
        console.error("Failed to start dev server:", err);
        console.log(
          import_chalk7.default.cyan("   Falling back to static HTML generation...\n")
        );
        useDevMode = false;
      }
    }
    console.log("Generating HTML...");
    const html = (0, import_core8.generateHTML)(graph);
    const defaultOutput = "visualization.html";
    const outPath = (0, import_path7.resolve)(dirPath, options.output || defaultOutput);
    (0, import_fs5.writeFileSync)(outPath, html, "utf8");
    console.log(import_chalk7.default.green(`\u2705 Visualization written to: ${outPath}`));
    if (options.open || options.serve) {
      const opener = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
      if (options.serve) {
        try {
          const port = typeof options.serve === "number" ? options.serve : 5173;
          const http = await import("http");
          const fsp = await import("fs/promises");
          const server = http.createServer(async (req, res) => {
            try {
              const urlPath = req.url || "/";
              if (urlPath === "/" || urlPath === "/index.html") {
                const content = await fsp.readFile(outPath, "utf8");
                res.writeHead(200, {
                  "Content-Type": "text/html; charset=utf-8"
                });
                res.end(content);
                return;
              }
              res.writeHead(404, { "Content-Type": "text/plain" });
              res.end("Not found");
            } catch (e) {
              void e;
              res.writeHead(500, { "Content-Type": "text/plain" });
              res.end("Server error");
            }
          });
          server.listen(port, () => {
            const addr = `http://localhost:${port}/`;
            console.log(
              import_chalk7.default.cyan(`\u{1F310} Local visualization server running at ${addr}`)
            );
            (0, import_child_process.spawn)(opener, [`"${addr}"`], { shell: true });
          });
          process.on("SIGINT", () => {
            server.close();
            process.exit(0);
          });
        } catch (err) {
          console.error("Failed to start local server:", err);
        }
      } else if (options.open) {
        (0, import_child_process.spawn)(opener, [`"${outPath}"`], { shell: true });
      }
    }
  } catch (err) {
    (0, import_core7.handleCLIError)(err, "Visualization");
  }
}
var visualizeHelpText = `
EXAMPLES:
  $ aiready visualize .  # Auto-detects latest report, generates HTML
  $ aiready visualize . --report .aiready/aiready-report-20260217-143022.json
  $ aiready visualize . --report report.json -o out/visualization.html --open
  $ aiready visualize . --report report.json --serve
  $ aiready visualize . --report report.json --serve 8080
  $ aiready visualize . --report report.json --dev

NOTES:
  - The value passed to --report is interpreted relative to the directory argument (first positional).
    If the report is not found, the CLI will suggest running 'aiready scan' to generate it.
  - Default output path: visualization.html (in the current directory).
  - --serve starts a tiny single-file HTTP server (default port: 5173) and opens your browser.
  - --dev starts a Vite dev server with live reload (requires local @aiready/visualizer installation).
    When --dev is not available, it falls back to static HTML generation.
`;
var visualiseHelpText = `
EXAMPLES:
  $ aiready visualise .  # Auto-detects latest report
  $ aiready visualise . --report .aiready/aiready-report-20260217-143022.json
  $ aiready visualise . --report report.json --serve 8080

NOTES:
  - Same options as 'visualize'. Use --serve to host the static HTML, or --dev for live reload.
`;

// src/commands/ai-signal-clarity.ts
var import_chalk8 = __toESM(require("chalk"));
var import_core9 = require("@aiready/core");

// src/commands/agent-grounding.ts
var import_chalk9 = __toESM(require("chalk"));
var import_core10 = require("@aiready/core");

// src/commands/testability.ts
var import_chalk10 = __toESM(require("chalk"));
var import_core11 = require("@aiready/core");

// src/commands/change-amplification.ts
var import_cli = require("@aiready/change-amplification/dist/cli.js");

// src/cli.ts
var import_meta = {};
var getDirname = () => {
  if (typeof __dirname !== "undefined") return __dirname;
  return (0, import_path8.dirname)((0, import_url.fileURLToPath)(import_meta.url));
};
var packageJson = JSON.parse(
  (0, import_fs6.readFileSync)((0, import_path8.join)(getDirname(), "../package.json"), "utf8")
);
var program = new import_commander.Command();
program.name("aiready").description("AIReady - Assess and improve AI-readiness of codebases").version(packageJson.version).addHelpText(
  "after",
  `
AI READINESS SCORING:
  Get a 0-100 score indicating how AI-ready your codebase is.
  Use --score flag with any analysis command for detailed breakdown.

EXAMPLES:
  $ aiready scan                          # Comprehensive analysis of current directory
  $ aiready scan --score                  # Get AI Readiness Score (0-100)
  $ aiready scan --tools patterns         # Run only pattern detection
  $ npx @aiready/cli scan                 # Industry standard way to run standard scan
  $ aiready scan --output json            # Output raw JSON for piping

GETTING STARTED:
  1. Run 'aiready scan' to analyze your codebase
  2. Use 'aiready scan --score' for AI readiness assessment
  3. Create aiready.json for persistent configuration
  4. Set up CI/CD with '--threshold' for quality gates

CONFIGURATION:
  Config files (searched upward): aiready.json, .aiready.json, aiready.config.*
  CLI options override config file settings

  Example aiready.json:
  {
    "scan": { "exclude": ["**/dist/**", "**/node_modules/**"] },
    "tools": {
      "pattern-detect": { "minSimilarity": 0.5 },
      "context-analyzer": { "maxContextBudget": 15000 }
    },
    "output": { "format": "json", "directory": ".aiready" }
  }

VERSION: ${packageJson.version}
DOCUMENTATION: https://aiready.dev/docs/cli
GITHUB: https://github.com/caopengau/aiready-cli
LANDING: https://github.com/caopengau/aiready-landing`
);
program.command("scan").description(
  "Run comprehensive AI-readiness analysis (patterns + context + consistency)"
).argument("[directory]", "Directory to analyze", ".").option(
  "-t, --tools <tools>",
  "Tools to run (comma-separated: patterns,context,consistency,doc-drift,deps-health,aiSignalClarity,grounding,testability,changeAmplification)"
).option(
  "--profile <type>",
  "Scan profile to use (agentic, cost, security, onboarding)"
).option(
  "--compare-to <path>",
  "Compare results against a previous AIReady report JSON"
).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(
  "--no-score",
  "Disable calculating AI Readiness Score (enabled by default)"
).option("--weights <weights>", "Custom scoring weights").option("--threshold <score>", "Fail CI/CD if score below threshold (0-100)").option(
  "--ci",
  "CI mode: GitHub Actions annotations, no colors, fail on threshold"
).option(
  "--fail-on <level>",
  "Fail on issues: critical, major, any",
  "critical"
).option("--api-key <key>", "Platform API key for automatic upload").option("--upload", "Automatically upload results to the platform").option("--server <url>", "Custom platform URL").addHelpText("after", scanHelpText).action(async (directory, options) => {
  await scanAction(directory, options);
});
program.command("patterns").description("Detect duplicate code patterns that confuse AI models").argument("[directory]", "Directory to analyze", ".").option("-s, --similarity <number>", "Minimum similarity score (0-1)", "0.40").option("-l, --min-lines <number>", "Minimum lines to consider", "5").option(
  "--max-candidates <number>",
  "Maximum candidates per block (performance tuning)"
).option(
  "--min-shared-tokens <number>",
  "Minimum shared tokens for candidates (performance tuning)"
).option(
  "--full-scan",
  "Disable smart defaults for comprehensive analysis (slower)"
).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 for patterns (0-100)"
).addHelpText("after", patternsHelpText).action(async (directory, options) => {
  await patternsAction(directory, options);
});
program.command("context").description("Analyze context window costs and dependency fragmentation").argument("[directory]", "Directory to analyze", ".").option("--max-depth <number>", "Maximum acceptable import depth", "5").option(
  "--max-context <number>",
  "Maximum acceptable context budget (tokens)",
  "10000"
).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 for context (0-100)"
).action(async (directory, options) => {
  await contextAction(directory, options);
});
program.command("consistency").description("Check naming conventions and architectural consistency").argument("[directory]", "Directory to analyze", ".").option("--naming", "Check naming conventions (default: true)").option("--no-naming", "Skip naming analysis").option("--patterns", "Check code patterns (default: true)").option("--no-patterns", "Skip pattern analysis").option(
  "--min-severity <level>",
  "Minimum severity: info|minor|major|critical",
  "info"
).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, markdown",
  "console"
).option("--output-file <path>", "Output file path (for json/markdown)").option(
  "--score",
  "Calculate and display AI Readiness Score for consistency (0-100)"
).action(async (directory, options) => {
  await consistencyAction(directory, options);
});
program.command("visualise").description("Alias for visualize (British spelling)").argument("[directory]", "Directory to analyze", ".").option(
  "--report <path>",
  "Report path (auto-detects latest .aiready/aiready-report-*.json if not provided)"
).option(
  "-o, --output <path>",
  "Output HTML path (relative to directory)",
  "packages/visualizer/visualization.html"
).option("--open", "Open generated HTML in default browser").option(
  "--serve [port]",
  "Start a local static server to serve the visualization (optional port number)",
  false
).option(
  "--dev",
  "Start Vite dev server (live reload) for interactive development",
  true
).addHelpText("after", visualiseHelpText).action(async (directory, options) => {
  await visualizeAction(directory, options);
});
program.command("visualize").description("Generate interactive visualization from an AIReady report").argument("[directory]", "Directory to analyze", ".").option(
  "--report <path>",
  "Report path (auto-detects latest .aiready/aiready-report-*.json if not provided)"
).option(
  "-o, --output <path>",
  "Output HTML path (relative to directory)",
  "packages/visualizer/visualization.html"
).option("--open", "Open generated HTML in default browser").option(
  "--serve [port]",
  "Start a local static server to serve the visualization (optional port number)",
  false
).option(
  "--dev",
  "Start Vite dev server (live reload) for interactive development",
  false
).addHelpText("after", visualizeHelpText).action(async (directory, options) => {
  await visualizeAction(directory, options);
});
program.command("change-amplification").description("Analyze graph metrics for change amplification").argument("[directory]", "Directory to analyze", ".").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) => {
  await (0, import_cli.changeAmplificationAction)(directory, options);
});
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", uploadHelpText).action(async (file, options) => {
  await uploadAction(file, options);
});
program.parse();
