Repository navigation
04: Stage a growing night without re-extracting unchanged epochs - #106
Draft
mikenrafter wants to merge 14 commits into
Draft
mikenrafter wants to merge 14 commits into
mikenrafter wants to merge 14 commits into
Conversation
This was referenced Nov 13, 2026
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
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. |
There was a problem hiding this comment.
Sorry @mikenrafter, this pull request is too large to review
It changes 29,089 lines. Sourcery can review pull requests with up to 20,000 changed lines.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Depends on 03 / #105.
Depends on 02 / #104.
Depends on 01 / #103.
This is part 04 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 mergemaininto this branch so the diff shrinks to this part alone.Staging a growing night repeats feature extraction for unchanged epochs and can mix incompatible epoch anchors across cache entries. This adds exact feature-row caches and anchored epoch accumulation while preserving the production session-clipped staging path, and keeps the separate causal research stager explicit.
What changes
CardioRowCache, anchoredEpochRowsand phase-aware memoization.The source retains van Hees 2013, Long 2016 and Fonseca 2015/2018 method citations and marks fitted/internal staging rules ESTIMATE. Deep sleep remains a low-confidence HR-flatness overlay; stage-minute bounds are evidence bounds, not calibrated confidence intervals. This area retains the parent's RR/spectral behavior and preserves the pre-bump session-onset/post-gap grid.
segmentSleepremains the sleep entry point. The causal stager is separately callable research behavior, not a replacement night score.Algebraic breakdown
CardioRowKey,CardioEpochRow,CardioRowCachemerge; lift extracts exact epoch features; finish is lookup and normal classification. Union is associative/idempotent with empty identity, but not commutative for inconsistent equal-key payloads. Under the valid-key contract identical keys mean identical rows. Work counters are not part of that algebra.cardio_row_cache_test.dartchecks merge, stale/mutated dependencies, phases, persistence and label parity. Row/label observations are exact with NaN-aware checks. Hash collision freedom is not proven. Merge costs O(other rows), not O(1).cardioEpochFeatures, productioncardioStagerEpochFeatureRow,EpochRows,_Runfold, no combine. Lift new HR/accel/RR channels; finishallRows/provisionalRows, orstageWindow. Late edge rows are recomputed until enough future context arrives. Ordered checkpointed fold, not a monoid.epoch_rows_test.dartand anchor tests check exact chunk/restart row parity, source-grid anchors, context/gaps and clipped-window behavior. Row comparisons explicitly handle nonfinite fields. Stage labels are tested against the frozen/reference paths under the tests' stated eligibility conditions.EpochRowsMemo,_PhaseEntryrowsForreuses a compatible phase or rebuilds it. No arbitrary merge; lift a source revision under an anchor; finish selectedEpochRows. Memoization, not a monoid.CausalStagerConfig,CausalSampleWindow,CausalEpochRow,CausalStagerStateinitial(config)observe(window, priorState)merges ordered evidence, closes past-only epochs and returnsCausalStageObservation; finish latest evidence/decision/abstention plus next checkpoint. Ordered state transition with overlap and clock rules, not a monoid.causal_stager_test.dartchecks future isolation, split/restart continuity, clock regression, gaps, coverage and explicit absence. JSON/current-version behavior is tested. Full parity with the retrospective stager is not an invariant because the information available differs._Merged/_Decisionfeature/decision helpers,CausalStage,CausalAbstentionStageSegment,SleepSession,HypnogramMetrics,HypnogramAggregator,_HypnogramStatehypnogram_aggregator_test.dartuses exact finished fields, including NaN-aware absent REM, across identities/association/splits/slicing/checkpoints.conversion_check_test.darttests the law checker against real hypnogram conversion.StageEpochEvidence,MinuteRange,StageMinuteRanges,stageMinuteRangesand evidence extensionstage_minute_ranges_test.dartand its property file check conservation, bounds, widening with uncertainty/margin and label preservation. Counts are exact; floating range checks use absolute1e-9in those files. No public monoid-law claim.Where the speedup comes from
Sleep staging repeatedly extracts features for unchanged epochs, so this PR caches those rows while still checking their inputs and classifying the whole night. This PR: 29.725 of the 109.065 s saved per night (27.25%). Overall after the full stack: 13.98×.
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
Row cache hits avoid the expensive feature windows for identical dependencies. Anchored rows retain final epochs and recompute only the unresolved context near the newest data. Neither feature caching nor epoch accumulation makes global baseline classification O(1): fingerprints, input validation, result assembly and whole-night scoring can still scan history. Causal observations retain past context instead of rescanning a whole night, but overlapping-window validation and retained-row summaries still cost work. Hypnogram combine retains wake spans; WASO finishing scans them. Stage bounds remain O(epoch count), and have no measured incremental speedup.
Fresh timings are in "Where the speedup comes from" above. Older numbers in the docs predate this split.
Tests
Full suite on this branch with Dart 3.13.0: 2,068 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 localwhoop_hist.jsonlcapture, and one wall-clock agreement test needs the DREAMT corpus.Suggested review order
ed13f25Sleep staging repeats feature extraction for unchanged epochs. Read the state and append transitions first, then the finish rules, then the law, checkpoint and reference tests.d29ee84merges the current 03: Update HRV and respiration windows incrementally #105 head, including the review fixes on 00: Make RR/HRV output changes independently reproducible #102 and Abdul's merges. It merged without conflicts.Change size
This part's own changes, measured against #105:
lib/+3,022/-214 in 11 files; tests, tools and docs +5,413 in 20 files.Questions for the reviewer