import {
  CLIError,
  ExitCode,
  SkillMetadataSchema,
  createCreateSkillCommand,
  logger
} from "./chunk-EFZOLZFB.js";

// src/index.ts
import { Command as Command28 } from "commander";
import { VERSION } from "@harness-engineering/core";

// src/commands/validate.ts
import { Command } from "commander";
import * as path2 from "path";
import { Ok as Ok2 } from "@harness-engineering/core";
import { validateAgentsMap, validateKnowledgeMap } from "@harness-engineering/core";

// src/config/loader.ts
import * as fs from "fs";
import * as path from "path";
import { Ok, Err } from "@harness-engineering/core";

// src/config/schema.ts
import { z } from "zod";
var LayerSchema = z.object({
  name: z.string(),
  pattern: z.string(),
  allowedDependencies: z.array(z.string())
});
var ForbiddenImportSchema = z.object({
  from: z.string(),
  disallow: z.array(z.string()),
  message: z.string().optional()
});
var BoundaryConfigSchema = z.object({
  requireSchema: z.array(z.string())
});
var AgentConfigSchema = z.object({
  executor: z.enum(["subprocess", "cloud", "noop"]).default("subprocess"),
  timeout: z.number().default(3e5),
  skills: z.array(z.string()).optional()
});
var EntropyConfigSchema = z.object({
  excludePatterns: z.array(z.string()).default(["**/node_modules/**", "**/*.test.ts"]),
  autoFix: z.boolean().default(false)
});
var PhaseGateMappingSchema = z.object({
  implPattern: z.string(),
  specPattern: z.string()
});
var PhaseGatesConfigSchema = z.object({
  enabled: z.boolean().default(false),
  severity: z.enum(["error", "warning"]).default("error"),
  mappings: z.array(PhaseGateMappingSchema).default([{ implPattern: "src/**/*.ts", specPattern: "docs/specs/{feature}.md" }])
});
var HarnessConfigSchema = z.object({
  version: z.literal(1),
  name: z.string().optional(),
  rootDir: z.string().default("."),
  layers: z.array(LayerSchema).optional(),
  forbiddenImports: z.array(ForbiddenImportSchema).optional(),
  boundaries: BoundaryConfigSchema.optional(),
  agentsMapPath: z.string().default("./AGENTS.md"),
  docsDir: z.string().default("./docs"),
  agent: AgentConfigSchema.optional(),
  entropy: EntropyConfigSchema.optional(),
  template: z.object({
    level: z.enum(["basic", "intermediate", "advanced"]),
    framework: z.string().optional(),
    version: z.number()
  }).optional(),
  phaseGates: PhaseGatesConfigSchema.optional()
});

// src/config/loader.ts
var CONFIG_FILENAMES = ["harness.config.json"];
function findConfigFile(startDir = process.cwd()) {
  let currentDir = path.resolve(startDir);
  const root = path.parse(currentDir).root;
  while (currentDir !== root) {
    for (const filename of CONFIG_FILENAMES) {
      const configPath = path.join(currentDir, filename);
      if (fs.existsSync(configPath)) {
        return Ok(configPath);
      }
    }
    currentDir = path.dirname(currentDir);
  }
  return Err(
    new CLIError('No harness.config.json found. Run "harness init" to create one.', ExitCode.ERROR)
  );
}
function loadConfig(configPath) {
  if (!fs.existsSync(configPath)) {
    return Err(new CLIError(`Config file not found: ${configPath}`, ExitCode.ERROR));
  }
  let rawConfig;
  try {
    const content = fs.readFileSync(configPath, "utf-8");
    rawConfig = JSON.parse(content);
  } catch (error) {
    return Err(
      new CLIError(
        `Failed to parse config: ${error instanceof Error ? error.message : "Unknown error"}`,
        ExitCode.ERROR
      )
    );
  }
  const parsed = HarnessConfigSchema.safeParse(rawConfig);
  if (!parsed.success) {
    const issues = parsed.error.issues.map((i) => `  - ${i.path.join(".")}: ${i.message}`).join("\n");
    return Err(new CLIError(`Invalid config:
${issues}`, ExitCode.ERROR));
  }
  return Ok(parsed.data);
}
function resolveConfig(configPath) {
  if (configPath) {
    return loadConfig(configPath);
  }
  const findResult = findConfigFile();
  if (!findResult.ok) {
    return findResult;
  }
  return loadConfig(findResult.value);
}

// src/output/formatter.ts
import chalk from "chalk";
var OutputMode = {
  JSON: "json",
  TEXT: "text",
  QUIET: "quiet",
  VERBOSE: "verbose"
};
var OutputFormatter = class {
  constructor(mode = OutputMode.TEXT) {
    this.mode = mode;
  }
  /**
   * Format raw data (for JSON mode)
   */
  format(data) {
    if (this.mode === OutputMode.JSON) {
      return JSON.stringify(data, null, 2);
    }
    return String(data);
  }
  /**
   * Format validation result
   */
  formatValidation(result) {
    if (this.mode === OutputMode.JSON) {
      return JSON.stringify(result, null, 2);
    }
    if (this.mode === OutputMode.QUIET) {
      if (result.valid) return "";
      return result.issues.map((i) => `${i.file ?? ""}: ${i.message}`).join("\n");
    }
    const lines = [];
    if (result.valid) {
      lines.push(chalk.green("v validation passed"));
    } else {
      lines.push(chalk.red(`x Validation failed (${result.issues.length} issues)`));
      lines.push("");
      for (const issue of result.issues) {
        const location = issue.file ? issue.line ? `${issue.file}:${issue.line}` : issue.file : "unknown";
        lines.push(`  ${chalk.yellow("*")} ${chalk.dim(location)}`);
        lines.push(`    ${issue.message}`);
        if (issue.suggestion && this.mode === OutputMode.VERBOSE) {
          lines.push(`    ${chalk.dim("->")} ${issue.suggestion}`);
        }
      }
    }
    return lines.join("\n");
  }
  /**
   * Format a summary line
   */
  formatSummary(label, value, success) {
    if (this.mode === OutputMode.JSON || this.mode === OutputMode.QUIET) {
      return "";
    }
    const icon = success ? chalk.green("v") : chalk.red("x");
    return `${icon} ${label}: ${value}`;
  }
};

// src/commands/validate.ts
async function runValidate(options) {
  const configResult = resolveConfig(options.configPath);
  if (!configResult.ok) {
    return configResult;
  }
  const config = configResult.value;
  const cwd = options.cwd ?? (options.configPath ? path2.dirname(path2.resolve(options.configPath)) : process.cwd());
  const result = {
    valid: true,
    checks: {
      agentsMap: false,
      fileStructure: false,
      knowledgeMap: false
    },
    issues: []
  };
  const agentsMapPath = path2.resolve(cwd, config.agentsMapPath);
  const agentsResult = await validateAgentsMap(agentsMapPath);
  if (agentsResult.ok) {
    result.checks.agentsMap = true;
  } else {
    result.valid = false;
    result.issues.push({
      check: "agentsMap",
      file: config.agentsMapPath,
      message: agentsResult.error.message,
      ...agentsResult.error.suggestions?.[0] !== void 0 && {
        suggestion: agentsResult.error.suggestions[0]
      }
    });
  }
  const knowledgeResult = await validateKnowledgeMap(cwd);
  if (knowledgeResult.ok && knowledgeResult.value.brokenLinks.length === 0) {
    result.checks.knowledgeMap = true;
  } else if (knowledgeResult.ok) {
    result.valid = false;
    for (const broken of knowledgeResult.value.brokenLinks) {
      result.issues.push({
        check: "knowledgeMap",
        file: broken.path,
        message: `Broken link: ${broken.path}`,
        suggestion: broken.suggestion || "Remove or fix the broken link"
      });
    }
  } else {
    result.valid = false;
    result.issues.push({
      check: "knowledgeMap",
      message: knowledgeResult.error.message
    });
  }
  result.checks.fileStructure = true;
  return Ok2(result);
}
function createValidateCommand() {
  const command = new Command("validate").description("Run all validation checks").option("--cross-check", "Run cross-artifact consistency validation").action(async (opts, cmd) => {
    const globalOpts = cmd.optsWithGlobals();
    const mode = globalOpts.json ? OutputMode.JSON : globalOpts.quiet ? OutputMode.QUIET : globalOpts.verbose ? OutputMode.VERBOSE : OutputMode.TEXT;
    const formatter = new OutputFormatter(mode);
    const result = await runValidate({
      configPath: globalOpts.config,
      json: globalOpts.json,
      verbose: globalOpts.verbose,
      quiet: globalOpts.quiet
    });
    if (!result.ok) {
      if (mode === OutputMode.JSON) {
        console.log(JSON.stringify({ error: result.error.message }));
      } else {
        logger.error(result.error.message);
      }
      process.exit(result.error.exitCode);
    }
    if (opts.crossCheck) {
      const { runCrossCheck: runCrossCheck2 } = await import("./validate-cross-check-LNIZ7KGZ.js");
      const cwd = process.cwd();
      const specsDir = path2.join(cwd, "docs", "specs");
      const plansDir = path2.join(cwd, "docs", "plans");
      const crossResult = await runCrossCheck2({ specsDir, plansDir, projectPath: cwd });
      if (crossResult.ok && crossResult.value.warnings > 0) {
        console.log("\nCross-artifact validation:");
        for (const w of crossResult.value.planToImpl) console.log(`  ! ${w}`);
        for (const w of crossResult.value.staleness) console.log(`  ! ${w}`);
        console.log(`
  ${crossResult.value.warnings} warnings`);
      }
    }
    const output = formatter.formatValidation({
      valid: result.value.valid,
      issues: result.value.issues
    });
    if (output) {
      console.log(output);
    }
    process.exit(result.value.valid ? ExitCode.SUCCESS : ExitCode.VALIDATION_FAILED);
  });
  return command;
}

// src/commands/check-deps.ts
import { Command as Command2 } from "commander";
import * as path3 from "path";
import { Ok as Ok3 } from "@harness-engineering/core";
import {
  validateDependencies,
  detectCircularDepsInFiles,
  defineLayer,
  TypeScriptParser
} from "@harness-engineering/core";

// src/utils/files.ts
import { glob } from "glob";
async function findFiles(pattern, cwd = process.cwd()) {
  return glob(pattern, { cwd, absolute: true });
}

// src/commands/check-deps.ts
async function runCheckDeps(options) {
  const cwd = options.cwd ?? process.cwd();
  const configResult = resolveConfig(options.configPath);
  if (!configResult.ok) {
    return configResult;
  }
  const config = configResult.value;
  const result = {
    valid: true,
    layerViolations: [],
    circularDeps: []
  };
  if (!config.layers || config.layers.length === 0) {
    return Ok3(result);
  }
  const rootDir = path3.resolve(cwd, config.rootDir);
  const parser = new TypeScriptParser();
  const layers = config.layers.map((l) => defineLayer(l.name, [l.pattern], l.allowedDependencies));
  const layerConfig = {
    layers,
    rootDir,
    parser,
    fallbackBehavior: "warn"
  };
  const depsResult = await validateDependencies(layerConfig);
  if (depsResult.ok) {
    for (const violation of depsResult.value.violations) {
      result.valid = false;
      result.layerViolations.push({
        file: violation.file,
        imports: violation.imports,
        fromLayer: violation.fromLayer ?? "unknown",
        toLayer: violation.toLayer ?? "unknown",
        message: violation.reason
      });
    }
  }
  const allFiles = [];
  for (const layer of config.layers) {
    const files = await findFiles(layer.pattern, rootDir);
    allFiles.push(...files);
  }
  const uniqueFiles = [...new Set(allFiles)];
  if (uniqueFiles.length > 0) {
    const circularResult = await detectCircularDepsInFiles(uniqueFiles, parser);
    if (circularResult.ok && circularResult.value.hasCycles) {
      result.valid = false;
      for (const cycle of circularResult.value.cycles) {
        result.circularDeps.push({ cycle: cycle.cycle });
      }
    }
  }
  return Ok3(result);
}
function createCheckDepsCommand() {
  const command = new Command2("check-deps").description("Validate dependency layers and detect circular dependencies").action(async (_opts, cmd) => {
    const globalOpts = cmd.optsWithGlobals();
    const mode = globalOpts.json ? OutputMode.JSON : globalOpts.quiet ? OutputMode.QUIET : globalOpts.verbose ? OutputMode.VERBOSE : OutputMode.TEXT;
    const formatter = new OutputFormatter(mode);
    const result = await runCheckDeps({
      configPath: globalOpts.config,
      json: globalOpts.json,
      verbose: globalOpts.verbose,
      quiet: globalOpts.quiet
    });
    if (!result.ok) {
      if (mode === OutputMode.JSON) {
        console.log(JSON.stringify({ error: result.error.message }));
      } else {
        logger.error(result.error.message);
      }
      process.exit(result.error.exitCode);
    }
    const issues = [
      ...result.value.layerViolations.map((v) => ({
        file: v.file,
        message: `Layer violation: ${v.fromLayer} -> ${v.toLayer} (${v.message})`
      })),
      ...result.value.circularDeps.map((c) => ({
        message: `Circular dependency: ${c.cycle.join(" -> ")}`
      }))
    ];
    const output = formatter.formatValidation({
      valid: result.value.valid,
      issues
    });
    if (output) {
      console.log(output);
    }
    process.exit(result.value.valid ? ExitCode.SUCCESS : ExitCode.VALIDATION_FAILED);
  });
  return command;
}

// src/commands/check-docs.ts
import { Command as Command3 } from "commander";
import * as path4 from "path";
import { Ok as Ok4, Err as Err2 } from "@harness-engineering/core";
import { checkDocCoverage, validateKnowledgeMap as validateKnowledgeMap2 } from "@harness-engineering/core";
async function runCheckDocs(options) {
  const cwd = options.cwd ?? process.cwd();
  const minCoverage = options.minCoverage ?? 80;
  const configResult = resolveConfig(options.configPath);
  if (!configResult.ok) {
    return configResult;
  }
  const config = configResult.value;
  const docsDir = path4.resolve(cwd, config.docsDir);
  const sourceDir = path4.resolve(cwd, config.rootDir);
  const coverageResult = await checkDocCoverage("project", {
    docsDir,
    sourceDir,
    excludePatterns: ["**/*.test.ts", "**/*.spec.ts", "**/node_modules/**"]
  });
  if (!coverageResult.ok) {
    return Err2(
      new CLIError(
        `Documentation coverage check failed: ${coverageResult.error.message}`,
        ExitCode.ERROR
      )
    );
  }
  const knowledgeResult = await validateKnowledgeMap2(cwd);
  let brokenLinks = [];
  if (knowledgeResult.ok) {
    brokenLinks = knowledgeResult.value.brokenLinks.map((b) => b.path);
  } else {
    logger.warn(`Knowledge map validation failed: ${knowledgeResult.error.message}`);
  }
  const coveragePercent = coverageResult.value.coveragePercentage;
  const result = {
    valid: coveragePercent >= minCoverage && brokenLinks.length === 0,
    coveragePercent,
    documented: coverageResult.value.documented,
    undocumented: coverageResult.value.undocumented,
    brokenLinks
  };
  return Ok4(result);
}
function createCheckDocsCommand() {
  const command = new Command3("check-docs").description("Check documentation coverage").option("--min-coverage <percent>", "Minimum coverage percentage", "80").action(async (opts, cmd) => {
    const globalOpts = cmd.optsWithGlobals();
    const mode = globalOpts.json ? OutputMode.JSON : globalOpts.quiet ? OutputMode.QUIET : globalOpts.verbose ? OutputMode.VERBOSE : OutputMode.TEXT;
    const formatter = new OutputFormatter(mode);
    const result = await runCheckDocs({
      configPath: globalOpts.config,
      minCoverage: parseInt(opts.minCoverage, 10),
      json: globalOpts.json,
      verbose: globalOpts.verbose,
      quiet: globalOpts.quiet
    });
    if (!result.ok) {
      if (mode === OutputMode.JSON) {
        console.log(JSON.stringify({ error: result.error.message }));
      } else {
        logger.error(result.error.message);
      }
      process.exit(result.error.exitCode);
    }
    if (mode === OutputMode.JSON) {
      console.log(JSON.stringify(result.value, null, 2));
    } else if (mode !== OutputMode.QUIET) {
      const { value } = result;
      console.log(
        formatter.formatSummary(
          "Documentation coverage",
          `${value.coveragePercent.toFixed(1)}%`,
          value.valid
        )
      );
      if (value.undocumented.length > 0 && (mode === OutputMode.VERBOSE || !value.valid)) {
        console.log("\nUndocumented files:");
        for (const file of value.undocumented.slice(0, 10)) {
          console.log(`  - ${file}`);
        }
        if (value.undocumented.length > 10) {
          console.log(`  ... and ${value.undocumented.length - 10} more`);
        }
      }
      if (value.brokenLinks.length > 0) {
        console.log("\nBroken links:");
        for (const link of value.brokenLinks) {
          console.log(`  - ${link}`);
        }
      }
    }
    process.exit(result.value.valid ? ExitCode.SUCCESS : ExitCode.VALIDATION_FAILED);
  });
  return command;
}

// src/commands/init.ts
import { Command as Command5 } from "commander";
import chalk3 from "chalk";
import * as fs5 from "fs";
import * as path8 from "path";
import { Ok as Ok6, Err as Err4 } from "@harness-engineering/core";

// src/templates/engine.ts
import * as fs2 from "fs";
import * as path5 from "path";
import Handlebars from "handlebars";
import { Ok as Ok5, Err as Err3 } from "@harness-engineering/core";

// src/templates/schema.ts
import { z as z2 } from "zod";
var MergeStrategySchema = z2.object({
  json: z2.enum(["deep-merge", "overlay-wins"]).default("deep-merge"),
  files: z2.literal("overlay-wins").default("overlay-wins")
});
var TemplateMetadataSchema = z2.object({
  name: z2.string(),
  description: z2.string(),
  level: z2.enum(["basic", "intermediate", "advanced"]).optional(),
  framework: z2.string().optional(),
  extends: z2.string().optional(),
  mergeStrategy: MergeStrategySchema.default({}),
  version: z2.literal(1)
});

// src/templates/merger.ts
function isPlainObject(val) {
  return typeof val === "object" && val !== null && !Array.isArray(val);
}
function deepMergeJson(base, overlay) {
  const result = { ...base };
  for (const key of Object.keys(overlay)) {
    if (isPlainObject(result[key]) && isPlainObject(overlay[key])) {
      result[key] = deepMergeJson(
        result[key],
        overlay[key]
      );
    } else {
      result[key] = overlay[key];
    }
  }
  return result;
}
var CONCAT_KEYS = /* @__PURE__ */ new Set(["dependencies", "devDependencies", "peerDependencies"]);
function mergePackageJson(base, overlay) {
  const result = { ...base };
  for (const key of Object.keys(overlay)) {
    if (CONCAT_KEYS.has(key) && isPlainObject(result[key]) && isPlainObject(overlay[key])) {
      result[key] = {
        ...result[key],
        ...overlay[key]
      };
    } else if (isPlainObject(result[key]) && isPlainObject(overlay[key])) {
      result[key] = deepMergeJson(
        result[key],
        overlay[key]
      );
    } else {
      result[key] = overlay[key];
    }
  }
  return result;
}

// src/templates/engine.ts
var TemplateEngine = class {
  constructor(templatesDir) {
    this.templatesDir = templatesDir;
  }
  listTemplates() {
    try {
      const entries = fs2.readdirSync(this.templatesDir, { withFileTypes: true });
      const templates = [];
      for (const entry of entries) {
        if (!entry.isDirectory()) continue;
        const metaPath = path5.join(this.templatesDir, entry.name, "template.json");
        if (!fs2.existsSync(metaPath)) continue;
        const raw = JSON.parse(fs2.readFileSync(metaPath, "utf-8"));
        const parsed = TemplateMetadataSchema.safeParse(raw);
        if (parsed.success) templates.push(parsed.data);
      }
      return Ok5(templates);
    } catch (error) {
      return Err3(
        new Error(
          `Failed to list templates: ${error instanceof Error ? error.message : String(error)}`
        )
      );
    }
  }
  resolveTemplate(level, framework) {
    const levelDir = this.findTemplateDir(level, "level");
    if (!levelDir) return Err3(new Error(`Template not found for level: ${level}`));
    const metaPath = path5.join(levelDir, "template.json");
    const metaRaw = JSON.parse(fs2.readFileSync(metaPath, "utf-8"));
    const metaResult = TemplateMetadataSchema.safeParse(metaRaw);
    if (!metaResult.success)
      return Err3(new Error(`Invalid template.json in ${level}: ${metaResult.error.message}`));
    const metadata = metaResult.data;
    let files = [];
    if (metadata.extends) {
      const baseDir = path5.join(this.templatesDir, metadata.extends);
      if (fs2.existsSync(baseDir)) files = this.collectFiles(baseDir, metadata.extends);
    }
    const levelFiles = this.collectFiles(levelDir, level);
    files = this.mergeFileLists(files, levelFiles);
    let overlayMetadata;
    if (framework) {
      const frameworkDir = this.findTemplateDir(framework, "framework");
      if (!frameworkDir) return Err3(new Error(`Framework template not found: ${framework}`));
      const fMetaPath = path5.join(frameworkDir, "template.json");
      const fMetaRaw = JSON.parse(fs2.readFileSync(fMetaPath, "utf-8"));
      const fMetaResult = TemplateMetadataSchema.safeParse(fMetaRaw);
      if (fMetaResult.success) overlayMetadata = fMetaResult.data;
      const frameworkFiles = this.collectFiles(frameworkDir, framework);
      files = this.mergeFileLists(files, frameworkFiles);
    }
    files = files.filter((f) => f.relativePath !== "template.json");
    const resolved = { metadata, files };
    if (overlayMetadata !== void 0) resolved.overlayMetadata = overlayMetadata;
    return Ok5(resolved);
  }
  render(template, context) {
    const rendered = [];
    const jsonBuffers = /* @__PURE__ */ new Map();
    for (const file of template.files) {
      const outputPath = file.relativePath.replace(/\.hbs$/, "");
      if (file.isHandlebars) {
        try {
          const raw = fs2.readFileSync(file.absolutePath, "utf-8");
          const compiled = Handlebars.compile(raw, { strict: true });
          const content = compiled(context);
          if (outputPath.endsWith(".json") && file.relativePath.endsWith(".json.hbs")) {
            if (!jsonBuffers.has(outputPath)) jsonBuffers.set(outputPath, []);
            jsonBuffers.get(outputPath).push(JSON.parse(content));
          } else {
            rendered.push({ relativePath: outputPath, content });
          }
        } catch (error) {
          const msg = error instanceof Error ? error.message : String(error);
          return Err3(
            new Error(
              `Template render failed in ${file.sourceTemplate}/${file.relativePath}: ${msg}`
            )
          );
        }
      } else {
        try {
          const content = fs2.readFileSync(file.absolutePath, "utf-8");
          rendered.push({ relativePath: file.relativePath, content });
        } catch (error) {
          const msg = error instanceof Error ? error.message : String(error);
          return Err3(
            new Error(
              `Template render failed in ${file.sourceTemplate}/${file.relativePath}: ${msg}`
            )
          );
        }
      }
    }
    try {
      for (const [outputPath, jsons] of jsonBuffers) {
        let merged = {};
        for (const json of jsons) {
          merged = outputPath === "package.json" ? mergePackageJson(merged, json) : deepMergeJson(merged, json);
        }
        rendered.push({ relativePath: outputPath, content: JSON.stringify(merged, null, 2) });
      }
    } catch (error) {
      const msg = error instanceof Error ? error.message : String(error);
      return Err3(new Error(`JSON merge failed: ${msg}`));
    }
    return Ok5({ files: rendered });
  }
  write(files, targetDir, options) {
    try {
      const written = [];
      for (const file of files.files) {
        const targetPath = path5.join(targetDir, file.relativePath);
        const dir = path5.dirname(targetPath);
        if (!options.overwrite && fs2.existsSync(targetPath)) continue;
        fs2.mkdirSync(dir, { recursive: true });
        fs2.writeFileSync(targetPath, file.content);
        written.push(file.relativePath);
      }
      return Ok5(written);
    } catch (error) {
      return Err3(
        new Error(
          `Failed to write files: ${error instanceof Error ? error.message : String(error)}`
        )
      );
    }
  }
  findTemplateDir(name, type) {
    const entries = fs2.readdirSync(this.templatesDir, { withFileTypes: true });
    for (const entry of entries) {
      if (!entry.isDirectory()) continue;
      const metaPath = path5.join(this.templatesDir, entry.name, "template.json");
      if (!fs2.existsSync(metaPath)) continue;
      const raw = JSON.parse(fs2.readFileSync(metaPath, "utf-8"));
      const parsed = TemplateMetadataSchema.safeParse(raw);
      if (!parsed.success) continue;
      if (type === "level" && parsed.data.level === name)
        return path5.join(this.templatesDir, entry.name);
      if (type === "framework" && parsed.data.framework === name)
        return path5.join(this.templatesDir, entry.name);
      if (parsed.data.name === name) return path5.join(this.templatesDir, entry.name);
    }
    return null;
  }
  collectFiles(dir, sourceName) {
    const files = [];
    const walk = (currentDir) => {
      const entries = fs2.readdirSync(currentDir, { withFileTypes: true });
      for (const entry of entries) {
        const fullPath = path5.join(currentDir, entry.name);
        if (entry.isDirectory()) {
          walk(fullPath);
        } else {
          files.push({
            relativePath: path5.relative(dir, fullPath),
            absolutePath: fullPath,
            isHandlebars: entry.name.endsWith(".hbs"),
            sourceTemplate: sourceName
          });
        }
      }
    };
    walk(dir);
    return files;
  }
  mergeFileLists(base, overlay) {
    const map = /* @__PURE__ */ new Map();
    for (const file of base) map.set(file.relativePath, file);
    for (const file of overlay) {
      if (file.relativePath.endsWith(".json.hbs")) {
        const baseKey = base.find((f) => f.relativePath === file.relativePath);
        if (baseKey) {
          map.set(`__overlay__${file.relativePath}`, file);
        } else {
          map.set(file.relativePath, file);
        }
      } else {
        map.set(file.relativePath, file);
      }
    }
    return Array.from(map.values());
  }
};

// src/utils/paths.ts
import * as fs3 from "fs";
import * as path6 from "path";
import { fileURLToPath } from "url";
var __filename = fileURLToPath(import.meta.url);
var __dirname = path6.dirname(__filename);
function findUpDir(targetName, marker, maxLevels = 8) {
  let dir = __dirname;
  for (let i = 0; i < maxLevels; i++) {
    const candidate = path6.join(dir, targetName);
    if (fs3.existsSync(candidate) && fs3.statSync(candidate).isDirectory()) {
      if (fs3.existsSync(path6.join(candidate, marker))) {
        return candidate;
      }
    }
    dir = path6.dirname(dir);
  }
  return null;
}
function resolveTemplatesDir() {
  return findUpDir("templates", "base") ?? path6.join(__dirname, "templates");
}
function resolvePersonasDir() {
  const agentsDir = findUpDir("agents", "personas");
  if (agentsDir) {
    return path6.join(agentsDir, "personas");
  }
  return path6.join(__dirname, "agents", "personas");
}
function resolveSkillsDir() {
  const agentsDir = findUpDir("agents", "skills");
  if (agentsDir) {
    return path6.join(agentsDir, "skills", "claude-code");
  }
  return path6.join(__dirname, "agents", "skills", "claude-code");
}

// src/commands/setup-mcp.ts
import { Command as Command4 } from "commander";
import * as fs4 from "fs";
import * as path7 from "path";
import * as os from "os";
import chalk2 from "chalk";
var HARNESS_MCP_ENTRY = {
  command: "npx",
  args: ["@harness-engineering/mcp-server"]
};
function readJsonFile(filePath) {
  if (!fs4.existsSync(filePath)) return null;
  try {
    return JSON.parse(fs4.readFileSync(filePath, "utf-8"));
  } catch {
    fs4.copyFileSync(filePath, filePath + ".bak");
    return null;
  }
}
function writeJsonFile(filePath, data) {
  const dir = path7.dirname(filePath);
  if (!fs4.existsSync(dir)) {
    fs4.mkdirSync(dir, { recursive: true });
  }
  fs4.writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n");
}
function configureMcpServer(configPath) {
  const config = readJsonFile(configPath) ?? {};
  if (!config.mcpServers) {
    config.mcpServers = {};
  }
  if (config.mcpServers["harness"]) {
    return false;
  }
  config.mcpServers["harness"] = HARNESS_MCP_ENTRY;
  writeJsonFile(configPath, config);
  return true;
}
function addGeminiTrustedFolder(cwd) {
  const trustedPath = path7.join(os.homedir(), ".gemini", "trustedFolders.json");
  const folders = readJsonFile(trustedPath) ?? {};
  if (folders[cwd] === "TRUST_FOLDER") {
    return false;
  }
  folders[cwd] = "TRUST_FOLDER";
  writeJsonFile(trustedPath, folders);
  return true;
}
function setupMcp(cwd, client) {
  const configured = [];
  const skipped = [];
  let trustedFolder = false;
  if (client === "all" || client === "claude") {
    const configPath = path7.join(cwd, ".mcp.json");
    if (configureMcpServer(configPath)) {
      configured.push("Claude Code");
    } else {
      skipped.push("Claude Code");
    }
  }
  if (client === "all" || client === "gemini") {
    const configPath = path7.join(cwd, ".gemini", "settings.json");
    if (configureMcpServer(configPath)) {
      configured.push("Gemini CLI");
    } else {
      skipped.push("Gemini CLI");
    }
    trustedFolder = addGeminiTrustedFolder(cwd);
  }
  return { configured, skipped, trustedFolder };
}
function createSetupMcpCommand() {
  return new Command4("setup-mcp").description("Configure MCP server for AI agent integration").option("--client <client>", "Client to configure (claude, gemini, all)", "all").action(async (opts, cmd) => {
    const globalOpts = cmd.optsWithGlobals();
    const cwd = process.cwd();
    const { configured, skipped, trustedFolder } = setupMcp(cwd, opts.client);
    if (!globalOpts.quiet) {
      console.log("");
      if (configured.length > 0) {
        logger.success("MCP server configured!");
        console.log("");
        for (const name of configured) {
          console.log(`  ${chalk2.green("+")} ${name}`);
        }
      }
      if (trustedFolder) {
        console.log("");
        logger.info("Added project to Gemini trusted folders (~/.gemini/trustedFolders.json)");
      }
      if (skipped.length > 0) {
        console.log("");
        logger.info("Already configured:");
        for (const name of skipped) {
          console.log(`  ${chalk2.dim("-")} ${name}`);
        }
      }
      console.log("");
      console.log(chalk2.bold("The harness MCP server provides:"));
      console.log("  - 15 tools for validation, entropy detection, and skill execution");
      console.log("  - 4 resources for project context, skills, rules, and learnings");
      console.log("");
      console.log(`Run ${chalk2.cyan("harness skill list")} to see available skills.`);
      console.log("");
    }
    process.exit(ExitCode.SUCCESS);
  });
}

// src/commands/init.ts
async function runInit(options) {
  const cwd = options.cwd ?? process.cwd();
  const name = options.name ?? path8.basename(cwd);
  const level = options.level ?? "basic";
  const force = options.force ?? false;
  const configPath = path8.join(cwd, "harness.config.json");
  if (!force && fs5.existsSync(configPath)) {
    return Err4(
      new CLIError("Project already initialized. Use --force to overwrite.", ExitCode.ERROR)
    );
  }
  const templatesDir = resolveTemplatesDir();
  const engine = new TemplateEngine(templatesDir);
  const resolveResult = engine.resolveTemplate(level, options.framework);
  if (!resolveResult.ok) {
    return Err4(new CLIError(resolveResult.error.message, ExitCode.ERROR));
  }
  const renderResult = engine.render(resolveResult.value, {
    projectName: name,
    level,
    ...options.framework !== void 0 && { framework: options.framework }
  });
  if (!renderResult.ok) {
    return Err4(new CLIError(renderResult.error.message, ExitCode.ERROR));
  }
  const writeResult = engine.write(renderResult.value, cwd, { overwrite: force });
  if (!writeResult.ok) {
    return Err4(new CLIError(writeResult.error.message, ExitCode.ERROR));
  }
  return Ok6({ filesCreated: writeResult.value });
}
function createInitCommand() {
  const command = new Command5("init").description("Initialize a new harness-engineering project").option("-n, --name <name>", "Project name").option("-l, --level <level>", "Adoption level (basic, intermediate, advanced)", "basic").option("--framework <framework>", "Framework overlay (nextjs)").option("-f, --force", "Overwrite existing files").option("-y, --yes", "Use defaults without prompting").action(async (opts, cmd) => {
    const globalOpts = cmd.optsWithGlobals();
    const result = await runInit({
      name: opts.name,
      level: opts.level,
      framework: opts.framework,
      force: opts.force
    });
    if (!result.ok) {
      logger.error(result.error.message);
      process.exit(result.error.exitCode);
    }
    const cwd = opts.cwd ?? process.cwd();
    const mcpResult = setupMcp(cwd, "all");
    if (!globalOpts.quiet) {
      console.log("");
      logger.success("Project initialized!");
      console.log("");
      logger.info("Created files:");
      for (const file of result.value.filesCreated) {
        console.log(`  ${chalk3.green("+")} ${file}`);
      }
      if (mcpResult.configured.length > 0) {
        console.log("");
        logger.info("MCP server configured for:");
        for (const name of mcpResult.configured) {
          console.log(`  ${chalk3.green("+")} ${name}`);
        }
      }
      console.log("");
      console.log(chalk3.bold("Next steps:"));
      console.log(`  1. Review ${chalk3.cyan("harness.config.json")}`);
      console.log(`  2. Update ${chalk3.cyan("AGENTS.md")} with your project context`);
      console.log(`  3. Run ${chalk3.cyan("harness validate")} to check your setup`);
      console.log("");
    }
    process.exit(ExitCode.SUCCESS);
  });
  return command;
}

// src/commands/cleanup.ts
import { Command as Command6 } from "commander";
import * as path9 from "path";
import { Ok as Ok7, Err as Err5, EntropyAnalyzer } from "@harness-engineering/core";
async function runCleanup(options) {
  const cwd = options.cwd ?? process.cwd();
  const type = options.type ?? "all";
  const configResult = resolveConfig(options.configPath);
  if (!configResult.ok) {
    return Err5(configResult.error);
  }
  const config = configResult.value;
  const result = {
    driftIssues: [],
    deadCode: [],
    patternViolations: [],
    totalIssues: 0
  };
  const rootDir = path9.resolve(cwd, config.rootDir);
  const docsDir = path9.resolve(cwd, config.docsDir);
  const entropyConfig = {
    rootDir,
    entryPoints: [path9.join(rootDir, "src/index.ts")],
    docPaths: [docsDir],
    analyze: {
      drift: type === "all" || type === "drift",
      deadCode: type === "all" || type === "dead-code",
      patterns: type === "all" || type === "patterns" ? { patterns: [] } : false
    },
    exclude: config.entropy?.excludePatterns ?? ["**/node_modules/**", "**/*.test.ts"]
  };
  const analyzer = new EntropyAnalyzer(entropyConfig);
  const analysisResult = await analyzer.analyze();
  if (!analysisResult.ok) {
    return Err5(
      new CLIError(`Entropy analysis failed: ${analysisResult.error.message}`, ExitCode.ERROR)
    );
  }
  const report = analysisResult.value;
  if (report.drift) {
    result.driftIssues = report.drift.drifts.map((d) => ({
      file: d.docFile,
      issue: `${d.issue}: ${d.details}`
    }));
  }
  if (report.deadCode) {
    result.deadCode = [
      ...report.deadCode.deadFiles.map((f) => ({ file: f.path })),
      ...report.deadCode.deadExports.map((e) => ({ file: e.file, symbol: e.name }))
    ];
  }
  if (report.patterns) {
    result.patternViolations = report.patterns.violations.map((v) => ({
      file: v.file,
      pattern: v.pattern,
      message: v.message
    }));
  }
  result.totalIssues = result.driftIssues.length + result.deadCode.length + result.patternViolations.length;
  return Ok7(result);
}
function createCleanupCommand() {
  const command = new Command6("cleanup").description("Detect entropy issues (doc drift, dead code, patterns)").option("-t, --type <type>", "Issue type: drift, dead-code, patterns, all", "all").action(async (opts, cmd) => {
    const globalOpts = cmd.optsWithGlobals();
    const mode = globalOpts.json ? OutputMode.JSON : globalOpts.quiet ? OutputMode.QUIET : globalOpts.verbose ? OutputMode.VERBOSE : OutputMode.TEXT;
    const formatter = new OutputFormatter(mode);
    const result = await runCleanup({
      configPath: globalOpts.config,
      type: opts.type,
      json: globalOpts.json,
      verbose: globalOpts.verbose,
      quiet: globalOpts.quiet
    });
    if (!result.ok) {
      if (mode === OutputMode.JSON) {
        console.log(JSON.stringify({ error: result.error.message }));
      } else {
        logger.error(result.error.message);
      }
      process.exit(result.error.exitCode);
    }
    if (mode === OutputMode.JSON) {
      console.log(JSON.stringify(result.value, null, 2));
    } else if (mode !== OutputMode.QUIET || result.value.totalIssues > 0) {
      console.log(
        formatter.formatSummary(
          "Entropy issues",
          result.value.totalIssues.toString(),
          result.value.totalIssues === 0
        )
      );
      if (result.value.driftIssues.length > 0) {
        console.log("\nDocumentation drift:");
        for (const issue of result.value.driftIssues) {
          console.log(`  - ${issue.file}: ${issue.issue}`);
        }
      }
      if (result.value.deadCode.length > 0) {
        console.log("\nDead code:");
        for (const item of result.value.deadCode.slice(0, 10)) {
          console.log(`  - ${item.file}${item.symbol ? `: ${item.symbol}` : ""}`);
        }
        if (result.value.deadCode.length > 10) {
          console.log(`  ... and ${result.value.deadCode.length - 10} more`);
        }
      }
      if (result.value.patternViolations.length > 0) {
        console.log("\nPattern violations:");
        for (const violation of result.value.patternViolations.slice(0, 10)) {
          console.log(`  - ${violation.file} [${violation.pattern}]: ${violation.message}`);
        }
        if (result.value.patternViolations.length > 10) {
          console.log(`  ... and ${result.value.patternViolations.length - 10} more`);
        }
      }
    }
    process.exit(result.value.totalIssues === 0 ? ExitCode.SUCCESS : ExitCode.VALIDATION_FAILED);
  });
  return command;
}

// src/commands/fix-drift.ts
import { Command as Command7 } from "commander";
import * as path10 from "path";
import {
  Ok as Ok8,
  Err as Err6,
  buildSnapshot,
  detectDocDrift,
  detectDeadCode,
  createFixes,
  applyFixes,
  generateSuggestions
} from "@harness-engineering/core";
async function runFixDrift(options) {
  const cwd = options.cwd ?? process.cwd();
  const dryRun = options.dryRun !== false;
  const configResult = resolveConfig(options.configPath);
  if (!configResult.ok) {
    return Err6(configResult.error);
  }
  const config = configResult.value;
  const rootDir = path10.resolve(cwd, config.rootDir);
  const docsDir = path10.resolve(cwd, config.docsDir);
  const entropyConfig = {
    rootDir,
    entryPoints: [path10.join(rootDir, "src/index.ts")],
    docPaths: [docsDir],
    analyze: {
      drift: true,
      deadCode: true,
      patterns: false
    },
    exclude: config.entropy?.excludePatterns ?? ["**/node_modules/**", "**/*.test.ts"]
  };
  const snapshotResult = await buildSnapshot(entropyConfig);
  if (!snapshotResult.ok) {
    return Err6(
      new CLIError(`Failed to build snapshot: ${snapshotResult.error.message}`, ExitCode.ERROR)
    );
  }
  const snapshot = snapshotResult.value;
  const driftResult = await detectDocDrift(snapshot);
  if (!driftResult.ok) {
    return Err6(
      new CLIError(`Failed to detect drift: ${driftResult.error.message}`, ExitCode.ERROR)
    );
  }
  const driftReport = driftResult.value;
  const deadCodeResult = await detectDeadCode(snapshot);
  if (!deadCodeResult.ok) {
    return Err6(
      new CLIError(`Failed to detect dead code: ${deadCodeResult.error.message}`, ExitCode.ERROR)
    );
  }
  const deadCodeReport = deadCodeResult.value;
  const fixes = createFixes(deadCodeReport);
  const appliedFixes = [];
  if (!dryRun && fixes.length > 0) {
    const applyResult = await applyFixes(fixes, { dryRun: false });
    if (!applyResult.ok) {
      return Err6(
        new CLIError(`Failed to apply fixes: ${applyResult.error.message}`, ExitCode.ERROR)
      );
    }
    for (const fix of applyResult.value.applied) {
      appliedFixes.push({
        file: fix.file,
        action: fix.action,
        applied: true
      });
    }
    for (const fix of applyResult.value.skipped) {
      appliedFixes.push({
        file: fix.file,
        action: fix.action,
        applied: false
      });
    }
    for (const { fix } of applyResult.value.errors) {
      appliedFixes.push({
        file: fix.file,
        action: fix.action,
        applied: false
      });
    }
  } else {
    for (const fix of fixes) {
      appliedFixes.push({
        file: fix.file,
        action: fix.action,
        applied: false
      });
    }
  }
  const suggestionReport = generateSuggestions(deadCodeReport, driftReport);
  const suggestions = [];
  for (const suggestion of suggestionReport.suggestions) {
    for (const file of suggestion.files) {
      suggestions.push({
        file,
        suggestion: suggestion.title
      });
    }
  }
  const result = {
    dryRun,
    fixes: appliedFixes,
    suggestions
  };
  return Ok8(result);
}
function createFixDriftCommand() {
  const command = new Command7("fix-drift").description("Auto-fix entropy issues (doc drift, dead code)").option("--no-dry-run", "Actually apply fixes (default is dry-run mode)").action(async (opts, cmd) => {
    const globalOpts = cmd.optsWithGlobals();
    const mode = globalOpts.json ? OutputMode.JSON : globalOpts.quiet ? OutputMode.QUIET : globalOpts.verbose ? OutputMode.VERBOSE : OutputMode.TEXT;
    const formatter = new OutputFormatter(mode);
    const result = await runFixDrift({
      configPath: globalOpts.config,
      dryRun: opts.dryRun,
      json: globalOpts.json,
      verbose: globalOpts.verbose,
      quiet: globalOpts.quiet
    });
    if (!result.ok) {
      if (mode === OutputMode.JSON) {
        console.log(JSON.stringify({ error: result.error.message }));
      } else {
        logger.error(result.error.message);
      }
      process.exit(result.error.exitCode);
    }
    if (mode === OutputMode.JSON) {
      console.log(JSON.stringify(result.value, null, 2));
    } else if (mode !== OutputMode.QUIET || result.value.fixes.length > 0 || result.value.suggestions.length > 0) {
      const { value } = result;
      const statusMessage = value.dryRun ? "(dry-run)" : "";
      console.log(
        formatter.formatSummary(
          `Fix drift ${statusMessage}`,
          `${value.fixes.length} fixes, ${value.suggestions.length} suggestions`,
          value.fixes.length === 0 && value.suggestions.length === 0
        )
      );
      if (value.fixes.length > 0) {
        console.log("\nFixes:");
        for (const fix of value.fixes.slice(0, 10)) {
          const status = fix.applied ? "[applied]" : "[pending]";
          console.log(`  ${status} ${fix.action}: ${fix.file}`);
        }
        if (value.fixes.length > 10) {
          console.log(`  ... and ${value.fixes.length - 10} more`);
        }
      }
      if (value.suggestions.length > 0 && (mode === OutputMode.VERBOSE || value.fixes.length === 0)) {
        console.log("\nSuggestions:");
        for (const suggestion of value.suggestions.slice(0, 10)) {
          console.log(`  - ${suggestion.file}: ${suggestion.suggestion}`);
        }
        if (value.suggestions.length > 10) {
          console.log(`  ... and ${value.suggestions.length - 10} more`);
        }
      }
      if (value.dryRun && value.fixes.length > 0) {
        console.log("\nRun with --no-dry-run to apply fixes.");
      }
    }
    process.exit(ExitCode.SUCCESS);
  });
  return command;
}

// src/commands/agent/index.ts
import { Command as Command10 } from "commander";

// src/commands/agent/run.ts
import { Command as Command8 } from "commander";
import * as path12 from "path";
import * as childProcess from "child_process";
import { Ok as Ok10, Err as Err8 } from "@harness-engineering/core";
import { requestPeerReview } from "@harness-engineering/core";

// src/persona/loader.ts
import * as fs6 from "fs";
import * as path11 from "path";
import YAML from "yaml";
import { Ok as Ok9, Err as Err7 } from "@harness-engineering/core";

// src/persona/schema.ts
import { z as z3 } from "zod";
var PersonaTriggerSchema = z3.discriminatedUnion("event", [
  z3.object({
    event: z3.literal("on_pr"),
    conditions: z3.object({ paths: z3.array(z3.string()).optional() }).optional()
  }),
  z3.object({
    event: z3.literal("on_commit"),
    conditions: z3.object({ branches: z3.array(z3.string()).optional() }).optional()
  }),
  z3.object({
    event: z3.literal("scheduled"),
    cron: z3.string()
  })
]);
var PersonaConfigSchema = z3.object({
  severity: z3.enum(["error", "warning"]).default("error"),
  autoFix: z3.boolean().default(false),
  timeout: z3.number().default(3e5)
});
var PersonaOutputsSchema = z3.object({
  "agents-md": z3.boolean().default(true),
  "ci-workflow": z3.boolean().default(true),
  "runtime-config": z3.boolean().default(true)
});
var PersonaSchema = z3.object({
  version: z3.literal(1),
  name: z3.string(),
  description: z3.string(),
  role: z3.string(),
  skills: z3.array(z3.string()),
  commands: z3.array(z3.string()),
  triggers: z3.array(PersonaTriggerSchema),
  config: PersonaConfigSchema.default({}),
  outputs: PersonaOutputsSchema.default({})
});

// src/persona/loader.ts
function loadPersona(filePath) {
  try {
    if (!fs6.existsSync(filePath)) {
      return Err7(new Error(`Persona file not found: ${filePath}`));
    }
    const raw = fs6.readFileSync(filePath, "utf-8");
    const parsed = YAML.parse(raw);
    const result = PersonaSchema.safeParse(parsed);
    if (!result.success) {
      return Err7(new Error(`Invalid persona ${filePath}: ${result.error.message}`));
    }
    return Ok9(result.data);
  } catch (error) {
    return Err7(
      new Error(`Failed to load persona: ${error instanceof Error ? error.message : String(error)}`)
    );
  }
}
function listPersonas(dir) {
  try {
    if (!fs6.existsSync(dir)) return Ok9([]);
    const entries = fs6.readdirSync(dir).filter((f) => f.endsWith(".yaml") || f.endsWith(".yml"));
    const personas = [];
    for (const entry of entries) {
      const filePath = path11.join(dir, entry);
      const result = loadPersona(filePath);
      if (result.ok) {
        personas.push({ name: result.value.name, description: result.value.description, filePath });
      }
    }
    return Ok9(personas);
  } catch (error) {
    return Err7(
      new Error(
        `Failed to list personas: ${error instanceof Error ? error.message : String(error)}`
      )
    );
  }
}

// src/persona/runner.ts
var TIMEOUT_ERROR_MESSAGE = "__PERSONA_RUNNER_TIMEOUT__";
async function runPersona(persona, executor) {
  const startTime = Date.now();
  const timeout = persona.config.timeout;
  const report = {
    persona: persona.name.toLowerCase().replace(/\s+/g, "-"),
    status: "pass",
    commands: [],
    totalDurationMs: 0
  };
  for (let i = 0; i < persona.commands.length; i++) {
    const command = persona.commands[i];
    if (command === void 0) continue;
    if (Date.now() - startTime >= timeout) {
      for (let j = i; j < persona.commands.length; j++) {
        const remaining = persona.commands[j];
        if (remaining !== void 0) {
          report.commands.push({ name: remaining, status: "skipped", durationMs: 0 });
        }
      }
      report.status = "partial";
      break;
    }
    const cmdStart = Date.now();
    const remainingTime = timeout - (Date.now() - startTime);
    const result = await Promise.race([
      executor(command),
      new Promise(
        (resolve13) => setTimeout(
          () => resolve13({ ok: false, error: new Error(TIMEOUT_ERROR_MESSAGE) }),
          remainingTime
        )
      )
    ]);
    const durationMs = Date.now() - cmdStart;
    if (result.ok) {
      report.commands.push({ name: command, status: "pass", result: result.value, durationMs });
    } else if (result.error.message === TIMEOUT_ERROR_MESSAGE) {
      report.commands.push({ name: command, status: "skipped", error: "timed out", durationMs });
      report.status = "partial";
      for (let j = i + 1; j < persona.commands.length; j++) {
        const skipped = persona.commands[j];
        if (skipped !== void 0) {
          report.commands.push({ name: skipped, status: "skipped", durationMs: 0 });
        }
      }
      break;
    } else {
      report.commands.push({
        name: command,
        status: "fail",
        error: result.error.message,
        durationMs
      });
      report.status = "fail";
      for (let j = i + 1; j < persona.commands.length; j++) {
        const skipped = persona.commands[j];
        if (skipped !== void 0) {
          report.commands.push({ name: skipped, status: "skipped", durationMs: 0 });
        }
      }
      break;
    }
  }
  report.totalDurationMs = Date.now() - startTime;
  return report;
}

// src/commands/agent/run.ts
async function runAgentTask(task, options) {
  const configResult = resolveConfig(options.configPath);
  if (!configResult.ok) {
    return configResult;
  }
  const agentTypeMap = {
    review: "architecture-enforcer",
    "doc-review": "documentation-maintainer",
    "test-review": "test-reviewer"
  };
  const agentType = agentTypeMap[task];
  if (!agentType) {
    return Err8(
      new CLIError(
        `Unknown task: ${task}. Available: ${Object.keys(agentTypeMap).join(", ")}`,
        ExitCode.ERROR
      )
    );
  }
  const config = configResult.value;
  const timeout = options.timeout ?? config.agent?.timeout ?? 3e5;
  const reviewResult = await requestPeerReview(
    agentType,
    {
      files: [],
      diff: "",
      commitMessage: task,
      metadata: { task, timeout }
    },
    { timeout }
  );
  if (!reviewResult.ok) {
    return Err8(new CLIError(`Agent task failed: ${reviewResult.error.message}`, ExitCode.ERROR));
  }
  const review = reviewResult.value;
  return Ok10({
    success: review.approved,
    output: review.approved ? `Agent task '${task}' completed successfully` : `Agent task '${task}' found issues:
${review.comments.map((c) => `  - ${c.message}`).join("\n")}`
  });
}
function createRunCommand() {
  return new Command8("run").description("Run an agent task").argument("[task]", "Task to run (review, doc-review, test-review)").option("--timeout <ms>", "Timeout in milliseconds", "300000").option("--persona <name>", "Run a persona by name").action(async (task, opts, cmd) => {
    const globalOpts = cmd.optsWithGlobals();
    if (opts.persona) {
      const personasDir = resolvePersonasDir();
      const filePath = path12.join(personasDir, `${opts.persona}.yaml`);
      const personaResult = loadPersona(filePath);
      if (!personaResult.ok) {
        logger.error(personaResult.error.message);
        process.exit(ExitCode.ERROR);
      }
      const persona = personaResult.value;
      const ALLOWED_COMMANDS = /* @__PURE__ */ new Set([
        "validate",
        "check-deps",
        "check-docs",
        "cleanup",
        "fix-drift",
        "add"
      ]);
      const executor = async (command) => {
        if (!ALLOWED_COMMANDS.has(command)) {
          return Err8(new Error(`Unknown harness command: ${command}`));
        }
        try {
          childProcess.execFileSync("npx", ["harness", command], { stdio: "inherit" });
          return Ok10(null);
        } catch (error) {
          return Err8(new Error(error instanceof Error ? error.message : String(error)));
        }
      };
      const report = await runPersona(persona, executor);
      if (!globalOpts.quiet) {
        logger.info(`Persona '${report.persona}' status: ${report.status}`);
        for (const c of report.commands) {
          const icon = c.status === "pass" ? "v" : c.status === "fail" ? "x" : "-";
          console.log(`  [${icon}] ${c.name} (${c.durationMs}ms)`);
        }
      }
      process.exit(report.status === "fail" ? ExitCode.ERROR : ExitCode.SUCCESS);
    }
    if (!task) {
      logger.error("Either a task argument or --persona flag is required.");
      process.exit(ExitCode.ERROR);
    }
    const result = await runAgentTask(task, {
      configPath: globalOpts.config,
      timeout: parseInt(opts.timeout, 10)
    });
    if (!result.ok) {
      logger.error(result.error.message);
      process.exit(result.error.exitCode);
    }
    logger.success(result.value.output);
    process.exit(ExitCode.SUCCESS);
  });
}

// src/commands/agent/review.ts
import { Command as Command9 } from "commander";
import { execSync } from "child_process";
import { Ok as Ok11, Err as Err9 } from "@harness-engineering/core";
import { createSelfReview, parseDiff } from "@harness-engineering/core";
async function runAgentReview(options) {
  const configResult = resolveConfig(options.configPath);
  if (!configResult.ok) {
    return configResult;
  }
  const config = configResult.value;
  let diff;
  try {
    diff = execSync("git diff --cached", { encoding: "utf-8" });
    if (!diff) {
      diff = execSync("git diff", { encoding: "utf-8" });
    }
  } catch {
    return Err9(new CLIError("Failed to get git diff", ExitCode.ERROR));
  }
  if (!diff) {
    return Ok11({
      passed: true,
      checklist: [{ check: "No changes to review", passed: true }]
    });
  }
  const parsedDiffResult = parseDiff(diff);
  if (!parsedDiffResult.ok) {
    return Err9(new CLIError(parsedDiffResult.error.message, ExitCode.ERROR));
  }
  const codeChanges = parsedDiffResult.value;
  const review = await createSelfReview(codeChanges, {
    rootDir: config.rootDir,
    diffAnalysis: {
      enabled: true,
      checkTestCoverage: true
    }
  });
  if (!review.ok) {
    return Err9(new CLIError(review.error.message, ExitCode.ERROR));
  }
  return Ok11({
    passed: review.value.passed,
    checklist: review.value.items.map((item) => ({
      check: item.check,
      passed: item.passed,
      details: item.details
    }))
  });
}
function createReviewCommand() {
  return new Command9("review").description("Run self-review on current changes").action(async (_opts, cmd) => {
    const globalOpts = cmd.optsWithGlobals();
    const mode = globalOpts.json ? OutputMode.JSON : globalOpts.quiet ? OutputMode.QUIET : OutputMode.TEXT;
    const result = await runAgentReview({
      configPath: globalOpts.config,
      json: globalOpts.json,
      verbose: globalOpts.verbose,
      quiet: globalOpts.quiet
    });
    if (!result.ok) {
      if (mode === OutputMode.JSON) {
        console.log(JSON.stringify({ error: result.error.message }));
      } else {
        logger.error(result.error.message);
      }
      process.exit(result.error.exitCode);
    }
    if (mode === OutputMode.JSON) {
      console.log(JSON.stringify(result.value, null, 2));
    } else if (mode !== OutputMode.QUIET) {
      console.log(result.value.passed ? "v Self-review passed" : "x Self-review found issues");
      console.log("");
      for (const item of result.value.checklist) {
        const icon = item.passed ? "v" : "x";
        console.log(`  ${icon} ${item.check}`);
        if (item.details && !item.passed) {
          console.log(`    ${item.details}`);
        }
      }
    }
    process.exit(result.value.passed ? ExitCode.SUCCESS : ExitCode.VALIDATION_FAILED);
  });
}

// src/commands/agent/index.ts
function createAgentCommand() {
  const command = new Command10("agent").description("Agent orchestration commands");
  command.addCommand(createRunCommand());
  command.addCommand(createReviewCommand());
  return command;
}

// src/commands/add.ts
import { Command as Command11 } from "commander";
import * as fs7 from "fs";
import * as path13 from "path";
import { Ok as Ok12, Err as Err10 } from "@harness-engineering/core";
var LAYER_INDEX_TEMPLATE = (name) => `// ${name} layer
// Add your ${name} exports here

export {};
`;
var MODULE_TEMPLATE = (name) => `/**
 * ${name} module
 */

export function ${name}(): void {
  // Add implementation
}
`;
var DOC_TEMPLATE = (name) => `# ${name}

## Overview

[Describe what ${name} does and why it exists.]

## Usage

\`\`\`typescript
import { ${name} } from './${name}';
\`\`\`
`;
async function runAdd(componentType, name, options) {
  const cwd = options.cwd ?? process.cwd();
  const NAME_PATTERN = /^[a-zA-Z][a-zA-Z0-9_-]*$/;
  if (!name || !NAME_PATTERN.test(name)) {
    return Err10(
      new CLIError(
        "Invalid name. Must start with a letter and contain only alphanumeric characters, hyphens, and underscores.",
        ExitCode.ERROR
      )
    );
  }
  const configResult = resolveConfig(options.configPath);
  if (!configResult.ok) {
  }
  const created = [];
  try {
    switch (componentType) {
      case "layer": {
        const layerDir = path13.join(cwd, "src", name);
        if (!fs7.existsSync(layerDir)) {
          fs7.mkdirSync(layerDir, { recursive: true });
          created.push(`src/${name}/`);
        }
        const indexPath = path13.join(layerDir, "index.ts");
        if (!fs7.existsSync(indexPath)) {
          fs7.writeFileSync(indexPath, LAYER_INDEX_TEMPLATE(name));
          created.push(`src/${name}/index.ts`);
        }
        break;
      }
      case "module": {
        const modulePath = path13.join(cwd, "src", `${name}.ts`);
        if (fs7.existsSync(modulePath)) {
          return Err10(new CLIError(`Module ${name} already exists`, ExitCode.ERROR));
        }
        fs7.writeFileSync(modulePath, MODULE_TEMPLATE(name));
        created.push(`src/${name}.ts`);
        break;
      }
      case "doc": {
        const docsDir = path13.join(cwd, "docs");
        if (!fs7.existsSync(docsDir)) {
          fs7.mkdirSync(docsDir, { recursive: true });
        }
        const docPath = path13.join(docsDir, `${name}.md`);
        if (fs7.existsSync(docPath)) {
          return Err10(new CLIError(`Doc ${name} already exists`, ExitCode.ERROR));
        }
        fs7.writeFileSync(docPath, DOC_TEMPLATE(name));
        created.push(`docs/${name}.md`);
        break;
      }
      case "skill": {
        const { generateSkillFiles: generateSkillFiles2 } = await import("./create-skill-4GKJZB5R.js");
        generateSkillFiles2({
          name,
          description: `${name} skill`,
          outputDir: path13.join(cwd, "agents", "skills", "claude-code")
        });
        created.push(`agents/skills/claude-code/${name}/skill.yaml`);
        created.push(`agents/skills/claude-code/${name}/SKILL.md`);
        break;
      }
      case "persona": {
        const personasDir = path13.join(cwd, "agents", "personas");
        if (!fs7.existsSync(personasDir)) {
          fs7.mkdirSync(personasDir, { recursive: true });
        }
        const personaPath = path13.join(personasDir, `${name}.yaml`);
        if (fs7.existsSync(personaPath)) {
          return Err10(new CLIError(`Persona ${name} already exists`, ExitCode.ERROR));
        }
        fs7.writeFileSync(
          personaPath,
          `name: ${name}
description: ${name} persona
triggers:
  - manual
focus_areas: []
`
        );
        created.push(`agents/personas/${name}.yaml`);
        break;
      }
      default: {
        const _exhaustive = componentType;
        return Err10(
          new CLIError(
            `Unknown component type: ${String(_exhaustive)}. Use: layer, module, doc, skill, persona`,
            ExitCode.ERROR
          )
        );
      }
    }
    return Ok12({ created });
  } catch (error) {
    return Err10(
      new CLIError(
        `Failed to add ${componentType}: ${error instanceof Error ? error.message : "Unknown error"}`,
        ExitCode.ERROR
      )
    );
  }
}
function createAddCommand() {
  const command = new Command11("add").description("Add a component to the project").argument("<type>", "Component type (layer, module, doc, skill, persona)").argument("<name>", "Component name").action(async (type, name, _opts, cmd) => {
    const globalOpts = cmd.optsWithGlobals();
    const result = await runAdd(type, name, {
      ...globalOpts.config !== void 0 && { configPath: globalOpts.config }
    });
    if (!result.ok) {
      logger.error(result.error.message);
      process.exit(result.error.exitCode);
    }
    if (!globalOpts.quiet) {
      logger.success(`Added ${type}: ${name}`);
      for (const file of result.value.created) {
        console.log(`  + ${file}`);
      }
    }
    process.exit(ExitCode.SUCCESS);
  });
  return command;
}

// src/commands/linter/index.ts
import { Command as Command14 } from "commander";

// src/commands/linter/generate.ts
import { Command as Command12 } from "commander";
import { generate } from "@harness-engineering/linter-gen";
function createGenerateCommand() {
  return new Command12("generate").description("Generate ESLint rules from harness-linter.yml").option("-c, --config <path>", "Path to harness-linter.yml", "./harness-linter.yml").option("-o, --output <dir>", "Override output directory").option("--clean", "Remove existing files before generating").option("--dry-run", "Preview without writing files").option("--json", "Output as JSON").option("--verbose", "Show detailed output").action(async (options) => {
    try {
      if (options.verbose) {
        logger.info(`Parsing config: ${options.config}`);
      }
      const result = await generate({
        configPath: options.config,
        outputDir: options.output,
        clean: options.clean,
        dryRun: options.dryRun
      });
      if (!result.success) {
        const errorMessages = result.errors.map((e) => {
          switch (e.type) {
            case "parse":
              return `Config error: ${e.error.message}`;
            case "template":
              return `Template error for '${e.ruleName}': ${e.error.message}`;
            case "render":
              return `Render error for '${e.ruleName}': ${e.error.message}`;
            case "write":
              return `Write error for '${e.path}': ${e.error.message}`;
          }
        });
        if (options.json) {
          console.log(JSON.stringify({ success: false, errors: errorMessages }, null, 2));
        } else {
          errorMessages.forEach((msg) => logger.error(msg));
        }
        process.exit(ExitCode.VALIDATION_FAILED);
      }
      if (options.json) {
        console.log(
          JSON.stringify(
            {
              success: true,
              outputDir: result.outputDir,
              rulesGenerated: result.rulesGenerated,
              dryRun: result.dryRun
            },
            null,
            2
          )
        );
      } else {
        if (result.dryRun) {
          logger.info("Dry run - no files written");
        }
        result.rulesGenerated.forEach((name) => {
          logger.success(`Generated ${name}.ts`);
        });
        logger.success(`Generated index.ts`);
        logger.info(`
Generated ${result.rulesGenerated.length} rules to ${result.outputDir}`);
      }
    } catch (err) {
      throw new CLIError(`Generation failed: ${err.message}`, ExitCode.ERROR);
    }
  });
}

// src/commands/linter/validate.ts
import { Command as Command13 } from "commander";
import { validate } from "@harness-engineering/linter-gen";
function createValidateCommand2() {
  return new Command13("validate").description("Validate harness-linter.yml config").option("-c, --config <path>", "Path to harness-linter.yml", "./harness-linter.yml").option("--json", "Output as JSON").action(async (options) => {
    try {
      const result = await validate({ configPath: options.config });
      if (options.json) {
        console.log(JSON.stringify(result, null, 2));
      } else if (result.success) {
        logger.success(`Config valid: ${result.ruleCount} rules defined`);
      } else {
        logger.error(`Config invalid: ${result.error.message}`);
        process.exit(ExitCode.VALIDATION_FAILED);
      }
    } catch (err) {
      throw new CLIError(`Validation failed: ${err.message}`, ExitCode.ERROR);
    }
  });
}

// src/commands/linter/index.ts
function createLinterCommand() {
  const linter = new Command14("linter").description(
    "Generate and validate ESLint rules from YAML config"
  );
  linter.addCommand(createGenerateCommand());
  linter.addCommand(createValidateCommand2());
  return linter;
}

// src/commands/persona/index.ts
import { Command as Command17 } from "commander";

// src/commands/persona/list.ts
import { Command as Command15 } from "commander";
function createListCommand() {
  return new Command15("list").description("List available agent personas").action(async (_opts, cmd) => {
    const globalOpts = cmd.optsWithGlobals();
    const personasDir = resolvePersonasDir();
    const result = listPersonas(personasDir);
    if (!result.ok) {
      logger.error(result.error.message);
      process.exit(ExitCode.ERROR);
    }
    if (globalOpts.json) {
      logger.raw(result.value);
    } else if (globalOpts.quiet) {
      for (const p of result.value) console.log(p.name);
    } else {
      if (result.value.length === 0) {
        logger.info("No personas found.");
      } else {
        console.log("Available personas:\n");
        for (const p of result.value) {
          console.log(`  ${p.name}`);
          console.log(`    ${p.description}
`);
        }
      }
    }
    process.exit(ExitCode.SUCCESS);
  });
}

// src/commands/persona/generate.ts
import { Command as Command16 } from "commander";
import * as fs8 from "fs";
import * as path14 from "path";

// src/persona/generators/runtime.ts
import { Ok as Ok13, Err as Err11 } from "@harness-engineering/core";

// src/utils/string.ts
function toKebabCase(name) {
  return name.toLowerCase().replace(/\s+/g, "-");
}

// src/persona/generators/runtime.ts
function generateRuntime(persona) {
  try {
    const config = {
      name: toKebabCase(persona.name),
      skills: persona.skills,
      commands: persona.commands,
      timeout: persona.config.timeout,
      severity: persona.config.severity
    };
    return Ok13(JSON.stringify(config, null, 2));
  } catch (error) {
    return Err11(
      new Error(
        `Failed to generate runtime config: ${error instanceof Error ? error.message : String(error)}`
      )
    );
  }
}

// src/persona/generators/agents-md.ts
import { Ok as Ok14, Err as Err12 } from "@harness-engineering/core";
function formatTrigger(trigger) {
  switch (trigger.event) {
    case "on_pr": {
      const paths = trigger.conditions?.paths?.join(", ") ?? "all files";
      return `On PR (${paths})`;
    }
    case "on_commit": {
      const branches = trigger.conditions?.branches?.join(", ") ?? "all branches";
      return `On commit (${branches})`;
    }
    case "scheduled":
      return `Scheduled (cron: ${trigger.cron})`;
  }
}
function generateAgentsMd(persona) {
  try {
    const triggers = persona.triggers.map(formatTrigger).join(", ");
    const skills = persona.skills.join(", ");
    const commands = persona.commands.map((c) => `\`harness ${c}\``).join(", ");
    const fragment = `## ${persona.name} Agent

**Role:** ${persona.role}

**Triggers:** ${triggers}

**Skills:** ${skills}

**When this agent flags an issue:** Fix violations before merging. Run ${commands} locally to validate.
`;
    return Ok14(fragment);
  } catch (error) {
    return Err12(
      new Error(
        `Failed to generate AGENTS.md fragment: ${error instanceof Error ? error.message : String(error)}`
      )
    );
  }
}

// src/persona/generators/ci-workflow.ts
import YAML2 from "yaml";
import { Ok as Ok15, Err as Err13 } from "@harness-engineering/core";
function buildGitHubTriggers(triggers) {
  const on = {};
  for (const trigger of triggers) {
    switch (trigger.event) {
      case "on_pr": {
        const prConfig = {};
        if (trigger.conditions?.paths) prConfig.paths = trigger.conditions.paths;
        on.pull_request = prConfig;
        break;
      }
      case "on_commit": {
        const pushConfig = {};
        if (trigger.conditions?.branches) pushConfig.branches = trigger.conditions.branches;
        on.push = pushConfig;
        break;
      }
      case "scheduled":
        on.schedule = [{ cron: trigger.cron }];
        break;
    }
  }
  return on;
}
function generateCIWorkflow(persona, platform) {
  try {
    if (platform === "gitlab") return Err13(new Error("GitLab CI generation is not yet supported"));
    const severity = persona.config.severity;
    const steps = [
      { uses: "actions/checkout@v4" },
      { uses: "actions/setup-node@v4", with: { "node-version": "20" } },
      { uses: "pnpm/action-setup@v4", with: { run_install: "frozen" } }
    ];
    for (const cmd of persona.commands) {
      const severityFlag = severity ? ` --severity ${severity}` : "";
      steps.push({ run: `npx harness ${cmd}${severityFlag}` });
    }
    const workflow = {
      name: persona.name,
      on: buildGitHubTriggers(persona.triggers),
      jobs: {
        enforce: {
          "runs-on": "ubuntu-latest",
          steps
        }
      }
    };
    return Ok15(YAML2.stringify(workflow, { lineWidth: 0 }));
  } catch (error) {
    return Err13(
      new Error(
        `Failed to generate CI workflow: ${error instanceof Error ? error.message : String(error)}`
      )
    );
  }
}

// src/commands/persona/generate.ts
function createGenerateCommand2() {
  return new Command16("generate").description("Generate artifacts from a persona config").argument("<name>", "Persona name (e.g., architecture-enforcer)").option("--output-dir <dir>", "Output directory", ".").option("--only <type>", "Generate only: ci, agents-md, runtime").action(async (name, opts, cmd) => {
    const globalOpts = cmd.optsWithGlobals();
    const personasDir = resolvePersonasDir();
    const filePath = path14.join(personasDir, `${name}.yaml`);
    const personaResult = loadPersona(filePath);
    if (!personaResult.ok) {
      logger.error(personaResult.error.message);
      process.exit(ExitCode.ERROR);
    }
    const persona = personaResult.value;
    const outputDir = path14.resolve(opts.outputDir);
    const slug = toKebabCase(persona.name);
    const only = opts.only;
    const generated = [];
    if (!only || only === "runtime") {
      const result = generateRuntime(persona);
      if (result.ok) {
        const outPath = path14.join(outputDir, `${slug}.runtime.json`);
        fs8.mkdirSync(path14.dirname(outPath), { recursive: true });
        fs8.writeFileSync(outPath, result.value);
        generated.push(outPath);
      }
    }
    if (!only || only === "agents-md") {
      const result = generateAgentsMd(persona);
      if (result.ok) {
        const outPath = path14.join(outputDir, `${slug}.agents.md`);
        fs8.writeFileSync(outPath, result.value);
        generated.push(outPath);
      }
    }
    if (!only || only === "ci") {
      const result = generateCIWorkflow(persona, "github");
      if (result.ok) {
        const outPath = path14.join(outputDir, ".github", "workflows", `${slug}.yml`);
        fs8.mkdirSync(path14.dirname(outPath), { recursive: true });
        fs8.writeFileSync(outPath, result.value);
        generated.push(outPath);
      }
    }
    if (!globalOpts.quiet) {
      logger.success(`Generated ${generated.length} artifacts for ${persona.name}:`);
      for (const f of generated) console.log(`  - ${f}`);
    }
    process.exit(ExitCode.SUCCESS);
  });
}

// src/commands/persona/index.ts
function createPersonaCommand() {
  const command = new Command17("persona").description("Agent persona management commands");
  command.addCommand(createListCommand());
  command.addCommand(createGenerateCommand2());
  return command;
}

// src/commands/skill/index.ts
import { Command as Command22 } from "commander";

// src/commands/skill/list.ts
import { Command as Command18 } from "commander";
import * as fs9 from "fs";
import * as path15 from "path";
import { parse as parse2 } from "yaml";
function createListCommand2() {
  return new Command18("list").description("List available skills").action(async (_opts, cmd) => {
    const globalOpts = cmd.optsWithGlobals();
    const skillsDir = resolveSkillsDir();
    if (!fs9.existsSync(skillsDir)) {
      logger.info("No skills directory found.");
      process.exit(ExitCode.SUCCESS);
      return;
    }
    const entries = fs9.readdirSync(skillsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
    const skills = [];
    for (const name of entries) {
      const yamlPath = path15.join(skillsDir, name, "skill.yaml");
      if (!fs9.existsSync(yamlPath)) continue;
      try {
        const raw = fs9.readFileSync(yamlPath, "utf-8");
        const parsed = parse2(raw);
        const result = SkillMetadataSchema.safeParse(parsed);
        if (result.success) {
          skills.push(result.data);
        }
      } catch {
      }
    }
    if (globalOpts.json) {
      logger.raw(skills);
    } else if (globalOpts.quiet) {
      for (const s of skills) console.log(s.name);
    } else {
      if (skills.length === 0) {
        logger.info("No skills found.");
      } else {
        console.log("Available skills:\n");
        for (const s of skills) {
          console.log(`  ${s.name} (${s.type})`);
          console.log(`    ${s.description}
`);
        }
      }
    }
    process.exit(ExitCode.SUCCESS);
  });
}

// src/commands/skill/run.ts
import { Command as Command19 } from "commander";
import * as fs10 from "fs";
import * as path16 from "path";
import { parse as parse3 } from "yaml";

// src/skill/complexity.ts
import { execSync as execSync2 } from "child_process";
function evaluateSignals(signals) {
  if (signals.fileCount >= 3) return "full";
  if (signals.newDir) return "full";
  if (signals.newDep) return "full";
  if (signals.fileCount <= 1) return "light";
  if (signals.testOnly) return "light";
  if (signals.docsOnly) return "light";
  return "full";
}
function detectComplexity(projectPath) {
  try {
    const base = execSync2("git merge-base HEAD main", {
      cwd: projectPath,
      encoding: "utf-8",
      stdio: ["pipe", "pipe", "pipe"]
    }).trim();
    const diffFiles = execSync2(`git diff --name-only ${base}`, {
      cwd: projectPath,
      encoding: "utf-8",
      stdio: ["pipe", "pipe", "pipe"]
    }).trim().split("\n").filter(Boolean);
    const diffStat = execSync2(`git diff --stat ${base}`, {
      cwd: projectPath,
      encoding: "utf-8",
      stdio: ["pipe", "pipe", "pipe"]
    }).trim();
    const signals = {
      fileCount: diffFiles.length,
      testOnly: diffFiles.every((f) => f.match(/\.(test|spec)\./)),
      docsOnly: diffFiles.every((f) => f.startsWith("docs/") || f.endsWith(".md")),
      newDir: diffStat.includes("create mode") || diffFiles.some((f) => {
        const parts = f.split("/");
        return parts.length > 1;
      }),
      newDep: diffFiles.some(
        (f) => ["package.json", "Cargo.toml", "go.mod", "requirements.txt"].includes(f)
      )
    };
    return evaluateSignals(signals);
  } catch {
    return "full";
  }
}

// src/commands/skill/preamble.ts
function buildPreamble(options) {
  const sections = [];
  if (options.complexity && options.phases && options.phases.length > 0) {
    const lines = [`## Active Phases (complexity: ${options.complexity})`];
    for (const phase of options.phases) {
      if (options.complexity === "light" && !phase.required) {
        lines.push(`- ~~${phase.name.toUpperCase()}~~ (skipped in light mode)`);
      } else {
        lines.push(`- ${phase.name.toUpperCase()} (${phase.required ? "required" : "optional"})`);
      }
    }
    sections.push(lines.join("\n"));
  }
  if (options.principles) {
    sections.push(`## Project Principles (from docs/principles.md)
${options.principles}`);
  }
  if (options.phase) {
    const lines = [`## Resuming at Phase: ${options.phase}`];
    if (options.priorState) {
      lines.push(`## Prior state loaded
${options.priorState}`);
    }
    if (options.stateWarning) {
      lines.push(`> ${options.stateWarning}`);
    }
    sections.push(lines.join("\n"));
  }
  if (options.party) {
    sections.push(
      "## Party Mode: Active\nEvaluate each approach from multiple contextually relevant perspectives before converging on a recommendation."
    );
  }
  return sections.length > 0 ? sections.join("\n\n---\n\n") + "\n\n---\n\n" : "";
}

// src/commands/skill/run.ts
function createRunCommand2() {
  return new Command19("run").description("Run a skill (outputs SKILL.md content with context preamble)").argument("<name>", "Skill name (e.g., harness-tdd)").option("--path <path>", "Project root path for context injection").option("--complexity <level>", "Complexity: auto, light, full", "auto").option("--phase <name>", "Start at a specific phase (for re-entry)").option("--party", "Enable multi-perspective evaluation").action(async (name, opts, _cmd) => {
    const skillsDir = resolveSkillsDir();
    const skillDir = path16.join(skillsDir, name);
    if (!fs10.existsSync(skillDir)) {
      logger.error(`Skill not found: ${name}`);
      process.exit(ExitCode.ERROR);
      return;
    }
    const yamlPath = path16.join(skillDir, "skill.yaml");
    let metadata = null;
    if (fs10.existsSync(yamlPath)) {
      try {
        const raw = fs10.readFileSync(yamlPath, "utf-8");
        const parsed = parse3(raw);
        const result = SkillMetadataSchema.safeParse(parsed);
        if (result.success) metadata = result.data;
      } catch {
      }
    }
    let complexity;
    if (metadata?.phases && metadata.phases.length > 0) {
      const requested = opts.complexity ?? "auto";
      if (requested === "auto") {
        const projectPath2 = opts.path ? path16.resolve(opts.path) : process.cwd();
        complexity = detectComplexity(projectPath2);
      } else {
        complexity = requested;
      }
    }
    let principles;
    const projectPath = opts.path ? path16.resolve(opts.path) : process.cwd();
    const principlesPath = path16.join(projectPath, "docs", "principles.md");
    if (fs10.existsSync(principlesPath)) {
      principles = fs10.readFileSync(principlesPath, "utf-8");
    }
    let priorState;
    let stateWarning;
    if (opts.phase) {
      if (metadata?.phases) {
        const validPhases = metadata.phases.map((p) => p.name);
        if (!validPhases.includes(opts.phase)) {
          logger.error(`Unknown phase: ${opts.phase}. Valid phases: ${validPhases.join(", ")}`);
          process.exit(ExitCode.ERROR);
          return;
        }
      }
      if (metadata?.state.persistent && metadata.state.files.length > 0) {
        for (const stateFilePath of metadata.state.files) {
          const fullPath = path16.join(projectPath, stateFilePath);
          if (fs10.existsSync(fullPath)) {
            const stat = fs10.statSync(fullPath);
            if (stat.isDirectory()) {
              const files = fs10.readdirSync(fullPath).map((f) => ({ name: f, mtime: fs10.statSync(path16.join(fullPath, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
              if (files.length > 0) {
                priorState = fs10.readFileSync(path16.join(fullPath, files[0].name), "utf-8");
              }
            } else {
              priorState = fs10.readFileSync(fullPath, "utf-8");
            }
            break;
          }
        }
        if (!priorState) {
          stateWarning = "No prior phase data found. Earlier phases have not been completed. Proceed with caution.";
        }
      }
    }
    const preamble = buildPreamble({
      ...complexity !== void 0 && { complexity },
      phases: metadata?.phases,
      ...principles !== void 0 && { principles },
      phase: opts.phase,
      ...priorState !== void 0 && { priorState },
      ...stateWarning !== void 0 && { stateWarning },
      party: opts.party
    });
    const skillMdPath = path16.join(skillDir, "SKILL.md");
    if (!fs10.existsSync(skillMdPath)) {
      logger.error(`SKILL.md not found for skill: ${name}`);
      process.exit(ExitCode.ERROR);
      return;
    }
    let content = fs10.readFileSync(skillMdPath, "utf-8");
    if (metadata?.state.persistent && opts.path) {
      const stateFile = path16.join(projectPath, ".harness", "state.json");
      if (fs10.existsSync(stateFile)) {
        const stateContent = fs10.readFileSync(stateFile, "utf-8");
        content += `

---
## Project State
\`\`\`json
${stateContent}
\`\`\`
`;
      }
    }
    process.stdout.write(preamble + content);
    process.exit(ExitCode.SUCCESS);
  });
}

// src/commands/skill/validate.ts
import { Command as Command20 } from "commander";
import * as fs11 from "fs";
import * as path17 from "path";
import { parse as parse4 } from "yaml";
var REQUIRED_SECTIONS = [
  "## When to Use",
  "## Process",
  "## Harness Integration",
  "## Success Criteria",
  "## Examples"
];
function createValidateCommand3() {
  return new Command20("validate").description("Validate all skill.yaml files and SKILL.md structure").action(async (_opts, cmd) => {
    const globalOpts = cmd.optsWithGlobals();
    const skillsDir = resolveSkillsDir();
    if (!fs11.existsSync(skillsDir)) {
      logger.info("No skills directory found.");
      process.exit(ExitCode.SUCCESS);
      return;
    }
    const entries = fs11.readdirSync(skillsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
    const errors = [];
    let validated = 0;
    for (const name of entries) {
      const skillDir = path17.join(skillsDir, name);
      const yamlPath = path17.join(skillDir, "skill.yaml");
      const skillMdPath = path17.join(skillDir, "SKILL.md");
      if (!fs11.existsSync(yamlPath)) {
        errors.push(`${name}: missing skill.yaml`);
        continue;
      }
      try {
        const raw = fs11.readFileSync(yamlPath, "utf-8");
        const parsed = parse4(raw);
        const result = SkillMetadataSchema.safeParse(parsed);
        if (!result.success) {
          errors.push(`${name}/skill.yaml: ${result.error.message}`);
          continue;
        }
        if (fs11.existsSync(skillMdPath)) {
          const mdContent = fs11.readFileSync(skillMdPath, "utf-8");
          for (const section of REQUIRED_SECTIONS) {
            if (!mdContent.includes(section)) {
              errors.push(`${name}/SKILL.md: missing section "${section}"`);
            }
          }
          if (!mdContent.trim().startsWith("# ")) {
            errors.push(`${name}/SKILL.md: must start with an h1 heading`);
          }
          if (result.data.type === "rigid") {
            if (!mdContent.includes("## Gates")) {
              errors.push(`${name}/SKILL.md: rigid skill missing "## Gates" section`);
            }
            if (!mdContent.includes("## Escalation")) {
              errors.push(`${name}/SKILL.md: rigid skill missing "## Escalation" section`);
            }
          }
        } else {
          errors.push(`${name}: missing SKILL.md`);
        }
        validated++;
      } catch (e) {
        errors.push(`${name}: parse error \u2014 ${e instanceof Error ? e.message : String(e)}`);
      }
    }
    if (globalOpts.json) {
      logger.raw({ validated, errors });
    } else if (errors.length > 0) {
      logger.error(`Validation failed with ${errors.length} error(s):`);
      for (const err of errors) console.error(`  - ${err}`);
      process.exit(ExitCode.ERROR);
    } else {
      if (!globalOpts.quiet) {
        logger.success(`All ${validated} skill(s) validated successfully.`);
      }
    }
    process.exit(ExitCode.SUCCESS);
  });
}

// src/commands/skill/info.ts
import { Command as Command21 } from "commander";
import * as fs12 from "fs";
import * as path18 from "path";
import { parse as parse5 } from "yaml";
function createInfoCommand() {
  return new Command21("info").description("Show metadata for a skill").argument("<name>", "Skill name (e.g., harness-tdd)").action(async (name, _opts, cmd) => {
    const globalOpts = cmd.optsWithGlobals();
    const skillsDir = resolveSkillsDir();
    const skillDir = path18.join(skillsDir, name);
    if (!fs12.existsSync(skillDir)) {
      logger.error(`Skill not found: ${name}`);
      process.exit(ExitCode.ERROR);
      return;
    }
    const yamlPath = path18.join(skillDir, "skill.yaml");
    if (!fs12.existsSync(yamlPath)) {
      logger.error(`skill.yaml not found for skill: ${name}`);
      process.exit(ExitCode.ERROR);
      return;
    }
    try {
      const raw = fs12.readFileSync(yamlPath, "utf-8");
      const parsed = parse5(raw);
      const result = SkillMetadataSchema.safeParse(parsed);
      if (!result.success) {
        logger.error(`Invalid skill.yaml: ${result.error.message}`);
        process.exit(ExitCode.ERROR);
        return;
      }
      const skill = result.data;
      if (globalOpts.json) {
        logger.raw(skill);
      } else {
        console.log(`Name:        ${skill.name}`);
        console.log(`Version:     ${skill.version}`);
        console.log(`Type:        ${skill.type}`);
        console.log(`Description: ${skill.description}`);
        console.log(`Triggers:    ${skill.triggers.join(", ")}`);
        console.log(`Platforms:   ${skill.platforms.join(", ")}`);
        console.log(`Tools:       ${skill.tools.join(", ")}`);
        if (skill.phases && skill.phases.length > 0) {
          console.log(`Phases:`);
          for (const p of skill.phases) {
            console.log(`  - ${p.name}: ${p.description}`);
          }
        }
        if (skill.depends_on.length > 0) {
          console.log(`Depends on:  ${skill.depends_on.join(", ")}`);
        }
        console.log(`Persistent:  ${skill.state.persistent}`);
      }
    } catch (e) {
      logger.error(`Failed to read skill: ${e instanceof Error ? e.message : String(e)}`);
      process.exit(ExitCode.ERROR);
      return;
    }
    process.exit(ExitCode.SUCCESS);
  });
}

// src/commands/skill/index.ts
function createSkillCommand() {
  const command = new Command22("skill").description("Skill management commands");
  command.addCommand(createListCommand2());
  command.addCommand(createRunCommand2());
  command.addCommand(createValidateCommand3());
  command.addCommand(createInfoCommand());
  return command;
}

// src/commands/state/index.ts
import { Command as Command26 } from "commander";

// src/commands/state/show.ts
import { Command as Command23 } from "commander";
import * as path19 from "path";
import { loadState } from "@harness-engineering/core";
function createShowCommand() {
  return new Command23("show").description("Show current project state").option("--path <path>", "Project root path", ".").action(async (opts, cmd) => {
    const globalOpts = cmd.optsWithGlobals();
    const projectPath = path19.resolve(opts.path);
    const result = await loadState(projectPath);
    if (!result.ok) {
      logger.error(result.error.message);
      process.exit(ExitCode.ERROR);
      return;
    }
    const state = result.value;
    if (globalOpts.json) {
      logger.raw(state);
    } else if (globalOpts.quiet) {
      console.log(JSON.stringify(state));
    } else {
      console.log(`Schema Version: ${state.schemaVersion}`);
      if (state.position.phase) console.log(`Phase:          ${state.position.phase}`);
      if (state.position.task) console.log(`Task:           ${state.position.task}`);
      if (state.lastSession) {
        console.log(`Last Session:   ${state.lastSession.date} \u2014 ${state.lastSession.summary}`);
      }
      if (Object.keys(state.progress).length > 0) {
        console.log("\nProgress:");
        for (const [task, status] of Object.entries(state.progress)) {
          console.log(`  ${task}: ${status}`);
        }
      }
      if (state.decisions.length > 0) {
        console.log(`
Decisions: ${state.decisions.length}`);
      }
      if (state.blockers.length > 0) {
        const open = state.blockers.filter((b) => b.status === "open").length;
        console.log(`Blockers:   ${open} open / ${state.blockers.length} total`);
      }
    }
    process.exit(ExitCode.SUCCESS);
  });
}

// src/commands/state/reset.ts
import { Command as Command24 } from "commander";
import * as fs13 from "fs";
import * as path20 from "path";
import * as readline from "readline";
function createResetCommand() {
  return new Command24("reset").description("Reset project state (deletes .harness/state.json)").option("--path <path>", "Project root path", ".").option("--yes", "Skip confirmation prompt").action(async (opts, _cmd) => {
    const projectPath = path20.resolve(opts.path);
    const statePath = path20.join(projectPath, ".harness", "state.json");
    if (!fs13.existsSync(statePath)) {
      logger.info("No state file found. Nothing to reset.");
      process.exit(ExitCode.SUCCESS);
      return;
    }
    if (!opts.yes) {
      const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
      const answer = await new Promise((resolve13) => {
        rl.question("Reset project state? This cannot be undone. [y/N] ", resolve13);
      });
      rl.close();
      if (answer.toLowerCase() !== "y" && answer.toLowerCase() !== "yes") {
        logger.info("Reset cancelled.");
        process.exit(ExitCode.SUCCESS);
        return;
      }
    }
    try {
      fs13.unlinkSync(statePath);
      logger.success("Project state reset.");
    } catch (e) {
      logger.error(`Failed to reset state: ${e instanceof Error ? e.message : String(e)}`);
      process.exit(ExitCode.ERROR);
      return;
    }
    process.exit(ExitCode.SUCCESS);
  });
}

// src/commands/state/learn.ts
import { Command as Command25 } from "commander";
import * as path21 from "path";
import { appendLearning } from "@harness-engineering/core";
function createLearnCommand() {
  return new Command25("learn").description("Append a learning to .harness/learnings.md").argument("<message>", "The learning to record").option("--path <path>", "Project root path", ".").action(async (message, opts, _cmd) => {
    const projectPath = path21.resolve(opts.path);
    const result = await appendLearning(projectPath, message);
    if (!result.ok) {
      logger.error(result.error.message);
      process.exit(ExitCode.ERROR);
      return;
    }
    logger.success(`Learning recorded.`);
    process.exit(ExitCode.SUCCESS);
  });
}

// src/commands/state/index.ts
function createStateCommand() {
  const command = new Command26("state").description("Project state management commands");
  command.addCommand(createShowCommand());
  command.addCommand(createResetCommand());
  command.addCommand(createLearnCommand());
  return command;
}

// src/commands/check-phase-gate.ts
import { Command as Command27 } from "commander";
import * as path22 from "path";
import * as fs14 from "fs";
import { Ok as Ok16 } from "@harness-engineering/core";
function resolveSpecPath(implFile, implPattern, specPattern, cwd) {
  const relImpl = path22.relative(cwd, implFile);
  const implBase = (implPattern.split("*")[0] ?? "").replace(/\/+$/, "");
  const afterBase = relImpl.startsWith(implBase + "/") ? relImpl.slice(implBase.length + 1) : relImpl;
  const segments = afterBase.split("/");
  const firstSegment = segments[0] ?? "";
  const feature = segments.length > 1 ? firstSegment : path22.basename(firstSegment, path22.extname(firstSegment));
  const specRelative = specPattern.replace("{feature}", feature);
  return path22.resolve(cwd, specRelative);
}
async function runCheckPhaseGate(options) {
  const configResult = resolveConfig(options.configPath);
  if (!configResult.ok) {
    return configResult;
  }
  const config = configResult.value;
  const cwd = options.cwd ?? (options.configPath ? path22.dirname(path22.resolve(options.configPath)) : process.cwd());
  if (!config.phaseGates?.enabled) {
    return Ok16({
      pass: true,
      skipped: true,
      missingSpecs: [],
      checkedFiles: 0
    });
  }
  const phaseGates = config.phaseGates;
  const missingSpecs = [];
  let checkedFiles = 0;
  for (const mapping of phaseGates.mappings) {
    const implFiles = await findFiles(mapping.implPattern, cwd);
    for (const implFile of implFiles) {
      checkedFiles++;
      const expectedSpec = resolveSpecPath(implFile, mapping.implPattern, mapping.specPattern, cwd);
      if (!fs14.existsSync(expectedSpec)) {
        missingSpecs.push({
          implFile: path22.relative(cwd, implFile),
          expectedSpec: path22.relative(cwd, expectedSpec)
        });
      }
    }
  }
  const pass = missingSpecs.length === 0;
  return Ok16({
    pass,
    skipped: false,
    severity: phaseGates.severity,
    missingSpecs,
    checkedFiles
  });
}
function createCheckPhaseGateCommand() {
  const command = new Command27("check-phase-gate").description("Verify that implementation files have matching spec documents").action(async (_opts, cmd) => {
    const globalOpts = cmd.optsWithGlobals();
    const mode = globalOpts.json ? OutputMode.JSON : globalOpts.quiet ? OutputMode.QUIET : globalOpts.verbose ? OutputMode.VERBOSE : OutputMode.TEXT;
    const formatter = new OutputFormatter(mode);
    const result = await runCheckPhaseGate({
      configPath: globalOpts.config,
      json: globalOpts.json,
      verbose: globalOpts.verbose,
      quiet: globalOpts.quiet
    });
    if (!result.ok) {
      if (mode === OutputMode.JSON) {
        console.log(JSON.stringify({ error: result.error.message }));
      } else {
        logger.error(result.error.message);
      }
      process.exit(result.error.exitCode);
    }
    const value = result.value;
    if (value.skipped) {
      if (mode === OutputMode.JSON) {
        console.log(formatter.format(value));
      } else if (mode !== OutputMode.QUIET) {
        logger.dim("Phase gates not enabled, skipping.");
      }
      process.exit(ExitCode.SUCCESS);
    }
    const output = formatter.formatValidation({
      valid: value.pass,
      issues: value.missingSpecs.map((m) => ({
        file: m.implFile,
        message: `Missing spec: ${m.expectedSpec}`
      }))
    });
    if (output) {
      console.log(output);
    }
    const summary = formatter.formatSummary(
      "Phase gate check",
      `${value.checkedFiles} files checked, ${value.missingSpecs.length} missing specs`,
      value.pass
    );
    if (summary) {
      console.log(summary);
    }
    if (!value.pass && value.severity === "error") {
      process.exit(ExitCode.VALIDATION_FAILED);
    }
    process.exit(ExitCode.SUCCESS);
  });
  return command;
}

// src/index.ts
function createProgram() {
  const program = new Command28();
  program.name("harness").description("CLI for Harness Engineering toolkit").version(VERSION).option("-c, --config <path>", "Path to config file").option("--json", "Output as JSON").option("--verbose", "Verbose output").option("--quiet", "Minimal output");
  program.addCommand(createValidateCommand());
  program.addCommand(createCheckDepsCommand());
  program.addCommand(createCheckDocsCommand());
  program.addCommand(createInitCommand());
  program.addCommand(createCleanupCommand());
  program.addCommand(createFixDriftCommand());
  program.addCommand(createAgentCommand());
  program.addCommand(createAddCommand());
  program.addCommand(createLinterCommand());
  program.addCommand(createPersonaCommand());
  program.addCommand(createSkillCommand());
  program.addCommand(createStateCommand());
  program.addCommand(createCheckPhaseGateCommand());
  program.addCommand(createCreateSkillCommand());
  program.addCommand(createSetupMcpCommand());
  return program;
}

export {
  findConfigFile,
  loadConfig,
  resolveConfig,
  OutputMode,
  OutputFormatter,
  TemplateEngine,
  loadPersona,
  listPersonas,
  runPersona,
  generateRuntime,
  generateAgentsMd,
  generateCIWorkflow,
  buildPreamble,
  runCheckPhaseGate,
  createProgram
};
