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
+1 -1
View File
@@ -136,7 +136,7 @@ docs/ Settings reference, and the design specs behind the work
## Tests
159 of them, under `tests/`. Run the lot, or a subset by pattern:
160 of them, under `tests/`. Run the lot, or a subset by pattern:
```sh
panama test # everything
@@ -644,7 +644,12 @@ Singleton {
"rustdesk": ["rustdesk"],
"kdeconnect": ["kdeconnect-app"],
"mission-center": ["flatpak", "run", "io.missioncenter.MissionCenter"],
"bluebubbles": ["flatpak", "run", "app.bluebubbles.BlueBubbles"]
"bluebubbles": ["flatpak", "run", "app.bluebubbles.BlueBubbles"],
// The Accessibility page's "Start Orca" button. It was calling
// openApplication("orca") with no "orca" here, so it set an error
// and launched nothing -- a dead button. orca ships in
// hyprland-packages, so this just runs it.
"orca": ["orca"]
};
const command = commands[id];
if (!command) {
@@ -56,6 +56,14 @@ SELF_INSTALLED='^(bun|claude|node|npm|pnpm)$'
# Anything added here needs that same property: absence must be loud.
OPTIONAL='^(docker)$'
# Provided by a package swap rather than a list entry. ffmpeg cannot be a list
# entry: RPM Fusion's ffmpeg CONFLICTS with the ffmpeg-free that Fedora ships
# preinstalled, so `dnf install ffmpeg` fails the whole transaction. The codec
# section swaps ffmpeg-free -> ffmpeg with --allowerasing instead. Either way
# /usr/bin/ffmpeg exists -- ffmpeg-free provides it too -- so panama-transcode
# always has it; it is simply never a name in a package list.
SWAPPED='^(ffmpeg)$'
# jq programs are quoted arguments, but the scanner is line-based and cannot
# tell a filter from a command. `not` is a jq builtin appearing inside one.
JQ_BUILTINS='^(not|empty|error|env|input|inputs)$'
@@ -116,6 +124,7 @@ while read -r script; do
[[ "$cmd" =~ $SESSION ]] && continue
[[ "$cmd" =~ $SELF_INSTALLED ]] && continue
[[ "$cmd" =~ $OPTIONAL ]] && continue
[[ "$cmd" =~ $SWAPPED ]] && continue
[[ "$cmd" =~ $JQ_BUILTINS ]] && continue
pkg="$(package_for "$cmd")"
+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