fix(metrics): preserve caller-owned detection predictions

AF
1m ago
+60-1

Summary

Detection matching clips predicted boxes in place. On CPU the processor can share the caller's tensor storage, so evaluating one document changes the model predictions supplied by the caller. Reusing the same prediction tensor for a larger page then evaluates previously clipped coordinates and can turn a perfect match into a miss.

Clip a local copy of the four box-coordinate columns and use that copy for matching. Scores, classes, caller-owned tensors and their backing storage are preserved. The clipping and matching calculations are otherwise unchanged.

Validation

  • Added 11 native detection-evaluation cases: the unchanged base has 6 failures and 5 passes; all 11 pass after the fix.
  • Covers float32/float64 predictions, contiguous and strided tensors, shared backing storage, out-of-bounds and in-bounds boxes, reuse across both page-size orders, unchanged targets, and pages without targets.
  • Hand-calculated perfect-match metrics verify that local clipping still affects matching correctly.
  • Ruff 0.15.10 check/format and git diff --check pass. The full optional-dependency suite and GPU execution were not run.

Checklist

  • Added regression tests for input preservation and repeated evaluation.
  • Preserved matching and score semantics.
  • Apply the bug label.