Desktop & Dock becomes Shell — Bar, Dock, Control Center, Tiling, Workspaces — the home for everything Quickshell draws. The settings- management cluster moves to System as Sync & Backup, Appearance's Shell tab dissolves, and 24-hour time finally lives on Date & Time, which always owned it. The bar gets what it never had: a way to survive the wallpaper. A second neutral text family (follow theme, or forced light or dark), a one-layer shadow under every glyph, and a gradient scrim for wallpapers nothing else survives — all off by default, pixel-identical until asked. Widgets earn toggles (weather, media, clipboard, calendar countdown), the vitals cluster stops leaving a dead pill behind, and Control Center's sections learn to step aside. The dock graduates from MVP: a context menu with window rows, pin, unpin, quit and new-window; scroll an icon to cycle its windows; drag to reorder on the dock itself; hover previews with one-shot captures; and "Add App to Dock" in the launcher. Three real bugs died en route — menus that slid away with the autohide, a readonly-property crash on every menu open, and a drag that drifted half a slot per icon on side docks. The pinned-apps editor in Settings becomes a drag strip. 166 contracts; the full suite is green except two live display and switcher tests that cannot run behind a locked session — re-verified on unlock. Claude-Session: https://claude.ai/code/session_01Ms2FbjQy31TVf3CEvQhGM8
191 lines
15 KiB
Markdown
191 lines
15 KiB
Markdown
# Settings redesign — deferred test runs
|
||
|
||
No contract is executed while the settings redesign is in flight: many are live
|
||
harnesses that open windows, drive overlays, and run display transactions on
|
||
the real desktop. Everything below runs **once, at the end of the redesign,
|
||
with Gabriel's go-ahead**, and failures get fixed then.
|
||
|
||
## The run
|
||
|
||
- `panama test` — the full suite (**166** contracts as of the phase 4 Shell
|
||
wave; the top-level README's count line is set to match and is itself
|
||
checked by `setup/readme-contract`).
|
||
|
||
## Known items to verify or investigate at the end
|
||
|
||
- `quickshell/welcome-contract` — failed once ("the welcome screen did not
|
||
open") during a full-suite run storming the live session; passed in
|
||
isolation minutes earlier after the Welcome.qml comment edit. Suspected
|
||
contention flake, not a regression. Confirm.
|
||
- `setup/readme-contract` — counts contracts; keep the README number in sync
|
||
as later phases add contracts (phase 2 added `phone-page-contract`).
|
||
- Phase 2 additions already written and passing when last run:
|
||
`my-home-settings-contract` (renamed from `home-phone-settings-contract`),
|
||
`phone-page-contract`, extended `home_assistant_bridge_test.py` and
|
||
`kdeconnect_bridge_test.py`.
|
||
- Each later phase (Appearance, …) appends its new/changed contracts here
|
||
instead of running them.
|
||
|
||
## Phase 3 (Appearance) — append below
|
||
|
||
The contracts wave is done. Everything below is written and **still to be
|
||
RUN**. Nothing in this list has been executed against a live harness: the
|
||
static halves were checked against the tree, but every harness run and the
|
||
full-suite pass are deferred to the end-of-redesign sweep.
|
||
|
||
### New contracts (3)
|
||
|
||
| Contract | What it pins |
|
||
|---|---|
|
||
| `quickshell/theme-catalog-contract` | `config/themes.json` shape (10 themes, 6 dark / 4 light), every palette and ansi block accepted by the model's own validators, moon and day byte-identical to the shell's pre-theme literals, `ThemeCatalog.qml`'s embedded fallback carrying both, and `Theme.qml` holding no palette ternary. |
|
||
| `quickshell/video-wallpaper-contract` | Three independent pause reasons (`FocusModes.gameRunning`, `Battery.acOnline` plus the preference, `manuallyPaused`) and pausing over mpv's JSON IPC; the mpvpaper argv (`hwdec=vaapi`, `no-audio`, `loop-file=inf`, `input-ipc-server=`); the hyprpaper stop/start choreography and `Wallpaper.refreshActive()`; `Wallpaper.qml`'s video routing branches; the helper's 60-file cap, depth-2 scan and mp4/mkv/webm filter; the still frame for the lock screen; `WallpaperIndicator` in `Bar.qml`'s right-hand row with its `visible` binding, spoken name and no animation; the two schema keys; the doctor check id. |
|
||
| `quickshell/settings-titlebar-contract` | No minimize or maximize anywhere in the settings chrome (comments may say the words, code may not); `height: shown ? 48 : 0` so hiding collapses rather than leaving a hole; `buttonsLeft` side-awareness with exactly one anchor released per element; the close button's `activeFocusOnTab`, `Accessible.role`/`name`, Return/Space handlers and focus treatment, and that it is the only button; Escape declared on the shell rather than inside the bar; the `panamaTitlebar` schema entry and its Appearance row. |
|
||
|
||
### Updated contracts (6)
|
||
|
||
| Contract | What it now pins |
|
||
|---|---|
|
||
| `quickshell/accent-controls-contract` | Rewritten around the new editor: the nine surviving components and their qmldir lines, `AccentPicker`/`ThemeProfilePicker` staying deleted *and* unregistered, the four wells and their single `apply()` path, one hyprpicker invocation aimed by a remembered target, `ColorWell`'s hex validation committing on Enter and focus-out but never per keystroke, the six HSV labels, the debounce (the write lives in `commitTimer`, `changeChannel` writes nothing, `releaseTimer` hands the sliders back), `commitActive` recomputing `accentName` through `nearestCuratedName` with `selectProfile`/`updateActive` both routing into it, `Theme.qml` reading `ThemeProfiles.activePalette`, the Themes and Theme editor tabs, four search labels, and the no-animation ban extended over all nine components. Live half rewritten against the rebuilt harness. |
|
||
| `quickshell/theme-profiles-contract` | Node half rebuilt for the optional-field model: `shippedProfiles()` with no argument still returns the three built-in fallbacks (back-compat), the ten catalog records survive with palettes and ansi and no effects, palette/ansi/effects survive a stored record with per-key effect clamping, an invalid palette drops the FIELD not the profile, the caller's shipped list owns the id and name space, `editProfile` passes untouched fields through and a shipped fork carries the whole palette, `nearestCuratedName` mappings (mauve→orchid, gruvbox-yellow→amber, grey→slate, per scheme), and `derivePalette`/`resaturatePalette`/`deriveAnsi`/`mixHex` producing palettes the validators accept. Live half now pins the per-mode selection flow: a light/dark flip returns to the theme chosen on that side, never a forced default. |
|
||
| `quickshell/desktop-style-contract` | `titlebarMaximizeButton` and `titlebarDoubleClick` asserted **gone** from the schema and from `DesktopStyle`, along with `action-double-click-titlebar`; `panamaTitlebar` added (bool, def true, group titlebar); the button layout pinned close-only on both sides with `minimize`/`maximize` banned from the function body; the Appearance greps moved to Fonts/Sizes/Rendering with exactly five `FontPicker` rows and their five role labels, plus the honest-titlebar subtitle. |
|
||
| `quickshell/settings-ownership-contract` | The ColorScheme block was pinning `inactiveBorderDark`/`inactiveBorderLight`, which no longer exist. It now pins the inactive border as the active theme's `gutter`, bans a regrown literal, pins the accent border roles through the new `hyprColor(value, alpha)` signature, requires both roles to be restated on a theme change, and cross-checks Hyprland's startup literals against moon's and day's gutters in `themes.json`. |
|
||
| `quickshell/lock-screen-settings-contract` | The "between Background and Shell typography" ordering check named a card that no longer exists. It now pins Background → Video playback → Lock screen order, and that all three sit on the Background tab. |
|
||
| `quickshell/settings-search-contract` | Seven fixed cases added for the new surface: themes, theme editor, dark mode, Catppuccin, Gruvbox, video wallpaper, titlebar. The schema-label sweep already covers the new keys automatically. |
|
||
|
||
### Verified against the new tree, no edit needed
|
||
|
||
- `quickshell/settings-hardcoded-values-contract` — its scope is `Settings.qml`,
|
||
which the theme work did not touch; `Theme.qml`'s literals are covered by
|
||
`theme-catalog-contract` instead.
|
||
- `quickshell/wallpaper-service-contract` — already carries the video routing
|
||
greps.
|
||
- `quickshell/wallpaper-settings-contract`, `wallpaper-policy-contract`,
|
||
`settings-nav-contract`, `settings-pages-contract`, `manual-contract`,
|
||
`settings-docs-contract`, `qmldir-registration-contract`,
|
||
`settings-sync-contract`, `settings-backup-contract` — checked, nothing stale.
|
||
- `quickshell/panama-doctor-contract` — already lists `input.video-wallpaper`.
|
||
|
||
### Docs updated in the same wave
|
||
|
||
- `modules/settings/README.md` — new **Appearance** section (Themes, Theme
|
||
editor, backgrounds still and moving, the honest titlebar); the border
|
||
ownership paragraph corrected to the theme's gutter.
|
||
- `manual/05-making-it-yours.md` — rewritten Appearance chapter: the two
|
||
galleries, per-mode memory, the four-well editor, video wallpapers, and why
|
||
there is no minimize.
|
||
- Top-level `README.md` — contract count 162 → 165, confirmed by
|
||
`setup/readme-contract`.
|
||
|
||
### Still open before the run
|
||
|
||
- The parallel pipeline wave's files (`gtk-theme-contract`,
|
||
`lock-screen-theme-contract`, `palette-contract`, the two bridge tests) are
|
||
not counted above. If that wave adds contracts, the README count line and the
|
||
count in this file both need bumping again before the suite runs.
|
||
- `AppearancePage.qml`'s `tab` property defaults to `"background"` while its
|
||
own comment says Themes leads. Decide which is intended before the run;
|
||
nothing currently pins it either way.
|
||
|
||
## Phase 4 (Shell category) — append below
|
||
|
||
Spec: `2026-08-24-shell-category-redesign.md`. Desktop & Dock became **Shell**
|
||
(Bar · Dock · Control Center · Tiling · Workspaces), System gained **Sync &
|
||
Backup**, and the dock got its feature wave.
|
||
|
||
Unlike phases 2 and 3, the static and stubbed contracts in this wave **were
|
||
run** as they were written, and every one of them passed in isolation against
|
||
the tree. Two things are still deferred. The **live-harness halves** were not
|
||
run — the session was locked, and `dock-position-contract` opens a probe shell
|
||
while `settings-pages-contract` starts a settings harness, so those ran static-
|
||
only (`PANAMA_SETTINGS_STATIC_ONLY=1`) or not at all. And the **full-suite
|
||
pass**, the only thing that catches contention between harnesses, happens next
|
||
with Gabriel driving.
|
||
|
||
### New contracts (1)
|
||
|
||
| Contract | What it pins |
|
||
|---|---|
|
||
| `quickshell/bar-visibility-contract` | The bar's own neutral family: `barFg`/`barFgDim`/`barFgMuted` exist, each forced tone is anchored on one literal with both dims mixed off it, and the `theme` branch returns `root.fg`/`fgDim`/`fgMuted` **by identity** rather than a copied colour. All thirteen bar-text files bind to those tokens and none paints neutral text with the `fg` family (`Theme.alpha(Theme.fg, …)` hover and separator fills are allowed; semantic tones were never in scope). `Bar.qml`'s scrim reads `visible: Settings.barBackdrop`, its shadow reads `layer.enabled: Settings.barTextShadow` over exactly one `MultiEffect` layer, and neither may be a literal `true` — both shipped hardcoded during the build, which is the regression this exists for. Plus the four widget gates ANDed with their state conditions, `VitalsWidget`'s whole-pill `visible`, `exclusiveZone: Theme.barHeight` still literal, no animation anywhere in `Bar.qml`, and the two right-click jumps landing on `bar`. |
|
||
|
||
Mutation-checked while writing: hardcoding the shadow, returning a literal from
|
||
the `theme` branch, putting one widget back on `Theme.fg`, deleting the vitals
|
||
pill's own `visible`, and adding a `Behavior` to `Bar.qml` each fail it with a
|
||
message naming the actual problem.
|
||
|
||
### Updated contracts (5)
|
||
|
||
| Contract | What it now pins |
|
||
|---|---|
|
||
| `quickshell/dock-position-contract` | `DockPinsEditor` → `DockPinsStrip`: `preventStealing` moved to the strip, the retired ↑/↓ buttons replaced by the strip's own keyboard path (Left/Right move, Delete unpins), and a new section for the **live** dock's drag-to-reorder — commits once on release, and measures a slot from a real icon rather than a constant, because a `DockItem` is taller than it is wide and a constant is wrong on one orientation. |
|
||
| `quickshell/settings-jump-contract` | `DockContextMenu`'s "Dock settings" now opens `dock`, not the retired `desktop`. |
|
||
| `quickshell/settings-pages-contract` | Six new pages added to the page sweep (Bar, Dock, ControlCenter, Tiling, Workspaces, Sync); `vitalsIntervalMs` and the graphics ChoiceGrid now required on `BarPage` rather than `AppearancePage`, since the vitals are bar content and not surface appearance. |
|
||
| `setup/projects-contract` | The saved-projects list moved from the deleted `DesktopPage.qml` to `WorkspacesPage.qml`. |
|
||
| `quickshell/panama-commands-contract` | The launcher's new `dock-add-app` → `panama-action dock-pin` command. |
|
||
|
||
### Verified against the new tree, no edit needed
|
||
|
||
Every one of these was **run** and passed after the phase-4 changes landed:
|
||
|
||
- `quickshell/settings-search-contract` — the new `bar`/`controlCenter`/
|
||
`datetime` groups and the re-pointed `dock`/`multitasking`/`edges`/`master`/
|
||
`notices`/`focus` routes are covered by the schema-label sweep already.
|
||
- `quickshell/settings-ownership-contract` — the six intentional mirrors and the
|
||
eleven README literals survived the rewrite; no new mirror was introduced.
|
||
- `quickshell/settings-nav-contract` — 14 categories, 38 leaves, 2 retired ids
|
||
(`home-phone`, `desktop`).
|
||
- `quickshell/manual-contract`, `gnome-handoff-contract` (15 handoffs against
|
||
38 pages), `control-center-contract`, `welcome-contract`,
|
||
`accent-controls-contract`, `theme-catalog-contract`,
|
||
`desktop-style-contract` — checked, nothing stale.
|
||
|
||
`welcome-contract` passed in isolation again here, which does not settle the
|
||
phase-3 flake above: that failure only appeared under a storming full-suite run.
|
||
|
||
### Docs updated in the same wave
|
||
|
||
- `docs/settings.md` and the 37 `settings-*` launcher commands — regenerated by
|
||
`panama-settings-docs` and `panama-settings-commands`; both `--check` modes
|
||
clean and both generators verified idempotent. `settings-desktop` is deleted,
|
||
`settings-bar`/`-dock`/`-control-center`/`-tiling`/`-workspaces`/`-sync` are
|
||
new, and `dock-add-app` joins them.
|
||
- `modules/settings/README.md` — new **Shell** section (the five tabs, the bar
|
||
token design and why it exists, the pins strip and the live dock's gestures,
|
||
the Control Center rule that only real sections get toggles) and a new
|
||
**System › Sync & Backup** section. Appearance corrected from six tabs to
|
||
five, saying where the Shell tab went.
|
||
- `manual/05-making-it-yours.md` — new **Shell** chapter section (bar
|
||
legibility, widget switches, why `use24Hour` is not there, the pins strip,
|
||
the dock's drag/right-click/scroll/preview gestures, **Add App to Dock**,
|
||
Control Center sections) plus **Carrying settings between machines**.
|
||
`manual/03-windows-and-workspaces.md` — the multi-display workspace switch
|
||
now points at Displays, which is where it actually is, instead of the deleted
|
||
Desktop & Dock page.
|
||
- Top-level `README.md` — contract count 165 → 166, recounted the way
|
||
`panama test` collects (executable, or `*_test.py`, excluding fixtures and
|
||
`__pycache__`).
|
||
|
||
### Still open before the run
|
||
|
||
- Four contracts in the working tree changed for reasons **outside** this
|
||
phase and are not accounted for above: `declared-assets-contract` (`pkill`,
|
||
from the video wallpaper work), `declared-dependencies-contract` (`cmp` →
|
||
diffutils), `panama-doctor-contract` (29 → 30 check ids), and
|
||
`lock-screen-helper-contract` / `video-wallpaper-contract` (theme-derived
|
||
literals and the mpv IPC key quoting). Confirm each belongs to a wave that
|
||
intended it before the suite runs.
|
||
- `tests/setup/update-command-contract` is untracked and belongs to the
|
||
separate `panama update` design, not to this redesign. It **is** inside the
|
||
166.
|
||
- `quickshell/dock-position-contract` has never had its **live** half run since
|
||
the strip landed: it opens a probe shell, and this wave ran under a locked
|
||
session. Its static half is what was verified. Run it first in the sweep.
|
||
- `quickshell/settings-pages-contract` passed static-only for the same reason.
|
||
Its compositor-integration half — the settings harness, its IPC, and the
|
||
page-open checks — is unverified against the six new pages.
|
||
- `Bar.qml` has one stray indentation glitch at its first `Row` (line 105).
|
||
Cosmetic, untouched here because the file is not this wave's to reformat.
|
||
- 2026-08-24 full-suite run: 166 contracts, all green except `displays-contract`
|
||
and `switcher-contract`, which are live interactive tests that cannot run
|
||
behind hyprlock (both passed in the same day's unlocked run; neither
|
||
subsystem changed in phase 4). Re-verify after unlock.
|