import {
  __esm
} from "./chunk-KFQGP6VL.js";

// ../core/dist/chunk-IIEDD47I.mjs
import { z } from "zod";
var ArchMetricCategorySchema, ViolationSchema, MetricResultSchema, CategoryBaselineSchema, ArchBaselineSchema, CategoryRegressionSchema, ArchDiffResultSchema, ThresholdConfigSchema, ArchConfigSchema, ConstraintRuleSchema, ViolationSnapshotSchema, ViolationHistorySchema, EmergenceConfidenceSchema, EmergentConstraintSuggestionSchema, EmergenceResultSchema;
var init_chunk_IIEDD47I = __esm({
  "../core/dist/chunk-IIEDD47I.mjs"() {
    "use strict";
    ArchMetricCategorySchema = z.enum([
      "circular-deps",
      "layer-violations",
      "complexity",
      "coupling",
      "forbidden-imports",
      "module-size",
      "dependency-depth"
    ]);
    ViolationSchema = z.object({
      id: z.string(),
      // stable hash: sha256(relativePath + ':' + category + ':' + normalizedDetail)
      file: z.string(),
      // relative to project root
      category: ArchMetricCategorySchema.optional(),
      // context for baseline reporting
      detail: z.string(),
      // human-readable description
      severity: z.enum(["error", "warning"])
    });
    MetricResultSchema = z.object({
      category: ArchMetricCategorySchema,
      scope: z.string(),
      // e.g., 'project', 'src/services', 'src/api/routes.ts'
      value: z.number(),
      // numeric metric (violation count, complexity score, etc.)
      violations: z.array(ViolationSchema),
      metadata: z.record(z.unknown()).optional()
    });
    CategoryBaselineSchema = z.object({
      value: z.number(),
      // aggregate metric value at baseline time
      violationIds: z.array(z.string())
      // stable IDs of known violations (the allowlist)
    });
    ArchBaselineSchema = z.object({
      version: z.literal(1),
      updatedAt: z.string().datetime(),
      // ISO 8601
      updatedFrom: z.string(),
      // commit hash
      metrics: z.record(ArchMetricCategorySchema, CategoryBaselineSchema)
    });
    CategoryRegressionSchema = z.object({
      category: ArchMetricCategorySchema,
      baselineValue: z.number(),
      currentValue: z.number(),
      delta: z.number()
    });
    ArchDiffResultSchema = z.object({
      passed: z.boolean(),
      newViolations: z.array(ViolationSchema),
      // in current but not in baseline -> FAIL
      resolvedViolations: z.array(z.string()),
      // in baseline but not in current -> celebrate
      preExisting: z.array(z.string()),
      // in both -> allowed, tracked
      regressions: z.array(CategoryRegressionSchema)
      // aggregate value exceeded baseline
    });
    ThresholdConfigSchema = z.record(
      ArchMetricCategorySchema,
      z.union([z.number(), z.record(z.string(), z.number())])
    );
    ArchConfigSchema = z.object({
      enabled: z.boolean().default(true),
      baselinePath: z.string().default(".harness/arch/baselines.json"),
      thresholds: ThresholdConfigSchema.default({}),
      modules: z.record(z.string(), ThresholdConfigSchema).default({})
    });
    ConstraintRuleSchema = z.object({
      id: z.string(),
      // stable hash: sha256(category + ':' + scope + ':' + description)
      category: ArchMetricCategorySchema,
      description: z.string(),
      // e.g., "Layer 'services' must not import from 'ui'"
      scope: z.string(),
      // e.g., 'src/services/', 'project'
      targets: z.array(z.string()).optional()
      // forward-compat for governs edges
    });
    ViolationSnapshotSchema = z.object({
      timestamp: z.string().datetime(),
      violations: z.array(ViolationSchema)
    });
    ViolationHistorySchema = z.object({
      version: z.literal(1),
      snapshots: z.array(ViolationSnapshotSchema)
    });
    EmergenceConfidenceSchema = z.enum(["low", "medium", "high"]);
    EmergentConstraintSuggestionSchema = z.object({
      suggestedRule: ConstraintRuleSchema,
      confidence: EmergenceConfidenceSchema,
      occurrences: z.number(),
      uniqueFiles: z.number(),
      pattern: z.string(),
      sampleViolations: z.array(ViolationSchema),
      rationale: z.string()
    });
    EmergenceResultSchema = z.object({
      suggestions: z.array(EmergentConstraintSuggestionSchema),
      totalViolationsAnalyzed: z.number(),
      windowWeeks: z.number(),
      minOccurrences: z.number()
    });
  }
});

// ../core/dist/chunk-XKLVJIPL.mjs
import { readFileSync, writeFileSync, renameSync, mkdirSync, existsSync } from "fs";
import { randomBytes } from "crypto";
import { join, dirname } from "path";
import { z as z2 } from "zod";
var CategorySnapshotSchema, TimelineSnapshotSchema, TimelineFileSchema, TrendLineSchema, TrendResultSchema, DEFAULT_STABILITY_THRESHOLDS, ALL_CATEGORIES, TimelineManager;
var init_chunk_XKLVJIPL = __esm({
  "../core/dist/chunk-XKLVJIPL.mjs"() {
    "use strict";
    init_chunk_IIEDD47I();
    CategorySnapshotSchema = z2.object({
      /** Aggregate metric value (e.g., violation count, avg complexity) */
      value: z2.number(),
      /** Count of violations in this category */
      violationCount: z2.number()
    });
    TimelineSnapshotSchema = z2.object({
      /** ISO 8601 timestamp of capture */
      capturedAt: z2.string().datetime(),
      /** Git commit hash at capture time */
      commitHash: z2.string(),
      /** Composite stability score (0-100, higher is healthier) */
      stabilityScore: z2.number().min(0).max(100),
      /** Per-category metric aggregates */
      metrics: z2.record(ArchMetricCategorySchema, CategorySnapshotSchema)
    });
    TimelineFileSchema = z2.object({
      version: z2.literal(1),
      snapshots: z2.array(TimelineSnapshotSchema)
    });
    TrendLineSchema = z2.object({
      /** Current value */
      current: z2.number(),
      /** Previous value (from comparison snapshot) */
      previous: z2.number(),
      /** Absolute delta (current - previous) */
      delta: z2.number(),
      /** Direction indicator */
      direction: z2.enum(["improving", "stable", "declining"])
    });
    TrendResultSchema = z2.object({
      /** Overall stability trend */
      stability: TrendLineSchema,
      /** Per-category trends */
      categories: z2.record(ArchMetricCategorySchema, TrendLineSchema),
      /** Number of snapshots analyzed */
      snapshotCount: z2.number(),
      /** Time range covered */
      from: z2.string(),
      to: z2.string()
    });
    DEFAULT_STABILITY_THRESHOLDS = {
      "circular-deps": 5,
      "layer-violations": 10,
      complexity: 100,
      coupling: 2,
      "forbidden-imports": 5,
      "module-size": 10,
      "dependency-depth": 10
    };
    ALL_CATEGORIES = ArchMetricCategorySchema.options;
    TimelineManager = class {
      timelinePath;
      constructor(rootDir) {
        this.timelinePath = join(rootDir, ".harness", "arch", "timeline.json");
      }
      /**
       * Load timeline from disk.
       * Returns empty TimelineFile if file does not exist or is invalid.
       */
      load() {
        if (!existsSync(this.timelinePath)) {
          return { version: 1, snapshots: [] };
        }
        try {
          const raw = readFileSync(this.timelinePath, "utf-8");
          const data = JSON.parse(raw);
          const parsed = TimelineFileSchema.safeParse(data);
          if (!parsed.success) {
            console.error(
              `Timeline validation failed for ${this.timelinePath}:`,
              parsed.error.format()
            );
            return { version: 1, snapshots: [] };
          }
          return parsed.data;
        } catch (error) {
          console.error(`Error loading timeline from ${this.timelinePath}:`, error);
          return { version: 1, snapshots: [] };
        }
      }
      /**
       * Save timeline to disk using atomic write (temp file + rename).
       * Creates parent directories if they do not exist.
       */
      save(timeline) {
        const dir = dirname(this.timelinePath);
        if (!existsSync(dir)) {
          mkdirSync(dir, { recursive: true });
        }
        const tmp = this.timelinePath + "." + randomBytes(4).toString("hex") + ".tmp";
        writeFileSync(tmp, JSON.stringify(timeline, null, 2));
        renameSync(tmp, this.timelinePath);
      }
      /**
       * Capture a new snapshot from current metric results.
       * Aggregates MetricResult[] by category, computes stability score,
       * appends to timeline (or replaces if same commitHash), and saves.
       */
      capture(results, commitHash) {
        const metrics = this.aggregateByCategory(results);
        const stabilityScore = this.computeStabilityScore(metrics);
        const snapshot = {
          capturedAt: (/* @__PURE__ */ new Date()).toISOString(),
          commitHash,
          stabilityScore,
          metrics
        };
        const timeline = this.load();
        const lastIndex = timeline.snapshots.length - 1;
        if (lastIndex >= 0 && timeline.snapshots[lastIndex].commitHash === commitHash) {
          timeline.snapshots[lastIndex] = snapshot;
        } else {
          timeline.snapshots.push(snapshot);
        }
        this.save(timeline);
        return snapshot;
      }
      /**
       * Compute trends between snapshots over a window.
       * @param options.last - Number of recent snapshots to analyze (default: 10)
       * @param options.since - ISO date string to filter snapshots from
       */
      trends(options) {
        const timeline = this.load();
        let snapshots = timeline.snapshots;
        if (options?.since) {
          const sinceDate = new Date(options.since);
          snapshots = snapshots.filter((s) => new Date(s.capturedAt) >= sinceDate);
        }
        if (options?.last && snapshots.length > options.last) {
          snapshots = snapshots.slice(-options.last);
        }
        if (snapshots.length === 0) {
          return this.emptyTrendResult();
        }
        if (snapshots.length === 1) {
          const only = snapshots[0];
          const m = only.metrics;
          return {
            stability: this.buildTrendLine(only.stabilityScore, only.stabilityScore, true),
            categories: this.buildCategoryTrends(m, m),
            snapshotCount: 1,
            from: only.capturedAt,
            to: only.capturedAt
          };
        }
        const first = snapshots[0];
        const last = snapshots[snapshots.length - 1];
        return {
          stability: this.buildTrendLine(last.stabilityScore, first.stabilityScore, true),
          categories: this.buildCategoryTrends(
            last.metrics,
            first.metrics
          ),
          snapshotCount: snapshots.length,
          from: first.capturedAt,
          to: last.capturedAt
        };
      }
      /**
       * Compute composite stability score from category metrics.
       * Equal weight across all categories. Score is 0-100 (higher = healthier).
       * health = max(0, 1 - (value / threshold)) per category.
       */
      computeStabilityScore(metrics, thresholds = DEFAULT_STABILITY_THRESHOLDS) {
        const healthScores = [];
        for (const category of ALL_CATEGORIES) {
          const snapshot = metrics[category];
          if (!snapshot) {
            healthScores.push(1);
            continue;
          }
          const threshold = thresholds[category] ?? 10;
          const health = Math.max(0, 1 - snapshot.value / threshold);
          healthScores.push(health);
        }
        const mean = healthScores.reduce((sum, h) => sum + h, 0) / healthScores.length;
        return Math.round(mean * 100);
      }
      // --- Private helpers ---
      aggregateByCategory(results) {
        const metrics = {};
        for (const result of results) {
          const existing = metrics[result.category];
          if (existing) {
            existing.value += result.value;
            existing.violationCount += result.violations.length;
          } else {
            metrics[result.category] = {
              value: result.value,
              violationCount: result.violations.length
            };
          }
        }
        for (const category of ALL_CATEGORIES) {
          if (!metrics[category]) {
            metrics[category] = { value: 0, violationCount: 0 };
          }
        }
        return metrics;
      }
      buildTrendLine(current, previous, isStabilityScore) {
        const delta = current - previous;
        let direction;
        if (Math.abs(delta) < 2) {
          direction = "stable";
        } else if (isStabilityScore) {
          direction = delta > 0 ? "improving" : "declining";
        } else {
          direction = delta < 0 ? "improving" : "declining";
        }
        return { current, previous, delta, direction };
      }
      buildCategoryTrends(currentMetrics, previousMetrics) {
        const trends = {};
        for (const category of ALL_CATEGORIES) {
          const current = currentMetrics[category]?.value ?? 0;
          const previous = previousMetrics[category]?.value ?? 0;
          trends[category] = this.buildTrendLine(current, previous, false);
        }
        return trends;
      }
      emptyTrendResult() {
        const zeroLine = { current: 0, previous: 0, delta: 0, direction: "stable" };
        const categories = {};
        for (const category of ALL_CATEGORIES) {
          categories[category] = { ...zeroLine };
        }
        return {
          stability: { ...zeroLine },
          categories,
          snapshotCount: 0,
          from: "",
          to: ""
        };
      }
    };
  }
});

export {
  ArchMetricCategorySchema,
  ViolationSchema,
  MetricResultSchema,
  CategoryBaselineSchema,
  ArchBaselineSchema,
  CategoryRegressionSchema,
  ArchDiffResultSchema,
  ThresholdConfigSchema,
  ArchConfigSchema,
  ConstraintRuleSchema,
  ViolationSnapshotSchema,
  ViolationHistorySchema,
  EmergenceConfidenceSchema,
  EmergentConstraintSuggestionSchema,
  EmergenceResultSchema,
  init_chunk_IIEDD47I,
  CategorySnapshotSchema,
  TimelineSnapshotSchema,
  TimelineFileSchema,
  TrendLineSchema,
  TrendResultSchema,
  DEFAULT_STABILITY_THRESHOLDS,
  TimelineManager,
  init_chunk_XKLVJIPL
};
