import {
  llmSpans
} from "./chunk-47X6LRCE.js";

// src/contamination-guard.ts
function checkCanaries(output, scenarios) {
  const leaks = [];
  for (const s of scenarios) {
    if (!s.canary) continue;
    if (output.includes(s.canary)) {
      leaks.push({ scenarioId: s.id, canary: s.canary, evidence: excerpt(output, s.canary) });
    }
  }
  return leaks;
}
function checkBehavioralCanary(output, scenario) {
  const pattern = scenario.forbiddenPattern ?? scenario.canary;
  if (!pattern) return null;
  const hit = matchForbidden(output, pattern);
  if (!hit) return null;
  return {
    scenarioId: scenario.id,
    canary: pattern,
    evidence: excerpt(output, hit)
  };
}
function runBehavioralCanaries(cases) {
  const leaks = [];
  for (const c of cases) {
    const leak = checkBehavioralCanary(c.output, c.scenario);
    if (leak) leaks.push({ ...leak, runId: c.runId ?? leak.runId });
  }
  return leaks;
}
function matchForbidden(output, pattern) {
  const re = tryParseRegex(pattern);
  if (re) {
    const m = output.match(re);
    return m && m[0].length > 0 ? m[0] : null;
  }
  return output.includes(pattern) ? pattern : null;
}
function tryParseRegex(pattern) {
  if (pattern.length < 2 || pattern[0] !== "/") return null;
  const last = pattern.lastIndexOf("/");
  if (last <= 0) return null;
  const body = pattern.slice(1, last);
  const flags = pattern.slice(last + 1);
  if (!/^[gimsuy]*$/.test(flags)) return null;
  try {
    return new RegExp(body, flags);
  } catch {
    return null;
  }
}
async function canaryLeakView(store, scenarios) {
  const targets = scenarios.filter((s) => !!s.canary);
  if (targets.length === 0) return [];
  const spans = await llmSpans(store);
  const leaks = [];
  for (const span of spans) {
    const output = span.output ?? "";
    for (const s of targets) {
      if (s.canary && output.includes(s.canary)) {
        leaks.push({
          scenarioId: s.id,
          canary: s.canary,
          runId: span.runId,
          evidence: excerpt(output, s.canary)
        });
      }
    }
  }
  return leaks;
}
var HoldoutAuditor = class {
  scenarios;
  accessLog = [];
  constructor(scenarios) {
    this.scenarios = scenarios;
  }
  /** Retrieve a holdout scenario for a declared purpose. Non-'evaluation' throws. */
  get(scenarioId, purpose) {
    if (purpose !== "evaluation" && purpose !== "debugging") {
      throw new Error(
        `HoldoutAuditor.get: purpose must be 'evaluation' or 'debugging', got ${purpose}`
      );
    }
    const s = this.scenarios.find((x) => x.id === scenarioId);
    if (!s) throw new Error(`holdout scenario "${scenarioId}" not found`);
    this.accessLog.push({ scenarioId, purpose, at: Date.now() });
    return s;
  }
  getAccessLog() {
    return this.accessLog;
  }
};
function excerpt(source, needle) {
  const at = source.indexOf(needle);
  if (at < 0) return "";
  const start = Math.max(0, at - 30);
  const end = Math.min(source.length, at + needle.length + 30);
  return (start > 0 ? "\u2026" : "") + source.slice(start, end) + (end < source.length ? "\u2026" : "");
}

export {
  checkCanaries,
  checkBehavioralCanary,
  runBehavioralCanaries,
  canaryLeakView,
  HoldoutAuditor
};
//# sourceMappingURL=chunk-SHTXZ4O2.js.map