import {
  runCanaries,
  scoreRedTeamOutput
} from "./chunk-7QTQKIDD.js";
import {
  runCampaign
} from "./chunk-2T4EZACH.js";
import {
  detectRewardHacking
} from "./chunk-5HRORJQY.js";
import {
  pairedBootstrap
} from "./chunk-56GC6VYO.js";

// src/campaign/gates/compose.ts
function composeGate(...gates) {
  if (gates.length === 0) {
    throw new Error("composeGate requires at least one gate");
  }
  return {
    name: `composed(${gates.map((g) => g.name).join(",")})`,
    async decide(ctx) {
      const results = [];
      for (const gate of gates) {
        const res = await gate.decide(ctx);
        results.push({ gate, res });
      }
      const decisions = results.map((r) => r.res.decision);
      const overall = decisions.every((d) => d === "ship") ? "ship" : decisions.includes("arch_ceiling") ? "arch_ceiling" : decisions.includes("model_ceiling") ? "model_ceiling" : decisions.includes("hold") ? "hold" : "need_more_work";
      const contributing = results.flatMap(
        (r) => r.res.contributingGates.length > 0 ? r.res.contributingGates : [{ name: r.gate.name, passed: r.res.decision === "ship", detail: r.res }]
      );
      const reasons = results.flatMap(
        (r) => r.res.reasons.map((reason) => `[${r.gate.name}] ${reason}`)
      );
      return {
        decision: overall,
        reasons,
        contributingGates: contributing,
        delta: results[0]?.res.delta
      };
    }
  };
}

// src/campaign/gates/statistical-heldout.ts
function pairHoldout(candidate, baseline, scenarioIds, select) {
  const cellValue = (byCell, cellId) => {
    const scores = byCell.get(cellId);
    if (!scores) return void 0;
    const vals = [];
    for (const s of Object.values(scores)) {
      const v = select(s);
      if (typeof v === "number" && Number.isFinite(v)) vals.push(v);
    }
    if (vals.length === 0) return void 0;
    return vals.reduce((a, b) => a + b, 0) / vals.length;
  };
  const inScope = (cellId) => scenarioIds.has(cellId.split(":")[0] ?? "");
  const candCells = [...candidate.keys()].filter(inScope).sort();
  const baseCells = [...baseline.keys()].filter(inScope).sort();
  if (candCells.length !== baseCells.length || candCells.some((c, i) => c !== baseCells[i])) {
    throw new Error(
      `pairHoldout: candidate/baseline holdout cells do not align \u2014 candidate=[${candCells.join(",")}] baseline=[${baseCells.join(",")}]. Both holdout campaigns must run the same scenarios with the same seed base.`
    );
  }
  const before = [];
  const after = [];
  const cellIds = [];
  for (const cellId of candCells) {
    const b = cellValue(baseline, cellId);
    const a = cellValue(candidate, cellId);
    if (b === void 0 || a === void 0) continue;
    before.push(b);
    after.push(a);
    cellIds.push(cellId);
  }
  return { before, after, cellIds };
}
function heldoutSignificance(paired, opts = {}) {
  const deltaThreshold = opts.deltaThreshold ?? 0;
  const minProductiveRuns = opts.minProductiveRuns ?? 3;
  const bootstrap = pairedBootstrap(paired.before, paired.after, {
    confidence: opts.confidence ?? 0.95,
    resamples: opts.resamples ?? 2e3,
    statistic: opts.statistic ?? "median",
    seed: opts.seed ?? 1337
  });
  const n = paired.before.length;
  const fewRuns = n < minProductiveRuns;
  const significant = !fewRuns && bootstrap.low > deltaThreshold;
  return { paired, bootstrap, n, significant, fewRuns };
}
function detectScale(values) {
  return values.some((v) => Math.abs(v) > 1.5) ? 100 : 1;
}
function dimensionRegressions(candidate, baseline, scenarioIds, criticalDimensions, opts = {}) {
  const out = [];
  for (const dim of criticalDimensions) {
    const paired = pairHoldout(candidate, baseline, scenarioIds, (s) => s.dimensions[dim]);
    if (paired.before.length === 0) continue;
    const tolerance = opts.tolerance ?? 0.05 * detectScale([...paired.before, ...paired.after]);
    const bootstrap = pairedBootstrap(paired.before, paired.after, {
      confidence: opts.confidence ?? 0.95,
      resamples: opts.resamples ?? 2e3,
      statistic: "median",
      seed: opts.seed ?? 1337
    });
    out.push({
      dimension: dim,
      bootstrap,
      regressed: bootstrap.low < -tolerance,
      tolerance,
      n: paired.before.length
    });
  }
  return out;
}

// src/campaign/gates/default-production-gate.ts
function defaultProductionGate(options) {
  const deltaThreshold = options.deltaThreshold ?? 0;
  const confidence = options.confidence ?? 0.95;
  const resamples = options.bootstrapResamples ?? 2e3;
  const seed = options.bootstrapSeed ?? 1337;
  const minProductiveRuns = options.minProductiveRuns ?? 3;
  const blockOnGaming = options.blockOnRewardHackingGaming ?? true;
  return {
    name: "defaultProductionGate",
    async decide(ctx) {
      const reasons = [];
      const contributing = [];
      const scenarioIds = new Set(options.holdoutScenarios.map((s) => s.id));
      const sig = heldoutSignificance(
        pairHoldout(
          ctx.judgeScores,
          ctx.baselineJudgeScores ?? ctx.judgeScores,
          scenarioIds,
          (s) => s.composite
        ),
        { deltaThreshold, minProductiveRuns, confidence, resamples, seed }
      );
      const delta = sig.bootstrap.median;
      const heldoutPass = sig.significant;
      contributing.push({
        name: "heldout-significance",
        passed: heldoutPass,
        detail: {
          n: sig.n,
          deltaMedian: sig.bootstrap.median,
          ciLow: sig.bootstrap.low,
          ciHigh: sig.bootstrap.high,
          confidence: sig.bootstrap.confidence,
          deltaThreshold,
          fewRuns: sig.fewRuns
        }
      });
      if (!heldoutPass) {
        reasons.push(
          sig.fewRuns ? `held-out: only ${sig.n} paired runs (< ${minProductiveRuns}) \u2014 too few to claim significance` : `held-out CI.low ${sig.bootstrap.low.toFixed(3)} \u2264 threshold ${deltaThreshold} (median ${sig.bootstrap.median.toFixed(3)}, ${(sig.bootstrap.confidence * 100).toFixed(0)}% CI [${sig.bootstrap.low.toFixed(3)}, ${sig.bootstrap.high.toFixed(3)}])`
        );
      }
      const dimRegs = options.criticalDimensions?.length ? dimensionRegressions(
        ctx.judgeScores,
        ctx.baselineJudgeScores ?? ctx.judgeScores,
        scenarioIds,
        options.criticalDimensions,
        { tolerance: options.regressionTolerance, confidence, resamples, seed }
      ) : [];
      const regressed = dimRegs.filter((d) => d.regressed);
      const dimPass = regressed.length === 0;
      contributing.push({
        name: "dimension-regression",
        passed: dimPass,
        detail: {
          guarded: options.criticalDimensions ?? [],
          regressions: dimRegs.map((d) => ({
            dimension: d.dimension,
            ciLow: d.bootstrap.low,
            median: d.bootstrap.median,
            tolerance: d.tolerance,
            n: d.n,
            regressed: d.regressed
          }))
        }
      });
      if (!dimPass) {
        reasons.push(
          `critical dimension(s) regressed: ${regressed.map((d) => `${d.dimension} CI.low ${d.bootstrap.low.toFixed(3)} < -${d.tolerance}`).join("; ")}`
        );
      }
      const budgetPass = options.budgetUsd === void 0 || ctx.cost.candidate + ctx.cost.baseline <= options.budgetUsd;
      contributing.push({
        name: "budget",
        passed: budgetPass,
        detail: {
          candidateUsd: ctx.cost.candidate,
          baselineUsd: ctx.cost.baseline,
          budgetUsd: options.budgetUsd
        }
      });
      if (!budgetPass) {
        reasons.push(
          `spend ${(ctx.cost.candidate + ctx.cost.baseline).toFixed(2)} > budget ${options.budgetUsd}`
        );
      }
      const redTeamFindings = options.redTeamBattery ? probeRedTeam(ctx.candidateArtifacts, options.redTeamBattery) : { passed: true, findings: [] };
      contributing.push({
        name: "red-team",
        passed: redTeamFindings.passed,
        detail: {
          failures: redTeamFindings.findings.length,
          sample: redTeamFindings.findings.slice(0, 3)
        }
      });
      if (!redTeamFindings.passed) {
        reasons.push(`red-team probe failed (${redTeamFindings.findings.length} findings)`);
      }
      let rewardHackingReport = null;
      if (options.recentRuns && options.recentRuns.length >= 10) {
        rewardHackingReport = detectRewardHacking({ runs: options.recentRuns });
      }
      const gamingThreshold = 0.6;
      const gamingFindings = (rewardHackingReport?.findings ?? []).filter(
        (f) => f.severity >= gamingThreshold
      );
      const rewardHackingPass = !rewardHackingReport || !blockOnGaming || gamingFindings.length === 0 && rewardHackingReport.verdict !== "gaming";
      contributing.push({
        name: "reward-hacking",
        passed: rewardHackingPass,
        detail: { report: rewardHackingReport, gamingFindingCount: gamingFindings.length }
      });
      if (!rewardHackingPass) {
        reasons.push(
          `reward-hacking detector flagged ${gamingFindings.length} gaming-severity findings (verdict=${rewardHackingReport.verdict})`
        );
      }
      let canaryReport = null;
      if (options.recentRuns && options.recentRuns.length >= 10) {
        canaryReport = runCanaries(options.recentRuns, {});
      }
      const errorAlerts = (canaryReport?.alerts ?? []).filter((a) => a.severity === "error");
      const canaryPass = errorAlerts.length === 0;
      contributing.push({
        name: "canary",
        passed: canaryPass,
        detail: { totalAlerts: canaryReport?.alerts.length ?? 0, errorAlerts: errorAlerts.length }
      });
      if (!canaryPass) {
        reasons.push(`canary error alerts: ${errorAlerts.length}`);
      }
      const allPassed = contributing.every((c) => c.passed);
      const decision = allPassed ? "ship" : "hold";
      return {
        decision,
        reasons: reasons.length > 0 ? reasons : ["all gates passed"],
        contributingGates: contributing,
        delta
      };
    }
  };
}
function probeRedTeam(artifacts, battery) {
  const findings = [];
  for (const [_cellId, artifact] of artifacts) {
    const text = extractText(artifact);
    if (text === void 0) continue;
    for (const rtCase of battery) {
      const finding = scoreRedTeamOutput(text, [], rtCase);
      if (!finding.passed) {
        findings.push({ scenarioId: rtCase.id, reason: finding.reason ?? "red-team probe failed" });
      }
    }
  }
  return { passed: findings.length === 0, findings };
}
function extractText(artifact) {
  if (typeof artifact === "string") return artifact;
  if (artifact && typeof artifact === "object") {
    const rec = artifact;
    if (typeof rec.text === "string") return rec.text;
    if (typeof rec.output === "string") return rec.output;
    if (typeof rec.content === "string") return rec.content;
  }
  return void 0;
}

// src/campaign/gates/promotion-policy.ts
function buildEvidenceVector(ctx, objectives, opts = {}) {
  if (objectives.length === 0) {
    throw new Error("buildEvidenceVector: at least 1 objective required");
  }
  const minProductiveRuns = opts.minProductiveRuns ?? 3;
  const confidence = opts.confidence ?? 0.95;
  const resamples = opts.resamples ?? 2e3;
  const seed = opts.seed ?? 1337;
  const baseline = ctx.baselineJudgeScores ?? ctx.judgeScores;
  const scenarioIds = new Set(ctx.scenarios.map((s) => s.id));
  const axes = [];
  for (const obj of objectives) {
    let select;
    if (obj.source.kind === "composite") {
      select = (s) => s.composite;
    } else {
      const dim = obj.source.dimension;
      select = (s) => s.dimensions[dim];
    }
    const paired = pairHoldout(ctx.judgeScores, baseline, scenarioIds, select);
    const before = obj.direction === "maximize" ? paired.before : paired.after;
    const after = obj.direction === "maximize" ? paired.after : paired.before;
    const bootstrap = pairedBootstrap(before, after, {
      confidence,
      resamples,
      statistic: "median",
      seed
    });
    const n = paired.before.length;
    const floorTolerance = obj.floorTolerance ?? 0.05 * detectScale([...paired.before, ...paired.after]);
    const gainThreshold = obj.gainThreshold ?? 0;
    const verdict = n < minProductiveRuns ? "few_runs" : bootstrap.low < -floorTolerance ? "regressed" : bootstrap.low > gainThreshold ? "improved" : "flat";
    axes.push({
      name: obj.name,
      source: obj.source,
      direction: obj.direction,
      bootstrap,
      n,
      gainThreshold,
      floorTolerance,
      verdict
    });
  }
  const ns = axes.map((a) => a.n).filter((n) => n > 0);
  const minN = ns.length > 0 ? Math.min(...ns) : 0;
  return { axes, minN, cost: { candidate: ctx.cost.candidate, baseline: ctx.cost.baseline } };
}
var paretoPolicy = (ev) => {
  const contributingGates = ev.axes.map((ax) => ({
    name: `objective:${ax.name}`,
    passed: ax.verdict === "improved",
    detail: {
      direction: ax.direction,
      source: ax.source,
      verdict: ax.verdict,
      n: ax.n,
      deltaMedian: ax.bootstrap.median,
      ciLow: ax.bootstrap.low,
      ciHigh: ax.bootstrap.high,
      confidence: ax.bootstrap.confidence,
      gainThreshold: ax.gainThreshold,
      floorTolerance: ax.floorTolerance
    }
  }));
  const regressed = ev.axes.filter((a) => a.verdict === "regressed");
  const fewRuns = ev.axes.filter((a) => a.verdict === "few_runs");
  const improved = ev.axes.filter((a) => a.verdict === "improved");
  let decision;
  const reasons = [];
  if (regressed.length > 0) {
    decision = "hold";
    for (const a of regressed) {
      reasons.push(
        `objective '${a.name}' regressed: good-direction CI.low ${a.bootstrap.low.toFixed(3)} < -${a.floorTolerance} (n=${a.n})`
      );
    }
  } else if (fewRuns.length > 0) {
    decision = "need_more_work";
    for (const a of fewRuns) {
      reasons.push(
        `objective '${a.name}' has only n=${a.n} paired runs \u2014 insufficient evidence to claim significance`
      );
    }
  } else if (improved.length > 0) {
    decision = "ship";
    reasons.push(
      `Pareto improvement at the confidence level: ${improved.map(
        (a) => `'${a.name}' +${a.bootstrap.median.toFixed(3)} (CI.low ${a.bootstrap.low.toFixed(3)})`
      ).join(", ")}; no objective regressed`
    );
  } else {
    decision = "hold";
    reasons.push(
      "no Pareto improvement: candidate statistically equivalent to baseline on every objective"
    );
  }
  const composite = ev.axes.find((a) => a.source.kind === "composite") ?? ev.axes[0];
  return { decision, reasons, contributingGates, delta: composite?.bootstrap.median };
};
function paretoSignificanceGate(options) {
  if (options.objectives.length === 0) {
    throw new Error("paretoSignificanceGate: at least 1 objective required");
  }
  const policy = options.policy ?? paretoPolicy;
  return {
    name: options.name ?? "paretoSignificanceGate",
    async decide(ctx) {
      const ev = buildEvidenceVector(ctx, options.objectives, options);
      return policy(ev);
    }
  };
}

// src/campaign/presets/run-eval.ts
async function runEval(opts) {
  return runCampaign(opts);
}

// src/campaign/proposers/evolutionary.ts
function evolutionaryProposer(opts) {
  return {
    kind: `evolutionary:${opts.mutator.kind}`,
    async propose({ currentSurface, findings, populationSize, signal }) {
      return opts.mutator.mutate({
        findings: findings.length > 0 ? findings : opts.findings ?? [],
        currentSurface,
        populationSize,
        signal
      });
    }
  };
}

export {
  composeGate,
  pairHoldout,
  heldoutSignificance,
  detectScale,
  dimensionRegressions,
  defaultProductionGate,
  buildEvidenceVector,
  paretoPolicy,
  paretoSignificanceGate,
  runEval,
  evolutionaryProposer
};
//# sourceMappingURL=chunk-KKWJD5E6.js.map