Skip to content

06: Day metrics and app integration on retained calculation state - #108

Draft
mikenrafter wants to merge 19 commits into
OpenStrap:mainfrom
mikenrafter:split/area-6-integration
Draft

mikenrafter wants to merge 19 commits into
OpenStrap:mainfrom
mikenrafter:split/area-6-integration

Conversation

@mikenrafter

Copy link
Copy Markdown
Contributor

Depends on 05 / #107.

Depends on 04 / #106.

Depends on 03 / #105.

Depends on 02 / #104.

Depends on 01 / #103.

This is part 06 of the split of #99. It targets main, so its diff also contains the earlier parts until they merge. Its own changes are the commits listed under "Suggested review order". After each earlier part merges, I'll merge main into this branch so the diff shrinks to this part alone.

The per-area states cannot support application adoption without keyed day consumers, dependency rules and end-to-end parity checks. This finishes the stack with incremental HRV/motion/minute consumers, energy contributions, the calculation-group registry and cross-area research/benchmark tools.

What changes

  • Add the incremental.dart library and its HRV, motion, minute and checkpoint parts, keeping their shared compilation unit intact.
  • Add keyed minute energy pricing, contribution summaries and hourly/day views.
  • Add the public group registry and import-closure checks.
  • Restore full shared comparison support and add cross-area persistence, adoption, frozen-output and property tests.
  • Add the remaining benchmarks, integration/mathematical docs, algorithm index/changelog changes and final exports.

No runtime dependency is added. The source retains Task Force 1996 HRV, Banister/Morton TRIMP, Keytel 2005, Mifflin-St Jeor 1990 and Tudor-Locke 2019 energy citations. Internal policy remains explicitly ESTIMATE. Missing coverage, cadence, profile or reference evidence keeps its existing absence/provenance rules. The parent owns changed batch arithmetic and its Edge kAlgoVersion requirement; the final frozen checks pin this stack to those outputs. The area 2 gap-aware screen change remains part of adoption.

Algebraic breakdown

Algorithm/structure State and empty Combine; lift; finish Laws and tested equality
CalculationMode One call mode; no accumulated state Controls reuse eligibility; no combine, lift or finish. Policy enum, not a monoid. calculation_cache_test.dart checks every mode's bypass/reuse behavior and exact invocation counters.
CalculationCache adoption Dependency-keyed result map and counters, initially empty, defined in area 1 No combine. Lift evaluates with dependency snapshot; finish returns cached/recomputed result. Edits, mismatches and forced mode invalidate; thrown computations must not publish partial entries. Full cache tests land here with mode enum. Exact counter/result checks, including failure and dependency ownership; no associative merge claim.
IncrementalHrvTime Retained NN/time prefix, level moments, eligible differences/lag sums, five-minute bins and jitter segment evidence; empty prefix/zero moments No combine. sync validates prefix and parameters, adds new data or rebuilds; finish constructs HRV and invokes batch on documented jitter/refusal paths. Checkpointed ordered prefix fold. hrv_time_test.dart, drift, checkpoint and incremental_laws_test.dart: chunk/restart/detour invariance, empty/idempotent sync, conservation, refusal atomicity, malformed checkpoint checks. Values max(1e-9, abs(expected)*1e-8), presence/counts/metadata exact. Checkpoint text equal after removing work counters as specified by laws.
_MotionBin, IncrementalEnmoSeries Sorted valid source prefix, trailing gravity sums/window index, per-minute magnitude lists and sums; empty No combine. Lift new accelerometer samples after prefix validation; finish per-minute ENMO, mean absolute deviation, dynamic amplitude and coverage. Changed reference/window or past edits rebuild. Ordered prefix fold. ENMO/drift/property tests check prefix, edited-history rebuild and JSON continuation, numeric max(1e-9, abs(expected)*1e-8), counts/absence/provenance exact. Magnitudes are retained because exact deviation depends on a moving center.
MinuteEnergyPricer, Calories._bill, source/abstention enums Fixed validated profile/anchors and one minute's optional HR/cadence evidence; absent pricer for missing prerequisites No general state combine. Lift one minute through Keytel/flex-HR or measured-cadence policy; finish contribution/source/abstention. A fixed pricer gives independent contributions, not a new physiological monoid API. Minute-energy tests cover flex threshold, missing cadence/HR/profile, source selection and per-minute absence. Shared formula parity alone is supplemented by explicit gate/value cases.
Summary-only IncrementalMinuteMetrics.sync(includeMinuteSeries: false) Same keyed bills/totals as full minute mode; empty bills No public combine. Lift replaces minute bills; finish aggregate energy/strain while omitting minute-record allocation. Ordered edit-aware fold. minute_summary_test.dart compares summary and batch results through append/restore/edit cases, numeric max(1e-9, abs(expected)*1e-8), exact null minute artifacts and metadata. Walking is included once in active total.
MinuteEnergy, MinuteEnergySeries, HourlyEnergy, Calories.assembleMinuteEnergySeries, minute/hourly/daily energy views Keyed priced-minute sequence plus basal rate and counts; empty/missing prerequisites abstain according to API Sequence/view construction and grouped summation; lift HR/cadence minutes; finish series/hourly totals or prorated basal plus active. Normalized views are not universally mergeable under different day lengths/profiles. minute_energy_test.dart, minute summary and metric tests check totals, keys, counts, sources, abstention and hourly grouping under the existing numeric comparisons.
_MinuteBill, MinuteMetrics, IncrementalMinuteMetrics Map and caller order of keyed bills, raw parameters, TRIMP/HR-active/walking totals, basal/pricer state; empty map/zero totals No public combine. sync replaces changed key contributions, removes missing keys, reprices on profile/anchor changes and finishes TRIMP/strain/energy/views. Keyed edit-aware fold, not a monoid: duplicate keys are refused and replacement order matters. Minute-metric/checkpoint/property tests: exact keys, counts, sources and metadata, numerical max(1e-9, abs(expected)*1e-8), chunk/restart/detour consistency, idempotence and invalid-input atomicity.
IncrementalLombScargle integration and RunningMoments/IntHistogram property laws Existing area 1 states Existing spectral prefix sync; no new merge API. Moments and histogram use their existing merges. incremental_laws_test.dart adds all sync laws and explicit associative/commutative/identity merge tests for moments/histogram. Histogram exact; moments/PSD use the file's numeric helper and independent moment/histogram references. Batch spectral comparisons share production helpers and establish path parity.
GroupKind, InputScope, InputDecl, GroupDecl, GroupRegistry, declarations and validation Fixed group declarations, dependencies, files and counters; empty registry is not a valid replacement for the required declared groups Dependency graph validation/projection, no row accumulation or combine. Not a monoid. registry_closure_test.dart verifies required declarations, public symbols, dependency cycles and actual import/export/part closure; not a scientific estimator test.
Cross-area adoption, persistence and frozen-output checks Original input fixtures, codec/checkpoint envelopes, reference outputs Tests/tooling only. No algorithm combine beyond the implementations under test. adopted_aggregators_test.dart requires batch versus one-slice bit identity; original per-area reference/law tests retain chunk tolerances. phase0_parity_test.dart and parent tool/reproduce_outputs.dart pin the frozen parent outputs. Persistence tests preserve NaN-aware per-element comparisons for matcher 0.12.17.
Research day curves, bench_*, probes, benchmark drivers Existing area 3 window states, source recipes and timing/error records Drive ordered folds or compare batch outputs; no new production accumulator contract. day_curves_test.dart tests the research consumers with full shared inputs. Benchmark timing output is not treated as a correctness test.

incremental.dart uses Dart part files and private helpers shared by HRV, motion, minutes and codecs. Keeping that compilation unit together avoids temporary duplicate state/codec APIs. Empty sync identity and idempotent same-prefix sync are transition laws; they do not imply these objects have an associative state merge.

Where the speedup comes from

The app reprices old minutes at every sync, so this PR adds keyed daily-energy state and the integration support needed to keep it. This PR: 0.000 of the 109.065 s saved per night (0.00%). Overall after the full stack: 13.98×.

Workload / calculation #102 batch s Retained s This PR saves s
day / Daily energy 0.000323 0.001226 -0.000903
night / no calls in this workload — — 0.000000

See the sync-work explanation in #103 for the timeline, overall table and Edge adoption requirement; these are AOT medians from at least five full schedules on generated data, with this PR credited only beyond #102 and its inherited gains included in the overall saving.

How each structure saves work

HRV and fixed-grid spectral arithmetic append only new points on eligible paths. Motion reuses trailing gravity and per-minute contributions. Keyed minute metrics reprice affected minutes and keep aggregate bills; dependency changes trigger exact rebuilds. Dependency memoization returns already-computed results when inputs are unchanged. Whole calls still validate/copy prefixes, motion sorts the supplied valid input, minute sync visits supplied keys and result/checkpoint rendering scales with retained output. Therefore these full APIs are not uniformly O(new data), even when expensive estimator arithmetic is.

Fresh timings are in "Where the speedup comes from" above. Older numbers in the docs predate this split. Historical evidence is retained with its input and limitations in docs/AGGREGATOR_DESIGN.md, docs/COMBINED_BUMP_STATUS.md and the preceding local PR-aggregators.md. tool/bench_aggregate.dart uses 30,000 synthetic beats; tool/bench_night_nn.dart defaults to seeds 1/2/3 and 32 overnight prefixes; tool/incremental_benchmark.dart reports elapsed time and processed-work counters on its deterministic fixture. tool/bench_phase0.dart and tool/bench_night_bins.dart use the frozen phase-0 source. tool/combined_bump_probe.dart optionally reads the original capture, so old real-night timings are not reproducible from the replacement fixture. The original docs' earlier failure/status narratives are historical snapshots, not the validation result for this stack.

Tests

Full suite on this branch with Dart 3.13.0: 2,805 passed, 7 skipped, 0 failed. dart analyze (Dart 3.11.4) reports no issues. Counts include the earlier parts' tests. The 7 skips are existing checks that need data outside the repo: six need a local whoop_hist.jsonl capture, and one wall-clock agreement test needs the DREAMT corpus.

The first full run after merging part 05 had one failure: IncrementalHrvTime.sync accepted a regressing clock that the batch HRV path refuses since #102. 9b23985 makes it hand regressing or length-mismatched clocks to the batch path before touching its retained state. It adds two tests that failed before the fix. The existing replacement test moved one timestamp so that the next one regressed. It now shifts the whole suffix, so its original assertions still run on valid input.

Suggested review order

  1. b3237d6 Day metrics and integration tools need reusable calculation state. Read the state and append transitions first, then the finish rules, then the joint law, persistence and adoption tests.
  2. d608d98 merges part 05. Only CHANGELOG.md conflicted; both sides are kept.
  3. 9b23985 Refuse invalid clocks in incremental HRV.

Change size

This part's own changes, measured against part 05: lib/ +1,781/-35 in 8 files; tests, tools and docs +10,817/-74 in 33 files. The tests are large because this part carries the 3,172-line joint incremental law suite and the 986-line cross-metric persistence suite, which need every earlier part.

Questions for the reviewer

  • Can the app supply dependency revisions that detect a replaced old timestamp, rather than only MAX(timestamp):COUNT(*)?
  • Should this package keep the research drivers once app adoption has its own end-to-end benchmarks?

mikenrafter and others added 19 commits November 1, 2026 09:30
Apply the batch clock refusal before touching retained state for regressions and supplied length mismatches. Keep the replacement and force fixture monotonic by shifting its suffix, and cover invalid clocks separately.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @mikenrafter, this pull request is too large to review

It changes 47,344 lines. Sourcery can review pull requests with up to 20,000 changed lines.

@coderabbitai

coderabbitai Bot commented Nov 13, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants