testsAndMisc/docs/superpowers/evidence/wake-alarm-plug-fans-warnings-2026-05.json
Krzysztof kuhy Rudnicki a9dead3e59 wake_alarm: Tapo P110 plug control, fan ramp via sudo, loud warnings
- Add python-kasa-based smart-plug control (_smart_plug.py) with
  turn_on_plug / turn_off_plug called around the alarm window.
  Reads ~/.config/wake_alarm/tapo.json (host/email/password).
- Hard timeout (TAPO_TIMEOUT_SECONDS) so plug never blocks the alarm.
- Install fan-control script + sudoers entry (install.sh step 6);
  _max_fans / _restore_fans now invoke it via /usr/bin/sudo -n so
  pwm1_enable writes succeed.
- Remove ntfy.sh push notifications entirely (silent no-op was useless).
- Replace every silent skip with _logger.warning() so failures are
  loud: missing xset / xrandr / speaker-test, unreadable hwmon files,
  fan script errors, missing Tapo config, kasa import failure, etc.
- wake-alarm.service: Restart=on-failure with 10s backoff.
- Tests: 100% line+branch coverage on python_pkg/wake_alarm.
2026-05-23 19:51:26 +02:00

47 lines
3.0 KiB
JSON

{
"intent": "Make the weekend wake alarm actually drive its peripherals (TP-Link Tapo P110 plug, NCT super-I/O case fans) and stop silently swallowing failures.",
"scope": [
"python_pkg/wake_alarm/_alarm.py",
"python_pkg/wake_alarm/_smart_plug.py (new)",
"python_pkg/wake_alarm/_constants.py",
"python_pkg/wake_alarm/install.sh",
"python_pkg/wake_alarm/wake-alarm-fans.sh (new)",
"python_pkg/wake_alarm/wake-alarm.service",
"python_pkg/wake_alarm/tests/* (+test_smart_plug.py)",
"meta/requirements.txt"
],
"changes": [
"Add python-kasa-backed smart-plug module (_smart_plug.py) with bounded asyncio.wait_for timeout; turn_on_plug/turn_off_plug wired into the alarm side-effect sequence.",
"Remove ntfy.sh push notifications entirely (silent no-op was useless on this setup).",
"Replace every silent `return` / contextlib.suppress in _alarm.py and _smart_plug.py with explicit _logger.warning() so missing xset/xrandr/speaker-test/hwmon/fan script/Tapo config all log a visible reason.",
"Fan ramp now invokes /usr/local/bin/wake-alarm-fans.sh via /usr/bin/sudo -n (sudoers NOPASSWD entry installed by install.sh step 6); previously the script ran without sudo and failed on pwm1_enable.",
"Extract _play_tone_on_sink helper to avoid ruff PERF203 from try/except inside a loop.",
"wake-alarm.service: Restart=on-failure with 10s backoff."
],
"verification": [
{
"command": "pre-commit run --files python_pkg/wake_alarm/_alarm.py python_pkg/wake_alarm/_constants.py python_pkg/wake_alarm/_smart_plug.py python_pkg/wake_alarm/tests/test_alarm.py python_pkg/wake_alarm/tests/test_alarm_part2.py python_pkg/wake_alarm/tests/test_smart_plug.py",
"result": "pass",
"evidence": "All hooks passed (ruff, ruff format, mypy, pylint, bandit, codespell, secrets, pytest coverage)."
},
{
"command": "python -m pytest python_pkg/wake_alarm/tests/ --cov=python_pkg.wake_alarm --cov-branch",
"result": "pass",
"evidence": "114 passed; 100% line and branch coverage on _alarm.py, _constants.py, _smart_plug.py, _state.py."
},
{
"command": "python -c 'from python_pkg.wake_alarm._alarm import _max_fans, _restore_fans; s=_max_fans(); print(s); _restore_fans(s)'",
"result": "pass",
"evidence": "state=('/sys/class/hwmon/hwmon6','0','255'); restore returned cleanly with no warnings."
}
],
"risks": [
"Tapo control depends on python-kasa availability on the target host; module logs a warning and no-ops if missing or if ~/.config/wake_alarm/tapo.json is absent.",
"Fan ramp depends on /etc/sudoers.d/wake-alarm and /usr/local/bin/wake-alarm-fans.sh being installed; install.sh now provisions both, otherwise alarm logs a warning and skips."
],
"rollback": [
"git revert the commit; the systemd user service auto-restarts and previous behaviour (ntfy stub, silent skips) returns.",
"Optional: `sudo rm /usr/local/bin/wake-alarm-fans.sh /etc/sudoers.d/wake-alarm` to undo install.sh step 6."
]
}