From PLAN.md step 7. Spec: docs/spec.md. Phase 1.
⟂ Parallel-safe — touches files no other concurrent step touches.
Files: src/flabel/correlate.py, tests/test_correlate.py
Changes: Pure. Tuple match in either direction, time-window disambiguation on multiple candidates, UnmatchedDetection with a reason when zero or still-ambiguous. Consolidate to one Label per flow with sorted sources and best_tier. Implement the unmatched gate: silent at zero, warn above zero, fail above the threshold.
Test that proves it: synthetic detections and flows only — no tools needed. One flow, one detection → one label. Two detections on one flow → one label with two sources. Port reuse with two candidate flows → resolved by time containment; detection outside both windows → ambiguous_flow_match. Tuple absent → no_flow_match. Threshold: 1 unmatched in 200 passes, 1 in 50 fails. best_tier is the minimum, not the maximum.
Depends on: 2. Parallel with: 8.
From
PLAN.mdstep 7. Spec:docs/spec.md. Phase 1.Files:
src/flabel/correlate.py,tests/test_correlate.pyChanges: Pure. Tuple match in either direction, time-window disambiguation on multiple candidates,
UnmatchedDetectionwith a reason when zero or still-ambiguous. Consolidate to oneLabelper flow with sortedsourcesandbest_tier. Implement the unmatched gate: silent at zero, warn above zero, fail above the threshold.Test that proves it: synthetic detections and flows only — no tools needed. One flow, one detection → one label. Two detections on one flow → one label with two sources. Port reuse with two candidate flows → resolved by time containment; detection outside both windows →
ambiguous_flow_match. Tuple absent →no_flow_match. Threshold: 1 unmatched in 200 passes, 1 in 50 fails.best_tieris the minimum, not the maximum.Depends on: 2. Parallel with: 8.