colour -> color, behaviour -> behavior, centre -> center, favourite ->
favorite, and about twenty other pairs, applied consistently across
comments, docs, error/UI copy, and a handful of QML identifiers that
used the British spelling as their actual name: SystemSettings'
serialiseValue/serialiseTable/normaliseGradient, Displays'
normaliseModes, Wallpaper's normalisePolicy, SettingsBackup's
serialiseHomeState, DateTime's ntpSynchronised property, Clipboard's
_normalise helper, and ShortcutCapture's cancelled signal (with its
onCancelled handler in ShortcutsPage.qml). Every call site and the two
tests that assert on the literal source text (settings-ownership and
settings-backup-live contracts) were updated in lockstep.
Left untouched: config/dot/espanso/match/packages/misspell-en/ is a
vendored third-party autocorrect dictionary -- its entries are typo
corrections, not our prose, and rewriting them would fight the
package's own purpose (and any future re-sync from upstream).
The already-American `favorites` property (Home page pinned
accessories) was never actually misspelled -- only nearby comments and
error strings said "favourites" -- so no data migration was needed
there.
Claude-Session: https://claude.ai/code/session_01E6TJUAh41HaP25MVHWkhRZ
Audited bar, dock, quick settings, date menu and Settings for three
things: a setting reachable in one UI but not another, a setting that
exists but is unreachable anywhere, and UI that states something false.
Night Light was fully exposed in Quick Settings and had no control
anywhere in Settings. It now has a card on Displays, where GNOME also
puts it, with on/off, schedule, times and temperature.
Adding those controls would have shipped the exact defect this audit
exists to find. NightLight declared enabled, temperature and automatic
as bindings on the store, but toggle() assigns to them, and an
assignment destroys a QML binding permanently -- so the service wrote to
the store and never read from it again. The Settings controls would have
written values the service ignored, while Quick Settings kept working.
It now follows the store. Every other service was swept for the same
pattern; this was the only one.
The night light schedule was two hardcoded literals, so the hours could
not be changed. They are schema keys now, with a row that renders 17.5
as "5:30 PM" and honours the 24-hour preference rather than showing a
decimal nobody reads as a time.
keyboardLayout was in the schema and read by input.lua but had no
control anywhere: configurable in principle, unreachable in practice. It
is surfaced on Input & Shortcuts as read-only, with the reason, because
it needs a compositor reload and a control implying instant apply would
be a smaller lie but still a lie.
Caffeine was a Quick Settings toggle mentioned only in a subtitle in
Settings. It has a real control now.
Claude-Session: https://claude.ai/code/session_01BRvzt4H8XXLPVH5MyYdk9L
Panama had grown into three configuration surfaces that only agreed because
they had been typed to agree: looks.lua hardcoded values, DesktopPreferences
independently defaulted the same values, and SystemSettings replayed them at
startup. Nothing kept them in sync, and the Lua side read no shared state at
all. This lands the first three stages of docs/superpowers/plans/2026-08-17-panama-cohesion.md.
Fix silently failing Hyprland writes. On a Lua-configured Hyprland, hyprctl
keyword refuses the write, prints the refusal to stdout, and still exits 0, so
the HDR, VRR, and direct-scanout toggles persisted their value and reported
success while the compositor never changed. Writes now go through hyprctl eval,
which has the same hazard on syntax and runtime errors, so success is defined
as reading the value back and finding it equal. The existing contract passed
throughout the outage because it re-applied the values already in place; the
new one flips each value to something it does not hold.
Derive preferences from a schema. Every setting used to be restated four times
-- a property alias, a JSON adapter property, a change handler, and a line in
reset -- where omitting any one failed silently. PreferenceSchema.qml is now
the single source, and persistence, validation, reset, and the Hyprland mapping
all derive from it. Unknown keys on disk survive a write so a rollback does not
discard a newer build's settings, and a corrupt file falls back to shipped
defaults. The store moved to ~/.config/panama/settings.json, migrating from the
old state directory without deleting it.
Share that file with Hyprland. prefs.lua reads it at config time with every
shipped literal kept as the fallback, so the config still stands alone. The Lua
is the default, the JSON is the truth, and Settings is the editor. The
compositor-adjustable surface goes from 3 keys to 23.
Also fixes two test-hygiene bugs found by running the suite end to end for the
first time: settings-pages-contract could see the window settings-window-contract
leaves behind, and the new write contract was persisting its deliberately-wrong
values into the user's real store.
Claude-Session: https://claude.ai/code/session_01BRvzt4H8XXLPVH5MyYdk9L