Files
dotfiles/docs/superpowers/specs/2026-05-11-power-profile-fan-trigger-design.md
T
funman300 5f00fdc2be docs: spec for power-profile→fan sync trigger
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 17:52:28 -07:00

3.7 KiB

Power-Profile → Fan-Profile Sync Trigger Design

Date: 2026-05-11 Status: Approved

Summary

When the user changes power profile via scripts/power-profile.sh --menu, also nudge the waybar fan widget so scripts/fan-profile.sh immediately re-evaluates its auto-mode mapping. Without this nudge, the fan strategy follows the new power profile only on the next 5 s waybar poll; with it, the change is essentially instant. If fan auto mode is off (the ~/.local/state/fan-profile-auto sentinel is absent), nothing changes — manual fan strategy is preserved.

Current Behaviour

scripts/power-profile.sh --menu ends with:

[ -n "$CHOICE" ] && powerprofilesctl set "$CHOICE" && pkill -RTMIN+8 waybar

Signal RTMIN+8 is the signal: value declared by waybar's custom/power-profile module — refreshes the power widget. The fan widget (signal: 9) is NOT refreshed; it only re-evaluates on its interval: 5 poll.

scripts/fan-profile.sh already has the coupling logic. When the auto sentinel exists, every status emit:

  1. Reads powerprofilesctl get
  2. Maps it via map_profile_to_strategy
  3. Calls fw-fanctrl use <mapped> if the active strategy differs

So changing the power profile causes the fan strategy to follow within ≤5 s already — but only on the next poll. The user wants this to be instant.

Target Behaviour

After the user picks a new power profile from the wofi menu:

  1. powerprofilesctl set applies the change.
  2. pkill -RTMIN+8 waybar refreshes the power widget.
  3. pkill -RTMIN+9 waybar refreshes the fan widget, which re-runs fan-profile.sh. If auto mode is on, fan-profile.sh notices the strategy mismatch and applies the new strategy via fw-fanctrl use. If auto mode is off, the script just re-renders the existing strategy (no functional change).

End-to-end latency: well under a second.

Why This Implementation

Reuses the existing single-source-of-truth mapping in fan-profile.sh::map_profile_to_strategy. Power-profile.sh doesn't need to know:

  • The mapping table (lives in fan-profile.sh)
  • The auto sentinel path (lives in fan-profile.sh)
  • The fw-fanctrl use command (lives in fan-profile.sh)

It just sends a "hey, you should re-evaluate" signal. Zero duplication. Zero new files. One line.

Implementation

scripts/power-profile.sh

Change line 13 from:

    [ -n "$CHOICE" ] && powerprofilesctl set "$CHOICE" && pkill -RTMIN+8 waybar

to:

    [ -n "$CHOICE" ] && powerprofilesctl set "$CHOICE" && pkill -RTMIN+8 waybar && pkill -RTMIN+9 waybar

The chained && means the fan-widget refresh fires only if the power-widget refresh succeeded, which only fires if powerprofilesctl set succeeded. So a failure to apply the profile (e.g. dbus not running) skips both refreshes — the bar reflects the unchanged state on its next 5 s poll.

Files Touched

  • scripts/power-profile.sh — one-line change to line 13.

Out of Scope

  • Power-profile changes via tools other than this script. If the user runs powerprofilesctl set X from a terminal or via a GNOME settings panel, the fan still follows on fan-profile.sh's 5 s poll (auto mode). Making that path zero-lag would need a dbus listener for org.freedesktop.UPower.PowerProfiles — bigger architectural change, deferred.
  • Changing the mappingpower-saver→lazy, balanced→medium, performance→agile is locked from the original fan-profile auto spec.
  • Making auto default-on — auto sentinel still has to be created via the fan wofi menu choice; this spec doesn't change that opt-in.
  • Race condition between powerprofilesctl set and fan-profile.sh re-read. powerprofilesctl set is synchronous on dbus; by the time it returns, powerprofilesctl get reflects the new value. No race.