7/9 - Released
|See Changelog
Skip to main content

Progression Engine v2

Why It Matters​

  • Unlocks tier-aware progression so powerlifters and tinkers can script complex programs (GZCLP, 5/3/1) without touching code.
  • Preserves friendly authoring for existing playbooks by extending condition/action blocks rather than introducing a DSL.
  • Lines up with monetisation strategy by gating set-level recommendations and premium playbooks behind role-based permissions.
  • Strengthens observability and simulation tooling so coaches can validate changes before athletes touch the bar.

Headline Capabilities​

Enhanced Playbook Authoring​

  • Tier & Stage Awareness: Rules can target tiers (T1–T3) and stages (STAGE_1–3) to rotate templates automatically.
  • Richer Conditions: Support for weekly modifiers, program blocks, training-max thresholds, cross-exercise volume, and more.
  • Action Toolkit: Adjust training max (absolute or percent), enforce pyramid templates, set/rep/rest targets, allocate assistance volume, and flag custom state.
  • Metadata & Premium Flag: isPremium and metadata fields unlock future pricing tiers without breaking legacy playbooks.

Runtime Execution​

  • Program Context Ingestion: Pulls weekly modifiers, coach overrides, and block metadata before evaluating rules.
  • Workout Context Summary: Computes total and per-tier volume, set counts, and skipped set ratios for cross-exercise logic.
  • Adaptive State Model: Stores tier stage history, training max, custom flags, and cycle week for each exercise snapshot.
  • Dual Edition Output: Generates community-edition (uniform) or full-edition (set-specific) recommendations depending on permissions.
  • Simulation Hooks: simulatePlaybook accepts overrides for state, modifiers, and tiers to test scenarios on demand.

Effective Workout Integration​

  • Suggestions propagate to Effective Workout targets: set templates, rep ranges, rest timers, tier stage, and assistance goals.
  • Coach overrides still trump automation—the engine honours absolute targets and protective overrides before firing actions.

Feature Walkthrough​

Sam completes his heavy squat session with all reps ✔️

  • Rule checks TIER_EQUALS T1 + TIER_STAGE_EQUALS Stage 1
  • ADVANCE_TIER_STAGE → Stage 2, ADJUST_TRAINING_MAX +5 kg
  • SET_SET_TEMPLATE forces pyramid next week, rest of metadata stored
  • Effective Workout shows 4×3–5 pyramid for the next session

Deep Dive Examples​

1. Sam & Coach Alex – Weekly Modifier Driven Deload​

Scenario: Alex schedules a deload in Week 4 using the weekly modifier builder.

Weekly Modifier Snapshot
{
"weekNumber": 4,
"nameAtEnrollment": "Deload Week",
"descriptionAtEnrollment": "Reduce load and reps by 20%",
"weightMultiplierAtEnrollment": 0.8,
"repsMultiplierAtEnrollment": 0.8,
"rpeMultiplierAtEnrollment": 0.85
}
  • Listener injects modifiers into ProgramContext.
  • Engine sees weightMultiplier < 0.9 → _shouldBlockProgression returns true.
  • ProgressionState still increments consecutiveSuccesses so Sam’s streak is preserved.
  • Effective Workout pulls the scaled targets from the modifier rather than progression suggestions.
  • When Sam starts Week 5, the modifier no longer applies, progression resumes.

2. Alex Adds a Peak-Block Rule for Stage 3​

Playbook Rule Snippet
{
"order": 3,
"conditions": [
{ "type": "TIER_EQUALS", "value": "T1" },
{ "type": "TIER_STAGE_EQUALS", "value": "STAGE_3" },
{ "type": "TRAINING_BLOCK_EQUALS", "value": "PEAKING" },
{ "type": "TRAINING_MAX_PERCENT_REACHED", "operator": "GTE", "value": 0.95 }
],
"actions": [
{ "type": "SET_SET_TEMPLATE", "template": "PYRAMID_DESCENDING" },
{ "type": "SET_SET_COUNT", "value": 3 },
{ "type": "SET_REST_TARGET", "seconds": 240 },
{ "type": "FLAG_CUSTOM_STATE", "key": "tmRetestDue", "value": true }
],
"userMessage": "You're in peak mode: reverse pyramid with 4 min rest. TM retest next week."
}
  • Once Alex switches Sam’s training block to “Peaking”, the rule fires only when Sam reaches Stage 3 and lifts ≥95 % of TM.
  • Effective Workout now shows descending pyramid, longer rest, and surfaces the custom flag so Alex can retest Sam’s TM.
  • If Sam fails a set, the Stage-Reset rule in the spec takes over and removes the retest flag automatically.

3. Tier-Stacked Volume Control for Accessories​

Coach Alex notices Sam’s T2 posterior chain work is climbing too high. He adds a guard rule:

Cross-Tier Volume Guard
{
"conditions": [
{ "type": "TIER_EQUALS", "value": "T1" },
{ "type": "CROSS_EXERCISE_VOLUME", "targetTier": "T2", "operator": "GT", "value": 4000 }
],
"actions": [
{ "type": "SET_ASSISTANCE_VOLUME", "tier": "T3", "totalReps": 60 },
{ "type": "FLAG_CUSTOM_STATE", "key": "accessoryVolumeManaged", "value": true },
{ "type": "SET_REST_TARGET", "seconds": 120 }
]
}
  • Sam’s RDL + glute bridge combo logs >4000 kg of Tier-2 volume → rule fires on the main squat exercise.
  • Assistance block for T3 glute work is capped to 60 reps, rest shortened to keep the session under 75 minutes.
  • The custom flag is stored in ProgressionState.customFlags so analytics dashboards can alert Alex when deloading is needed.

4. Coach Override vs. Automation​

Alex prescribes an absolute bench single at 145 kg for Sam’s test week.

  • Program override (absoluteTargetWeight) is stored on the PWE snapshot.
  • During evaluation, _shouldBlockProgression sees the override and returns early.
  • ProgressionState still tracks success/failure for future rules; suggestions are not created.
  • When Alex removes the override, the next automated workout picks up with the new stage and TM values.

5. Premium vs Community Editions​

UserPermissionOutput
Sam (MemberPro)can_use_advanced_progression_features ✅Receives set-specific weights, warmups, AMRAP cues, assistance quotas.
Chris (Member)can_use_advanced_progression_features ❌Gets uniform working-set recommendations; warmups still generated; assistance stays generic.
  • Same playbook; edition is chosen at runtime.
  • If Sam shares a workout screenshot, it’s obvious he’s on premium due to per-set instructions; Chris sees the simpler view.

6. Simulating Tweaks Before Deployment​

Alex edits the Stage-2 rule and wants to verify if +2.5 kg absolute jump is too aggressive.

Simulator Example
await progressionPlaybookService.simulatePlaybook(playbook, {
sets: [
{ weight: 110, reps: 5, skipped: false },
{ weight: 112.5, reps: 5, skipped: false },
{ weight: 115, reps: 5, skipped: false }
],
targetReps: 5,
trainingMax: 125,
tierStage: 'STAGE_2',
currentWeekNumber: 9
}, trainingFocus);
  • Output includes triggered rule, state diff, suggested TM, and warmup/working sets.
  • Alex can iterate until the result fits his programming philosophy, then push the change live.

Permissions & Monetisation​

CapabilityPermissionRoles (by seed)Behaviour when missing
Assign premium playbookscan_assign_premium_playbooksMemberPro, Coach, AdminPlaybook assignment denied
Use advanced (set-level) recommendationscan_use_advanced_progression_featuresMemberPlus+, Coach, AdminEngine emits community edition suggestions
View effective workoutcan_view_effective_workoutsAll seeded rolesAccess denied; prompts upgrade
  • Role metadata service already surfaces upgrade prompts for UI.
  • Premium gating happens both during assignment and at runtime to prevent orphaned suggestions.

Developer Workflow​

Authoring & Schema​

  1. Add or migrate Prisma models (ProgressionPlaybook, UserProgramPWESnapshot, WorkoutExerciseProgressionSuggestion).
  2. Seed new permissions via prisma/mongo/seeds/core/00permissions.seeder.ts.
  3. Extend playbook CRUD UI/API to expose new metadata, conditions, and actions.

Runtime Integration​

  1. Ensure ProgressionPlaybookService.processWorkout receives program context (listener and GraphQL paths updated).
  2. Update Effective Workout service/GraphQL to consume expanded suggestion metadata.
  3. Pipe enhanced logs and metrics into observability dashboards (rule IDs, tiers, stage transitions).

Testing Strategy​

LayerCoverageCommand
UnitNew condition/action handlers (TIER_EQUALS, SET_SET_TEMPLATE, etc.)npm run test -- progressionPlaybook.engine
IntegrationProgram-aware scenarios (deload, failure reset, premium fallback, cross-volume)npm run test -- progression-playbook-engine.integration
SimulationCompare legacy vs v2 output for unchanged rulesDedicated harness (simulatePlaybook)
  • Integration harness spins up an isolated Mongo replica + canonical seed; tests clean up automatically (see tests/integration/progression-playbook-engine.integration.test.ts).
  • Before releasing, run the full suite (npm run test && npm run coverage) and update docs/telemetry dashboards.

Rollout Checklist​

  1. ✅ Ship schema migrations and seed permission changes.
  2. ✅ Deploy engine v2 behind feature flag, verify parity with existing playbooks.
  3. ✅ Run integration simulations for flagship programs (GZCLP, 5/3/1) with canned data.
  4. ✅ Enable premium gating and advanced edition for pilot roles.
  5. ✅ Monitor metrics (evaluation duration, rule hit rate, fallback counts) and business events.
  6. 🔁 Collect user feedback, iterate on additional actions/conditions as needed.

Quick Reference​

  • Source of truth: src/services/progressionPlaybook/progressionPlaybook.service.ts
  • Listener context provider: src/listeners/progression-playbook.listener.ts
  • Effective workout consumer: src/services/effectiveWorkout/effectiveWorkout.service.ts
  • Spec & design artifacts: specs/003-progression-engine-v2/spec.md (detailed requirements)
  • Sample integration scenarios: tests/integration/progression-playbook-engine.integration.test.ts

Need more detail? We’ll publish a full specification and data model doc soon, with types and schema diffs.