Skip to content
Body and activity

Body and activity

Everything Luna knows about your body comes through the profile page (⋯ → Profile & connections) and a handful of ProfileService records. It is all health data. Only the trainer and nutritionist aspects may have it put into their prompts (see The companion).

Your profile

What Luna knows holds the facts coaching is built on:

FieldNotes
Body mass, goal body mass, heightEvery meal target is anchored to body mass. “No goal” is a valid state, and Luna never invents one from your direction.
Directionlose, maintain or gain
Unitsmetric or imperial, display only. Everything is stored and computed in metric.
Birth year, sexOptional. Sex is never inferred or defaulted.
Dietary preferences, equipment, constraintsFed to the plan generators
Profession, current focus, routine environmentContext for the model only (“train in the evening” is wrong advice if your evenings are taken). None of these change a calorie target.

Updates merge: only the fields you send are written, so telling Luna “I’m 82kg now” doesn’t erase your height. The server rejects implausible values with messages like “N cm is not a plausible height”.

Data connections

ConnectionSourceStatus
StepsHealth Connect (Android), Google Fit REST (web, debug)Wired. See Habits and streaks.
Body compositionHealth ConnectAndroid only
Sleep and heart rateHealth Connect (“Last night from your ring”)Android only
Local weatherOpen-Meteo, fetched by the appWeb only
Garmin—“Not wired yet — planned for sessions, HR and sleep”
Strava—“Not wired yet — planned for runs and rides”

Luna only reads from Health Connect. It requests no write permission.

Body composition

Each scale reading (BodyComposition) records when it was taken, weight, body-fat %, BMI, fat-free mass, and whatever else the scale reports. It also records a source (manual, scale_photo or health_connect) and whether it was read off a screen by a vision model (photo_derived). Zero means “not reported” on every field, so the app shows a missing reading as missing rather than as 0%. A measured BMR changes the meal baseline (BMR × 1.35), and the meal plan says so.

Last night

A wearable day (WearableDay) groups sleep, activity and stress reports for your local day, so a sleep that starts at 23:10 belongs to the night you’d call it. The short “insights” text is written in Go from thresholds, never generated. Any note the device itself supplied is kept verbatim, credited to the device, and never presented as Luna’s words.

The wearable’s step count is used as context only. It is never journaled as a habit, because the streak stands on one step source (the phone), and counting the ring’s steps as well would count the same walk twice.

Tracked activities

⋯ → Track an activity records a GPS walk, run or ride. It needs location permission (“Luna needs location permission to track a route.”). When you save, two things are written:

  1. A workout habit event, so the day counts toward the training streak.
  2. An activity summary (RecordActivity) with the kind, start time, distance, and both moving time and elapsed time. The app says which one a pace uses.

The route never leaves your phone. Only the summary is stored. The map under the live track is drawn from OpenStreetMap tiles, which means OpenStreetMap sees the tile requests. Past activities are listed under Saved activities.

Your own account of how you run

Inner context is three lists you write, stored verbatim:

  • Baseline: how you work when things are normal.
  • Stressors: what is costing you right now, unranked.
  • Strategies: what you already know helps.

It exists so coaching stops ignoring the person receiving it. For example, it keeps a hard evening session out of a week you have flagged as bad.

  • Luna never writes, infers or edits it.
  • It is not a diagnosis, score or trend. There is no severity and no history.
  • It changes what Luna suggests, not what Luna talks about. The prompt tells Luna never to quote it back or raise it unprompted.
  • Only counsel, trainer and nutritionist may read it. It has its own scope, separate from the health journal.
  • To clear it, save it empty (UpdateInnerContext with an empty message). Each update replaces the whole record, and from then on nothing reads the old text. The store is append-only, though, so earlier versions stay in the log until an operator deletes them (see Privacy and data).