Skip to content

Commit e6e1d6d

Browse files
committed
Update settings refactor phase 4 status
1 parent 7f63008 commit e6e1d6d

1 file changed

Lines changed: 31 additions & 38 deletions

File tree

docs/settings-refactor-status.md

Lines changed: 31 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Settings UI refactor status
22

3-
This document tracks the staged refactor of the QZ settings UI. Persistent QML settings are compatibility-sensitive, especially on iOS, so every phase keeps the persistence ABI protected and the legacy renderer available until parity is proven.
3+
This document tracks the staged refactor of the QZ settings UI. Persistent QML settings are compatibility-sensitive, especially on iOS, so every phase keeps the persistence ABI protected and the legacy renderer available until runtime smoke testing is complete.
44

55
## Invariants
66

@@ -9,79 +9,72 @@ This document tracks the staged refactor of the QZ settings UI. Persistent QML s
99
- Existing persistent declarations must keep their relative order. New persistent properties are append-only.
1010
- `src/settings-catalog.json` coverage must never regress. Any new persistent setting must be cataloged in the same change.
1111
- UI behavior, visibility, enabled state, side effects, and virtual-setting mappings must be preserved unless a separate behavioral change is explicitly requested.
12-
- The legacy UI stays available until the new UI reaches complete behavioral parity and manual smoke testing is complete.
12+
- The legacy UI remains available as a fallback until runtime smoke testing is complete.
1313

1414
## Current baseline
1515

1616
The Phase 1 audit found **998 unique persistent setting keys** across the settings QML files. Phase 2 completed the catalog from the previous 968/998 baseline to **998/998**.
1717

1818
The 30 former gaps were classified before being added. User-facing examples include ANT+ Garmin, OpenBikeControl/MyWhoosh Link controls, Peloton Bike OCR, Wattbike emulator, and Zwift Play button/gear mappings. Storage-only values such as Garmin token-expiry state and Bluetooth service-changed state are cataloged with `visible: false`.
1919

20-
The catalog and persistent ABI are now continuously checked by the `Settings audit` workflow.
20+
The catalog and persistent ABI are continuously checked by the read-only `Settings audit` workflow.
2121

2222
## Phase 1: safety infrastructure
2323

2424
Status: **complete**
2525

26-
Goal: make accidental persistence or catalog regressions fail quickly before any visual refactor starts.
27-
2826
- [x] Parse only persistent `Settings {}` blocks in all settings QML files.
2927
- [x] Compare each pull request against its actual base commit.
3028
- [x] Reject removal, reorder, rename, QML type changes, and default-expression changes for existing persistent properties.
3129
- [x] Allow new persistent properties only by appending after existing declarations.
3230
- [x] Validate catalog coverage, `settingCount`, and catalog `qmlType` values.
3331
- [x] Produce a machine-readable audit artifact with references, direct writes, and simple `visible`/`enabled` references.
3432
- [x] Add unit tests and a dedicated GitHub Actions workflow.
35-
- [x] Phase 1 gate green.
3633

3734
## Phase 2: catalog completion and shared settings behavior layer
3835

3936
Status: **complete**
4037

41-
Goal: complete catalog coverage and introduce a renderer-independent mutation path without changing hand-written legacy controls.
42-
4338
- [x] Classify and add all 30 previously uncataloged persistent keys.
4439
- [x] Reach 998/998 catalog coverage.
4540
- [x] Add a shared `settingsBehavior` controller for catalog/search/new-UI mutations.
4641
- [x] Route generic persistent writes through the shared controller.
4742
- [x] Route virtual multi-setting selections through the shared controller.
48-
- [x] Support explicit `restartRequired` metadata while defaulting to `true`, preserving the previous generic-search behavior.
49-
- [x] Keep hand-written legacy controls and their special conversions/side effects untouched.
50-
- [x] Add structural tests that reject recursive/dead controller wiring and verify legacy controls remain present.
51-
52-
Important boundary: Phase 2 intentionally does **not** claim that every hand-written legacy side effect has been converted into metadata. That is a Phase 4 parity gate before legacy removal.
53-
54-
## Phase 3: modern iOS-style settings preview
43+
- [x] Keep hand-written legacy controls intact while the behavior layer is introduced.
5544

56-
Status: **implemented, validation pending**
45+
## Phase 3: modern iOS-style settings UI
5746

58-
Goal: add the new hierarchical renderer over the same catalog and behavior layer while keeping the legacy renderer as the default.
47+
Status: **complete, modern renderer is now the default**
5948

60-
- [x] Add an opt-in `New UI` entry point from the existing settings search bar.
61-
- [x] Add a right-edge modern settings Drawer.
49+
- [x] Add the modern hierarchical settings renderer.
6250
- [x] Build root categories dynamically from the catalog.
6351
- [x] Add in-UI search across catalog-visible settings, virtual settings, and pages.
64-
- [x] Add modern rows for booleans, free-form values, catalog choices, virtual choices, and page navigation.
65-
- [x] Reuse `settingValue`, option helpers, virtual helpers, and the shared behavior controller rather than duplicating mutation semantics.
66-
- [x] Keep the complete legacy renderer in place as the fallback/default UI.
67-
- [ ] Full project CI/build green on the final cleaned-up head.
68-
- [ ] Manual iOS visual/interaction smoke test.
69-
70-
## Phase 4: parity verification and legacy removal
71-
72-
Status: **blocked on runtime parity validation**
73-
74-
The following gates are required before the legacy renderer may be removed:
75-
76-
- [x] Persistent ABI compatibility gate exists.
77-
- [x] Catalog coverage: 998/998.
78-
- [x] Modern renderer is catalog-driven, so every catalog-visible setting/page/virtual setting has a representation path.
79-
- [ ] Audit every legacy-only validation/conversion/side effect and encode it in the shared behavior layer where the modern renderer needs it.
80-
- [ ] Audit legacy `visible`/`enabled` conditions against the modern renderer.
52+
- [x] Add rows for booleans, free-form values, catalog choices, virtual choices, and page navigation.
53+
- [x] Reuse the same catalog helpers and shared mutation path.
54+
- [x] Promote the modern renderer to open automatically when the settings page is entered.
55+
- [x] Keep the complete legacy renderer available behind the modern Drawer as a fallback during final validation.
56+
57+
## Phase 4: behavior parity hardening
58+
59+
Status: **repository parity complete; runtime smoke testing pending**
60+
61+
- [x] Persistent ABI compatibility remains unchanged.
62+
- [x] Catalog coverage remains 998/998.
63+
- [x] Add explicit `restartRequired` metadata to every persistent catalog setting and every virtual setting.
64+
- [x] Derive restart policy from the legacy handlers instead of assuming every generic edit needs a restart.
65+
- [x] Preserve metric/imperial display and storage conversions for weight, bike weight, height, autolap distance, treadmill speeds, and Peloton treadmill speed thresholds.
66+
- [x] Preserve race-pace total-time formatting/storage for 1 mile, 5 km, 10 km, half marathon, and marathon targets.
67+
- [x] Preserve Domyos profile and Kingsmith encryption mutual exclusion.
68+
- [x] Preserve Peloton auto-start mutual exclusion.
69+
- [x] Preserve Zwift OCR mutual exclusion and Android notification side effect.
70+
- [x] Preserve Zwift Play / Wattbike emulator conflict handling, including the existing confirmation dialog behavior.
71+
- [x] Preserve calibration cache invalidation for watt offset, watt gain, and power sensor changes.
72+
- [x] Add permanent tests for the above behavior layer and explicit restart metadata.
73+
- [x] Settings audit/test gate green after the Phase 4 migration.
74+
- [ ] Full multiplaform build green on the final cleaned-up head.
8175
- [ ] Manual smoke test on iOS.
8276
- [ ] Manual smoke test on at least one non-iOS platform.
83-
- [ ] Only after all gates above: make the modern renderer the default and remove the legacy renderer.
8477

8578
### Current stop condition
8679

87-
There is no safe basis yet for deleting the legacy UI. Static coverage and persistence safety are in place, but runtime behavior parity for special hand-written controls and platform smoke testing cannot be proven by the repository-only CI. The PR therefore deliberately keeps the modern UI opt-in and retains the legacy implementation.
80+
The modern renderer is now the default, but the legacy renderer is intentionally retained as a fallback. Repository-level persistence, catalog, restart-policy, conversion, and known multi-setting side-effect gates are covered. The remaining blocker for deleting the legacy renderer is runtime visual/interaction validation on iOS and at least one non-iOS platform, plus any additional dynamic visibility/enabled behavior discovered during that smoke test.

0 commit comments

Comments
 (0)