Fix the second dead settings button, and pin the class shut

A sweep for controls wired to targets the backend does not handle -- the shape
of the dictation bug -- found one more: "Start Orca" on the Accessibility page
called openApplication("orca") with no "orca" in the command map, so it set an
error and launched nothing. orca ships in hyprland-packages; it now runs.

That is the whole count. Every service-method call across 84 settings pages
resolves, every helper subcommand a service invokes is implemented, every
openGnomePanel handoff is allow-listed. Two dead buttons existed in the entire
settings app -- the dictation Download and this -- and both are fixed.

settings-buttons-contract pins the class: every openApplication id and
openGnomePanel panel a QML button passes must be present in SystemSettings'
dispatch maps, both of which return false silently on an unknown name.
Verified it catches the orca button when the fix is reverted.

And a dependency-contract exception the ffmpeg fix needed: ffmpeg is provided
by a swap (ffmpeg-free -> ffmpeg), never a list entry, because listing it is
the conflict that fix removed -- so panama-transcode's use of it is satisfied
without a package name to point at.

Claude-Session: https://claude.ai/code/session_01Epx9ZC1gwm81K3jm9x9CKh
This commit is contained in:
Gabriel Brown
2026-08-23 14:11:15 -04:00
parent 14fc4fc8a3
commit 50077a0c31
4 changed files with 68 additions and 2 deletions
+52
View File
@@ -0,0 +1,52 @@
#!/usr/bin/env bash
# A settings button that calls a target the backend does not handle is a dead
# control: it looks identical to a working one until someone presses it and
# nothing happens. Two dispatch maps in SystemSettings.qml decide whether a
# button lands -- openApplication(id) and openGnomePanel(panel) -- and both
# silently return false on an unknown name. This pins every id and panel a QML
# button passes to being present in those maps.
#
# It exists because two such buttons shipped: "Start Orca" called
# openApplication("orca") with no "orca" in the map, and the dictation card
# called a helper subcommand that did not exist. This catches the first shape;
# the helper-subcommand shape is caught by each service's own contract.
set -uo pipefail
repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
qs="$repo_dir/config/dot/quickshell"
sysset="$qs/services/SystemSettings.qml"
fail() { printf 'settings buttons contract: %s\n' "$1" >&2; exit 1; }
[[ -r "$sysset" ]] || fail "missing $sysset"
python3 - "$qs" "$sysset" <<'PY'
import re, sys, pathlib
qs, sysset = pathlib.Path(sys.argv[1]), pathlib.Path(sys.argv[2])
text = sysset.read_text()
# openApplication's command map keys.
m = re.search(r'function openApplication.*?const commands = \{(.*?)\};', text, re.S)
app_ids = set(re.findall(r'"([a-z0-9-]+)"\s*:', m.group(1))) if m else set()
# openGnomePanel's allow-list.
m = re.search(r'isGnomePanelAllowed.*?return \[(.*?)\]\.indexOf', text, re.S)
panels = set(re.findall(r'"([a-z-]+)"', m.group(1))) if m else set()
problems = []
for page in sorted((qs/'modules').rglob('*.qml')):
t = page.read_text()
for app_id in re.findall(r'openApplication\("([^"]+)"\)', t):
if app_id not in app_ids:
problems.append(f'{page.name}: openApplication("{app_id}") -- not in the command map, so the button does nothing')
for panel in re.findall(r'openGnomePanel\("([a-z-]+)"', t):
if panel not in panels:
problems.append(f'{page.name}: openGnomePanel("{panel}") -- not allow-listed, so the handoff opens nothing')
if problems:
print(f"settings buttons contract: {len(problems)} dead button(s)")
for p in problems: print(" -", p)
sys.exit(1)
print(f"settings buttons contract: ok ({len(app_ids)} app ids, {len(panels)} panels, every button resolves)")
PY