follow-up(statistics): P3 cleanups from #126 review (dwell multiplier, labels, excluded/trusted flags) #128
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#128
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?
Non-blocking findings from the pass-2 review of #126 (#106), moved here under the review policy so the PR could merge. See the review comment on #126 for details.
Design point settled in the 2026-09-26 grilling for the statistics deck RFC (#80): see Decision under the first Spec item. All items are now ready for implementation.
Spec
excludedandtrustedcan disagree.is_excludedreads the latestAUTOMATIC_NOCTURNALlog (occupancy_repository.pyget_counted_cycle_quality_range_async,auditsCTE), whileis_trustedreads the highest-priority current verdict (verdictsCTE). Supersession only runs between nocturnal logs, so anAUTO_EXCLUDEDday with a later trustedRETROACTIVE_GUARD_AUDIT(or aMANUAL_ADMINreset during the day) readsexcluded=true, trusted=true, and the usual-weekday baseline would use it.Decision (maintainer, 2026-09-26):
excludedis derived from the same winning verdict astrusted: a retroactive guard audit, then the nocturnal audit as set by the admin trust toggle (MANUAL_TRUSTED/MANUAL_EXCLUDED), then the automatic nocturnal verdict. A retroactive audit therefore clears an automatic exclusion. This applies toDailyStatistics.excluded/trusted, the deck's data-quality marker, the usual-weekday baseline, and the picker'sexcluded_days.MANUAL_ADMINandMANUAL_OVERRIDElogs (live offset recalibrations) say nothing about the day's data quality and must not rank as a cycle verdict. Remove them from_CYCLE_VERDICT_PRIORITY_SQL(or filter them out of every verdict query). That fragment also drives the trusted-history query used for k learning, so check that query still returns what calibration expects (resets carry nocomputed_exit_multiplier, so the k history should be unaffected; pin this with a test).docs/api/README.md(theexcluded/trusted/excluded_dayswording) andCONTEXT.mdif it describes verdict priority.Tests:
AUTO_EXCLUDED+ later retroactive audit →excluded=false, trusted=true, counted in the baseline and not inexcluded_days;TRUSTEDnocturnal + aMANUAL_ADMINreset → the reset changes nothing;AUTO_EXCLUDED+MANUAL_ADMINreset → still excluded and untrusted.Document the null label.
docs/api/README.md("Each usual daypart carries its clocklabel… the label is the same for all of them") should say thatlabelisnullwhen source days' clock spans differ.Stale comment at
analytics_service.py(~230, usual-weekday candidate selection): "oldest first, as the range query expects; the trust verdict is then read only until enough days pass". Both halves are false now: the range query accepts any order and trust comes from the batch. Thesorted(candidates)can go unless order matters elsewhere.Standards
occupancies(response)intests/test_statistics_dwell_labels_excluded.pyhas no annotations;_shared_label(usable: list[tuple[datetime.date, list[Any]]], …)could use the daypart model type instead ofAny.seed_day's; extract aseed_events(day)helper.> MIN_PLAUSIBLE_EXIT_MULTIPLIERto> 0still passes, so add a case at 0.5 or 0.4 to pin the boundary;label=_shared_label(usable, index)tousable[0][1][index].labelstill passes, so test the helper through the response, not only as a unit.float(log["computed_exit_multiplier"])is repeated in_cycle_exit_multiplier_asyncand the hourly series; the log helper could return the parsed multiplier.🤖 Generated with Claude Code