Skip to content

[Superseded] feat: Drop-Set Mode for Old School workouts (Issue #673)#682

Closed
9thLevelSoftware wants to merge 9 commits into
mainfrom
enhancement/drop-set-old-school-673
Closed

[Superseded] feat: Drop-Set Mode for Old School workouts (Issue #673)#682
9thLevelSoftware wants to merge 9 commits into
mainfrom
enhancement/drop-set-old-school-673

Conversation

@9thLevelSoftware

@9thLevelSoftware 9thLevelSoftware commented Jul 25, 2026

Copy link
Copy Markdown
Owner

Important

SUPERSEDED — DO NOT REOPEN OR MERGE. This PR implements the abandoned automatic DELOAD_OCCURRED / cross-set regression design. The authoritative replacement is the user-prompted failed-set replay plan in Issue #673, implemented as three new sequential PRs.

Summary

Adds a Drop-Set Mode option for Old School exercises. When enabled, weight automatically decreases by the configured amount only when a rep is failed (cable release detected), rather than on every rep.

Changes

Data Model + DB

  • Added dropSetEnabled and dropSetMinWeightKg fields to RoutineExercise and WorkoutParameters
  • DB migration 43: additive ALTER TABLE for new columns
  • Backup/restore: new fields with Kotlinx defaults for backward compatibility

BLE + Engine

  • BLE packet factory: zero progressionRegressionKg when drop-set enabled (app controls drops, not machine)
  • ActiveSessionEngine: drop-set deload handler reduces weight instead of arming stall timer
  • Weight deferred to next set via existing pendingWeightChangeKg mechanism (no mid-set BLE commands)
  • WorkoutCoordinator: dropSetDropCount and dropSetOriginalWeightKg state tracking

UI

  • Drop-Set Mode toggle in ExerciseEditBottomSheet (Old School mode only)
  • Minimum Weight slider (weight won't drop below this value)
  • Stall detection disabled when drop-set active (mutual exclusivity, Approach A)
  • Toggle only enabled when Weight Change Per Rep is negative

Repository + Sync

  • Repository layer: save/load drop-set fields
  • Sync: portal pull defaults drop-set to disabled (same as progressionKg pattern)
  • RoutineFlowManager: propagate fields at all 4 WorkoutParameters construction sites

Behavior

  • Cross-set drops only: weight reduction applies to the next set, not the current set (machine cannot accept mid-set BLE commands)
  • Old School mode only: not available in Echo, Just Lift, or other modes
  • Mutual exclusivity: stall detection is disabled when drop-set is active
  • Weight floor: configurable minimum weight prevents drops below threshold
  • Backward compatible: defaults to disabled, existing routines unaffected

Release Notes

Drop-Set Mode for Old School Workouts

Added a Drop-Set Mode option for Old School exercises. When enabled, the weight automatically decreases by the configured amount only when a rep is failed (cable release detected), rather than on every rep. The reduced weight takes effect at the next set start for safety.

To use: set a negative Weight Change Per Rep, then toggle Drop-Set Mode on. Optionally configure a minimum weight floor to prevent the weight from dropping below a threshold.

Drop-Set Mode is mutually exclusive with deload-based stall detection (velocity-based stall detection remains active). Available in Old School mode only.

Historical reference: #673 (superseded; does not close the issue)

Implements drop-set mode for Old School workouts where weight decreases
only when a rep is failed (cable release detected via DELOAD_OCCURRED).

Changes:
- Data model: add dropSetEnabled + dropSetMinWeightKg to RoutineExercise
  and WorkoutParameters
- DB migration 43: additive ALTER TABLE for new columns
- BLE: zero progressionRegressionKg when drop-set enabled (machine does
  per-rep adjustment, app controls drops)
- RoutineFlowManager: propagate drop-set fields at all 4 WorkoutParameters
  construction sites
- ActiveSessionEngine: drop-set deload handler reduces weight instead of
  arming stall timer; weight deferred to next set via pendingWeightChangeKg
- WorkoutCoordinator: dropSetDropCount and dropSetOriginalWeightKg state
- ViewModel: state flows, load/save mapping, event handlers
- UI: Drop-Set Mode toggle + Minimum Weight slider in ExerciseEditBottomSheet,
  gated by Old School mode + negative Weight Change Per Rep
- Stall detection disabled when drop-set active (mutual exclusivity)
- Backup/restore: new fields with Kotlinx defaults for backward compat
- Sync: portal pull defaults drop-set to disabled

Cross-set drops only (no mid-set BLE). Old School mode only.
Mutual exclusivity with deload-based stall detection (Approach A).

Closes #673

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cb93489f09

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

- SchemaManifest.kt: add dropSetEnabled/dropSetMinWeightKg columns to RoutineExercise CREATE TABLE and SchemaHealOperations (iOS Schema Sync)
- DataBackupManager.kt: add .toDouble() for Float→Double conversion on dropSetMinWeightKg (Lint/Unit Tests)
- ActiveSessionEngine.kt: preserve dropped weight across set boundary via _userAdjustedWeightDuringRest
- ActiveSessionEngine.kt: refresh drop-set settings when advancing exercises (startRestTimer, startNextSetOrExercise, advanceToNextSetInSingleExercise)
- ActiveSessionEngine.kt: add floor guard in handleDropSetDeload to deduplicate persistent deload events
- ExerciseEditBottomSheet.kt: widen min-weight slider range to 0..110 kg
- ExerciseEditBottomSheet.kt: auto-disable drop-set when Weight Change Per Rep becomes nonnegative

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 026c765162

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

- SchemaManifest: move dropSetEnabled/dropSetMinWeightKg after stallDetectionEnabled
  to match .sq column order (iOS Schema Sync Check)
- ActiveSessionEngine: inline drop-set deload handler at call site to fix
  'Unresolved reference' and 'private not applicable to local function' errors

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bb8f266156

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

5 test files constructing RoutineExercise SQLDelight rows need the new
migration-43 columns (dropSetEnabled=0, dropSetMinWeightKg=0.0).

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 228389800d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Previous commit incorrectly added dropSetEnabled/dropSetMinWeightKg to
Exercise table inserts. This adds them only to RoutineExercise SQLDelight
constructor calls, after stallDetectionEnabled (matching column order).

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ee95dfa0e3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

- SchemaParityTest: bump EXPECTED_SCHEMA_VERSION 43→44 (CI fix)
- ActiveSessionEngine: move drop-set check BEFORE shouldEnableAutoStop
  gate so drop-set fires even when stallDetectionEnabled is false
- ActiveSessionEngine: use dedicated dropSetNextWeightKg instead of
  adjustWeight during active set so saveWorkoutSession captures the
  original load (not the dropped next-set target)
- ActiveSessionEngine: consume dropSetNextWeightKg only for same-exercise
  transitions so dropped weight does not bleed into unrelated exercises
- DefaultWorkoutSessionManager: consume dropSetNextWeightKg in autoplay-off
  proceedFromSummary path; add dropSetEnabled/dropSetMinWeightKg to params
- ExerciseConfigViewModel: clear drop-set when leaving Old School mode
- ExerciseEditBottomSheet: use unit-aware maxWeight for min-weight slider
- SqlDelightSyncRepository: preserve local drop-set fields during portal
  pulls (snapshot before delete, restore during merge)
- SingleExerciseDefaults/Document: add dropSetEnabled + dropSetMinWeightKg
- SingleExerciseScreen: restore drop-set fields from saved defaults
- WorkoutCoordinator: add dropSetNextWeightKg pending field

Addresses all 10 Codex review comments (5×P1, 2×P1, 3×P2).
Closes #673

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bc920c6bf6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 178aa0e51d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 189d486e62

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4e606cbe02

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

frame,
BleConstants.ActivationPacket.OFFSET_PROGRESSION,
params.progressionRegressionKg,
if (params.dropSetEnabled && params.progressionRegressionKg < 0f) 0f else params.progressionRegressionKg,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Gate progression suppression on Old School mode

When a portal pull changes a locally configured drop-set exercise to Pump or TUT, the sync merge preserves both dropSetEnabled and its negative progression while replacing the mode. Starting that routine bypasses the editor normalization, and this condition serializes zero progression even though the active-session drop-set guard correctly rejects non-Old-School modes, so the configured firmware regression silently stops working. Fresh evidence beyond the resolved runtime guard is that packet serialization still checks only the persisted flag; include the Old School mode requirement here as well.

Useful? React with 👍 / 👎.

Comment on lines +4878 to +4880
val nextSetWeight = if (pendingDropWeight != null && (isSameRoutineExercise || isSameExerciseContinuation)) {
coordinator.dropSetNextWeightKg = null
pendingDropWeight

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve drops through same-exercise SetReady transitions

For a zero-rest transition to an adjacent routine entry representing the same physical exercise, this branch consumes the pending drop and assigns it to nextSetWeight, but the subsequent isSameExerciseContinuation path calls plain enterSetReady(), which reloads setWeightsPerCableKg or weightPerCableKg and overwrites that value. The next set therefore uses its planned weight despite the explicit continuation handling here. Fresh evidence beyond the resolved ordinary set-boundary reports is this separate same-exercise-continuation path; pass nextSetWeight through enterSetReadyWithAdjustments() or otherwise preserve it.

Useful? React with 👍 / 👎.

@9thLevelSoftware 9thLevelSoftware changed the title feat: Drop-Set Mode for Old School workouts (Issue #673) [Superseded] feat: Drop-Set Mode for Old School workouts (Issue #673) Jul 25, 2026
@9thLevelSoftware
9thLevelSoftware deleted the enhancement/drop-set-old-school-673 branch July 26, 2026 00:53
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.

1 participant