Releases: 9thLevelSoftware/Project-Phoenix-MP
Release list
v0.9.5
What's Changed
- feat(audio): add verbal encouragement & vulgar mode voice assets by @9thLevelSoftware in #612
- feat(issue-611): verbal encouragement at VBT failure with tiered vulgar pools + Dominatrix easter egg + 18+ gate by @9thLevelSoftware in #613
- fix(settings): align adult mode dialogs with theme by @9thLevelSoftware in #614
- fix(theme): UX-audit Phase 0 — design-token foundations by @9thLevelSoftware in #616
- fix(ui): UX-audit Phase 1 — high-severity mechanical fixes by @9thLevelSoftware in #617
- refactor(ui): UX-audit Phase 2 — systemic design-token sweeps by @9thLevelSoftware in #618
- refactor(ui): UX-audit Phase 3 — component consolidation by @9thLevelSoftware in #619
- fix(ux): UX-audit Phase 4A — flow fixes (non-BLE) by @9thLevelSoftware in #624
- fix(#333): permanent Pixel 6/7 BLE fix — small-MTU compatibility mode… by @9thLevelSoftware in #621
- fix(#333): mark wasEverConnected @volatile (PR #623 follow-up) by @9thLevelSoftware in #625
- fix(ux): UX-audit Phase 4B — BLE flow guards (HOLD: device validation required) by @9thLevelSoftware in #626
- feat(ui): UX-audit Phase 5A — beautification by @9thLevelSoftware in #628
- fix(ux): UX-audit Phase 5B — flow polish (HOLD: device validation required) by @9thLevelSoftware in #629
- fix: E2E quality audit remediation — 80 findings across 6 phases by @9thLevelSoftware in #630
- fix(#333): extend BLE compatibility mode auto-detect to Pixel Tablet and Pixel Fold by @9thLevelSoftware in #631
- fix(#620): rebuild cycle templates E2E — root-cause fix, live 1RM/PR wiring, customization by @9thLevelSoftware in #633
- fix(#635): explicit isBodyweight flag — stop deriving from unreliable equipment metadata by @9thLevelSoftware in #636
- Fix #634: PR stable UUIDs and pull rate limiting by @9thLevelSoftware in #637
Full Changelog: v0.9.3...v0.9.5
v0.9.4
What's Changed
- feat(audio): add verbal encouragement & vulgar mode voice assets by @9thLevelSoftware in #612
- feat(issue-611): verbal encouragement at VBT failure with tiered vulgar pools + Dominatrix easter egg + 18+ gate by @9thLevelSoftware in #613
Full Changelog: v0.9.3...v0.9.4
Pixel 6/7 BLE Fix — Test Build
Debug APK for testing the permanent Pixel 6/7 BLE compatibility mode fix (issue #333, PR #615).
What's in this build:
- Vendored Kable patch forcing legacy 1-arg
writeCharacteristic()on all API levels - Small-MTU compatibility mode for Pixel 6/7 (BCM4389) devices
- Auto-detection of affected devices + manual override in Settings
- Busy-retry updated to handle
Write failed: Unknownfrom the legacy write path
Testing needed:
- Pixel 6/7 owners: does workout CONFIG start reliably now?
- Non-Pixel Android 13+ devices: any regressions in BLE writes?
- General: LED/color-scheme writes, exercise transitions, heartbeat stability
v0.9.3
What's Changed
- fix: recover iOS audio after foregrounding by @9thLevelSoftware in #523
- Pr 523 review fix by @9thLevelSoftware in #524
- Fix routine auto-backup export scope by @9thLevelSoftware in #527
- Fix mobile Cloud Sync stale error persistence by @9thLevelSoftware in #529
- Remove forward slash from translation by @Anthonyzou in #530
- fix(ios): sort routine auto-backup prune by mtime, not filename by @cursor[bot] in #533
- fix(issue-534): include equipment rack vest in body-weight Effective Load by @9thLevelSoftware in #535
- fix(mobile): clear rack selection on per-exercise advance (issue #536) by @9thLevelSoftware in #537
- fix(mobile): localize Just Lift Echo-mode UI for Italian (issue #540) by @9thLevelSoftware in #542
- fix(ios): parse comma decimal in CompactNumberPicker for it-IT (issue #539) by @9thLevelSoftware in #543
- fix(issue-541): add set picker to SetReadyScreen and route cycles through it by @9thLevelSoftware in #544
- fix(issue-549): refresh Home cycle banner via checkAndAutoAdvance by @9thLevelSoftware in #550
- Fix ExerciseConfigModal eccentric percent label by @9thLevelSoftware in #545
- Fix Rest Timer eccentric percent localization by @9thLevelSoftware in #546
- Fix progression eccentric percent localization by @9thLevelSoftware in #547
- Fix Routine Overview eccentric percentage localization by @9thLevelSoftware in #548
- [codex] Align weight handling with official per-cable behavior by @9thLevelSoftware in #551
- fix(android): unblock Health Connect workout export for existing write-only users (Issue #531) by @cursor[bot] in #552
- fix(echo): restore warm-up progression on Android 16 / OnePlus 15 (Fixes #553) by @9thLevelSoftware in #554
- fix: rack leak on autoplay advance and bodyweight Health Connect export by @cursor[bot] in #557
- fix: home cycle start race and VBT assessment per-cable 1RM storage by @cursor[bot] in #561
- fix: contain uncaught coroutine exception in AppLifecycleObserver foreground sync (#566) by @9thLevelSoftware in #569
- fix(ios): relocate rest timer liveRegion off zero-size AX node (#565) by @9thLevelSoftware in #567
- fix(just-lift): cap wheel drag hot zone + side-by-side weight cards on iPhone portrait (#571) by @9thLevelSoftware in #574
- fix(mobile): same-exercise continuation defers BLE CONFIG mode change (Issue #572) by @9thLevelSoftware in #573
- fix(mobile): set Idle before same-exercise SetReady to prevent rest-screen stall (PR #573 review) by @cursor[bot] in #575
- Cursor/critical bug investigation 38cb by @9thLevelSoftware in #577
- feat: Add TUT and Beast Mode to Just Lift mode selector (#538) by @9thLevelSoftware in #564
- [codex] Add equipment rack behavior overrides by @9thLevelSoftware in #579
- fix(issue-582): make SetReadyScreen body scrollable so Equipment Rack is reachable by @9thLevelSoftware in #583
- fix(issue-586): reject implausible historical set-duration averages in routine estimates by @9thLevelSoftware in #587
- Keep screen awake throughout Just Lift by @jeffreybozek in #588
- fix(slider): round-to-nearest-integer in ProgressionSlider to prevent skipped values (#571 continued) by @9thLevelSoftware in #590
- fix(sync,history): preserve local metrics across pull + exclude ghost rows (Fixes #591) by @9thLevelSoftware in #592
- fix(routine): prompt for bodyweight reps on routine sets with null duration (Fixes #593) by @9thLevelSoftware in #594
- fix(audio): correct setup-rep sound timing (#531) by @9thLevelSoftware in #596
- feat(1rm): velocity-based 1RM foundation (Phases 1-2) (#517) by @9thLevelSoftware in #597
- feat(1rm): % of 1RM scaling, badges, backfill + review fixes (Phases 3-5) (#517) by @9thLevelSoftware in #598
- feat(1rm): send velocity-estimated 1RM in exercise sync DTO (#517) by @9thLevelSoftware in #599
- RCA & fixes for phoenix-review findings (sync, auth, migration, …) by @9thLevelSoftware in #601
- fix(ble): retry reps notification subscription on GATT busy by @9thLevelSoftware in #603
- feat(workout): prompt for session bodyweight by @9thLevelSoftware in #606
- Add upcoming-set Weight Change / Rep controls by @9thLevelSoftware in #605
- chore: bump app version to 0.9.3 by @9thLevelSoftware in #607
- feat(issue-584): show rack contributors in effective load by @9thLevelSoftware in #608
- feat(issue-595): seed routine exercises from PR defaults by @9thLevelSoftware in #609
New Contributors
- @Anthonyzou made their first contribution in #530
- @cursor[bot] made their first contribution in #533
- @jeffreybozek made their first contribution in #588
Full Changelog: v0.9.2...v0.9.3
v0.9.2 - Equipment Rack, Health Sync, Routine Intelligence, and Stability
v0.9.2 - Equipment Rack, Health Sync, Routine Intelligence, and Stability
This release collects 33 commits after v0.9.1, from the first published v0.9.1 GitHub release tag through the current main version bump to 0.9.2.
The main themes are accessory/equipment load tracking, richer Health Connect and HealthKit behavior, better PR/1RM consistency, safer routine-start modifiers, workout audio improvements, TV remote navigation, and a large stability pass across sync, history, analytics, OAuth, BLE, backups, and release builds.
Upgrade Notes
- No manual database action should be required. The app includes the new SQLDelight migrations for this release.
- Health integration users may need to grant or retry permissions so Phoenix can write workouts and read scale body weight.
- Next-set weight recommendations are suggestion-only. They do not change a saved routine unless you explicitly tap Apply for the next set.
- Active Recovery and Heavy Deload are one-shot routine launch modifiers. They do not rewrite the saved routine.
- Equipment Rack counterweights can reduce the machine-facing load before a set. Use that behavior only for real counterweight/retractor setups; use Added resistance or Display only for most accessories.
New and Improved Features
Equipment Rack for Accessories and External Load
Phoenix now has a local Equipment Rack for accessories such as weighted vests, dip belts, chains, bands, assistance/counterweight devices, attachments, and other added gear.
How to use it:
- Open Settings.
- Tap Equipment Rack.
- Tap Add rack item.
- Enter the item name, weight, category, behavior, and enabled state.
- Start or continue a workout.
- On Set Ready, select enabled rack items from the Equipment rack card, or tap Manage to edit the rack.
What to expect:
- Added resistance items add to displayed/logged effective load without increasing the machine command.
- Counterweight items subtract from the machine load before the set, with clamping in the workout flow.
- Display only items are shown as context without changing effective or machine load.
- The Set Ready screen summarizes the selected items and the active workout HUD can show rack context.
- Rack definitions are preserved through app backup/import, and routine-start paths now seed rack context correctly for the first exercise.
Health Connect and HealthKit Improvements
Phoenix Health integration now does more than a basic workout write.
How to use it:
- Open Settings.
- Open Integrations.
- In Health Apps, enable Google Health Connect on Android or Apple Health on iOS.
- Grant the requested permissions.
- Use Retry permissions if a permission is missing.
- Use Sync previous to backfill eligible previous Phoenix workouts.
What to expect:
- Android exports Phoenix workouts to Health Connect as structured strength workouts with per-set exercise segments where supported.
- iOS continues to export aggregate strength workouts to HealthKit because Apple's public write API does not provide an equivalent per-set strength segment model.
- Exports are deduplicated with Phoenix client record IDs so repeated syncs do not intentionally duplicate the same workout.
- Enabling Health attempts to import the latest eligible scale body-weight sample into Phoenix.
- Imported body weight is one-way from the platform health store into Phoenix, validated to the 20-300 kg range, and displayed in Settings > Body Weight and on the Health integration card.
- If no eligible scale body weight exists, Phoenix reports that state instead of overwriting with junk data.
Personal Records and 1RM Parity
The app now treats mobile 1RM and PR data as the source of truth more consistently.
What changed:
- Phoenix uses a canonical hybrid 1RM estimator: Brzycki for 10 reps or fewer, Epley for more than 10 reps.
- CSV export, mobile calculations, and portal sync now share the same estimated 1RM logic.
- Mobile sync sends estimated 1RM and dedicated personal record data to the portal.
- PR sync now carries richer PR metadata, including phase/type handling.
- Manual 1RM values entered during cycle creation are saved immediately after confirmation, so canceling later in the flow no longer loses them.
- Percent-of-PR routines can fall back to stored exercise 1RM when no personal record exists.
- Exercise configuration and workout setup surfaces can show PR percentage context, including phase labels where available.
How to use it:
- Enter or confirm 1RM values during training-cycle creation when prompted.
- Complete workouts normally; Phoenix will continue updating PRs when new performances beat existing records.
- Use portal sync when connected to carry PR and estimated 1RM data to Phoenix Portal.
- For percent-of-PR routines, expect weights to resolve from the best matching PR first, then stored exercise 1RM when no PR exists.
Next-Set Weight Recommendations
PR: #499
Phoenix can now suggest whether to increase, decrease, or maintain load for the next set.
How to use it:
- Open Settings.
- Enable Weight Suggestions.
- Complete a cable-loaded set with enough quality, biomechanics, or set data.
- On the next Set Ready screen, review the recommendation card.
- Tap Apply to update the next set weight, or Dismiss to keep the current load.
What to expect:
- Recommendations are conservative and suggestion-only.
- Increases require completed target reps and strong rep quality.
- Decreases can appear when velocity loss, severe target miss, or low quality suggests the load is too high.
- Maintain appears when the safest answer is to keep the current load.
- Recommendations are suppressed for bodyweight exercises, missing data, invalid loads, and out-of-range changes.
- Applying a suggestion changes the active next set, not the saved routine defaults.
Active Recovery and Heavy Deload Routine Modifiers
PR: #511
Routine cards now offer temporary deload-style starts.
How to use it:
- Open Routines.
- Find the routine you want to run.
- Choose Start Active Recovery or Start Heavy Deload from the routine card actions.
- Pick 50%, 55%, or 60%.
- Start the modified routine.
What to expect:
- Active Recovery reduces working weights to the selected percentage of the best available 1RM baseline, keeps working reps, and simplifies/scales warmups.
- Heavy Deload keeps weights but scales reps, timed durations, and warmup reps to the selected percentage.
- Percent-of-PR weights are resolved before the modifier is applied.
- The transformed routine is temporary for that launch. The saved routine remains unchanged.
Timed-Set Countdown Cues and Stronger Rep Sound
Workout audio should be easier to hear and harder to drop during fast transitions.
How to use it:
- Keep Countdown Beeps enabled in Settings to hear countdown cues.
- Keep Rep completion sound enabled for the stronger regular-rep cue.
- Use timed sets as normal.
What to expect:
- Timed sets emit audible countdown ticks during the last 10 seconds when beeps are enabled.
- Countdown tick playback speeds up as the timer approaches zero.
- The regular rep completion cue now uses a stronger sound on Android and iOS.
- iOS haptic/audio collection no longer cancels in-flight sounds during rapid rep counting.
- Final reps can play both the spoken rep number and the distinct final-rep alert when voice counting is enabled.
- Rest-ending cues are now emitted through the same guarded audio pipeline.
Android TV and D-Pad Remote Navigation
PR: #510
Remote input is now less hostile on TV-style devices.
How to use it:
- On Android TV or D-pad/no-touch setups, focus a slider and press Left or Right to change its value.
- Press Up or Down to move focus instead of accidentally changing the slider.
- Focus a text field and press OK, Enter, or the center D-pad button to enter edit mode.
- Press Back or Escape to leave edit mode or hide the keyboard.
What to expect:
- Phone and tablet touch behavior is unchanged.
- TV-style slider and text-field behavior is centralized so future controls can use the same rules.
System, Light, and Dark Theme Selection
PR: #504
Theme selection now supports System, Light, and Dark explicitly.
How to use it:
- Open Settings.
- Go to Appearance.
- Use the Theme segmented control to choose System, Light, or Dark.
What to expect:
- System follows the platform theme.
- Light and Dark force the selected mode.
- The toolbar theme toggle cycles through System, Light, and Dark.
- iOS system theme changes no longer require destroying and recreating the Compose host, preserving app state such as navigation and active workout context.
- New theme strings are localized in German, Spanish, French, and Dutch.
Just Lift Tagging and Better Portal Classification
PR: #483
Just Lift sessions are easier to label, and synced muscle-group data is no longer collapsed into "General" for known catalog exercises.
How to use it:
- When finishing an untagged Just Lift set with reps, use the prompt to tag the lift before continuing.
- In History, open an old untagged Just Lift entry and use the Tag exercise action to retroactively label it.
- Skip is still available if you do not want to tag a set.
What to expect:
- Untagged Just Lift sessions sync as "Just Lift" instead of a null/unknown session name.
- Known catalog exercises resolve their real muscle group during mobile portal push.
- Retroactive tagging refreshes history through existing SQLDelight flows and creates the completed-set/PR context needed for tracking.
Project Website and Policy Refresh
The static docs site was rebuilt around the actually shipped app surface instead of stale early-beta plans.
What changed:
- The site now describes the current Phoenix app, Health integrations, Phoenix Portal sync, exercise library, routines, modes, diagnostics, voice Safe Word, and release history more accu...
Pixel BLE Experiment v14 - notification readiness logging
#333 Pixel BLE experiment v14
This debug build keeps Flag I / official small-MTU behavior active, then adds exported notification-readiness diagnostics around the Kable observe subscription gate.
Changes from v13:
- Logs each notification subscription start into exported connection logs.
- Logs subscription success into exported connection logs.
- Converts the inner 2s subscription timeout into an exported NOTIFICATION error instead of letting it be reported as the outer 15s initialization timeout.
- Cancels the observation job when the subscription gate times out.
Expected log markers:
- [#333 v14] Starting REPS notification subscription
- [#333 v14] REPS notifications subscribed
- [#333 v14] REPS notification subscription timed out
Verification:
- ./gradlew.bat --% :shared:testAndroidHostTest --tests com.devil.phoenixproject.data.ble.BleNotificationSubscriptionGateTest --tests com.devil.phoenixproject.data.ble.BleReadyGateTest --tests com.devil.phoenixproject.data.ble.PixelGattPolicyTest --tests com.devil.phoenixproject.data.ble.KableBleConnectionManagerTest --tests com.devil.phoenixproject.data.ble.BleOperationQueueTest --tests com.devil.phoenixproject.presentation.manager.BleConnectionManagerTest -Pskip.supabase.check=true
- ./gradlew.bat --% :androidApp:assembleDebug -Pskip.supabase.check=true
APK SHA-256: 181A4D66BD4C4EAC53AC358DE38AC9AD5E1A1994A09E7A3780954DA82D926748
Pixel BLE Experiment v13 - bounded ready gate
Pixel BLE Experiment v13 - bounded ready gate
This diagnostic build follows v12 after the Flag I small-MTU test stalled after service discovery and notification setup start.
Changes in v13:
- Keeps Flag I: skips app-side requestMtu(), keeps CONFIG writes on Kable WithResponse, disables heartbeat traffic, and skips post-CONFIG diagnostic reads.
- Skips pre-ready diagnostic firmware/version reads on the Flag I path so best-effort reads cannot block critical notification setup.
- Binds the app-level BLE ready gate to connect(), so the app either reaches ready/polling or reports a bounded Device initialization timeout instead of staying in Connecting indefinitely.
Expected evidence if the same stall reproduces:
Pixel BLE Experiment v12 - Flag I small-MTU path
Issue #333 Pixel BLE experiment v12.
This pre-release tests Flag I: Official Small-MTU Path on Pixel 6/7 Android 16.
What changed in this debug build:
- Adds Developer Tools Flag I.
- On Pixel devices with Flag I enabled, the app does not call requestMtu().
- Keeps CONFIG writes on Kable WithResponse.
- Starts core notifications through the v10 ready gate.
- Disables the app heartbeat loop, including TX read and no-op write.
- Skips the post-CONFIG diagnostic read.
- Adds [#333 Flag I] logs for MTU path, max write length, flags, CONFIG details, and write result.
Validation target:
- Pixel 6/7 on Android 16 with a Trainer.
- Enable only Flag I before starting the failing workout.
- Pass if CONFIG does not fail with GATT_ERROR(133), cables engage, reps count, and 5 consecutive sessions pass.
v0.9.1 - Stability, Diagnostics, and Integration Sync
TUT IS FINALLY NOT TUT-TALLY BROKEN
Yes, the Time Under Tension saga finally gets a victory lap: Echo and activation defaults now line up with official app behavior, and the packet layout no longer stomps on the profile tail that made TUT/Eccentric behavior so weird.
This release collects 45 commits since the original v0.9.0 release. It focuses on BLE/audio reliability, Smart Insights correctness, bodyweight and routine accuracy, expanded integration sync, diagnostics, and navigation polish.
Enhancements
- Added configurable weight increments from user preferences for finer workout load control (#266, #410).
- Improved Smart Insights and Smart Suggestions with fetch-time timestamp refreshes, clock-sensitive recomputation, shared
nowMsweekly-volume calculations, broader muscle-group taxonomy, inclusive readiness cutoffs, Snapshot/Trends/Diagnostics/Actions organization, per-card metadata, and average-intensity time-of-day analysis (#412, #413, #414, #415, #416, #417, #418, #419, #420). - Refined workout completion criteria and health integration parity, including stricter working-rep completion rules, better zero-rep filtering for stats, optional calorie permission handling, standardized Health workout titles, and Health Connect device metadata (#443, 0d457bf).
- Replaced Just Lift auto-detection with post-set exercise tagging, including Mini Exercise Picker support and retagging updates for PR tracking and completed-set sync (#436).
- Modernized the iOS sound sync pipeline, reorganized sound assets, and cleaned up export tooling (#450).
- Redesigned the Home screen into the Launch Pad experience with a custom navigation bar (#467).
- Implemented the expanded mobile API feature architecture for external training integration sync, including DTOs, SQLDelight persistence, repositories, cursors, retry/entitlement state, view models, navigation, and integration screens (#470).
- Aligned Echo and activation packet defaults with official app behavior, including non-overlap activation layout, official Echo defaults, and corrected Echo duration generation (#474).
- Added Recent Activity replay links into Single Exercise flows (#475).
- Added and refined BLE diagnostics, diagnostic fault decoding, protocol parser behavior, metric polling, connection logging, diagnostics UI, replay navigation, theme/dynamic-color handling, localized strings, and settings/navigation flows (#476, #477).
- Updated release/version tooling and verified app version metadata across Android, iOS, and shared Settings display (269b8b9).
Bug Fixes
- Restored Android workout cue audio routing and release packaging reliability, including media-stream hardware volume behavior, release resource packaging, and rollback of the transient ducking regression (#421, #423, #428, #429, #430, #431, ec0f673, b0e809b).
- Fixed firmware warmup rep sync/tracking for variable warmups and standard sets (#422, #449).
- Fixed per-cable weight display, softMax handling, and BLE force-target progression separation (#433, #436).
- Hardened Compose layouts for iOS accessibility scaling (#432).
- Fixed bodyweight volume handling across the workout session flow, limited bodyweight rep prompts to timed sets, gated accessory-weight/post-session-load display, and hid cable-only toggles for bodyweight exercises (#444, #445, #446, 79ae47f, 3a1e58f).
- Fixed routine auto-start and early load dumping on warmups, including splitting auto-start side effects to avoid connection loops (#411, #462, #463, #466).
- Fixed stale Exercise Variety recency handling for renamed exercise IDs (#469).
- Fixed dynamic percent-of-PR routine set weights, saved fallback snapshots, nearest-half-kg rounding, and routine load resolution from current PR data (#472).
- Fixed portal sync stall-detection preservation (536e4ea).
- Fixed top-level superset reorder persistence while preserving restored audio routing (b0e809b).
- Fixed high-priority Insights tab behavior and follow-up timestamp refresh regressions (#420, #419).
- Added Issue #390 BLE diagnostic logging for calf-raise weight tracing to support field debugging (71cf430).
Quality and Maintenance
- Removed obsolete generated artifacts and stale instrumented E2E harness pieces while preserving shared/common regression coverage (2029cf1, 72d4283).
- Updated target SDK to 37 and refreshed build/dependency configuration where needed (72d4283, 0d457bf).
- Expanded regression coverage across BLE packets/parsing/polling, workout lifecycle, bodyweight handling, dynamic percent-of-PR loading, integrations, replay routes, diagnostics, theme behavior, and release cue resource packaging.
Change Coverage
Included merged PRs and direct commits since v0.9.0: #410, #412, #413, #414, #415, #416, #417, #418, #419, #420, #421, #422, #423, #428, #429, #430, #431, #432, #433, #436, #443, #444, #445, #446, #449, #450, #466, #467, #469, #470, #472, #474, #475, #476, #477, plus direct commits 71cf430, ec0f673, 0d457bf, b0e809b, 536e4ea, 79ae47f, 72d4283, 269b8b9, 3a1e58f, and 2029cf1.
Full Changelog: v0.9.0...v0.9.1
Issue #232 Diagnostic Build v1 - BLE restart logging
Diagnostic prerelease for GitHub issue #232: intermittent machine restart / disconnect loop.
Artifact
- APK: phoenix-issue-232-diagnostic-v1-debug.apk
- App id: com.devil.phoenixproject.debug
- Version: 0.9.0-DEBUG, versionCode 5
- Branch: issue232_test
- Commit: b192b00
- SHA-256: 00481B1B04A272167646EB0DBF4736D04AF86580F78478827FE0279EAA772B7A
Purpose
This build is intended to validate the issue #232 diagnosis before behavior changes. It adds diagnostic logging around the machine restart/disconnect path; it is not intended to change the BLE behavior under test.
Diagnostic coverage
- BLE connection phase transitions, notification subscription completion, MTU, firmware, and when polling starts.
- Monitor, diagnostic, heuristic, and heartbeat polling lifecycle plus first raw sample bytes.
- Workout command timeline with opcode, command family, payload size, hex, caller/context, phase, queue state, duration, and result.
- Echo command 0x4E decoded fields and full frame hex.
- Stop path distinction between soft stop 0x50 and hard reset 0x0A.
- Active session set-completion triggers and RepCounterFromMachine shouldStopWorkout transitions.
Requested validation
Please capture Phoenix logs from app launch through the first restart, Android logcat Bluetooth stack events for the same window, machine firmware from the official app, and the routine settings: Echo mode, Echo level, eccentric percentage, warmup reps, and working reps.