Add 2-4 word length preset (closes #475)#480
Conversation
Splits the previous 3-7 length tier into a new 2-4 option (for users who want shorter, higher-precision completions) and a 4-7 option (the former 3-7, lower bound bumped so it doesn't overlap with 2-4 and the tier chain stays aligned with 7-12 and 12-20). Existing users whose saved preset is '3-7' migrate to '4-7' on launch instead of silently falling back to the default. Quick onboarding template also tracks the rename. Closes #475.
| let resolvedWordCountPreset: SuggestionWordCountPreset = { | ||
| let storedRaw = userDefaults.string(forKey: Self.selectedWordCountPresetDefaultsKey) | ||
| // Migrate the retired "3-7" raw value to its replacement "4-7" so users who picked | ||
| // the short preset don't silently jump to the default after #475 split the short | ||
| // tier into 2-4 and 4-7. | ||
| if storedRaw == Self.legacyShortPresetRawValue { | ||
| return .fourToSeven | ||
| } | ||
| return storedRaw.flatMap(SuggestionWordCountPreset.init(rawValue:)) | ||
| ?? configuration.defaultWordCountPreset | ||
| }() |
There was a problem hiding this comment.
Missing test coverage for the "3-7" migration path
The migration of "3-7" → .fourToSeven is described in the PR description as the most important rollout concern (users silently jumping to the default preset), but there is no test that exercises this path in SuggestionSettingsModel. If someone accidentally removes or misplaces the if storedRaw == … guard in a future refactor, the test suite will still pass. The existing GhostTextOpacitySettingsTests already shows how to build an isolated UserDefaults suite and reload a SuggestionSettingsModel; the same pattern could seed "3-7" into selectedWordCountPresetDefaultsKey and assert the model reads back .fourToSeven.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Summary
Adds a new "2-4 words" option to the suggestion length picker (settings + menu bar), as requested in #475. The previous "3-7" tier is renamed to "4-7" so the lower bound of each tier matches the upper bound of the previous tier, keeping the chain consistent with the existing 7-12 and 12-20 tiers. The 4-7 tier keeps the same 11-token budget the old 3-7 had, so its behavior is unchanged.
Validation
Linked issues
Closes #475.
Risk / rollout notes
SuggestionSettingsModelnow rewrites the legacy"3-7"raw value to.fourToSevenon launch. Without this users on the short tier would silently fall back to the default12-20after the rename, which would be a worse experience than the issue is trying to add..fourToSeveninstead of.threeToSeven. Same token budget (11) and same upper word bound (7), so behavior is preserved for users completing onboarding after this lands. Deliberately did not retarget Quick to the new shorter.twoToFourto keep this PR scoped to the issue..twoToFourtier is 6 (matches the existing ~1.5x upper-bound rule documented in the enum).Greptile Summary
Adds a new
2-4word-count preset (twoToFour) to the suggestion length picker and renames the old3-7tier to4-7(fourToSeven) so tier boundaries chain cleanly. A UserDefaults migration inSuggestionSettingsModelsilently upgrades any persisted\"3-7\"raw value to.fourToSevenon launch, preventing existing users from falling back to the default preset.twoToFour = \"2-4\"with a token budget of 6 (consistent with the ~1.5× upper-bound rule);fourToSeveninherits the oldthreeToSevenbudget of 11.\"3-7\"key and rewrites it to\"4-7\"in-process at init, then persists the new value — a one-shot, invisible upgrade..fourToSeven(same token budget and upper word bound as before), keeping new-user behavior unchanged.Confidence Score: 4/5
Safe to merge; the enum rename, migration, and onboarding re-targeting are all correct and consistent.
The migration in SuggestionSettingsModel is the most sensitive part of the change — existing users who had selected the old shortest tier depend on it to land on .fourToSeven rather than the app default. The logic itself is correct, but there is no dedicated unit test exercising this UserDefaults upgrade path. If the guard were accidentally removed in a future refactor, the test suite would not catch it. Everything else — the enum, token budgets, onboarding template, and updated tests — is well-structured and internally consistent.
The migration block in SuggestionSettingsModel.swift (lines 176-186) would benefit from a companion test seeding "3-7" into an isolated UserDefaults suite and asserting the loaded preset is .fourToSeven.
Important Files Changed
Flowchart
%%{init: {'theme': 'neutral'}}%% flowchart TD A[SuggestionSettingsModel init] --> B{Read UserDefaults selectedWordCountPreset} B -- nil --> E[Use configuration.defaultWordCountPreset] B -- storedRaw == 3-7 legacy --> C[Resolve to .fourToSeven] B -- valid current raw value --> D[Resolve via SuggestionWordCountPreset.init] B -- unknown invalid value --> E C --> F[persistSelectedWordCountPreset writes 4-7 back] D --> F E --> F F --> G[Published selectedWordCountPreset]Reviews (1): Last reviewed commit: "Add 2-4 word length preset and re-bound ..." | Re-trigger Greptile