JuliusBrussee/caveman · error · Error

${where} dataset carries ${roleCounts.adversarial} adversari

Error message

${where} dataset carries ${roleCounts.adversarial} adversarial cases

What it means

Thrown when the count of role "adversarial" cases exceeds the cap, which is 2 when the change set declares a confidence guard and 1 when it does not. The guard-aware cap exists because a guarded change set legitimately earns one extra adversarial slot (the stale-input case); an unguarded one must not pad its adversarial coverage.

Source

Thrown at packages/shared/contracts/scripts/validate-continuous-improvement.mjs:306

    // evidence has no threshold to sit beside, so those two cases must NOT be
    // generated for it — a "boundary" case against a guard that does not exist
    // tests nothing while counting as adversarial coverage.
    const confidenceGuard = item.change_set.applicability.all.some((condition) =>
      condition === "failure_location_confidence >= 0.90" ||
      condition === "symbol_resolution == unique" ||
      condition === "targeted_test_reproduces == true");
    const perturbations = new Set(dataset.cases.map((entry) => entry.perturbation));
    for (const [perturbation, label] of [["guard_threshold_boundary", "boundary"], ["stale_input", "stale-input"]]) {
      if (perturbations.has(perturbation) !== confidenceGuard) {
        throw new Error(`${where} ${confidenceGuard ? "omits" : "generated"} a ${label} case ${confidenceGuard ? "for" : "against"} a change set that ${confidenceGuard ? "declares" : "declares no"} confidence guard`);
      }
    }
    const expectedTargets = Math.min(4, dataset.target_failure_cases.length);
    const expectedPriors = Math.min(2, dataset.prior_success_cases.length);
    if (roleCounts.target_failure !== expectedTargets) throw new Error(`${where} dataset carries ${roleCounts.target_failure} target-failure cases, want ${expectedTargets}`);
    if (roleCounts.prior_success !== expectedPriors) throw new Error(`${where} dataset carries ${roleCounts.prior_success} prior-success cases, want ${expectedPriors}`);
    if (roleCounts.boundary > 1) throw new Error(`${where} dataset carries ${roleCounts.boundary} boundary cases, want at most one`);
    if (roleCounts.adversarial > (confidenceGuard ? 2 : 1)) throw new Error(`${where} dataset carries ${roleCounts.adversarial} adversarial cases`);
    if (roleCounts.boundary !== dataset.boundary_cases.length) throw new Error(`${where} boundary case list disagrees with the composed dataset`);
    if (roleCounts.adversarial !== dataset.generated_cases.length) throw new Error(`${where} generated case list disagrees with the composed dataset`);
    const composed = roleCounts.target_failure + roleCounts.prior_success + roleCounts.boundary + roleCounts.adversarial;
    if (composed !== dataset.cases.length) throw new Error(`${where} dataset roles (${composed}) do not account for its ${dataset.cases.length} cases`);
    if (dataset.replay_case_ids.length !== datasetCaseIDs.size) throw new Error(`${where} replay manifest carries ${dataset.replay_case_ids.length} ids for ${datasetCaseIDs.size} dataset cases`);
    for (const datasetCaseID of dataset.replay_case_ids) {
      if (!datasetCaseIDs.has(datasetCaseID)) throw new Error(`${where} replay manifest case ${datasetCaseID} is not a composed dataset case`);
    }

    // The guard grader exists exactly when there is a perturbed case to catch a
    // candidate on; a required grader with no case behind it is decoration.
    const perturbed = dataset.cases.some((entry) => entry.perturbation !== "none");
    if (perturbed !== item.eval_pack.graders.includes("guard_respected")) {
      throw new Error(`${where} guard_respected grader ${perturbed ? "missing for" : "declared without"} perturbed dataset cases`);
    }
    for (const proof of item.replay.trial_proofs) {
      if (!datasetCaseIDs.has(proof.dataset_case_id)) throw new Error(`${where} replay trial ${proof.id} replays a case outside the composed dataset`);
      for (const arm of [proof.baseline, proof.candidate]) {

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Count role "adversarial" entries and trim to 2 with a guard, 1 without.
  2. If a guard was removed, drop the stale-input case (and boundary case — see error 495) along with it.
  3. Regenerate the dataset from the current applicability rather than accumulating cases.

Example fix

// before: no guard in applicability.all
roles: ["adversarial","adversarial"]

// after: unguarded cap is 1
roles: ["adversarial"]
Defensive patterns

Strategy: validation

Validate before calling

const GUARD_CONDITIONS = new Set([
  "failure_location_confidence >= 0.90",
  "symbol_resolution == unique",
  "targeted_test_reproduces == true",
]);
const hasGuard = item.change_set.applicability.all.some((c) => GUARD_CONDITIONS.has(c));
const adversarialCount = dataset.cases.filter((c) => c.role === "adversarial").length;
const ok = adversarialCount <= (hasGuard ? 2 : 1);

Prevention

When it happens

Trigger: Three adversarial cases on a guarded change set; two adversarial cases on an unguarded one (e.g., both misleading_tool_output and stale_input kept after removing the guard from applicability).

Common situations: Removing a confidence-guard condition from applicability without recomposing the dataset; adding extra adversarial cases by hand.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/7100f2fd64bb9873. Report an issue: GitHub.