This is how to answer a ticket about workouts not appearing, appearing twice, or disappearing. It assumes you can read the tenant database.
== "I logged a workout and it is not there" ==
Almost always a sync that has not completed rather than data that is gone. The apps log locally first and sync afterwards, deliberately: a set has to persist in under 100ms and a network round trip cannot promise that.
Ask, in this order:
# '''Is the phone online now?''' The app queues offline and drains on reconnect. A member on airplane mode has the session, it just has not left the device. # '''Did they force-quit during the session?''' The draft persists after every set change, so it should resume. If it did not, that is a real bug and worth an engineering ticket with the device and OS version. # '''Are they looking at the right day?''' The log date is the member's LOCAL day, taken from the client. Somebody who trained at 00:30 sees it under that date, not the previous one.
Check the server side with:
SELECT id, client_uuid, log_date, status, total_sets, created_at FROM workout_sessions WHERE user_id = ? ORDER BY started_at DESC LIMIT 10;
A row with status = 'in_progress' and an old started_at is a
session the member never finished. That is not a defect; the app will still show it
and they can complete or discard it.
== "The same workout is in there twice" ==
This should not happen, and if it does it is worth escalating rather than deleting one by hand.
Sessions are keyed on (user_id, client_uuid) with a UNIQUE index, so a
replayed sync updates in place. Two rows means two different UUIDs, which means
either two genuinely separate sessions or a client that minted a second UUID for
one workout.
Workouts read back from Apple Health or Health Connect are keyed on
(user_id, external_uid), also UNIQUE, so a session Loopa wrote out and
then read back in cannot land twice.
SELECT id, client_uuid, external_uid, source, started_at, ended_at, total_sets FROM workout_sessions WHERE user_id = ? AND log_date = ?;
If the two rows have different sources - one loopa and one
healthkit - the member logged in Loopa and a watch recorded the same
session independently. Deleting the platform-sourced one is the right fix, and it
is worth an engineering note so the time-window dedupe can be tightened.
== "My calories burned doubled" ==
A completed session is mirrored into the daily activity ledger so the dashboard, the reports and the challenge snapshots see it. The mirror's id is stored on the session, and a re-finalised session '''updates''' that mirror rather than adding a second one.
If a member's burn looks doubled, check whether the day carries two activity sessions for one workout:
SELECT id, activity_session_id, log_date, energy_kcal FROM workout_sessions WHERE user_id = ? AND log_date = ?;
A session with activity_session_id IS NULL that nevertheless has a
mirror on the day is the shape to escalate.
== "Why does it say my calories are estimated?" ==
Because they are, unless the health platform reported measured active energy for that session. Loopa estimates from the exercise's MET value, the member's body weight and the session's elapsed time. That is an average over a population applied to one person, and it is labelled rather than presented as a measurement.
This is also why '''eating back exercise calories is off by default'''. Both sides of the estimate are noisy and they compound. The setting exists because members ask for it; the default states our position. It is under More, then Preferences, then Workouts.
== Free versus Premium ==
Do not tell a member that logging is a paid feature. It is not, and the pricing page says so.
'''Free:''' logging sessions, the whole exercise library, custom exercises, personal record detection, full history, three saved routines, and reading and replying to a coach's comments.
'''Premium:''' programs and the training calendar, the volume and strength analytics, progressive overload suggestions, unlimited routines, and CSV export.
A member who hits the routine cap gets a 402 with the upgrade copy. A member told they must pay to save a set has hit a bug - escalate it.
This is how to answer a ticket about workouts not appearing, appearing twice, or disappearing. It assumes you can read the tenant database. == "I logged a workout and it is not there" == Almost always a sync that has not completed rather than data that is gone. The apps log locally first and sync afterwards, deliberately: a set has to persist in under 100ms and a network round trip cannot promise that. Ask, in this order: # '''Is the phone online now?''' The app queues offline and drains on reconnect. A member on airplane mode has the session, it just has not left the device. # '''Did they force-quit during the session?''' The draft persists after every set change, so it should resume. If it did not, that is a real bug and worth an engineering ticket with the device and OS version. # '''Are they looking at the right day?''' The log date is the member's LOCAL day, taken from the client. Somebody who trained at 00:30 sees it under that date, not the previous one. Check the server side with: <syntaxhighlight lang="sql"> SELECT id, client_uuid, log_date, status, total_sets, created_at FROM workout_sessions WHERE user_id = ? ORDER BY started_at DESC LIMIT 10; </syntaxhighlight> A row with <code>status = 'in_progress'</code> and an old <code>started_at</code> is a session the member never finished. That is not a defect; the app will still show it and they can complete or discard it. == "The same workout is in there twice" == This should not happen, and if it does it is worth escalating rather than deleting one by hand. Sessions are keyed on <code>(user_id, client_uuid)</code> with a UNIQUE index, so a replayed sync updates in place. Two rows means two different UUIDs, which means either two genuinely separate sessions or a client that minted a second UUID for one workout. Workouts read back from Apple Health or Health Connect are keyed on <code>(user_id, external_uid)</code>, also UNIQUE, so a session Loopa wrote out and then read back in cannot land twice. <syntaxhighlight lang="sql"> SELECT id, client_uuid, external_uid, source, started_at, ended_at, total_sets FROM workout_sessions WHERE user_id = ? AND log_date = ?; </syntaxhighlight> If the two rows have different sources - one <code>loopa</code> and one <code>healthkit</code> - the member logged in Loopa and a watch recorded the same session independently. Deleting the platform-sourced one is the right fix, and it is worth an engineering note so the time-window dedupe can be tightened. == "My calories burned doubled" == A completed session is mirrored into the daily activity ledger so the dashboard, the reports and the challenge snapshots see it. The mirror's id is stored on the session, and a re-finalised session '''updates''' that mirror rather than adding a second one. If a member's burn looks doubled, check whether the day carries two activity sessions for one workout: <syntaxhighlight lang="sql"> SELECT id, activity_session_id, log_date, energy_kcal FROM workout_sessions WHERE user_id = ? AND log_date = ?; </syntaxhighlight> A session with <code>activity_session_id IS NULL</code> that nevertheless has a mirror on the day is the shape to escalate. == "Why does it say my calories are estimated?" == Because they are, unless the health platform reported measured active energy for that session. Loopa estimates from the exercise's MET value, the member's body weight and the session's elapsed time. That is an average over a population applied to one person, and it is labelled rather than presented as a measurement. This is also why '''eating back exercise calories is off by default'''. Both sides of the estimate are noisy and they compound. The setting exists because members ask for it; the default states our position. It is under More, then Preferences, then Workouts. == Free versus Premium == Do not tell a member that logging is a paid feature. It is not, and the pricing page says so. '''Free:''' logging sessions, the whole exercise library, custom exercises, personal record detection, full history, three saved routines, and reading and replying to a coach's comments. '''Premium:''' programs and the training calendar, the volume and strength analytics, progressive overload suggestions, unlimited routines, and CSV export. A member who hits the routine cap gets a 402 with the upgrade copy. A member told they must pay to save a set has hit a bug - escalate it.