Skip to content

Body composition and Healthspan contributors: manual/imported trends and local drivers #763

Open

Description

@tigercraft4

Context

WHOOP now surfaces Healthspan/body-composition-style features such as biological/fitness age framing and body composition integrations. NOOP has local Fitness Age/Vitality work, but needs a clean-room plan for body composition inputs and contributor explanations.

Related / does not replace:

Proposed scope

Add local body composition and healthspan contributor support:

  • manual and imported entries for weight, body-fat percentage, lean mass, waist/measurement fields where appropriate, and VO2/cardio-fitness estimates where available;
  • trend charts and contributor explanations for Fitness Age/Vitality-style surfaces;
  • source labeling for manual, Apple Health/Health Connect, CSV/imported, or device-derived inputs;
  • calibration/insufficient-data states;
  • transparent formulas and confidence labels, not proprietary biological-age claims.

Non-goals / safety constraints

  • NOOP must not invent body-fat, lean-mass, or VO2 values from strap data alone.
  • No medical diagnosis or clinical risk scoring.
  • No cloud sync/account requirement.
  • No WHOOP/Sage proprietary logic or UI assets.

Acceptance criteria

  • User can store and review local body composition entries.
  • Imported/manual values have source labels and timestamps.
  • Fitness Age/Vitality contributors can explain which local inputs moved a trend.
  • Missing/old/stale inputs are clearly labeled.
  • Swift/Kotlin storage and analytics remain parity-compatible.
  • Backup/export behavior is specified for any new fields.

Verification

  • Migration tests cover new storage.
  • Analytics tests cover trend and contributor calculations.
  • Import tests cover supported Health/Health Connect/CSV fields when implemented.
  • App targets compile after UI changes.

Activity

  1. ryanbr commented on Jul 25, 2026

    @ryanbr
    Owner

    Scope reads right — the non-goals line up with docs/SCOPE.md, and "must not invent body-fat/lean-mass/VO2 from strap data alone" is the same rule as the unproven-derivation clause in CLAUDE.md. Nothing here needs a scope change.

    More of this exists than the issue implies:

    So the genuinely new inputs are body-fat %, lean mass, and additional measurements.

    The real work is a storage-shape change, not analytics. Weight/height/waist are currently Profile scalars — one current value, no history. "Trend charts" needs them as a dated series (metricSeries or a new table), plus migrations that agree across Room and GRDB. That's the bulk of the effort and worth scoping first; the contributor explanations are cheap once the series exists.

    On the export acceptance criterion — worth pinning concretely, because #718 just hit the failure mode. Cycle data landed in metricSeries, which means it rides .noopbak (whole-file copy) but is excluded from the CSV export, since the sidecar is built from strap-derived source ids only and is never re-imported. Result: it survives a same-platform restore and is lost on an Android↔iOS move. Any new body-comp series will inherit exactly that unless the export path is part of the design.

    Suggest splitting: (1) dated body-composition storage + migrations + source labels, (2) trends UI, (3) contributor explanations. (1) is the dependency and the only part with parity/migration risk.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions