JuliusBrussee/caveman · error · Error
${where} change set or eval pack is bound to another case
Error message
${where} change set or eval pack is bound to another case What it means
Thrown when change_set.case_id or eval_pack.case_id differs from the enclosing case's id. Every change set and eval pack is private to exactly one case; a mismatched binding means the artifacts were copied from another case and would attribute one case's proposal/evaluation to another.
Source
Thrown at packages/shared/contracts/scripts/validate-continuous-improvement.mjs:222
}
}
const upstream = new Set(item.diagnosis.root_cause_hypothesis.upstream_node_ids);
for (const nodeID of upstream) {
if (!slice.node_chain.includes(nodeID) || nodeID === slice.manifestation_node_id) {
throw new Error(`${where} diagnosis upstream node ${nodeID} is not an upstream node of its causal slice`);
}
}
// A case that proposes nothing must carry nothing: no operator, no eval
// pack, no replay. Anything else would present an abstention as a proposal.
if (item.status === "diagnosis_only") {
if (item.change_set.operator_id !== "" || item.eval_pack.id !== "" || item.replay.status !== "not_run") {
throw new Error(`${where} is diagnosis-only but carries a change set, eval pack or replay`);
}
continue;
}
if (item.change_set.case_id !== item.id || item.eval_pack.case_id !== item.id) {
throw new Error(`${where} change set or eval pack is bound to another case`);
}
// The case must investigate the pair its own opportunity named. A cohort
// built from a differently-derived pair would describe one comparison and
// measure another.
const source = report.opportunities.find((opportunity) => opportunity.id === item.opportunity_id);
if (!source) throw new Error(`${where} names an opportunity that is not in this report`);
if (armVariants.get("baseline").id !== source.current_variant_id || armVariants.get("alternative").id !== source.alternative_variant_id) {
throw new Error(`${where} cohort arms (${armVariants.get("baseline").id}/${armVariants.get("alternative").id}) are not the variants opportunity ${source.id} named`);
}
// Every required grader is one the recorded interpreter actually computes.
// `json_schema` is deliberately absent: over a typed interpreter result it
// could only assert that a hash is non-empty, which is a grader that cannot
// fail and therefore inflates how much a replay was checked.
const knownGraders = new Set(["exact_match", "tool_order", "tool_count", "guard_respected"]);
for (const grader of item.eval_pack.graders) {
if (!knownGraders.has(grader)) throw new Error(`${where} requires grader ${grader}, which the recorded interpreter does not compute`);View on GitHub (pinned to 27d5a3981a)
Solutions
- Set item.change_set.case_id and item.eval_pack.case_id to the enclosing case's item.id.
- Prefer generating new cases programmatically over copy-paste so nested ids are always rewritten.
- Re-run the validator to catch any other nested ids that still reference the old case.
Example fix
// before
case id: "case-9"
change_set: {case_id: "case-8", ...}
eval_pack: {case_id: "case-9", ...}
// after
change_set: {case_id: "case-9", ...}
eval_pack: {case_id: "case-9", ...} Defensive patterns
Strategy: validation
Validate before calling
const bound = item.change_set.case_id === item.id && item.eval_pack.case_id === item.id;
Prevention
- Always create change_set and eval_pack with the parent case id passed in, never by literal.
- Add an id-rewrite step to any case-cloning utility so nested case_id fields are updated automatically.
When it happens
Trigger: Cloning a case (including its change_set and eval_pack) to create a new case with a new id without updating the nested case_id fields.
Common situations: Duplicating cases in the report fixture to grow the corpus; splitting one case into two; renaming case ids during a refactor.
Related errors
- ${where} hard chain edge ${edge.from}->${edge.to} is not a h
- ${where} is diagnosis-only but carries a change set, eval pa
- ${where} names an opportunity that is not in this report
- ${at} names source unit ${entry.source_unit_id} that is not
- {label}: duplicate identity {'/'.join(identity)}
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/f7f8fb88e84cfb16.
Report an issue: GitHub.