// src/rl/active-curriculum.ts
function varianceBasedCurriculum(observations, candidateCells, opts) {
  const variancePrior = opts.variancePrior ?? 0.05;
  const floor = opts.floorPerCell ?? 1;
  const budget = opts.budget;
  const grouped = /* @__PURE__ */ new Map();
  for (const o of observations) {
    const k = `${o.variantId}::${o.scenarioId}`;
    const arr = grouped.get(k) ?? [];
    arr.push(o.score);
    grouped.set(k, arr);
  }
  const cellStats = candidateCells.map((c) => {
    const k = `${c.variantId}::${c.scenarioId}`;
    const samples = grouped.get(k) ?? [];
    const n = samples.length;
    const mean = n === 0 ? 0.5 : samples.reduce((s, v) => s + v, 0) / n;
    const variance = n < 2 ? variancePrior : samples.reduce((s, v) => s + (v - mean) ** 2, 0) / (n - 1) + variancePrior;
    const weight = Math.sqrt(variance) + 1 / Math.sqrt(Math.max(1, n));
    return { variantId: c.variantId, scenarioId: c.scenarioId, n, mean, variance, weight };
  });
  const floorTotal = floor * cellStats.length;
  if (floorTotal >= budget) {
    const each = Math.max(1, Math.floor(budget / Math.max(1, cellStats.length)));
    return cellStats.map((c) => ({
      variantId: c.variantId,
      scenarioId: c.scenarioId,
      count: each,
      reason: `floor allocation (budget tight; n=${c.n})`
    }));
  }
  const remaining = budget - floorTotal;
  const totalWeight = cellStats.reduce((s, c) => s + c.weight, 0);
  return cellStats.map((c) => {
    const proportional = totalWeight === 0 ? 0 : Math.round(c.weight / totalWeight * remaining);
    return {
      variantId: c.variantId,
      scenarioId: c.scenarioId,
      count: floor + proportional,
      reason: `variance ${c.variance.toFixed(3)} (n=${c.n}, mean=${c.mean.toFixed(3)})`
    };
  });
}
function thompsonCurriculum(observations, candidateCells, opts) {
  const threshold = opts.decisionThreshold ?? 0.5;
  const alpha0 = opts.priorAlpha ?? 1;
  const beta0 = opts.priorBeta ?? 1;
  const rng = makeRng(opts.seed);
  const grouped = /* @__PURE__ */ new Map();
  for (const o of observations) {
    const k = `${o.variantId}::${o.scenarioId}`;
    const cur = grouped.get(k) ?? { passes: 0, failures: 0 };
    const pass = o.pass ?? o.score >= threshold;
    if (pass) cur.passes += 1;
    else cur.failures += 1;
    grouped.set(k, cur);
  }
  const stats = candidateCells.map((c) => {
    const k = `${c.variantId}::${c.scenarioId}`;
    const cur = grouped.get(k) ?? { passes: 0, failures: 0 };
    const a = alpha0 + cur.passes;
    const b = beta0 + cur.failures;
    const sampled = sampleBeta(a, b, rng);
    const distance = Math.abs(sampled - threshold);
    const variance = a * b / ((a + b) ** 2 * (a + b + 1));
    const sigma = Math.max(0.05, Math.sqrt(variance));
    const weight = Math.exp(-((distance / sigma) ** 2));
    return {
      variantId: c.variantId,
      scenarioId: c.scenarioId,
      n: cur.passes + cur.failures,
      sampled,
      sigma,
      weight,
      a,
      b
    };
  });
  const totalWeight = stats.reduce((s, c) => s + c.weight, 0);
  return stats.map((c) => {
    const proportional = totalWeight === 0 ? 0 : Math.round(c.weight / totalWeight * opts.budget);
    return {
      variantId: c.variantId,
      scenarioId: c.scenarioId,
      count: Math.max(0, proportional),
      reason: `Beta(${c.a.toFixed(1)},${c.b.toFixed(1)}) sample=${c.sampled.toFixed(3)} (target ${threshold})`
    };
  });
}
function observationsFromRunRecords(runs, opts = {}) {
  const threshold = opts.passThreshold ?? 0.5;
  const useHoldout = opts.useHoldout ?? true;
  const out = [];
  for (const r of runs) {
    if (!r.scenarioId) continue;
    const score = useHoldout ? r.outcome.holdoutScore ?? r.outcome.searchScore : r.outcome.searchScore ?? r.outcome.holdoutScore;
    if (typeof score !== "number" || !Number.isFinite(score)) continue;
    out.push({
      variantId: r.candidateId,
      scenarioId: r.scenarioId,
      score,
      pass: score >= threshold
    });
  }
  return out;
}
function makeRng(seed) {
  if (seed === void 0) return Math.random;
  let s = seed >>> 0;
  return () => {
    s = s + 1831565813 >>> 0;
    let t = s;
    t = Math.imul(t ^ t >>> 15, t | 1);
    t ^= t + Math.imul(t ^ t >>> 7, t | 61);
    return ((t ^ t >>> 14) >>> 0) / 4294967296;
  };
}
function sampleBeta(alpha, beta, rng) {
  const a = Math.max(1, alpha);
  const b = Math.max(1, beta);
  const x = sampleGamma(a, rng);
  const y = sampleGamma(b, rng);
  return x / (x + y);
}
function sampleGamma(shape, rng) {
  const d = shape - 1 / 3;
  const c = 1 / Math.sqrt(9 * d);
  while (true) {
    let x;
    let v;
    do {
      const u1 = rng() || 1e-12;
      const u2 = rng() || 1e-12;
      x = Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2);
      v = 1 + c * x;
    } while (v <= 0);
    v = v * v * v;
    const u = rng();
    if (u < 1 - 0.0331 * x ** 4) return d * v;
    if (Math.log(u) < 0.5 * x * x + d * (1 - v + Math.log(v))) return d * v;
  }
}

export {
  varianceBasedCurriculum,
  thompsonCurriculum,
  observationsFromRunRecords
};
//# sourceMappingURL=chunk-VZSRQ272.js.map