The phone and PC each compute a nominally SHARED manual-workout budget over
the same merged records, and disagreed on both halves of it.
The cap: _constants.py has said 10 per 30 days since 298daf0; the Dart mirror
was still 5, so between 5 and 9 the phone hard-blocked the form for a workout
the PC would have accepted and credited. The stricter side wins, so this cost
logged workouts rather than granting extra ones.
The counting rule: count_in_window counts ENTRIES ("each logged manual workout
consumes its own budget slot"), while countManualBudget built a Set of date
strings and counted DAYS -- despite a docstring claiming it mirrored the PC.
Three workouts on one day read 3/2 on the PC, over its 7-day cap, but 1/2 on
the phone, which kept accepting. Both now report 3 for that input. Per-entry is
the correct semantic because each entry separately earns weekly-count and
shutdown credit, so each must separately cost budget.
The wire fixture could never have caught either: the caps and the counting rule
never travel on the wire. The comment claiming it was "the tripwire that
catches drift" was wrong and is corrected. The real guard,
TestCrossLanguageBudgetConstants, parses manual_workout.dart and compares it to
the imported Python constants -- one test that fails on EITHER side's drift.
Asserting a Python constant against a Python literal would have stayed green
through 298daf0, which is the drift that actually happened.
Also: the history volume chart summed targetWeight x targetSets x targetReps,
so a session where every set failed plotted identically to one completed in
full -- the line only moved when progression changed the target. It now sums
weight x doneReps over the logged sets. On today's real session that is 2790 ->
1440 kg, because 5 sets of bench press were logged at 0 reps and were being
counted at full credit. No targetWeight fallback per set: weight is
non-nullable and always serialized, and substituting the target would overstate
a set the user never did.
design.md/dfesign_v2.md: record that the Crucial (progress lost on exit) and
High (sound + vibration) items are done, that breaks are still per-set, and
that the warmup fraction shipped as 4/5 -- neither the 2/3 nor the 3/4 the
specs asked for, and 4/5 is what is wanted.
Verified on the phone (release build, signed with the shared key, installed
with adb install -r so the workout history survived); 907 Python and 313 Dart
tests pass with the coverage bar green.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A4y93ZSnk2w5LH3B12LHNc
3.4 KiB
Why: Stronglift app on my rooted device stopped working, we need a new app for tracking workout on that note please disable screen locker functionality until app is ready to go and fully tested functionally
Functional Requirements: Tracks workouts (current {sets}x{reps}x{weight (in kg)}): Workout A: Dumbbell Lunge 5x12x7.5 Dumbbell Bench Press 5x12x22.5 Dumbbell Row 4x6x22.5 Dumbbell Curl 3x12x12.5
Workout B:
Dumbbell Romanian Deadlift 5x7x27.5
Dummbbell Overhead Press 5x12x7.5
Dumbbell Bench Press 5x12x22.5
Situp 3x30x10
Exercisees succeeded means that the user was able to do ALL sets with ALL reps Automatically increases weight (in increments of 2.5kg) or number of reps (if maximum weight of 27.5 kg was reached for given exercise (see Dumbbell Romanian Deadlift) Situp has maximum weight of 10kg) if user succeeded in doing this exercise in a continuous way for between 1-5 days in a row (selectable by user unless max weight reached in which case 27.5 kg should always be chosen) automatically decreases weight (in decrements of 2.5kg) if user failed to do the exercise for 1-5 days in a row (selectable by user) automatically decreases weight if user had a break from using the app Tracks how much time workout took -> Fully automatically, user CANNOT set it manually Adds optional warmup exercises (With weight equal 2/3 of target weight (rounding DOWN to nearest increment of 2.5kg) and always having 5 reps exactly and exactly one set) before each exercise (after warmup 3 minutes break too) SUPERSEDED (2026-08-09): the warmup fraction shipped as 4/5, not 2/3 (nor the 3/4 in dfesign_v2.md). 4/5 is confirmed intended; see Exercise.warmupWeight in workout_app/lib/models/exercise.dart. adds breaks between exercises (3 minutes if exercise succeeded and 5 minutes if it failed) The user selects exercise as done by tapping on a circle with number of reps for this exercise, exercises are organized in rows where one row = one full set of one exercise, tapping on a circle again means that the user failed to do the exercise and it decreases the rep by "1" tappign again further reduces this count, if user holds finger over the specific circle they can reset the state of this circle (which should cancel any failed/succeed state) shows history of workouts and a graph for showing progress Crucial: The app should be able to communicate with this pc (arch linux) and inform it if the user had succeed to do the exercises and transfer full info about todays workout to the pc, crucially: time and how many sets reps and weight was done, change screen locker if needed The app should be capable of working in the background without any problem and display status notifications allowing user to click on "done rep" from the status bar After break time is over app should play a sound and vibrate the phone and generally point the user attention towards the app
Technical Requirements: App should work on rooted and unrooted phones with minimum android version of at least 12 Full test coverage (100%) (but first check the functionality and if the functionality fully works and is approved by user THEN start writing ANY tests at all please) I connected an unrooted phone with adb on to the pc use it for testing
Nice to have: make it work on both desktops (linux only is fine) and android phones (just android is fine)