{"record":{"id":"fa4f5449f8025783","repo":"JuliusBrussee/caveman","slug":"where-manifestation-node-slice-manifestation","errorCode":null,"errorMessage":"${where} manifestation node ${slice.manifestation_node_id} is not a node of variant ${sliceVariant.id}","messagePattern":"(.+?) manifestation node (.+?) is not a node of variant (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/shared/contracts/scripts/validate-continuous-improvement.mjs","lineNumber":177,"sourceCode":"    for (const trace of item.representative_traces) {\n      const variant = armVariants.get(trace.arm);\n      if (!variant || variant.id !== trace.variant_id) throw new Error(`${where} representative trace names a variant that is not that arm's variant`);\n      if (!unitsByID.has(trace.analysis_unit_id)) throw new Error(`${where} representative trace ${trace.analysis_unit_id} is not an analysis unit of this report`);\n      if (!familyUnits.has(trace.analysis_unit_id)) throw new Error(`${where} representative trace ${trace.analysis_unit_id} is not a member of the cohort's task family`);\n      if (!variant.analysis_unit_ids.includes(trace.analysis_unit_id)) throw new Error(`${where} representative trace ${trace.analysis_unit_id} did not run that arm's workflow variant`);\n      selectedPerArm.set(trace.arm, (selectedPerArm.get(trace.arm) ?? 0) + 1);\n    }\n    for (const [arm, count] of selectedPerArm) {\n      if (count > 3) throw new Error(`${where} arm ${arm} carries ${count} representative traces, more than three`);\n    }\n\n    const slice = item.causal_slice;\n    const sliceVariant = variantsByID.get(slice.variant_id);\n    if (!sliceVariant) throw new Error(`${where} causal slice references a workflow variant that is not in this report`);\n    if (sliceVariant.id !== armVariants.get(\"baseline\").id) throw new Error(`${where} causal slice is not taken from the baseline arm's variant`);\n    const sliceNodes = new Set(sliceVariant.nodes.map((node) => node.id));\n    if (slice.manifestation_node_id !== \"\" && !sliceNodes.has(slice.manifestation_node_id)) {\n      throw new Error(`${where} manifestation node ${slice.manifestation_node_id} is not a node of variant ${sliceVariant.id}`);\n    }\n    if (item.diagnosis.manifestation.node_id !== slice.manifestation_node_id) {\n      throw new Error(`${where} diagnosis manifestation node disagrees with its causal slice`);\n    }\n    for (const nodeID of slice.node_chain) {\n      if (!sliceNodes.has(nodeID)) throw new Error(`${where} causal slice node ${nodeID} is not a node of variant ${sliceVariant.id}`);\n    }\n    if (slice.manifestation_node_id !== \"\" && !slice.node_chain.includes(slice.manifestation_node_id)) {\n      throw new Error(`${where} causal slice omits its own manifestation node`);\n    }\n    const provenDependency = (edge) => edge.strength === \"hard\" && (edge.type === \"data\" || edge.type === \"control\") && edge.evidence_refs.length > 0;\n    const variantEdges = new Map(sliceVariant.edges.map((edge) => [`${edge.from}\u0000${edge.to}\u0000${edge.type}`, edge]));\n    for (const edge of slice.hard_edges) {\n      if (!provenDependency(edge)) throw new Error(`${where} hard chain carries an unproven edge ${edge.from}->${edge.to}`);\n      if (!sliceNodes.has(edge.from) || !sliceNodes.has(edge.to)) throw new Error(`${where} hard chain edge ${edge.from}->${edge.to} names a node outside variant ${sliceVariant.id}`);\n      if (!slice.node_chain.includes(edge.from) || !slice.node_chain.includes(edge.to)) {\n        throw new Error(`${where} hard chain edge ${edge.from}->${edge.to} is outside the slice's node chain`);\n      }","sourceCodeStart":159,"sourceCodeEnd":195,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/766dce6b1394ebb56a3090748d5a0240a5aefb36/packages/shared/contracts/scripts/validate-continuous-improvement.mjs#L159-L195","documentation":"When causal_slice.manifestation_node_id is non-empty it must be a node of the slice variant — an id in sliceVariant.nodes (validate-continuous-improvement.mjs:175-178). The empty string is the allowed 'no manifestation pinned' sentinel and is skipped; any other id must exist among that variant's nodes.","triggerScenarios":"The node was renamed or removed from the variant's nodes array; the node id was copied from a different variant's node set; the id has a wrong prefix (node/exec-plan vs node/exec).","commonSituations":"Renaming node ids in a refactor; hand-authoring a slice against a mental model of the graph instead of the fixture's nodes list; sentinel misuse — writing a placeholder id instead of \"\".","solutions":["Set manifestation_node_id to an existing node id of the baseline variant.","If no manifestation node should be asserted, use \"\" — and make diagnosis.manifestation.node_id \"\" too (error 616).","Re-run the validator."],"exampleFix":"// before — variant nodes are [node/parse, node/exec]\n\"manifestation_node_id\": \"node/exec-plan\"\n// after\n\"manifestation_node_id\": \"node/exec\"","handlingStrategy":"validation","validationCode":"const danglingManifestationNodes = (report) => {\n  const byID = new Map(report.workflow_variants.map((v) => [v.id, v]));\n  return report.cases.filter((c) => {\n    const nodes = new Set(byID.get(c.causal_slice.variant_id)?.nodes.map((n) => n.id) ?? []);\n    return c.causal_slice.manifestation_node_id !== '' && !nodes.has(c.causal_slice.manifestation_node_id);\n  }).map((c) => c.id);\n};","typeGuard":null,"tryCatchPattern":"try {\n  execFileSync(process.execPath, [VALIDATOR, reportPath, spansPath]);\n} catch (err) {\n  if (/manifestation node .* is not a node/.test(err.message)) {\n    failCI(`manifestation node not in the slice variant's node set: ${err.message}`);\n  } else throw err;\n}","preventionTips":["Copy manifestation node ids from the variant's nodes array, never from memory.","Use \"\" when no manifestation node is asserted — and mirror it in the diagnosis (error 616).","After renaming nodes, sweep manifestation ids and node chains together."],"tags":["fixtures","cross-validation","causal-slice","node","referential-integrity"],"backgroundTag":"dangling-node-reference","analyzedSha":"766dce6b1394ebb56a3090748d5a0240a5aefb36","analyzedAt":"2026-08-18T03:14:35.516Z","contentChangedAt":"2026-08-18T03:14:35.516Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}