Seeding is deliberately conservative: a role whose preferred applications are all missing is left alone rather than forced. That is right, and it is also silent -- so a curated handler nobody installs presents as the machine quietly going back to deciding defaults by installation order, which is the problem seeding exists to fix. None of Loupe, Papers, Decibels, Nautilus, mpv or sushi was declared anywhere. Preview works, on org.gnome.NautilusPreviewer2 rather than the interface its bus name suggests, but it opened tiled -- shoving the file manager aside for something meant to be an overlay -- so it gets a float and center rule sized to leave the file underneath visible. xdg-utils and desktop-file-utils were undeclared too; seeding from link-dotfiles started calling them, and the dependency contract said so. Claude-Session: https://claude.ai/code/session_01BRvzt4H8XXLPVH5MyYdk9L
146 lines
6.6 KiB
Markdown
146 lines
6.6 KiB
Markdown
# Desktop integration: the parts an OS owns that we still hand to someone else
|
|
|
|
Written 2026-08-19, after the default-applications work landed.
|
|
|
|
Settings is now a superpowered control panel, and files open in the right
|
|
applications. What remains are the jobs a desktop environment is expected to own
|
|
but that this one currently delegates, ignores, or leaves to whatever GNOME
|
|
component happens to be installed.
|
|
|
|
Six items, ordered so each one is useful the day it lands rather than only at the
|
|
end. Effort labels are relative to each other, not to the clock.
|
|
|
|
## What the probe found
|
|
|
|
Two of these are far cheaper than assumed:
|
|
|
|
- **`sushi` 50 is already installed** and owns `org.gnome.NautilusPreviewer`, so
|
|
Quick Look is a wiring-and-declaring job, not a build.
|
|
- **Vicinae script commands already exist and are repo-managed**
|
|
(`config/local/share/vicinae/scripts/panama/`, linked by
|
|
`setup/scripts/link-vicinae-scripts`), so launcher search is a generator on top
|
|
of a mechanism that works.
|
|
|
|
And two need software this machine does not have: `restic` (backups) is not
|
|
installed, and nothing enumerates the keyring beyond lock state.
|
|
|
|
---
|
|
|
|
## Phase 1 — Finish the file-opening story (small)
|
|
|
|
Curating defaults only helps if the applications are actually present. A fresh
|
|
install seeds `org.gnome.Loupe`, `org.gnome.Papers` and `org.gnome.Decibels`
|
|
only when they exist; otherwise it correctly leaves the role alone and the
|
|
machine falls back to installation order — the exact problem we just fixed.
|
|
|
|
- Declare Loupe, Papers, Decibels, Nautilus, mpv and sushi so a fresh machine
|
|
actually has what seeding prefers.
|
|
- Wire preview.
|
|
- Extend the family contract to assert every preferred handler is a declared
|
|
package.
|
|
|
|
**Done when** a fresh machine gets the same handlers this one has, and the
|
|
contract fails loudly if a curated application is not a declared dependency.
|
|
|
|
**Landed 2026-08-19.** The previewer answers on `org.gnome.NautilusPreviewer2`,
|
|
not the `NautilusPreviewer` interface its bus name suggests, and it opened
|
|
*tiled* -- shoving the file manager aside for something meant to be an overlay
|
|
-- so it now has a float-and-center window rule. No compositor keybind: the
|
|
selection to preview lives in the file manager, and nothing outside it knows
|
|
what is selected. `xdg-utils` and `desktop-file-utils` were also undeclared,
|
|
which the dependency contract caught the moment seeding started calling them.
|
|
|
|
## Phase 2 — Make GTK applications wear our accent (small)
|
|
|
|
The named accents theme our own surfaces; Loupe, Papers, Nautilus and every other
|
|
libadwaita application still render in GNOME blue. GNOME exposes
|
|
`org.gnome.desktop.interface accent-color` as an enum (blue, teal, green,
|
|
yellow, orange, red, pink, purple, slate).
|
|
|
|
- Give each named accent a nearest-GNOME-enum member in `Theme.qml`, beside the
|
|
dark/light pair it already carries.
|
|
- Apply it alongside the existing GTK theme write, so one accent change moves
|
|
both worlds.
|
|
- Contract: every named accent maps to a member the enum actually publishes,
|
|
read from `gsettings range` rather than a hardcoded list.
|
|
|
|
**Done when** switching accent visibly recolors Papers and Nautilus.
|
|
|
|
## Phase 3 — Disks and storage (medium)
|
|
|
|
There is no way to see what is using the disk, and removable media is handled by
|
|
`udiskie` in the tray with no surface in Settings. `udisks2` is installed.
|
|
|
|
- Helper `panama-disks`: JSON snapshot of filesystems, sizes, usage, mount
|
|
points, removable devices, and SMART health where the device exposes it.
|
|
- Page: usage bars per filesystem, removable devices with mount / unmount /
|
|
eject, and "open in Files".
|
|
- **Deliberately out of scope: partitioning and formatting.** A settings pane is
|
|
the wrong place to hand someone a way to erase a disk in two clicks; that stays
|
|
with GNOME Disks, which we can launch.
|
|
|
|
**Done when** the page answers "what is filling my drive" and "is it safe to pull
|
|
this USB stick out".
|
|
|
|
## Phase 4 — Launcher-native settings search (small)
|
|
|
|
Settings has a search index. The launcher has script commands. They do not know
|
|
about each other, so finding a setting means opening Settings first.
|
|
|
|
- Generate one script command per settings page from the same schema that feeds
|
|
in-app search, with the page's keywords, so typing "night light" in the
|
|
launcher opens that page directly.
|
|
- Generator gets a `--check` staleness mode, matching `panama-settings-docs`.
|
|
- Contract: every page has a command, every command resolves to a real page.
|
|
|
|
**Open question for Gabriel:** the existing launcher commands are titled
|
|
"Panama: Open Settings", which the debranding pass did not touch. Keep the prefix
|
|
so desktop commands group together in the launcher, or drop it to match the rest?
|
|
|
|
**Done when** the launcher is the fastest way to reach any setting.
|
|
|
|
## Phase 5 — Keychain and secrets (medium, security-sensitive)
|
|
|
|
`panama-keyring` knows whether the keyring is locked and can unlock it. Nothing
|
|
can see what is *in* it, so managing a stored credential means installing
|
|
Seahorse.
|
|
|
|
- Extend the helper to enumerate collections and items through libsecret,
|
|
returning **attributes and labels only**.
|
|
- Page: unlock state, lock/unlock, items grouped by collection, delete, change
|
|
password.
|
|
- Rules that are non-negotiable and get their own contracts: a secret value never
|
|
appears in a snapshot, never reaches a command line (argv is world-readable via
|
|
`/proc`), never lands in a log or an error message, and is revealed only on an
|
|
explicit per-item request.
|
|
|
|
**Done when** a stored password can be found, inspected and removed without
|
|
leaving Settings, and the contracts prove no value leaks on the way.
|
|
|
|
## Phase 6 — Backups (large, staged)
|
|
|
|
The one genuinely missing safety net. `restic` is not installed.
|
|
|
|
- **6a** — destination and repository setup, plus a manual snapshot. Repository
|
|
password lives in the keyring (which is why this follows phase 5), never in the
|
|
repo and never on argv.
|
|
- **6b** — a systemd user timer, with the page showing schedule, last run, and
|
|
failures.
|
|
- **6c** — restore: browse a snapshot and copy files out.
|
|
|
|
Blast radius: writes to a destination the user chooses. Nothing in this phase
|
|
modifies or deletes existing data; restore copies out rather than over.
|
|
|
|
**Done when** losing the home directory is an inconvenience rather than a
|
|
catastrophe.
|
|
|
|
---
|
|
|
|
## Order and reasoning
|
|
|
|
Phases 1 and 2 finish work already in flight and are visible immediately. Phase 3
|
|
is self-contained and answers a question people actually ask. Phase 4 is small
|
|
but changes daily habit. Phase 5 must precede 6 because 6 needs somewhere safe to
|
|
keep a repository password. Phase 6 is the largest and is staged so each part
|
|
stands alone.
|