When implementing content extraction/layout algorithms, treat “heuristics” as probabilistic classifiers: constrain them with invariants, gate them with evidence, and lock behavior with targeted regression tests.
Practical standard (apply per heuristic): 1) State the invariant explicitly and enforce its shape
2) Only compare like with like (units/scopes)
3) Evidence-gate before acting
4) Make classification value-driven, not structure-driven
5) Add a failing boundary regression test for each “veto”
Illustrative pattern (Rust-style):
fn maybe_merge_with_evidence(items: &[Item], context: &Ctx) -> Option<Merged> {
// 1) Invariant + shape constraints
if !context.invariant_holds(items) {
return None;
}
// 2) Evidence gating (floors + sparsity / repeated-context)
let evidence = context.evidence_score(items);
if evidence < context.EVIDENCE_FLOOR {
return None;
}
// 3) Finally apply transformation
Some(context.apply_merge(items))
}
Outcome: fewer false positives (corruption) and fewer over-broad fixes, because heuristics only activate when their evidence is strong and their inputs match the invariant assumptions.