Skip to content

Commit 4f9a5cc

Browse files
carterscodeclaude
andcommitted
fix(presets): exclude power plan from quick-apply presets
The Recommended / Extreme / Reset quick buttons no longer stage, monitor, or revert the Windows power plan. The active power scheme is now isolated as a one-time, user-initiated setup on the CPU / Power tab, so a preset click never overwrites (Recommended/Extreme) or undoes (Reset) the user's chosen plan. - RecommendedPreset: drop the SetPowerPlan/ResetPowerPlan calls; remove the now-orphaned SetPowerPlan, ResetPowerPlan, SafeListPlans helpers and the unused installedPlans overloads (recipe stays for the dual-CCD guardrail). - Settings UI blurbs note each preset leaves the power plan to the CPU/Power tab. - Tests: lock in that Recommended/Extreme don't touch the plan and Reset preserves a user's manual power-plan setup. - Docs: correct STAGED-APPLY-ARCHITECTURE.md and the wiki preset descriptions. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent e2fdfe4 commit 4f9a5cc

5 files changed

Lines changed: 70 additions & 117 deletions

File tree

docs/STAGED-APPLY-ARCHITECTURE.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,9 @@ The three buttons (`Services/RecommendedPreset.cs`):
130130

131131
| Button | Builder | What it stages | Confirmation? |
132132
|---|---|---|---|
133-
| Apply recommended | `RecommendedPreset.ApplyToDraft` | Conservative gaming preset: the hand-picked subset of toggles at their recommended gaming value, plus services / displays / the CPU-aware power plan. **Memory Integrity / VBS and UWP AI-app removal are deliberately excluded** (security tradeoff + irreversible). Monitor + Auto-apply turned **on** for each touched setting. | none |
134-
| Apply extreme | `RecommendedPreset.ApplyExtremeToDraft` | Every managed toggle at its most-aggressive gaming value -- including **Memory Integrity / VBS off** and the contested **Nagle / NIC** tweaks -- plus services, displays and the CPU-aware power plan. Monitor + Auto-apply **on**. Still excludes irreversible UWP AI-app removal. | yes -- a warning `MessageBox` (kernel-driver protection / anti-cheat / reboot) before `RunPreset` is called |
135-
| Reset all to defaults | `RecommendedPreset.ResetToDefaultsToDraft` | Every managed setting back to its Windows out-of-box value, with Monitor + Auto-apply turned **off** so a subsequent Apply restores defaults and GamerGuardian stops re-asserting. Displays are only un-monitored (their Want is hardware-specific). UWP AI-app removals are not touched. | yes -- a warning `MessageBox` before `RunPreset` is called |
133+
| Apply recommended | `RecommendedPreset.ApplyToDraft` | Conservative gaming preset: the hand-picked subset of toggles at their recommended gaming value, plus services / displays. **Memory Integrity / VBS and UWP AI-app removal are deliberately excluded** (security tradeoff + irreversible), and **the power plan is excluded** -- it stays a one-time, user-initiated setup on the CPU / Power tab. Monitor + Auto-apply turned **on** for each touched setting. | none |
134+
| Apply extreme | `RecommendedPreset.ApplyExtremeToDraft` | Every managed toggle at its most-aggressive gaming value -- including **Memory Integrity / VBS off** and the contested **Nagle / NIC** tweaks -- plus services and displays. Monitor + Auto-apply **on**. Still excludes irreversible UWP AI-app removal, and like Recommended **does not touch the power plan** (CPU / Power tab only). | yes -- a warning `MessageBox` (kernel-driver protection / anti-cheat / reboot) before `RunPreset` is called |
135+
| Reset all to defaults | `RecommendedPreset.ResetToDefaultsToDraft` | Every managed setting back to its Windows out-of-box value, with Monitor + Auto-apply turned **off** so a subsequent Apply restores defaults and GamerGuardian stops re-asserting. Displays are only un-monitored (their Want is hardware-specific). UWP AI-app removals are not touched, and **the power plan is left exactly as the user set it** (isolated from the presets). | yes -- a warning `MessageBox` before `RunPreset` is called |
136136

137137
All three are **idempotent**: each per-setting helper compares the draft's `(DesiredOn/Want, Monitor, AutoApply)` triple to the target and stages (and logs) only the deltas; a second click when everything already matches stages zero changes and reports "already correct". The `[PREF-STAGE]` `settingName` carries a `[Recommended]` / `[Extreme]` / `[Reset]` tag prefix so the log shows which preset staged each delta.
138138

docs/wiki/Settings-and-tabs.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Other conventions:
2626

2727
App preferences and the one-click setup — not a monitored-setting tab.
2828

29-
- **One-click setup** — three whole-config presets. Each only *stages* changes (review them per-tab, then **Apply** / **Save & close** to commit, or **Cancel** to discard) and each is idempotent, so re-running after an update only picks up the new deltas:
29+
- **One-click setup** — three whole-config presets. Each only *stages* changes (review them per-tab, then **Apply** / **Save & close** to commit, or **Cancel** to discard) and each is idempotent, so re-running after an update only picks up the new deltas. None of them touch the **power plan** — that's isolated as a one-time, user-initiated setup on the **CPU / Power** tab:
3030
- **Apply recommended** — GamerGuardian's safe gaming preset: sets each covered setting's **Want**, turns **Monitor** on, opts into **Auto-apply**. Keeps Memory Integrity / VBS **on** (security) and leaves Privacy / Debloat / the contested network tweaks for you to choose. Skips the irreversible UWP AI-app removals.
3131
- **Apply extreme** — everything that could even *remotely* help gaming, on: **every** toggle at its most-aggressive value — including Memory Integrity / VBS **off** and the contested Nagle / NIC tweaks — with **Monitor and Auto-apply turned on for every setting**. Disabling Memory Integrity / VBS breaks Valorant (Vanguard) and weakens malware protection, and several changes need a reboot — it asks for confirmation first.
3232
- **Reset all to defaults** — the inverse: stages every setting back to its **Windows default** and turns **Monitor + Auto-apply off**. Applying then restores Windows' shipped behavior (which re-enables features you may have turned off, like Copilot, ads/suggestions, and telemetry services).

src/GamerGuardian/Services/RecommendedPreset.cs

Lines changed: 19 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ namespace GamerGuardian.Services;
1313
/// settings have been added picks up only the new ones; everything already
1414
/// in the recommended state is reported as "already correct" and skipped.</para>
1515
///
16-
/// <para><b>Conservative.</b> Two categories are intentionally NOT in the
16+
/// <para><b>Conservative.</b> Three categories are intentionally NOT in the
1717
/// preset:
1818
/// <list type="bullet">
1919
/// <item><b>Memory Integrity and the full VBS-stack toggle</b> -- security
@@ -23,6 +23,11 @@ namespace GamerGuardian.Services;
2323
/// <item><b>UWP AI app removal</b> -- irreversible without the Microsoft
2424
/// Store. Policy toggles are sufficient to disable Copilot; opt-in only
2525
/// for actual uninstall.</item>
26+
/// <item><b>The Windows power plan</b> -- isolated by design. The active
27+
/// power scheme is a one-time, user-initiated setup on the CPU / Power tab
28+
/// (pick a prebuilt plan or build the CPU-aware optimized one). No preset
29+
/// button -- Recommended, Extreme, or Reset -- touches it, so the user's
30+
/// choice is never overwritten or reverted.</item>
2631
/// </list></para>
2732
///
2833
/// <para>The preset mutates the draft directly (no per-field PropertyChanged
@@ -47,12 +52,9 @@ public sealed record Result(
4752
public static Result ApplyToDraft(AppConfig draft) =>
4853
ApplyToDraft(draft, CpuTuneCatalog.Resolve(CpuDetector.Current));
4954

50-
public static Result ApplyToDraft(AppConfig draft, CpuTuneResult recipe) =>
51-
ApplyToDraft(draft, recipe, SafeListPlans());
52-
53-
// installedPlans is injectable so the power-plan step is testable without a
54-
// live OS power-scheme enumeration.
55-
public static Result ApplyToDraft(AppConfig draft, CpuTuneResult recipe, IDictionary<Guid, string> installedPlans)
55+
// recipe drives the dual-CCD service guardrail. The power plan is NOT staged
56+
// here -- it stays a one-time, user-initiated setup on the CPU / Power tab.
57+
public static Result ApplyToDraft(AppConfig draft, CpuTuneResult recipe)
5658
{
5759
if (draft is null) throw new ArgumentNullException(nameof(draft));
5860

@@ -88,8 +90,7 @@ public static Result ApplyToDraft(AppConfig draft, CpuTuneResult recipe, IDictio
8890
Count(SetToggle(g.InputInsights, "Typing / input insights", "ai.inputinsights", changes));
8991
Count(SetToggle(g.OfficeCopilot, "Office 365 Copilot", "ai.office", changes));
9092

91-
// ---- Power plan: CPU-aware recommended prebuilt (Balanced for modern) ----
92-
Count(SetPowerPlan(g.PowerPlan, recipe, installedPlans, changes));
93+
// ---- Power plan: intentionally NOT staged (isolated, one-time user setup) ----
9394

9495
// ---- Services with a RecommendedTarget ----
9596
foreach (var def in ServiceCatalog.All)
@@ -131,10 +132,7 @@ public static Result ApplyToDraft(AppConfig draft, CpuTuneResult recipe, IDictio
131132
public static Result ApplyExtremeToDraft(AppConfig draft) =>
132133
ApplyExtremeToDraft(draft, CpuTuneCatalog.Resolve(CpuDetector.Current));
133134

134-
public static Result ApplyExtremeToDraft(AppConfig draft, CpuTuneResult recipe) =>
135-
ApplyExtremeToDraft(draft, recipe, SafeListPlans());
136-
137-
public static Result ApplyExtremeToDraft(AppConfig draft, CpuTuneResult recipe, IDictionary<Guid, string> installedPlans)
135+
public static Result ApplyExtremeToDraft(AppConfig draft, CpuTuneResult recipe)
138136
{
139137
if (draft is null) throw new ArgumentNullException(nameof(draft));
140138

@@ -149,9 +147,8 @@ public static Result ApplyExtremeToDraft(AppConfig draft, CpuTuneResult recipe,
149147
Count(SetToggleTo(pref, label, desiredOn, monitor: true, autoApply: true, "Extreme", changes));
150148
}
151149

152-
// Power plan: still the CPU-aware prebuilt (never blindly High Performance).
153-
// Building the custom optimized scheme stays an explicit CPU/Power action.
154-
Count(SetPowerPlan(g.PowerPlan, recipe, installedPlans, changes));
150+
// Power plan: intentionally NOT staged. Even Extreme leaves the active
151+
// power scheme to the user's one-time CPU / Power tab setup.
155152

156153
foreach (var def in ServiceCatalog.All)
157154
{
@@ -182,12 +179,11 @@ public static Result ApplyExtremeToDraft(AppConfig draft, CpuTuneResult recipe,
182179
// Windows out-of-box value and turn Monitor + Auto-apply OFF, so a subsequent
183180
// Apply restores Windows defaults and GamerGuardian stops re-asserting anything.
184181
// Displays are only un-monitored (their Want is hardware-specific, so it's left
185-
// alone). UWP AI app removals are not touched (reinstalling is Store-only).
182+
// alone). UWP AI app removals are not touched (reinstalling is Store-only). The
183+
// power plan is also left alone -- it's an isolated, user-owned one-time setup,
184+
// so Reset never reverts or un-monitors it.
186185

187-
public static Result ResetToDefaultsToDraft(AppConfig draft) =>
188-
ResetToDefaultsToDraft(draft, SafeListPlans());
189-
190-
public static Result ResetToDefaultsToDraft(AppConfig draft, IDictionary<Guid, string> installedPlans)
186+
public static Result ResetToDefaultsToDraft(AppConfig draft)
191187
{
192188
if (draft is null) throw new ArgumentNullException(nameof(draft));
193189

@@ -202,7 +198,8 @@ public static Result ResetToDefaultsToDraft(AppConfig draft, IDictionary<Guid, s
202198
Count(SetToggleTo(pref, label, desiredOn, monitor: false, autoApply: false, "Reset", changes));
203199
}
204200

205-
Count(ResetPowerPlan(g.PowerPlan, installedPlans, changes));
201+
// Power plan: intentionally NOT reset. The user's one-time power-plan
202+
// setup is isolated from the presets and left untouched.
206203

207204
// Reset only services the user is actually managing -- don't materialize a
208205
// Default pref for every catalog entry the user never touched.
@@ -219,31 +216,6 @@ public static Result ResetToDefaultsToDraft(AppConfig draft, IDictionary<Guid, s
219216
return new Result(changed, alreadyCorrect, changes);
220217
}
221218

222-
private static bool ResetPowerPlan(PowerPlanPref pref, IDictionary<Guid, string> plans, List<string> changes)
223-
{
224-
// Windows default plan is Balanced. Stage it (unmanaged) if it's installed;
225-
// otherwise just stop monitoring whatever plan is selected.
226-
var balanced = PowerPlanMonitor.Balanced;
227-
plans.TryGetValue(balanced, out var name);
228-
var guidStr = balanced.ToString();
229-
230-
bool already = !pref.Monitor && !pref.AutoApply
231-
&& pref.Desired == PowerPlanChoice.Balanced
232-
&& (name is null || string.Equals(pref.DesiredGuid, guidStr, StringComparison.OrdinalIgnoreCase));
233-
if (already) return false;
234-
235-
var before = pref.DesiredName ?? pref.Desired.ToString();
236-
pref.Desired = PowerPlanChoice.Balanced;
237-
if (name is not null) { pref.DesiredGuid = guidStr; pref.DesiredName = name; }
238-
pref.Monitor = false;
239-
pref.AutoApply = false;
240-
ChangeLogger.LogPreferenceChange("[Reset] Power plan", "preset",
241-
$"Want={before}",
242-
$"Want={name ?? "Balanced"} Monitor=Off AutoApply=Off");
243-
changes.Add($"Power plan: Balanced (Windows default), Monitor off, Auto-apply off");
244-
return true;
245-
}
246-
247219
private static bool ResetDisplay(DisplayPreference dp, string label, List<string> changes)
248220
{
249221
bool changed = false;
@@ -375,36 +347,6 @@ private static bool SetRefresh(RefreshRatePref pref, string label, List<string>
375347
return true;
376348
}
377349

378-
private static bool SetPowerPlan(PowerPlanPref pref, CpuTuneResult recipe,
379-
IDictionary<Guid, string> plans, List<string> changes)
380-
{
381-
// CPU-aware: recommend the prebuilt plan the catalog picked (Balanced for
382-
// modern CPUs) -- never blindly High Performance. Building the custom
383-
// optimized plan stays an explicit action on the CPU / Power tab. If the
384-
// recommended plan isn't installed, leave the power plan alone.
385-
var choice = recipe.RecommendedPrebuilt;
386-
var targetGuid = PowerPlanMonitor.ToGuid(choice);
387-
if (!plans.TryGetValue(targetGuid, out var name))
388-
return false;
389-
390-
var guidStr = targetGuid.ToString();
391-
var (bGuid, bMon, bAuto) = (pref.DesiredGuid, pref.Monitor, pref.AutoApply);
392-
bool already = string.Equals(bGuid, guidStr, StringComparison.OrdinalIgnoreCase)
393-
&& bMon && bAuto && pref.Desired == choice;
394-
if (already) return false;
395-
396-
pref.DesiredGuid = guidStr;
397-
pref.DesiredName = name;
398-
pref.Desired = choice;
399-
pref.Monitor = true;
400-
pref.AutoApply = true;
401-
ChangeLogger.LogPreferenceChange("[Recommended] Power plan", "preset",
402-
$"Want={bGuid ?? "(unset)"} Monitor={B(bMon)} AutoApply={B(bAuto)}",
403-
$"Want={name} Monitor=On AutoApply=On");
404-
changes.Add($"Power plan: {name} (CPU-aware recommendation), Monitor on, Auto-apply on");
405-
return true;
406-
}
407-
408350
/// <summary>True when the service backs the AMD CCD-routing stack / Game Bar
409351
/// and the detected CPU is asymmetric dual-CCD X3D (so it must not be disabled).</summary>
410352
public static bool ShouldProtectServiceOnDualCcd(string serviceName, CpuTuneResult recipe)
@@ -414,11 +356,5 @@ public static bool ShouldProtectServiceOnDualCcd(string serviceName, CpuTuneResu
414356
serviceName.Contains(f, StringComparison.OrdinalIgnoreCase));
415357
}
416358

417-
private static IDictionary<Guid, string> SafeListPlans()
418-
{
419-
try { return Monitors.PowerPlanMonitor.ListAvailablePlans(); }
420-
catch { return new Dictionary<Guid, string>(); }
421-
}
422-
423359
private static string B(bool x) => x ? "On" : "Off";
424360
}

src/GamerGuardian/UI/SettingsWindow.xaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,15 +160,15 @@
160160
<StackPanel Margin="0,4,0,0">
161161
<TextBlock TextWrapping="Wrap" FontSize="12"
162162
Foreground="{DynamicResource TextFillColorSecondaryBrush}">
163-
<Run FontWeight="SemiBold" Text="Apply recommended"/><Run Text=" -- GamerGuardian's safe gaming preset: sets the recommended Want, Monitor on, Auto-apply on. Keeps Memory Integrity / VBS on (security) and leaves Privacy / Debloat / contested network tweaks for you to choose."/>
163+
<Run FontWeight="SemiBold" Text="Apply recommended"/><Run Text=" -- GamerGuardian's safe gaming preset: sets the recommended Want, Monitor on, Auto-apply on. Keeps Memory Integrity / VBS on (security) and leaves Privacy / Debloat / contested network tweaks for you to choose. Does not touch your power plan -- set that once yourself on the CPU / Power tab."/>
164164
</TextBlock>
165165
<TextBlock TextWrapping="Wrap" FontSize="12" Margin="0,4,0,0"
166166
Foreground="{DynamicResource TextFillColorSecondaryBrush}">
167-
<Run FontWeight="SemiBold" Text="Apply extreme"/><Run Text=" -- everything that could even remotely help gaming, on: every toggle at its most-aggressive value (including Memory Integrity / VBS OFF and the contested Nagle / NIC tweaks), with Monitor AND Auto-apply turned on for every setting. Disabling Memory Integrity / VBS breaks Valorant (Vanguard) and weakens malware protection."/>
167+
<Run FontWeight="SemiBold" Text="Apply extreme"/><Run Text=" -- everything that could even remotely help gaming, on: every toggle at its most-aggressive value (including Memory Integrity / VBS OFF and the contested Nagle / NIC tweaks), with Monitor AND Auto-apply turned on for every setting. Disabling Memory Integrity / VBS breaks Valorant (Vanguard) and weakens malware protection. Still leaves your power plan alone -- that's a separate one-time setup on the CPU / Power tab."/>
168168
</TextBlock>
169169
<TextBlock TextWrapping="Wrap" FontSize="12" Margin="0,4,0,0"
170170
Foreground="{DynamicResource TextFillColorSecondaryBrush}">
171-
<Run FontWeight="SemiBold" Text="Reset all to defaults"/><Run Text=" -- stages every setting back to its Windows default and turns Monitor + Auto-apply off. Applying then restores Windows' shipped behavior (this re-enables features like Copilot, ads and telemetry services you may have turned off)."/>
171+
<Run FontWeight="SemiBold" Text="Reset all to defaults"/><Run Text=" -- stages every setting back to its Windows default and turns Monitor + Auto-apply off. Applying then restores Windows' shipped behavior (this re-enables features like Copilot, ads and telemetry services you may have turned off). Leaves your power plan as-is -- manage that on the CPU / Power tab."/>
172172
</TextBlock>
173173
</StackPanel>
174174
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,12,0,0">

0 commit comments

Comments
 (0)