[data-veracity] Little's Law dwell time is inflated by the guard floor across closed hours #32
Labels
No labels
blocked
bug
enhancement
high-priority
low-priority
needs-info
needs-triage
ready-for-agent
ready-for-human
referenced
research
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
gabogg/hikcentral#32
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
The deck publishes Mean Dwell as a headline KPI, computed per
RFC-ARCH-2026-004§3.3:Ōcomes fromget_cycle_average_occupancy_async(app/db/occupancy_repository.py:1065), which Riemann-integrates occupancy across the full 24-hour cycle and floors every sample at the patrol guard count:Two biases, both upward, both in the same direction:
guards × ~10 h. With|T| = 86,400 sand the default 8 guards that is a constant additive bias onŌ, and therefore onW_mean.max(...)clamp truncates the negative tail. Ifkis even slightly over-estimated, the late-night accumulator would go negative; clamping it at the guard count discards that negative area. The result is thatŌcan only ever be biased up by calibration error, never down — so a driftingkand a rising dwell time look identical.Why it matters for this deck specifically
Little's Law (
L = λW) assumes a stationary or cyclically-closed system. A 24-hour window in which eight to ten hours are a clamped constant floor is neither. The RFC's own §3.3 states the stationarity precondition and then applies the formula over the full cycle anyway."Mean dwell 94 minutes" will be read by an executive as "the average visitor stays an hour and a half". It is not that number — it is an integral over a window that includes the mall being shut.
KPIs corrupted
Mean Dwell (Day), Avg Dwell (Week ledger and KPI strip), the per-day
average_dwell_minutescolumn inDayOfWeekProfile, and any cycle-over-cycle dwell-stability trend built on them.Suggested fix
ŌandW_meanover the retail open window (open_time→close_time, already resolved per cycle byresolve_schedule_context/get_active_schedule_info_async), not over the 04:00→04:00 accounting cycle.|T|becomes the open duration;Ibecomes ingress within it.Ōmeasures visitors, not visitors plus security staff.dwell_open_window_minutesandresting_headcount. One number cannot mean both.94 min · 10:00–22:00), so the figure is self-describing on a boardroom wall.Decision needed
This changes a published number's definition. Worth agreeing the window before Phase 2 implements the aggregation, because changing it afterwards makes historical comparisons discontinuous.
✅ Design settled (grilling session)
Mean Dwell → open-window, visitors, floored at zero
Ō/W_meanoveropen_time → close_time, inside the configured accounting cycle (per-malldaily_reset_time, CONTEXT.md:79 — not hardcoded 04:00).|T|= open duration;I= ingress within it.O(t) = max(0, E − X_adj)— drop the daytime+N_patroloffset and themax(N_patrol, …)clamp. This fixes bias #2 (the clamp hideskover-estimation) and resolves a live code/doc contradiction: code runsmax(N_patrol, round(I − k·E + N_patrol))while CONTEXT.md:91 specifiesmax(0, E − X_adj + offset).patrol_guard_countstays calibration-only (nocturnal quiet-window convergence, CONTEXT.md:83). It no longer contributes to the daytime metric — guards drift through the sensors unpredictably, so no fixed daytime baseline is meaningful. Bias #1 (guard floor × closed hours) disappears automatically once we stop integrating closed hours.94 min · 10:00–22:00.Time-of-day dwell (new, from the interview)
Added to scope
Acceptance criteria (supersede "Decision needed")
Ō/W_meancomputed overopen_time→close_timewithin the configured accounting cycle.+N_patroldaytime offset removed; code matches CONTEXT.md'smax(0,…).patrol_guard_countused only for nocturnal calibration convergence.CONTEXT.mdoccupancy formula corrected; open-window dwell + dayparts documented.Ō; a slightly-highkcan now drive occupancy below the old guard floor (negative tail not truncated).Re-tagged
ready-for-agent.Being addressed in draft PR #70, one of four [data-veracity] drafts declared on 2026-09-23 (#68, #69, #70, #71). Each will be triaged, reviewed and implemented in order; the PR description lists the open design points to settle first.
gabogg referenced this issue2026-09-24 13:13:51 +00:00
gabogg referenced this issue2026-09-24 13:13:53 +00:00