// src/sequential.ts
function pairedEvalueSequence(deltas, opts = {}) {
  const c = opts.bound ?? 1;
  const alpha = opts.alpha ?? 0.05;
  const initialShrink = opts.initialBetShrinkage ?? 0.5;
  const rope = opts.rope ?? null;
  if (c <= 0) throw new Error("pairedEvalueSequence: bound must be > 0");
  if (alpha <= 0 || alpha >= 1) throw new Error("pairedEvalueSequence: alpha must be in (0,1)");
  if (rope && !(Number.isFinite(rope.low) && Number.isFinite(rope.high) && rope.low <= rope.high)) {
    throw new Error("pairedEvalueSequence: rope must satisfy low \u2264 high");
  }
  const steps = [];
  let clipped = false;
  let evalue = 1;
  let decisionFiredAt = null;
  let sum = 0;
  let sumSq = 0;
  let count = 0;
  for (let i = 0; i < deltas.length; i++) {
    let d = deltas[i];
    if (d < -c || d > c) {
      d = Math.max(-c, Math.min(c, d));
      clipped = true;
    }
    const muHat = count === 0 ? 0 : sum / count;
    const varHat = count === 0 ? c * c : Math.max(1e-12, sumSq / count - muHat * muHat);
    const t = i + 1;
    const shrink = initialShrink * Math.min(1, count / 32);
    let lambda = muHat / (varHat + c * c) * shrink;
    const lambdaMax = 0.99 / c;
    if (lambda > lambdaMax) lambda = lambdaMax;
    if (lambda < -lambdaMax) lambda = -lambdaMax;
    evalue = evalue * (1 + lambda * d);
    if (!Number.isFinite(evalue) || evalue < 0) evalue = 0;
    sum += d;
    sumSq += d * d;
    count += 1;
    const pValue = Math.min(1, 1 / Math.max(evalue, 1e-300));
    const cs = empiricalBernsteinCs(sum, sumSq, count, c, alpha);
    let decision = "continue";
    if (rope && cs.low >= rope.low && cs.high <= rope.high) decision = "equivalent";
    else if (evalue >= 2 / alpha && muHat > 0) decision = "promote_now";
    else if (evalue >= 2 / alpha && muHat < 0) decision = "reject_now";
    else if (rope && cs.high < rope.low) decision = "reject_now";
    if (decision !== "continue" && decisionFiredAt === null) decisionFiredAt = t;
    steps.push({ t, delta: d, evalue, pValue, csLow: cs.low, csHigh: cs.high, decision });
  }
  const finalDecision = steps.length === 0 ? "continue" : steps[steps.length - 1].decision;
  return { steps, finalDecision, decisionFiredAt, clipped };
}
function evaluateInterimReleaseConfidence(input) {
  const candidates = input.deltaSeries.map((s) => {
    const seq = pairedEvalueSequence(s.deltas, {
      alpha: input.alpha,
      bound: input.bound,
      rope: input.rope
    });
    const last = seq.steps[seq.steps.length - 1];
    return {
      candidateId: s.candidateId,
      decision: seq.finalDecision,
      decisionFiredAt: seq.decisionFiredAt,
      finalEvalue: last?.evalue ?? 1,
      finalPValue: last?.pValue ?? 1,
      pairs: seq.steps.length,
      csLow: last?.csLow ?? Number.NEGATIVE_INFINITY,
      csHigh: last?.csHigh ?? Number.POSITIVE_INFINITY
    };
  });
  const promote = candidates.find((c) => c.decision === "promote_now");
  if (promote)
    return {
      candidates,
      recommendation: { decision: "promote_now", candidateId: promote.candidateId }
    };
  const live = candidates.find((c) => c.decision === "continue");
  if (live) return { candidates, recommendation: { decision: "continue", candidateId: null } };
  const equiv = candidates.find((c) => c.decision === "equivalent");
  if (equiv)
    return {
      candidates,
      recommendation: { decision: "equivalent", candidateId: equiv.candidateId }
    };
  return { candidates, recommendation: { decision: "reject_now", candidateId: null } };
}
function empiricalBernsteinCs(sum, sumSq, n, bound, alpha) {
  if (n === 0) return { low: -bound, high: bound };
  const mean = sum / n;
  const variance = Math.max(0, sumSq / n - mean * mean);
  const psi = Math.log(2 / alpha) + 1.7 * Math.log(Math.log(Math.max(Math.E, n)) + 1);
  const radius = Math.sqrt(2 * variance * psi / n) + 3 * bound * psi / n;
  return { low: mean - radius, high: mean + radius };
}

export {
  pairedEvalueSequence,
  evaluateInterimReleaseConfidence
};
//# sourceMappingURL=chunk-MAZ26DC7.js.map