# Task Plan ## Checklist - [x] Re-read the current `people_flow_project` same-person dedupe implementation and existing tests. - [x] Verify the plan covers both code-path inspection and executable validation of actual output. - [x] Run focused tests covering window identity and counting dedupe. - [x] Reproduce a same-person reentry scenario through the runtime counting path and inspect the resulting output values. - [x] If available, compare the synthetic output with remote runtime artifacts or logs for consistency. - [x] Record the validation result and any remaining evidence gap in the Review section. ## Scope And Risks - Scope: validate whether the previously changed `people_flow_project` logic really counts the same person only once when that person exits and re-enters multiple times within the same half-hour window. - Expected touch points: read-only inspection of `managed/people_flow_project/src/people_flow/counting.py`, `managed/people_flow_project/src/people_flow/window_identity.py`, `managed/people_flow_project/src/people_flow/pipeline.py`, focused tests, and possibly remote output artifacts or logs. - Risk: remote runtime payloads may not expose enough identity detail to prove dedupe for a specific real person, so synthetic execution may be the strongest evidence. - Risk: the local environment may lack heavy runtime dependencies for a full pipeline run; if so, validation should use the narrowest dependency-light path that still exercises the production counting logic. ## Validation Intent - First confirm the current code path still routes `person_keys` from `WindowIdentityResolver` into `LineCrossCounter` and ultimately into `total_people` in the half-hour payload. - Run the focused tests that directly cover reentry dedupe. - Execute one synthetic scenario through the real resolver and counter classes and inspect the actual emitted values such as `events`, `crossings`, and `total_people`. ## Review - Status: completed. - Result: the current `people_flow_project` same-person dedupe logic behaves correctly for the intended case: within one half-hour window, the same visual person can disappear, reappear under a new track id, cross the counting line again, and still contribute only `1` to the final `total_people` output. - Verification: - re-read the active code path and confirmed `managed/people_flow_project/src/people_flow/pipeline.py` passes `person_keys = identity_resolver.resolve(...)` into `counter.update(...)`, and the emitted half-hour payload uses `counter.total_people` as `total_people`; - ran `pytest tests/test_counting.py` under `managed/people_flow_project` and got `2 passed` for the focused dedupe tests; - executed a local synthetic scenario with the real `WindowIdentityResolver` and `LineCrossCounter` classes: track `1` crossed once, then the same constant-signature person disappeared and re-entered as track `2` and crossed again; observed `first_keys = {1: 'person:00001'}`, `second_keys = {2: 'person:00001'}`, `first_events = [{'track_id': 1, 'direction': 'negative_to_positive'}]`, `second_events = []`, `total_people = 1`, and payload-like output `{'total_people': 1, 'tracks': [{'track_id': 1, 'direction': 'negative_to_positive'}]}`; - inspected remote runtime artifacts on `10.8.0.11` and confirmed the latest `people_flow_project` window artifact and webhook event are still emitted through the same `half_hour_report` shape with `total_people` and `tracks` fields; the most recent remote window ended at `2026-05-12T16:27:58+08:00` with `total_people = 48`.