What problem does this solve?
This is a follow-up to #327 and PR #333. That work introduced planned versus completed weekly muscle volume; this proposal improves the underlying muscle-weight metadata by preserving explicit zero-credit relationships without changing the current 0.4 secondary-muscle fallback.
openGym currently assigns 1.0 to primary muscles and 0.4 to every secondary muscle. That remains a useful fallback, but some exercise metadata includes muscles that should not receive effective hypertrophy-set credit. They may be anatomical stabilizers, antagonists, or inherited catalogue associations rather than meaningful contributors to the training stimulus.
Removing those muscles from metadata is not ideal because it loses an explicit, reviewable decision. The data should be able to say that a muscle remains associated with an exercise while contributing zero effective sets:
muscleWeights: {
chest: 1,
triceps: 0.4,
biceps: 0,
}
Today, musclesOf() only retains explicit weights greater than zero:
if (Number.isFinite(weight) && weight > 0) snapshot[slug] = weight
As a result, an explicit zero cannot survive the effective-weight resolution or exerciseMuscleSnapshot(). It is therefore impossible to distinguish between a deliberately reviewed zero, an exercise-muscle pair that has not been reviewed, and metadata that was accidentally removed.
There is also an important behavioral constraint: returning zero-valued keys directly from musclesOf() would be unsafe because consumers such as strengthOf() currently treat every returned key as recently trained without checking its numeric value.
The global 0.4 value is not the main issue here. Current evidence does not justify replacing it with another universal coefficient. The immediate improvement is to preserve explicit zeros for reviewed exercise-muscle relationships while ensuring they never contribute to effective training calculations.
Proposed approach
1. Preserve explicit zero-weight overrides
Use the existing owner-approved correction layer in frontend/src/lib/exercise-muscle-batch-1.js rather than modifying the generated exercises-data.js catalogue.
Conceptually:
export const USER_EXERCISE_MUSCLE_OVERRIDES = Object.freeze({
'0150': {
muscleWeightOverrides: {
triceps: 0,
},
},
'0606': {
muscleWeightOverrides: {
chest: 0,
triceps: 0,
},
},
})
The exact field name is open to maintainer preference. The important contract is that zero is a deliberate persisted value, not the absence of metadata.
2. Separate complete metadata from effective stimulus
Introduce a zero-aware resolver, conceptually muscleWeightsOf(ex), that returns the complete reviewed weight map, including explicit zeros.
Keep musclesOf(ex) as the effective-stimulus view and return only weights greater than zero:
export function musclesOf(ex) {
return Object.fromEntries(
Object.entries(muscleWeightsOf(ex))
.filter(([, weight]) => weight > 0)
)
}
This keeps current volume, fatigue, recovery, strength, and body-map consumers safe without requiring every caller to understand zero-weight metadata.
3. Preserve zero values in snapshots
exerciseMuscleSnapshot() should store the complete map from the zero-aware resolver rather than the positive-only effective map. This preserves reviewed zero values for custom exercises and historical entries even if the catalogue entry is later changed or deleted.
4. Preserve taxonomy separately
muscleGroupsOf() should continue to expose anatomical/taxonomic membership independently from effective-set contribution. A muscle with weight 0 may remain inspectable and auditable, but it must not shade the body map or contribute to effective volume.
Initial reviewed candidates
The first small correction batch could assign explicit zero effective-set credit to mappings that currently appear to overstate meaningful hypertrophy stimulus:
- Triceps in pull-ups and lat pulldowns.
- Chest and triceps in T-bar rows.
- Biceps in chest presses.
- Hamstrings in calf presses.
- Hamstrings in seated hip abduction.
- Calves in hack squats and leg presses when no dynamic plantar flexion occurs.
- Biceps in pec-deck or machine-fly movements.
- Deltoids in direct triceps extensions when their role is only stabilization.
Each correction should remain an explicit override so it can be independently reviewed or revised later.
Acceptance criteria
Expected files
frontend/src/lib/exercise-muscle-batch-1.js
frontend/src/lib/muscles.js
frontend/src/lib/muscles.test.js
frontend/src/lib/recovery.test.js
frontend/src/lib/strength-exercises.test.js
frontend/src/lib/exercises-data.js should remain unchanged because it is generated. Plan.jsx and Stats.jsx should not require direct changes because they already consume the shared load helpers.
Out of scope
- Replacing the global
0.4 fallback with 0.5 or another universal value.
- Recalibrating all catalogue exercises in one change.
- Presenting exercise-muscle weights as exact physiological equivalences.
- Removing a muscle from metadata solely because its effective weight is zero.
Evidence context
The best current aggregate evidence found that counting indirect sets as 0.5 fit hypertrophy outcomes better than counting them as 0 or 1. However, only those three models were compared, and the authors explicitly describe fractional counting as a heuristic rather than a universal physiological coefficient. This proposal therefore keeps the existing fallback and focuses only on explicit, reviewable zero-credit relationships.
If this direction makes sense, we would be happy to implement it and open a focused PR.
Dependencies
What problem does this solve?
This is a follow-up to #327 and PR #333. That work introduced planned versus completed weekly muscle volume; this proposal improves the underlying muscle-weight metadata by preserving explicit zero-credit relationships without changing the current
0.4secondary-muscle fallback.openGym currently assigns
1.0to primary muscles and0.4to every secondary muscle. That remains a useful fallback, but some exercise metadata includes muscles that should not receive effective hypertrophy-set credit. They may be anatomical stabilizers, antagonists, or inherited catalogue associations rather than meaningful contributors to the training stimulus.Removing those muscles from metadata is not ideal because it loses an explicit, reviewable decision. The data should be able to say that a muscle remains associated with an exercise while contributing zero effective sets:
Today,
musclesOf()only retains explicit weights greater than zero:As a result, an explicit zero cannot survive the effective-weight resolution or
exerciseMuscleSnapshot(). It is therefore impossible to distinguish between a deliberately reviewed zero, an exercise-muscle pair that has not been reviewed, and metadata that was accidentally removed.There is also an important behavioral constraint: returning zero-valued keys directly from
musclesOf()would be unsafe because consumers such asstrengthOf()currently treat every returned key as recently trained without checking its numeric value.The global
0.4value is not the main issue here. Current evidence does not justify replacing it with another universal coefficient. The immediate improvement is to preserve explicit zeros for reviewed exercise-muscle relationships while ensuring they never contribute to effective training calculations.Proposed approach
1. Preserve explicit zero-weight overrides
Use the existing owner-approved correction layer in
frontend/src/lib/exercise-muscle-batch-1.jsrather than modifying the generatedexercises-data.jscatalogue.Conceptually:
The exact field name is open to maintainer preference. The important contract is that zero is a deliberate persisted value, not the absence of metadata.
2. Separate complete metadata from effective stimulus
Introduce a zero-aware resolver, conceptually
muscleWeightsOf(ex), that returns the complete reviewed weight map, including explicit zeros.Keep
musclesOf(ex)as the effective-stimulus view and return only weights greater than zero:This keeps current volume, fatigue, recovery, strength, and body-map consumers safe without requiring every caller to understand zero-weight metadata.
3. Preserve zero values in snapshots
exerciseMuscleSnapshot()should store the complete map from the zero-aware resolver rather than the positive-only effective map. This preserves reviewed zero values for custom exercises and historical entries even if the catalogue entry is later changed or deleted.4. Preserve taxonomy separately
muscleGroupsOf()should continue to expose anatomical/taxonomic membership independently from effective-set contribution. A muscle with weight0may remain inspectable and auditable, but it must not shade the body map or contribute to effective volume.Initial reviewed candidates
The first small correction batch could assign explicit zero effective-set credit to mappings that currently appear to overstate meaningful hypertrophy stimulus:
Each correction should remain an explicit override so it can be independently reviewed or revised later.
Acceptance criteria
0through1are accepted.1.0primary and0.4secondary behavior.Expected files
frontend/src/lib/exercises-data.jsshould remain unchanged because it is generated.Plan.jsxandStats.jsxshould not require direct changes because they already consume the shared load helpers.Out of scope
0.4fallback with0.5or another universal value.Evidence context
The best current aggregate evidence found that counting indirect sets as
0.5fit hypertrophy outcomes better than counting them as0or1. However, only those three models were compared, and the authors explicitly describe fractional counting as a heuristic rather than a universal physiological coefficient. This proposal therefore keeps the existing fallback and focuses only on explicit, reviewable zero-credit relationships.If this direction makes sense, we would be happy to implement it and open a focused PR.
Dependencies