Skip to content

history: one workoutAt(w), replacing the copies that had drifted - #407

Merged
DuarteSantos8 merged 1 commit into
DuarteSantos8:mainfrom
kurktchiev:gh/workout-at
Oct 9, 2026
Merged

DuarteSantos8 merged 1 commit into
DuarteSantos8:mainfrom
kurktchiev:gh/workout-at

Conversation

@kurktchiev

@kurktchiev kurktchiev commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

"When did this workout happen" was written by hand ten times in eight files, each as
w.start || new Date(w.d).getTime() or a close variant: lib/coach-insights.js,
lib/effort.js, lib/muscles.js, lib/recovery.js, lib/strength-exercises.js
(two copies), lib/coach-demo.js, views/Stats.jsx (two copies), and the MCP
server's muscle_balance in mcp/src/tools.js.

new Date('2026-09-22') is UTC midnight, which any negative UTC offset drags
back into the day before. Every other date helper in the app parses local
noon so no timezone or DST shift can move the day. And ||
discards a legitimate start of 0.

lastWorkSetAt and the effort/recovery windows feed the retained-strength
and fatigue decay off this, so imported history with no start was dated at
UTC midnight instead of local noon: up to a day early west of UTC (17 h at
UTC-5), and nothing reported it. muscleBalanceWindow and the Stats volume/last-trained
numbers dated their own cutoffs the same way, which can move a workout in or
out of a window right at the edge.

One exported workoutAt in history.js now answers it, and every call site
routes through it, the MCP server included (it already imports history.js),
so there's one rule to get right. exercise-history.js
already had this right in its own local startOf; it now shares the same
function instead of keeping a correct copy of its own next to the wrong ones.
entriesWithId in strength-exercises.js keeps -Infinity for the undated
case on purpose, because isNewerOccurrence compares with !== then >,
and a NaN pair would answer "not equal, not greater" instead of falling
through to insertion order.

frontend 9 new tests in workout-at.test.js, run with npx vitest run --maxWorkers=2, including a source-tree grep that fails if any file outside
history.js, in frontend/src or mcp/src, hand-rolls the pattern again.
7 of the 9 fail against the old code (checked by reverting the fix and
re-running), and the grep test names all eight offending files. With the fix
in, the full frontend, mcp and api suites pass on 39bc71e.

Conflicts with two open PRs, beyond the ones each already has with main:

🤖 Generated with Claude Code

"When did this workout happen" was written by hand ten times in eight
files, each as w.start || new Date(w.d).getTime() or a close variant:

  lib/coach-insights.js, lib/effort.js, lib/muscles.js, lib/recovery.js,
  lib/strength-exercises.js (two copies), lib/coach-demo.js, views/Stats.jsx (two copies),
  and the MCP server's muscle_balance in mcp/src/tools.js

new Date('2026-09-22') is UTC midnight, which any negative UTC offset drags
back into the day before. Every other date helper in the app parses local
noon precisely so no timezone or DST shift can move the day. And `||`
discards a legitimate start of 0.

lastWorkSetAt and the effort/recovery windows feed the retained-strength
and fatigue decay off this, so imported history with no start was dated
at UTC midnight instead of local noon: up to a day early west of UTC
(17 h at UTC-5), and nothing reported it. muscleBalanceWindow and the Stats volume/last-
trained numbers dated their own cutoffs the same way, moving a workout in
or out of a window at the edge.

One exported workoutAt in history.js now answers it, and every call site
routes through it, the MCP server included (it already imports
history.js), so there is one rule to get right. exercise-history.js
already had this right in its own local startOf; it now shares the same
function instead of keeping a correct copy of its own. entriesWithId in
strength-exercises.js keeps -Infinity for the undated case on purpose,
because isNewerOccurrence compares with !== then >, and a NaN pair would
answer "not equal, not greater" instead of falling through to insertion
order.

frontend 9 new tests in workout-at.test.js, including a source-tree grep
that fails if any file outside history.js, in frontend/src or mcp/src,
hand-rolls the pattern again.
7 of the 9 fail against the old code (checked by stashing the fix and
re-running); the grep test names all eight offending files.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
crstnmac added a commit to crstnmac/openGym that referenced this pull request Oct 9, 2026
@DuarteSantos8
DuarteSantos8 merged commit 117072f into DuarteSantos8:main Oct 9, 2026
4 checks passed
@kurktchiev
kurktchiev deleted the gh/workout-at branch October 9, 2026 15:34
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