Skip to content

feat(calories): price sub-gate walking minutes from measured cadence (CADENCE-Adults) - #52

Merged
abdulsaheel merged 1 commit into
OpenStrap:mainfrom
DropTabl:feat/walking-cadence-energy
Aug 26, 2026
Merged

feat(calories): price sub-gate walking minutes from measured cadence (CADENCE-Adults)#52
abdulsaheel merged 1 commit into
OpenStrap:mainfrom
DropTabl:feat/walking-cadence-energy

Conversation

@DropTabl

@DropTabl DropTabl commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

The gap

MOT-02 raised the HR-flex gate to the ACSM moderate floor and its own changelog measured the cost: billed wake minutes fell to 4.9%, median daily active energy to 48 kcal. That was the right call for HR — Keytel has no fitted data below the exercise domain — but it left walking priced at zero: a one-hour walk at 95 bpm adds nothing to Active energy for its entire duration. This is now a user-facing bug report on edge ("Walking calories are not counted": the workout and steps record fine, Active Calories never move). MT-05 already established the 1 Hz accel channel cannot fill this gap (Brage's branches can't read a 1 Hz gravity vector).

The fix

Measured cadence is the one signal on this platform that actually resolves gait — the 100 Hz pedometer — and CADENCE-Adults (Tudor-Locke et al. 2019, IJBNPA 16:8) publishes the cadence↔MET line for exactly this region: heuristic thresholds 100/110/120/130 steps/min ↔ 3/4/5/6 METs.

Calories.dailyEnergy gains an optional cadenceSpmPerMin series, index-aligned with hrPerMin (null = nobody measured that minute):

  • A minute the HR gate accepts bills by HR alone, exactly as before — a minute is never billed twice.
  • A minute the HR gate refuses (below flex, or no HR at all — measured gait stands on its own), whose measured cadence is at/above the study's own moderate floor, bills (MET − 1) basal-minutes of surplus via the new metFromCadenceSpm — linear between the published anchors, clamped at both ends of the fitted range: under 100 spm the study does not price it (the same "only exercise-domain minutes bill" philosophy the HR gate already holds); over 130 spm is running, which drives HR over the gate and bills there.
  • The result record gains a walking component (already folded into active) so callers can disclose how much of the day came from measured walking.
  • No cadence series → byte-identical behaviour to today. Misaligned series throws; unusable anchors still abstain, cadence or not.

ALGORITHMS.md gets the row + citation.

Numbers

80 kg / 180 cm / 30 y male (Mifflin 1780 kcal/day): a one-hour walk at 110 spm bills 60 × 3 × 1.24 ≈ 222 kcal of walking surplus — previously 0.

Tests

New walking cadence term (CADENCE-Adults) group: the published MET anchors and clamps, the reported below-gate walk billing, the no-double-billing invariant, unmeasured/ambling/non-finite minutes staying basal, gait-on-off-skin-HR minutes billing, misalignment throwing, and anchor abstention unchanged. dart analyze clean; full suite green (591 tests).

Edge side (per-minute cadence from live_coverage, threading through wakeDayEnergy and the pipeline mirror, kAlgoVersion bump + pin) follows as a draft PR on OpenStrap/edge once this lands.

…(CADENCE-Adults)

MOT-02 knowingly traded walking away: the HR-flex gate bills nothing below
the ACSM moderate floor because Keytel has no fitted data there, so a walk at
95 bpm added ZERO active kcal for its entire duration (edge report: "Walking
calories are not counted" — the workout and its steps record fine, Active
energy never moves). MT-05 established the 1 Hz accel cannot fill that gap.

Measured cadence can: it is the one signal on this platform that actually
resolves gait (the 100 Hz pedometer), and CADENCE-Adults (Tudor-Locke et al.
2019, IJBNPA 16:8) publishes the cadence↔MET line for exactly this region —
heuristic thresholds 100/110/120/130 steps/min for 3/4/5/6 METs.

dailyEnergy gains an optional cadenceSpmPerMin series, index-aligned with
hrPerMin (null = nobody measured that minute — which is most minutes; the
pedometer only runs while the phone holds the live link):

- A minute the HR gate accepts bills by HR alone, exactly as before. HR sees
  intensity cadence cannot, and a minute is never billed twice.
- A minute the HR gate refuses (below flex, or no HR at all — measured gait
  stands on its own), whose measured cadence is at/above the study's own
  moderate floor (100 spm), bills (MET − 1) basal-minutes of surplus via the
  new metFromCadenceSpm — linear between the published anchors, clamped at
  both ends of the fitted range (under 100 spm the study does not price it;
  over 130 spm is running, which drives HR over the gate and bills there).
- The result record gains a `walking` component (already included in
  `active`) so callers can disclose how much of the day's active energy came
  from measured walking rather than HR.
- No cadence series → byte-identical behaviour to before.
- Misaligned series throws; unusable anchors still abstain, cadence or not.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015TxisrChNFxtVMXFFNRGtV
@coderabbitai

coderabbitai Bot commented Aug 25, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 9e7d0187-3302-400a-9148-80d7f95635a0


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

Comment @coderabbitai help to get the list of available commands.

@abdulsaheel
abdulsaheel merged commit a077a4a into OpenStrap:main Aug 26, 2026
3 checks passed
DropTabl added a commit to DropTabl/edge that referenced this pull request Aug 26, 2026
…(v77)

The reported bug ("Walking calories are not counted"): a Walking workout
records fine, its steps count fine, and the day's Active energy never moves.
Root cause is not a wiring or sync failure — MOT-02's HR-flex gate
deliberately bills nothing below the ACSM moderate floor, and a walk lives
entirely below it. The session's own bout number (which bills sub-gate
samples at the resting rate) made the gap read like a sync bug.

The analytics half (OpenStrap/analytics#52) prices sub-gate minutes from
MEASURED cadence — CADENCE-Adults' published 100/110/120/130 spm ↔ 3/4/5/6
METs line, the one gait signal this platform actually has after MT-05 ruled
the 1 Hz accel out. This is the edge half:

- lib/compute/step_cadence.dart: the ONE windows→minutes cadence mapping,
  from the day's RESOLVED live_coverage spans (credited, never raw rows, so
  band/phone overlap cannot double-price a step). Partial coverage pro-rates
  DOWN — a walk's boundary minute under-bills rather than half a minute of
  walking pricing a full MET-minute; untouched minutes are null, unmeasured.
- Both energy passes feed it through that one mapping: the coordinator's
  canonical wakeDayEnergy AND the pipeline's early-read mirror
  (DayBundleInput carries the spans across the isolate), so the early read
  and the derived day bill a walk identically instead of the number growing
  when the coordinator's pass lands.
- wakeDayEnergy filters the cadence series in the SAME pass as the off-skin
  HR filter — dropping an HR entry without its cadence would price every
  later cadence against the wrong minute (pinned by test).
- The TDEE block discloses the term (live_coverage_pedometer in inputs_used,
  walking kcal in the note) only on days it actually priced something.
- kAlgoVersion 76 → 77. A day with no pedometer coverage derives
  byte-identical to v76.

PIN GATE: the pubspec analytics pin is NOT flipped yet — it must move to the
OpenStrap/analytics#52 merge SHA (together with kAnalyticsPin) before this
can merge, per invariant OpenStrap#5. Draft until then.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015TxisrChNFxtVMXFFNRGtV
DropTabl added a commit to DropTabl/edge that referenced this pull request Aug 26, 2026
… exists to consume

All three pin locations move together to analytics main @ a077a4a, the
OpenStrap/analytics#52 merge commit: the cadence→MET walking term in
Calories.dailyEnergy (CADENCE-Adults). Unlike the usual repin this one
exists to move a number — that number IS this branch's change, priced in
by the kAlgoVersion 77 bump and the v77 migration. The hop is exactly
OpenStrap#52 and nothing else (calories.dart + its tests).
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