Skip to content

fix(coach): a bonus set no longer reads as a stall the athlete never had - #287

Merged
DuarteSantos8 merged 1 commit into
DuarteSantos8:mainfrom
kurktchiev:gh/coach-bonus-sets
Sep 28, 2026
Merged

DuarteSantos8 merged 1 commit into
DuarteSantos8:mainfrom
kurktchiev:gh/coach-bonus-sets

Conversation

@kurktchiev

Copy link
Copy Markdown
Contributor

readSession in api/coach/core/payload.js is a deliberate duplicate of the one in
frontend/src/lib/progression.js. The two runtimes share no build step, the same
trade-off server.js already makes for effectiveRoutineId. The copy missed issue #233:
the frontend grades only the sets the plan asked for, this one graded every set logged.

So a fourth set taken short of the goal on a clean 3x10 is a hit in the app and a miss
in the Coach's payload. stallCount reads only this copy, so it reports a stall that
did not happen, and the review and the next proposal are built on it. Two such sessions
and the Coach starts suggesting a deload.

The same logged.slice(0, Math.max(1, planned)) as the frontend, in the same place.
count deliberately keeps reading every logged set: extra sets are the dimension
bodyweight work grows once reps hit their ceiling (#33), they just do not decide whether
the prescription was met.

The header comment claimed coach-parity.test.js pinned these rules against the
frontend's originals. It pins three of the five: modeOf, isBw, isPerSide. isWarmupSet
and readSession were pinned by nothing, which is how this drifted without anything
noticing. api/test/payload-parity.test.js pins them now, and it has to be its own file:
it imports the frontend's real readSession, and a vitest test cannot import into a
node:test file or back.

The new test fails against the old payload.js.

🤖 Generated with Claude Code

`readSession` in api/coach/core/payload.js is a deliberate duplicate of the one in
frontend/src/lib/progression.js. The two runtimes share no build step, the same
trade-off server.js already makes for effectiveRoutineId. The copy missed issue DuarteSantos8#233:
the frontend grades only the sets the plan asked for, this one graded every set logged.

So a fourth set taken short of the goal on a clean 3x10 is a hit in the app and a miss
in the Coach's payload. `stallCount` reads only this copy, so it reports a stall that
did not happen, and the review and the next proposal are built on it. Two such sessions
and the Coach starts suggesting a deload.

The same `logged.slice(0, Math.max(1, planned))` as the frontend, in the same place.
`count` deliberately keeps reading every logged set: extra sets are the dimension
bodyweight work grows once reps hit their ceiling (DuarteSantos8#33), they just do not decide whether
the prescription was met.

The header comment claimed coach-parity.test.js pinned these rules against the
frontend's originals. It pins three of the five: modeOf, isBw, isPerSide. isWarmupSet
and readSession were pinned by nothing, which is how this drifted without anything
noticing. api/test/payload-parity.test.js pins them now, and it has to be its own file:
it imports the frontend's real readSession, and a vitest test cannot import into a
node:test file or back.

The new test fails against the old payload.js.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@DuarteSantos8
DuarteSantos8 merged commit a62fb35 into DuarteSantos8:main Sep 28, 2026
4 checks passed
@DuarteSantos8

Copy link
Copy Markdown
Owner

Thanks @kurktchiev, and good catch on the server copy of readSession. The parity test is a nice guard.

Released in v1.3.9: https://github.com/DuarteSantos8/openGym/releases/tag/v1.3.9

@kurktchiev
kurktchiev deleted the gh/coach-bonus-sets branch September 29, 2026 11:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants