What
Two related pieces of drift, worth one decision rather than two passes.
1. 116 broad-exception-caught, concentrated where the risk is highest:
40 device_sync.py
32 plugin.py
13 export_recovery_menu_mixin.py (was server_menu_mixin.py)
8 pairing_menu_mixin.py
5 ws_json_client.py
5 commission_jobs.py
Many are legitimate — the house rule that bookkeeping must never sink a reconcile, or that an Indigo callback must not raise into the UI thread, is right and documented at most sites. But 116 is too many to have been decided 116 times, and the workspace degradation-path standard is explicit that "no such thing" and "the lookup itself failed" must not collapse into one handler.
2. 111 inert # noqa: BLE001 comments. The repo uses two suppression idioms for the identical pattern:
# noqa: BLE001 — inbound-side files (device_sync, plugin, device_settings, settings_report, commission_jobs, …)
# pylint: disable=broad-except — outbound-side files (ct_learner, export_*, bridge_client, ws_json_client, …)
A few files use both. Only pylint is wired into CI (#305), so all 111 noqa comments are decorative — they suppress nothing, and they imply a linter that does not run here.
Why it matters
The noqas are actively misleading: someone adding a broad catch copies the nearest neighbour and may pick the idiom that does nothing. And a real over-broad catch is invisible in a list of 116.
Suggested order
- Decide the convention. Either wire up ruff/flake8 so
BLE001 means something, or standardise on # pylint: disable=broad-except and delete the 111 noqas. The second is less work and matches what CI actually enforces.
- Triage the 116 by whether the handler distinguishes failure modes, not by count. The ones that matter are where a broad catch gates behaviour rather than a display value —
device_sync and plugin first, since they hold 72 of them between them.
- Anything genuinely load-bearing keeps its catch and gains a comment saying which failures it is absorbing and why that is safe.
Do not do this as one sweeping PR. It touches every file in the plugin and would be unreviewable; per-module, highest-risk-first.
Found
During the 2026-08-25 refactor review. Deliberately not attempted in that arc — it is a behaviour-change class, not a pure refactor.
What
Two related pieces of drift, worth one decision rather than two passes.
1. 116
broad-exception-caught, concentrated where the risk is highest:Many are legitimate — the house rule that bookkeeping must never sink a reconcile, or that an Indigo callback must not raise into the UI thread, is right and documented at most sites. But 116 is too many to have been decided 116 times, and the workspace degradation-path standard is explicit that "no such thing" and "the lookup itself failed" must not collapse into one handler.
2. 111 inert
# noqa: BLE001comments. The repo uses two suppression idioms for the identical pattern:# noqa: BLE001— inbound-side files (device_sync,plugin,device_settings,settings_report,commission_jobs, …)# pylint: disable=broad-except— outbound-side files (ct_learner,export_*,bridge_client,ws_json_client, …)A few files use both. Only pylint is wired into CI (#305), so all 111
noqacomments are decorative — they suppress nothing, and they imply a linter that does not run here.Why it matters
The
noqas are actively misleading: someone adding a broad catch copies the nearest neighbour and may pick the idiom that does nothing. And a real over-broad catch is invisible in a list of 116.Suggested order
BLE001means something, or standardise on# pylint: disable=broad-exceptand delete the 111noqas. The second is less work and matches what CI actually enforces.device_syncandpluginfirst, since they hold 72 of them between them.Do not do this as one sweeping PR. It touches every file in the plugin and would be unreviewable; per-module, highest-risk-first.
Found
During the 2026-08-25 refactor review. Deliberately not attempted in that arc — it is a behaviour-change class, not a pure refactor.