{"record":{"id":"2bc1cc3b120cd5ab","repo":"ruvnet/ruflo","slug":"tunedistillation-source-db-checksum-changed-durin","errorCode":null,"errorMessage":"tuneDistillation: source DB checksum changed during tuning — refusing to report a result","messagePattern":"tuneDistillation: source DB checksum changed during tuning — refusing to report a result","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"v3/@claude-flow/cli/src/services/distill-tuning.ts","lineNumber":338,"sourceCode":"  });\n  const baseline = scoreQuerySet(heldOutBaselineIndex, heldOutQuerySet, topK);\n\n  const heldOut: HeldOutScore = {\n    mrrAt10: winnerFull.mrrAtK,\n    recallAt10: winnerFull.recallAtK,\n    queryCount: winnerFull.queryCount,\n    baselineMrrAt10: baseline.mrrAtK,\n    baselineRecallAt10: baseline.recallAtK,\n  };\n  // Overfit: held-out MRR is more than 20% (relative) worse than the winner's\n  // own train score. Guard divide-by-zero — a zero train score can't overfit.\n  const overfit = winner.trainScore > 0 && heldOut.mrrAt10 < winner.trainScore * 0.8;\n\n  const sourceChecksumAfter = sha256File(dbPath);\n  if (sourceChecksumAfter !== sourceChecksumBefore) {\n    // This must be structurally impossible (dbPath is never opened with a DB\n    // connection anywhere above) — a mismatch means an invariant was broken.\n    throw new Error('tuneDistillation: source DB checksum changed during tuning — refusing to report a result');\n  }\n\n  return {\n    candidates,\n    winner,\n    heldOut,\n    overfit,\n    provenance: {\n      gridSize: configs.length,\n      corpusSize: outerSplit.totalRows,\n      trainSize: outerSplit.trainRowids.length,\n      heldOutSize: outerSplit.heldOutRowids.length,\n      metric: 'mrr@10',\n      tunedAt: now ?? Date.now(),\n      sourceDbPath: dbPath,\n      sourceChecksumSha256: sourceChecksumAfter,\n    },\n  };","sourceCodeStart":320,"sourceCodeEnd":356,"githubUrl":"https://github.com/ruvnet/ruflo/blob/6b01dc5a687b26b3e218f796de45ec51f8fa9e8c/v3/@claude-flow/cli/src/services/distill-tuning.ts#L320-L356","documentation":"tuneDistillation computes a sha256 of the source db before tuning and asserts it is byte-identical afterward. The source db is never opened for writes anywhere in the harness (only read-only temp copies are used), so a checksum change means a broken invariant — typically an external concurrent writer modified the source during the run. To avoid reporting a result built on shifting data, it refuses to return.","triggerScenarios":"Another process writes to the same dbPath while tuneDistillation runs (memory system writing new patterns, a separate distillation run, a sync process), or the file was replaced/swapped during the run.","commonSituations":"Running tuning against the live memory db while agents are actively storing patterns; two tuning jobs pointed at the same db; a backup/sync tool touching the file mid-run.","solutions":["Quiesce writers against dbPath for the duration of the run, or run tuning against a snapshot copy.","Copy the source db to an isolated path and pass that copy as dbPath.","Schedule tuning during idle periods when no memory writes occur.","If it still fires, treat it as a bug report — the harness guarantees it does not write the source."],"exampleFix":"// before — tuning the live db while agents write to it\nawait tuneDistillation({ dbPath: liveDbPath, ... }); // may throw 'checksum changed'\n\n// after — run against an isolated copy\nconst snapshot = path.resolve(tmpDir, 'tune-source.db');\nfs.copyFileSync(liveDbPath, snapshot);\nawait tuneDistillation({ dbPath: snapshot, ... });","handlingStrategy":"try-catch","validationCode":"// Prevent by ensuring no concurrent writer touches dbPath during the run.\nconst snapshot = path.resolve(tmpDir, 'tune-source.db');\nfs.copyFileSync(dbPath, snapshot);\nawait tuneDistillation({ dbPath: snapshot, ... });","typeGuard":null,"tryCatchPattern":"try {\n  return await tuneDistillation({ dbPath, ... });\n} catch (e) {\n  if ((e as Error).message.includes('checksum changed')) {\n    // retry against an isolated snapshot with writers quiesced\n    const snap = copyToTemp(dbPath, tmpDir, 'tune-snap');\n    return await tuneDistillation({ dbPath: snap, ... });\n  }\n  throw e;\n}","preventionTips":["Run tuning against a snapshot copy, not the live memory db.","Quiesce memory writers during tuning windows.","Never point two tuning jobs at the same db.","Exclude the db from backup/sync tools that touch it mid-run."],"tags":["distillation","integrity","safety","typescript"],"backgroundTag":null,"analyzedSha":"6b01dc5a687b26b3e218f796de45ec51f8fa9e8c","analyzedAt":"2026-08-12T13:20:50.148Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}