187 lines
15 KiB
JSON
187 lines
15 KiB
JSON
{
|
|
"format": "trainlog-session-generation-policy-v1",
|
|
"version": 1,
|
|
"policy_id": "session_generator_v1",
|
|
"status": "canonical_frozen",
|
|
"scientific_review_date": "2026-09-09",
|
|
"confidence": "moderate",
|
|
"scope": "Editable single-session resistance-training suggestions for adults; separate from frozen read-only TRAINING_KNOWLEDGE_V1.",
|
|
"numeric_rule_status": "All exact defaults, windows, thresholds, scores and caps are practical engineering conventions, not validated individualized prescriptions.",
|
|
"source_refs": ["acsm_2009", "acsm_2026_generator", "currier_2023", "grgic_2022", "kassiano_2022", "moran_navarro_2017_generator", "singer_2024_generator", "vieira_2022"],
|
|
"additional_references": [
|
|
{
|
|
"ref_id": "acsm_2026_generator",
|
|
"title": "American College of Sports Medicine Position Stand. Resistance Training Prescription for Muscle Function, Hypertrophy, and Physical Performance in Healthy Adults: An Overview of Reviews",
|
|
"authors_or_organization": "Currier BS and colleagues; American College of Sports Medicine",
|
|
"year": 2026,
|
|
"pmid": "41843416",
|
|
"doi": "10.1249/MSS.0000000000003897",
|
|
"url": "https://pubmed.ncbi.nlm.nih.gov/41843416/",
|
|
"type": "intervention_evidence",
|
|
"notes": "Overview of 137 systematic reviews: resistance training improves multiple outcomes; heavier loads favor strength, higher weekly volume favors hypertrophy; many other prescription variables do not consistently alter outcomes.",
|
|
"limitations": "Healthy adults and multiweek interventions, not validation of this one-session algorithm; searches current to October 2024. Does not validate an unknown MAX as 1RM.",
|
|
"accessed_on": "2026-09-09"
|
|
},
|
|
{
|
|
"ref_id": "moran_navarro_2017_generator",
|
|
"title": "Time course of recovery following resistance training leading or not to failure",
|
|
"authors_or_organization": "Moran-Navarro R and colleagues",
|
|
"year": 2017,
|
|
"pmid": "28965198",
|
|
"doi": "10.1007/s00421-017-3725-7",
|
|
"url": "https://pubmed.ncbi.nlm.nih.gov/28965198/",
|
|
"type": "intervention_evidence",
|
|
"notes": "Failure and nonfailure protocols produced different recovery courses even with matched total repetition volume.",
|
|
"limitations": "Ten trained men, bench press and squat, selected acute markers; cannot calibrate body-zone recovery from Trainlog history.",
|
|
"accessed_on": "2026-09-09"
|
|
},
|
|
{
|
|
"ref_id": "singer_2024_generator",
|
|
"title": "Give it a rest: a systematic review with Bayesian meta-analysis on the effect of inter-set rest interval duration on muscle hypertrophy",
|
|
"authors_or_organization": "Singer A and colleagues",
|
|
"year": 2024,
|
|
"pmid": "39205815",
|
|
"doi": "10.3389/fspor.2024.1429789",
|
|
"url": "https://pubmed.ncbi.nlm.nih.gov/39205815/",
|
|
"type": "intervention_evidence",
|
|
"notes": "Nine studies suggest a small hypertrophy advantage to rests exceeding 60 seconds, with broad uncertainty and little detected difference above 90 seconds.",
|
|
"limitations": "Small heterogeneous evidence base; does not establish exactly 120 seconds as universally optimal.",
|
|
"accessed_on": "2026-09-09"
|
|
}
|
|
],
|
|
"goals": {
|
|
"general": {"sets": 2, "repetitions": 10, "rest_seconds": 90, "sets_range": [1, 3], "repetitions_range": [8, 12], "rest_seconds_range": [60, 120]},
|
|
"strength": {"sets": 3, "repetitions": 6, "rest_seconds": 180, "sets_range": [2, 3], "repetitions_range": [5, 8], "rest_seconds_range": [180, 300]},
|
|
"hypertrophy": {"sets": 3, "repetitions": 10, "rest_seconds": 120, "sets_range": [2, 3], "repetitions_range": [8, 12], "rest_seconds_range": [90, 180]},
|
|
"endurance": {"sets": 2, "repetitions": 16, "rest_seconds": 60, "sets_range": [1, 3], "repetitions_range": [15, 20], "rest_seconds_range": [45, 90]}
|
|
},
|
|
"goal_range_interpretation": "Inclusive broad editable guidance, not RM zones, validated optimal intervals or hard physiological limits; default generation uses the single default values unless explicitly overridden, and then recomputes duration and load qualification.",
|
|
"zone_expansion": {
|
|
"full_body": ["chest", "back", "shoulders", "arms", "core", "glutes", "thighs", "calves"],
|
|
"upper_body": ["chest", "back", "shoulders", "arms"],
|
|
"chest": ["chest"],
|
|
"back": ["back"],
|
|
"shoulders": ["shoulders"],
|
|
"arms": ["arms"],
|
|
"core": ["core"],
|
|
"lower_body": ["glutes", "thighs", "calves"],
|
|
"glutes": ["glutes"],
|
|
"thighs": ["thighs"],
|
|
"calves": ["calves"]
|
|
},
|
|
"eligibility": {
|
|
"recording_mode": "SETS",
|
|
"tracking_mode": "REPS",
|
|
"knowledge_resolution": "resolved_family_variant_limited",
|
|
"allowed_confidence": ["high", "moderate"],
|
|
"require_runtime_exercise_id": true,
|
|
"require_explicit_equipment_compatibility": true,
|
|
"unknown_conditional_and_unlinked_capabilities": "exclude_with_reason",
|
|
"scientific_zone_role": "primary_or_secondary",
|
|
"persisted_zone_disagreement": "explain_without_mutation",
|
|
"equipment_choice": "Among available compatible contexts prefer newest qualifying working-load anchor, then bytewise equipment_id; select one context per exercise. MAX does not select a context."
|
|
},
|
|
"load": {
|
|
"lookback_seconds": 2419200,
|
|
"window": "0 <= reference_instant - occurrence_instant <= lookback_seconds",
|
|
"required_context": ["exact_exercise_id", "non_null_exact_equipment_id", "external_load_semantics", "no_known_execution_context_conflict"],
|
|
"priority": ["recent_repeated_performed_sets", "absent"],
|
|
"working_rule": "In the newest qualifying completed occurrence require at least proposed sets actual rows with positive finite weight and actual repetitions >= proposed repetitions. Reuse the minimum weight among those qualifying rows without increase. An occurrence with fewer qualifying rows cannot establish repeated-dose support.",
|
|
"actual_load_mode_compatibility": "Exact known scientifically compatible external equipment is required. Occurrence mode external qualifies; mode none qualifies only for actual-only shape with all targets absent and rest_seconds=0. This applies independently of exchange version and never rewrites stored mode. Explicit assistance or conflicting/unknown equipment never qualifies.",
|
|
"planned_load_mode": "Follow normal desktop plan invariants: absent numeric target weight means load_mode none; present target weight means external or assistance. Keep selected equipment resistance semantics separate from planning mode. Generator assistance numeric weight remains absent.",
|
|
"working_confidence": "uncertain",
|
|
"working_meaning": "Observed repetition completion only; effort, failure, technique, range and physiological readiness are not established. Warmup rows cannot be reliably separated.",
|
|
"max_rule": "No numeric prescription from explicit MAX. An occurrence-owned maximum without repetition count does not establish 1RM or any goal-specific repetition capacity. A compatible explicit MAX may be exposed only as context with explicit_max_present_no_numeric_prescription; target weight remains absent unless repeated actual-set evidence qualifies.",
|
|
"max_confidence": "uncertain",
|
|
"max_only_does_not_create_performed_sets": true,
|
|
"assistance": "omit_numeric_load_and_explain_assistance",
|
|
"bodyweight_or_unknown_semantics": "omit_numeric_load",
|
|
"machine_increment": "not_known; retain a qualifying observed actual load unchanged as an indicative editable value; invent no increment and perform no automatic rounding",
|
|
"progression": "none"
|
|
},
|
|
"exposure": {
|
|
"short_window_seconds": 86400,
|
|
"long_window_seconds": 259200,
|
|
"window": "0 <= reference_instant - occurrence_instant < window_seconds",
|
|
"timestamp_policy": "reuse_exact_TRAINING_KNOWLEDGE_V1_instant_comparison",
|
|
"invalid_timestamp": "Invalid reference input fails request validation; any invalid stored timestamp encountered by the required history reader fails analysis explicitly under the existing temporal contract. Return the specific error and no complete exposure or generation result; never skip malformed timestamps as outside-window data.",
|
|
"counted_rows": "completed-history actual SETS+REPS rows with repetitions > 0; weight may be absent; deduplicate by occurrence/set identity",
|
|
"excluded": ["draft", "target_only", "zero_performed_sets", "explicit_max_only", "continuous_activity", "future_occurrence"],
|
|
"zone_source": "resolved_scientific_interpretation; unknown history marked unclassified, never converted from names",
|
|
"primary_secondary": "separate integer counts per zone; one set counts once in each explicitly supported role; never sum role counts as equivalent effective sets",
|
|
"requested_zone_aggregation": "Expand the requested zone, then evaluate each distinct actual row once: primary if its scientific primary is in the expansion; otherwise secondary if any scientific secondary is in the expansion; otherwise neither. Primary wins over all secondary descendant matches. Do not add leaf counters to form parent counters.",
|
|
"summary_consistency": "For each 24h/72h summary, set_count=primary_count+secondary_count is the deduplicated number of recorded rows, not effective physiological sets; session_count is distinct matching session IDs; pattern_ids is the sorted distinct union from exactly those matching rows. Last exposure is the newest matching nonfuture actual-row occurrence across the complete queried history, independently of the windows, with its source session/occurrence IDs and scientific pattern IDs. Unknown or incomplete history cannot produce a complete summary claim.",
|
|
"recent_primary_sets_24h_threshold": 1,
|
|
"recent_secondary_sets_24h_threshold": 3,
|
|
"repeated_primary_sets_72h_threshold": 6,
|
|
"repeated_secondary_sets_72h_threshold": 12,
|
|
"status": "recent_exposure if either short threshold; repeated_exposure if either long threshold; both flags may coexist; otherwise no_threshold_observed, never recovered",
|
|
"warning_levels": {
|
|
"none": "No primary or secondary exposure threshold met in a successfully completed analysis; does not mean recovered or safe.",
|
|
"notice": "At least one secondary threshold met and no primary threshold met.",
|
|
"warning": "At least one primary threshold met, regardless of secondary flags; informational and nonblocking."
|
|
},
|
|
"unknown_history": "insufficient_information; zero observed classified sets does not prove no activity",
|
|
"user_continuation": "always_available; flags are informational, not a medical restriction or biological recovery estimate"
|
|
},
|
|
"selection": {
|
|
"max_exercises": 6,
|
|
"max_per_exact_pattern": 1,
|
|
"duplicate_exercise": "forbidden",
|
|
"pattern_overlap": "exclude candidate if any of its exact pattern IDs is already selected",
|
|
"optional_preferences": {
|
|
"preferred_exercise_ids": "soft preference on exact UUID; duplicate requested IDs have no extra effect",
|
|
"excluded_exercise_ids": "hard exclusion on exact UUID; wins over preferred",
|
|
"excluded_pattern_ids": "hard exclusion if any scientific pattern ID intersects the supplied known pattern IDs",
|
|
"precedence": "Availability, scientific eligibility, explicit exclusions, duplicate/diversity limits and duration fit are applied before coverage priority and score. Preference never creates an unavailable or unreviewed candidate.",
|
|
"unknown_ids": "Unknown exercise IDs yield no candidate and are reported as unavailable/unmatched preferences or exclusions; unknown pattern IDs fail request validation."
|
|
},
|
|
"recency": {
|
|
"same_exercise_window_seconds": 259200,
|
|
"same_pattern_window_seconds": 604800,
|
|
"window": "0 <= reference_instant - occurrence_instant < window_seconds",
|
|
"evidence": "At least one positive-repetition actual row in completed history; same exercise means exact UUID across equipment contexts, same pattern means nonempty intersection of resolved scientific pattern IDs. Count neither targets nor MAX-only occurrences; identity/pattern selection recency never authorizes cross-equipment load transfer.",
|
|
"application": "Apply each boolean recency penalty once, additively to existing zone penalties, with no cooldown exclusion. Exact boundary ages are outside their respective windows."
|
|
},
|
|
"score": {
|
|
"requested_primary_zone": 100,
|
|
"requested_secondary_zone_only": 60,
|
|
"new_primary_zone": 20,
|
|
"new_pattern": 30,
|
|
"qualifying_working_load_history": 5,
|
|
"preferred_exercise": 15,
|
|
"recent_same_exercise": -25,
|
|
"recent_same_pattern": -15,
|
|
"recent_primary_threshold_on_candidate_primary": -30,
|
|
"recent_secondary_threshold_on_candidate_primary": -10,
|
|
"repeated_primary_threshold_on_candidate_primary": -20,
|
|
"repeated_secondary_threshold_on_candidate_primary": -10,
|
|
"any_exposure_flag_on_candidate_secondary_zones": -10
|
|
},
|
|
"algorithm": "Greedy highest total score among eligible candidates fitting remaining duration; recompute coverage bonuses after each selection; tie by bytewise exercise_id then equipment_id. Each boolean score applies at most once. Primary and secondary match base scores are mutually exclusive.",
|
|
"group_coverage": "For full_body prefer an as-yet unrepresented upper/lower/core region before repeating a represented region whenever a fitting candidate exists. For upper_body prefer one push and one pull before further upper-body patterns whenever available. For lower_body prefer knee extension/hip extension and knee flexion before other functions whenever available. Apply these as candidate-pool priorities before numeric score.",
|
|
"upper_push_patterns": ["horizontal_push", "vertical_push"],
|
|
"upper_pull_patterns": ["horizontal_pull", "vertical_pull"],
|
|
"lower_extension_patterns": ["knee_dominant", "hip_dominant", "single_joint_knee_extension"],
|
|
"lower_flexion_patterns": ["single_joint_knee_flexion"],
|
|
"coverage_shortage": "report actual missing patterns/regions; never invent exercises or fill time with redundant variants"
|
|
},
|
|
"duration": {
|
|
"presets_minutes": [30, 45, 60],
|
|
"custom_min_minutes": 10,
|
|
"custom_max_minutes": 120,
|
|
"preparation_seconds": 300,
|
|
"setup_and_transition_seconds_per_exercise": 60,
|
|
"estimated_seconds_per_repetition": 4,
|
|
"exercise_seconds_formula": "60 + sets * repetitions * 4 + (sets - 1) * rest_seconds",
|
|
"session_seconds_formula": "300 + sum(exercise_seconds)",
|
|
"budget_rule": "Do not exceed requested estimate, shorten rests, add sets, or duplicate patterns to fill spare time. Return a shorter session with explanation when candidates or diversity are limited.",
|
|
"precision": "planning estimate only; preparation is a time allowance, not a performed exercise or individualized warmup protocol"
|
|
},
|
|
"guidance": {
|
|
"effort": "Use a controllable load and finish with repetitions still possible; adjust downward or stop if the proposed repetitions cannot be completed with the intended technique.",
|
|
"load": "Starting suggestion only; confirm equipment and adjust after warming up. No logged value proves today's capability.",
|
|
"rest": "Rest longer if needed; actual session time may exceed the estimate.",
|
|
"recent_exposure": "Recent recorded exposure; recovery is not measured. Review how you feel; you may continue, modify, or choose another zone."
|
|
}
|
|
}
|