Training coaching
Training is the trainer aspect’s domain. A plan is built with you, reviewed before anything is live, and then followed on the Training card every day.
Plans are grounded in a real catalogue
Every exercise in a plan is a real entry in an embedded catalogue of 868 movements from free-exercise-db (public domain). Names, target muscles, equipment and step-by-step instructions always come from the catalogue, never from the model. When the model helps with a plan, it may only return catalogue ids from a shortlist it was given. Anything else is dropped and reported.
The server also works out, without asking the model:
- Weekly hard sets per body part (
weekly_sets_by_body_part). - The progression mechanic. This is one line describing how the plan advances, and it never claims “ascending load” for flat sets.
- The rationale and a status note that echoes any constraint you gave (“left shoulder injury — pressing suspended”).
Four ways to get a plan
| Route | How | Model involved? |
|---|---|---|
| Ask in chat | “make me a 4 day workout plan”. A create word, a training word and a plan word together trigger the deterministic plan action. Days (“4 days”, “3x”) and session length (“45 min”) are read from the text. | No. The plan is generated in Go and streamed as a draft deck to approve. |
| Design it on the plan screen | ⋯ → Training plan, then fill in the goal, days per week, session length, experience, equipment you actually have, and anything to design around. Tap Design my plan. | No (DraftPlan is deterministic). |
| Revise it | Ask luna for a change, for example “swap the deadlifts, my back is sore”. | Yes (RevisePlan). The result is judged before you see it. |
| Rebuild from photos | Sparkle button → Rebuild my plan from photos (a coach’s sheet, a whiteboard, a screenshot; PDFs on the phone app). | Yes (PlanFromImages, vision). Every movement is matched to the catalogue by name, and anything unmatched is dropped. |
Nothing is live until you save it. Drafts, revisions and photo readings
all come back unsaved. Save as my plan (or Save revision) calls
SavePlan, which rebuilds the plan against the catalogue and makes it
active. You can keep several saved plans (a winter block, a travel week) and
switch between them under My plans without rewriting them
(SetActivePlan).
To swap one movement by hand, search the catalogue from the plan screen
(“Search movements — “row”, “squat”…”). This uses SearchExercises, and the
catalogue attribution is shown with the results.
Loads: a dash until you lift
LUNA never derives a weight from body mass, experience or goal. Each
prescribed set says where its load came from (LoadSource):
| Source | Meaning |
|---|---|
| unspecified | Luna has never been told what you lift for this movement. The app shows a dash, never a number. |
| bodyweight | The catalogue lists the movement as bodyweight. |
| user entered | You typed it. |
| last session | Carried forward from what you actually lifted last time. |
| derived from 1RM | Computed from a one-rep max you stated. |
The session runner in the plan console is the only way a load enters the
system. You work through the session one set at a time, and each set is saved
to the server (LogSet) the moment you mark it done. It isn’t buffered
until the end, so a phone that kills the app mid-workout loses nothing. A
logged set records reps, load in kg (0 is a valid bodyweight set), an optional
RPE from 1 to 10, a warm-up flag and a note. Next week’s prescription is built
from these sets.
Unlocked trainer skills
With Periodization unlocked, plans gain week-by-week progression and a deload week. With Conditioning unlocked, training days end with a finisher from the catalogue. A locked skill produces exactly the plan you’d get without the feature. See Levels, traits and skills.
Form review from photos
Sparkle button → Judge my exercise form sends still frames, not
video, with the exercise name (ReviewWorkoutForm). Automatic video-to-frame
sampling is not built yet. One request looks at up to 3 images. If you
pick more frames, the app uses the first three and says so.
The critique goes through the judging ladder (below). If the judge dissents, you get Luna’s non-recommendation instead of the model’s critique.
The judging ladder
Every proposal the model makes that you might act on is checked before it is shown: plan revisions, plans read from photos, meal food choices, meal-photo estimates and form reviews. The verdict travels with the result:
- Concur: shown as is.
- Dissent: withheld. For a revision you get your unchanged plan back, and Luna says why.
- Unable to judge: shown but marked “not verified”. This is common for photos, because a text judge can’t see the image.
Deterministic plans (chat action and DraftPlan) and all the arithmetic
(targets, streaks, points) aren’t judged, because no model proposed them.
Free chat replies aren’t judged either: they stream token by token, so there
is no finished proposal to check. That is a known, open gap.