Phase 4: the optional application categories, and the Firefox chrome. Everything Panama installed until now was what every machine gets, which meant a work laptop acquired emulators and a desktop that wanted Steam had to be told about it by hand. The interview now offers the categories in setup/packages/extras/ as a checklist -- gaming, creative, communication, virtualization -- and nothing is preselected, because a default here installs applications nobody chose on a machine whose owner answered a question they thought was about something else. A category is one file, and a category mixes both package managers because the applications do: Steam is in RPM Fusion, Slack publishes only a flatpak. So a bare line is a dnf package and a flatpak: line is a Flathub ID, and one file holds the whole answer rather than splitting each category across two. The menu is read from the directory rather than written down, so adding a category is adding a file. Every name in all four was resolved against the actual repositories before being written down, and the contract re-resolves them -- the point of admitting applications one at a time is that they stay installable, and a typo here fails on somebody else's machine, not this one. Firefox is declared, and its chrome is Edge-Frfox, vendored into config/firefox. sunhat carried that theme with no license and no attribution; it is MIT, and now it says so and says whose it is. It is the only piece of Panama's configuration that does not go to a path this repository chooses. Firefox owns the profile directory, names it with a random salt, and does not create one until the browser has been run -- so link-dotfiles finds or creates a profile and links both halves into it. Both, or neither works: chrome/ is the CSS and user.js sets the preference that makes Firefox read chrome/ at all, without which the theme is a directory of dead files. Two assumptions there were wrong, and the contract exists for both. Firefox has moved to the XDG directories -- the profile root is ~/.config/mozilla/firefox on this build, not ~/.mozilla/firefox, and writing to the wrong one themes nothing and says nothing about it. And -CreateProfile turns out to be non-interactive, so a fresh machine gets the theme on the first install rather than the second. The contract runs link-dotfiles for real against a throwaway home with no profile in it and looks at what came out; it was checked by pointing the search at the legacy path only and watching it fail. Also: the enrolment/enrollment spellings from the last commit are corrected. This repository is US-spelled everywhere else -- color 1131 times against colour never -- and consistency in prose is worth as much as it is in code. Claude-Session: https://claude.ai/code/session_01NvgBuSWB5sE43yWmg21ozj
458 lines
27 KiB
Markdown
458 lines
27 KiB
Markdown
# Panama: fresh-install correctness and the sunhat deprecation
|
|
|
|
Panama installs a desktop it does not fully provision. The Quickshell shell names
|
|
fonts nothing installs, a cursor theme nothing installs, and a wallpaper that does
|
|
not exist; four settings pages shell out to packages no list declares. None of this
|
|
shows up on this machine, because this machine accumulated those pieces under
|
|
sunhat and never lost them. It shows up on the next machine.
|
|
|
|
This spec closes that gap, moves every question the installer needs to the front of
|
|
the run, and ports the parts of sunhat that still matter — so sunhat can be deleted.
|
|
|
|
## Why now
|
|
|
|
Recent work built a large Quickshell desktop: a bar, dock, overview, lock screen,
|
|
notification server, and a Settings application with thirty-odd pages. Almost all
|
|
of it was verified against a running system. Almost none of it was verified against
|
|
a system where Panama had just been installed for the first time.
|
|
|
|
The existing `tests/quickshell/declared-dependencies-contract.sh` was written for
|
|
exactly this class of bug and reports PASS, because it checks only commands that
|
|
scripts invoke. Fonts, cursor themes, wallpapers, and packages consumed by GUI
|
|
handoffs are invisible to it. A dependency checker with a blind spot is worse than
|
|
none, because it reports PASS — that argument is already in that file's own header
|
|
comment, and it applies to the checker itself.
|
|
|
|
## What is broken
|
|
|
|
Verified against the repository at `3b01f1e`.
|
|
|
|
| Gap | Evidence |
|
|
|---|---|
|
|
| No fonts installed | `setup/scripts/change-settings:32` sets `VictorMono Nerd Font 10`. `kitty`, `ghostty`, `hyprlock.conf.template`, `Theme.qml` and `Fonts.qml` all name Nerd Font families. No stage installs a font. `Fonts.qml` documents that a mono family without Nerd glyphs replaces every icon in the shell with tofu. |
|
|
| No cursor theme installed | `oreo_blue_cursors` is named in `change-settings:33`, both GTK `settings.ini.template` files, `config/dot/uwsm/env:23`, `config/dot/hypr/env.lua:52`, and `PreferenceSchema.qml:985`. It exists in `~/.local/share/icons` on this machine only. |
|
|
| No wallpaper, though the code says one ships | `Wallpaper.qml:32` declares `shippedPath` as `~/Pictures/Wallpapers/faroe_islands.jpg`. `panama-lock:139` falls back to the same path, `hyprpaper.conf` names it twice, and `lock-screen-settings-harness.qml` uses it as a fixture. Nothing ships it. `PreferenceSchema.qml:826` defaults `wallpaperPath` to `""`. |
|
|
| `gnome-control-center` undeclared | `SystemSettings.qml:599` allow-lists 23 GNOME panels; 15+ rows across `OnlineAccountsPage`, `RegionPage`, `AccessibilityPage`, `ConnectivityPage`, `ShortcutsPage`, `SoundPage`, `PrivacyPage` and `HealthPage` call `openGnomePanel`. No list declares the package. |
|
|
| `snapper` undeclared | `panama-snapshots` drives the entire Snapshots page through `snapper`. |
|
|
| Four more undeclared, found by the new contract | Crawling QML for launched commands — which the dependency contract never reads — also caught `gnome-calendar` (`CalendarAgenda.qml:180`), `podman` (`Containers.qml:149`, the Containers page backend), `pipewire-utils` for `pw-dump`/`pw-play` (`PrivacyState.qml:169`, `SoundTest.qml:35`), and `flatpak`, which `install-packages` itself uses. |
|
|
| `espanso`, `ghostty` undeclared | Both have configs symlinked by `link-dotfiles`; neither is in a package list. `ghostty` is in Terra and is now declared. **`espanso` is in no enabled repository** — sunhat built it from source — so under the dnf/flatpak rule it stays undeclared. Its config remains linked, which costs nothing, and installing it is a separate decision. |
|
|
| `.bashrc` breaks on a fresh box | `config/bash/.bashrc` ends with an unguarded `. "$HOME/.cargo/env"`, which does not exist until `rustup-init` has run, so every shell start emits an error. The file also carries a committed `# >>> Codex installer >>>` block. |
|
|
| README describes a desktop that is not installed | The Desktops section advertises GNOME with Forge, Dash-to-Dock, Openbar and Vitals. Nothing in `setup/` installs or configures any of it. |
|
|
|
|
## Decisions
|
|
|
|
These were settled during design and are recorded so the plan does not relitigate
|
|
them.
|
|
|
|
**The GNOME session is cut; `gnome-control-center` stays.** These are different
|
|
things and only the first is free. The session — Forge, Dash-to-Dock, Openbar,
|
|
Vitals, the README's parity claims — is dead weight and goes. The control center is
|
|
load-bearing: it is where Panama's own Settings sends you for Online Accounts,
|
|
Region, Accessibility, Color, Wellbeing and Wacom, and commit `0c364f3` shows the
|
|
handoff list was deliberately narrowed to what Panama does not own. It becomes a
|
|
declared dependency rather than an accident of this machine's history.
|
|
|
|
**The installer asks everything up front, then runs untouched.** sunhat's failure
|
|
mode was a prompt or a failure twenty minutes in, with a person needed at the
|
|
keyboard to get past it. Panama's answer is not "no prompts" — some of what the
|
|
installer needs genuinely changes between machines and between years, and a stale
|
|
hardcoded answer is worse than a question. The answer is that every question is
|
|
asked before any package work begins, and nothing asks again afterwards.
|
|
|
|
**Answers are not persisted.** Each run asks fresh. The only default shown is the
|
|
current hostname, which today's installer already shows. This is a deliberate
|
|
simplicity choice: no answers file to keep in sync, nothing personal on disk, and
|
|
re-answering six questions costs less than maintaining state that can go stale.
|
|
|
|
**Hardware is detected, then confirmed.** Gib's machines span AMD, Intel and NVIDIA
|
|
in both laptops and desktops. The installer probes — `lspci` for GPUs,
|
|
`mokutil --sb-state` for secure boot, DMI for chassis — and asks a question that
|
|
names what it found: *"Found NVIDIA RTX 4070 — install akmod-nvidia and enroll a
|
|
secure boot key? [Y/n]"*. Detection alone would remove the ability to decline a
|
|
proprietary driver on a machine that has the card; asking alone would make a person
|
|
recite their own hardware.
|
|
|
|
**Nothing personal is committed.** Panama should be cloneable by someone else and
|
|
yield a working desktop. Identity, hostnames and machine layout come from prompts
|
|
and from gitignored local state — `~/.config/panama/settings.json` is already
|
|
exactly this — never from files in the repository.
|
|
|
|
**Applications are admitted one at a time, and dnf or flatpak only.** A short
|
|
always-installed core, plus categories chosen from a `gum` checklist during the
|
|
interview, so a work laptop does not acquire emulators and a desktop does not skip
|
|
Steam. But the menu starts nearly empty and grows by explicit decision, one
|
|
application per decision — it is not seeded by porting sunhat's list.
|
|
|
|
The categories shipped are `gaming`, `creative`, `communication` and
|
|
`virtualization`, one file each under `setup/packages/extras/`. A category mixes
|
|
both package managers because the applications do — Steam is in RPM Fusion, Slack
|
|
publishes only a flatpak — so a bare line is a dnf package and a `flatpak:` line
|
|
is a Flathub ID, and one file holds the whole answer for a category rather than
|
|
splitting it across two. The interview reads the menu from the directory, so
|
|
adding a category is adding a file, and nothing is preselected: a default here
|
|
would install applications nobody chose.
|
|
|
|
The rule is that every application Panama installs must come from dnf or from
|
|
Flathub, with flatpak preferred where both exist. Anything requiring a pinned RPM
|
|
URL, a `curl | bash`, or a source build is admitted only case by case, with a stated
|
|
reason why no packaged form exists.
|
|
|
|
sunhat is the argument for this rule, not a counterexample to it. Its
|
|
`sources/dotenv.sh` hardcodes `upscayl-2.11.5`, `lact-0.5.4-0.x86_64.fedora-40.rpm`
|
|
and `jdk-22` — URLs that were stale within a release cycle and that turn a re-run
|
|
into a 404. Every application Panama declares is one it has to keep installable,
|
|
and the cost of that promise is only bearable if a package manager is keeping it.
|
|
|
|
Panama already carries three exceptions: the `oh-my-posh` and `bun` install scripts
|
|
in `install-packages`, and `helium-browser-bin` from the `lionheartp/Hyprland` COPR.
|
|
They stay — each is idempotent and guarded — but they are the ceiling, not a
|
|
precedent. New exceptions need the same standard.
|
|
|
|
**Bash scripts carry no `.sh` extension.** A shebang and the executable bit select
|
|
the interpreter; the extension is redundant. This applies to the 159 existing files
|
|
as well as new ones.
|
|
|
|
## Design
|
|
|
|
### The installer
|
|
|
|
`./install` becomes four movements:
|
|
|
|
```
|
|
ascii → interview → stages (uninterrupted) → panama-doctor summary
|
|
```
|
|
|
|
The interview is a new script, `setup/scripts/interview`, that runs before any
|
|
other stage and asks, in order:
|
|
|
|
- Hostname — defaulting to the current one, as today
|
|
- Git identity: name, email, editor
|
|
- Run `gh auth login`? — skipped without asking when `gh auth status` already passes
|
|
- Generate an SSH key? — skipped without asking when one already exists
|
|
- Hardware confirmations, each naming what was detected
|
|
- Remove Fedora's preinstalled bloat?
|
|
- Update firmware with `fwupdmgr`?
|
|
- Which application extras to install — a `gum` checklist
|
|
|
|
Answers reach the stages as `PANAMA_*` environment variables, but not by the
|
|
obvious route. Stages run as child processes of `install`, and a child cannot export
|
|
into its parent or its siblings — so the interview cannot simply set variables and
|
|
expect the next stage to see them. Instead it writes `KEY=value` lines to a
|
|
`mktemp` file whose path `install` chose; `install` sources that file, exports the
|
|
names, and deletes it on the existing `trap ... EXIT INT TERM` that already restores
|
|
the idle settings. The answers exist for the length of one run and never touch a
|
|
durable path, which is what keeps "no persisted answers" honest.
|
|
|
|
The interview is therefore listed in `STAGES` like any other stage, but `install`
|
|
treats it specially: it is the only stage whose output the installer reads back.
|
|
|
|
A stage that needs an answer reads its variable and treats absent as "no". This
|
|
matters for re-running an individual stage by hand, which is a debugging path that
|
|
must keep working, and it means the interview is never a prerequisite for repairing
|
|
one piece of a machine.
|
|
|
|
The run ends with `panama-doctor`, printing its summary. Today the only signal that
|
|
an install worked is a failed-stage count; a failure that produced no non-zero exit
|
|
— a font that did not land, a service that did not start — scrolls past unnoticed.
|
|
`docs/UPSTREAM-INSPIRATION.md` already lists a first-run health check as a
|
|
candidate; the health check now exists, so this is wiring rather than building.
|
|
|
|
### Stages
|
|
|
|
The `STAGES` array in `install` is explicit rather than glob-ordered, and stays that
|
|
way. The new order:
|
|
|
|
| Stage | Status | Responsibility |
|
|
|---|---|---|
|
|
| `interview` | new | Every prompt, before any work |
|
|
| `install-packages` | edited | Repos, package lists, extras |
|
|
| `link-dotfiles` | edited | Adds the wallpaper and the cursor theme; drops `forge` |
|
|
| `change-settings` | edited | Unchanged in substance |
|
|
| `link-vicinae-scripts` | unchanged | |
|
|
| `setup-identity` | new | git config, `gh auth login`, SSH key |
|
|
| `install-hardware` | new | NVIDIA, akmods, secure boot, debloat, firmware — all conditional |
|
|
|
|
Two things in this table changed while building it, and the reasons are worth
|
|
keeping.
|
|
|
|
There is no `install-cursors`. The cursor theme is vendored into the repository
|
|
and exposed by the same narrow per-directory symlink `link-dotfiles` already uses
|
|
for icons and Vicinae themes, so it needs no stage of its own — and because
|
|
`link-dotfiles` precedes `change-settings`, the ordering constraint that stage
|
|
was invented to satisfy holds anyway.
|
|
|
|
`install-hardware` runs *last*, not fourth. The constraint was always "late", and
|
|
fourth of eight is not late: MOK enrollment arms a prompt consumed at the next
|
|
boot and a firmware update may ask for a reboot, so a machine that reboots out of
|
|
this stage should already be completely configured — dotfiles linked, settings
|
|
applied, identity set. Placing it after `setup-identity` costs nothing, since
|
|
nothing later depends on it.
|
|
|
|
Ordering constraints that are not obvious and must not be broken:
|
|
|
|
- `link-dotfiles` precedes `change-settings`, because `change-settings` sets a
|
|
gsettings value naming a cursor theme. Setting it before the theme exists is not
|
|
an error, but it does mean the first session renders with a fallback. Fonts are
|
|
installed by `install-packages`, which already runs first.
|
|
- `setup-identity` follows `install-packages`, because `gh` is installed there.
|
|
- `install-hardware` is last, for the reason above. It also has to follow its own
|
|
driver install: akmods generates the certificate that MOK enrollment enrolls, so
|
|
there is nothing to enroll until `akmod-nvidia` is on the machine.
|
|
|
|
Every stage stays independently re-runnable and independently failable, which is
|
|
the existing contract and the reason Panama exists.
|
|
|
|
### Fonts
|
|
|
|
There is no font stage. Terra — which `install-packages` already enables — packages
|
|
every Nerd Font as an RPM (`victormono-nerd-fonts` and siblings, 3.5.0-1.fc44), and
|
|
Fedora now packages the Microsoft core fonts as `mscore-fonts`. So the entire gap
|
|
closes by adding five lines to `desktop-packages`:
|
|
|
|
- `victormono-nerd-fonts` — required. It is what `change-settings` sets as
|
|
`monospace-font-name` and what the shell draws every icon with.
|
|
- `jetbrainsmono-nerd-fonts`, `firamono-nerd-fonts`, `cascadiamono-nerd-fonts` —
|
|
Panama ships a font picker; a picker with one option is not a picker.
|
|
- `mscore-fonts` — web development means checking pages that assume Arial and
|
|
Georgia resolve.
|
|
|
|
This supersedes sunhat's approach, which downloaded release zips from GitHub with
|
|
`wget` and unpacked them into `~/.local/share/fonts`. That is precisely the install
|
|
method this repository is trying to stop using, and it turned out to be unnecessary.
|
|
|
|
### Cursors
|
|
|
|
`oreo_blue_cursors` is packaged nowhere — not Fedora, not RPM Fusion, not Terra. It
|
|
comes from `varlesh/oreo-cursors` on GitHub, so the dnf/flatpak rule cannot apply and
|
|
one of its exceptions has to.
|
|
|
|
The theme is **vendored into the repository** at
|
|
`config/local/share/icons/oreo_blue_cursors` (3.3MB, 63 files, no symlinks) and
|
|
exposed by `link-dotfiles` with the same narrow per-directory symlink it already uses
|
|
for Panama's application icons and Vicinae themes. Downloading at install time was
|
|
rejected: it would add a fourth network exception and a URL that can rot, which is
|
|
the failure this spec exists to prevent. Vendoring costs 3.3MB in git once, and then
|
|
the cursor is simply always there.
|
|
|
|
Only the blue variant ships, and nothing else needs changing to make that true:
|
|
`cursorTheme` is a free string in the schema, and `panama-desktop-style`'s `catalog()`
|
|
enumerates the pointer themes actually present in the XDG icon directories. The picker
|
|
therefore offers exactly what is installed, so shipping one theme instead of three
|
|
removes options from the list rather than leaving it advertising themes that are not
|
|
there.
|
|
|
|
### Wallpaper
|
|
|
|
`config/wallpapers/faroe_islands.jpg` (4000x2444, 644K) is committed. `link-dotfiles`
|
|
copies it to `~/Pictures/Wallpapers/` when absent, and seeds `wallpaperPath` in
|
|
`settings.json` **only when that key is still empty**. An existing choice is never
|
|
overwritten — the same rule every other seeding step in `link-dotfiles` already
|
|
follows for kitty, tmux, GTK and hyprlock.
|
|
|
|
### The assets contract
|
|
|
|
A new `tests/quickshell/declared-assets-contract` covers what the dependency
|
|
contract structurally cannot. It fails when:
|
|
|
|
- A font family named in `config/` or in a `gsettings set` call is not installed by
|
|
`install-fonts`
|
|
- A cursor theme named in `config/` is not installed by `install-cursors`
|
|
- The default `wallpaperPath` names a file the repository does not ship
|
|
- A package invoked by a settings-page helper or a GUI handoff is undeclared
|
|
- A directory under `config/dot/` is neither in `link-dotfiles`'s `dirs` array nor
|
|
given explicit handling
|
|
|
|
All four of today's gaps fail this test. That is the acceptance criterion for the
|
|
test itself: it must be written against the broken tree and observed to fail before
|
|
the fixes land.
|
|
|
|
It is named without a `.sh` extension from the start, while its siblings still carry
|
|
one until phase 6. That inconsistency is deliberate and temporary — new files follow
|
|
the convention immediately rather than being written wrong and renamed later.
|
|
|
|
### GNOME excision
|
|
|
|
`config/dot/forge` is deleted and `forge` removed from `link-dotfiles`'s `dirs`.
|
|
The README's Desktops section is rewritten to describe one desktop. The comment in
|
|
`link-dotfiles` explaining why GNOME and Hyprland coexist goes with it.
|
|
|
|
`gnome-control-center` is added to `desktop-packages` with a comment naming what
|
|
depends on it, so a future reader does not mistake it for GNOME-session residue and
|
|
remove it. `gnome-settings-hyprland.desktop` stays.
|
|
|
|
### The `panama` command
|
|
|
|
Three subcommands are added to the existing dispatcher, which was written to grow
|
|
this way:
|
|
|
|
- `panama doctor` — front `panama-doctor` from a terminal, not only from Settings
|
|
- `panama test` — run every contract under `tests/`, with a pass/fail summary. The
|
|
suite is 119 files with no entry point and no mention in the README; it is the
|
|
main safety net and it is currently invisible.
|
|
- `panama upgrade` — re-run `./install` from anywhere
|
|
|
|
### Dropping the `.sh` extension
|
|
|
|
159 files: 110 under `tests/quickshell`, 47 under
|
|
`config/local/share/vicinae/scripts`, 2 under `tests/hypr`. All are already
|
|
executable and all already carry a bash shebang, so the rename is `git mv` plus
|
|
three comment references and two lines in `panama-settings-commands`, which
|
|
generates the Vicinae command files and globs for `settings-*.sh`.
|
|
|
|
The one real risk is Vicinae's script discovery. Its documentation states a script
|
|
command needs a plain text file, the three `@vicinae.*` directives, a shebang, and
|
|
the executable bit — no extension requirement. That is close enough to a guarantee
|
|
to act on, but not close enough to skip verifying: after the rename, reload with
|
|
`vicinae cmd launch core:reload-scripts` and confirm all 47 commands still resolve
|
|
before the change is considered done. If discovery does key off the extension, the
|
|
Vicinae directory is exempted and the reason recorded here.
|
|
|
|
### Machine-specific configuration
|
|
|
|
Monitor layout, keybinds and input differences stay in gitignored local state —
|
|
`~/.config/panama/settings.json`, written by the Settings application. Panama ships
|
|
defaults; a machine deviates locally. No per-hostname directories enter the
|
|
repository, because that is what "cloneable by someone else" costs.
|
|
|
|
This is a decision to *not* build something. sunhat branched its Hyprland config on
|
|
hostname and it was one of the things that made sunhat unmaintainable.
|
|
|
|
## Ported from sunhat
|
|
|
|
Everything below blocks sunhat's deletion.
|
|
|
|
- **NVIDIA and secure boot** — `akmod-nvidia`, `xorg-x11-drv-nvidia-cuda` and MOK
|
|
enrollment via `mokutil --import`. sunhat's version opened an editor to hand-edit
|
|
grub; the replacement does not, because a step that requires a human mid-run is
|
|
the failure this repository exists to avoid. It turned out not to need one:
|
|
sunhat's editor step existed to delete duplicated kernel arguments, and `grubby
|
|
--update-kernel=ALL --args=` replaces an argument that already exists rather than
|
|
appending a second copy, so the duplicates cannot accumulate.
|
|
|
|
Enrollment is likewise non-interactive, and did not need a compromise either.
|
|
`mokutil --generate-hash` and `--hash-file` are exactly the pair for this: the
|
|
interview asks for the password, hashes it immediately, and records only the
|
|
hash — so the plaintext never reaches the answers file, the environment, or a
|
|
command line, and the stage still runs without prompting.
|
|
|
|
`rebuild_nvidia_kmod` was not ported. akmods already rebuilds on kernel updates
|
|
through its own systemd unit, and a helper that duplicates that is one more
|
|
thing to keep true.
|
|
- **Fedora debloat** — behind an interview question. sunhat's list was
|
|
`gnome-contacts`, `gnome-tour`, `gnome-maps`, `totem` and three LibreOffice
|
|
components; on Fedora 44 `totem` has been replaced by `showtime` and LibreOffice
|
|
is not preinstalled at all, so the list is `gnome-contacts`, `gnome-tour`,
|
|
`gnome-maps` and `showtime`. A package that is not installed is never passed to
|
|
dnf, which is what lets the list outlive a Fedora release rather than starting to
|
|
fail on one.
|
|
- **Firmware** — `fwupdmgr refresh` and `update`, behind an interview question.
|
|
Panama's Updates page covers this after installation; the installer covers the
|
|
first run.
|
|
- **Applications** — the extras *mechanism*, and only the applications explicitly
|
|
agreed. sunhat's ~70 installers are a list of candidates to review, not a manifest
|
|
to port; most of them install by methods that no longer work. Reviewing them is
|
|
its own task, done one application at a time against the dnf/flatpak rule above,
|
|
and it does not block anything else in this spec.
|
|
- **Firefox** — the package itself, which Panama did not previously install, plus
|
|
sunhat's `themes/firefox` userChrome. Helium is the daily driver; Firefox stays
|
|
because web development means checking a second engine. If Helium supports
|
|
userChrome, it gets the equivalent treatment.
|
|
|
|
The theme is [Edge-Frfox](https://github.com/bmFtZQ/edge-frfox), MIT, vendored
|
|
into `config/firefox` with its provenance recorded — sunhat carried it with
|
|
neither. It is the only piece of Panama's configuration that does not go to a
|
|
path this repository chooses: Firefox owns the profile directory, names it with
|
|
a random salt, and does not create one until the browser has been run. So
|
|
`link-dotfiles` finds or creates a profile and links both halves into it —
|
|
`chrome/` for the CSS and `user.js` for the preference that makes Firefox read
|
|
`chrome/` at all, which without the other is a directory of dead files.
|
|
|
|
Two things here were assumptions that turned out wrong, and the contract exists
|
|
for both. Firefox has moved to the XDG directories, so the profile root is
|
|
`~/.config/mozilla/firefox` on a current build and `~/.mozilla/firefox` on an
|
|
older one; writing to the wrong one themes nothing and says nothing. And
|
|
`-CreateProfile` turns out to be non-interactive, so a fresh machine gets the
|
|
theme on the first install rather than the second.
|
|
|
|
Deliberately not ported: sunhat's `configs/docker/compose_files`. Those are server
|
|
workloads — caddy, gitea, homeassistant, nextcloud_aio, pihole, vaultwarden,
|
|
wireguard, searxng — and belong to whatever runs them, not to a workstation
|
|
installer. They remain recoverable from sunhat's git history.
|
|
|
|
## Repository hygiene
|
|
|
|
- **Done.** The seven branches that appeared unmerged were audited with
|
|
`git cherry -v main <branch>`. Six of them — `feat/panama-displays`,
|
|
`feat/panama-settings-pages`, `feat/settings-home-completion`,
|
|
`feat/settings-sound`, `fix/settings-backup-complete` and
|
|
`fix/settings-sidebar-scroll` — had every commit marked patch-equivalent to one
|
|
already in `main`, and every file they added was verified present in `main`. They
|
|
looked unmerged only because the work re-landed through a different route. Deleted,
|
|
along with their worktrees.
|
|
- `feat/roadmap-completion` is the sole branch with unlanded work: 5 commits, 13
|
|
files absent from `main`, 62 commits behind. It carries a theme-profile system, a
|
|
dock context menu, overview-thumbnail capture reliability, and wallpaper/lock
|
|
hardening, with its own spec and plan. It does not conflict with this work — it
|
|
*depends* on it, since its lock generator falls back to the shipped wallpaper this
|
|
spec makes exist. Rebasing it is its own task.
|
|
- Six worktrees remain on branches already merged to `main`
|
|
(`home-accessories-customization`, `panama-commands`, `panama-displays-review`,
|
|
`panama-settings-home-phone`, `settings-notification-rules`, `settings-ownership`).
|
|
They are clutter, not risk; pruning them stays in phase 6.
|
|
- Guard the `.cargo/env` source in `config/bash/.bashrc` and remove the Codex block.
|
|
- Rewrite the README: one desktop, the real install stages, and the test suite.
|
|
- Audit `docs/settings.md` (21K) for claims that no longer hold.
|
|
|
|
## Phases
|
|
|
|
Each phase is independently shippable and independently useful.
|
|
|
|
1. **Install correctness** — fonts and the four other undeclared packages, the
|
|
vendored cursor theme, the shipped wallpaper, the `.bashrc` fixes, and the assets
|
|
contract. Closes every gap that would visibly break a fresh machine.
|
|
2. **The interview** — up-front prompts, hardware detection, `panama-doctor` at the
|
|
end of the run.
|
|
3. **Hardware flows** — NVIDIA, secure boot, debloat, firmware.
|
|
4. **Applications and theming** — the extras menu mechanism, Firefox and its theme.
|
|
The menu ships with the categories agreed at the time and nothing more; filling
|
|
it is ongoing work, one application per decision, not part of this phase.
|
|
5. **GNOME excision and documentation** — Forge removal, README rewrite,
|
|
`docs/settings.md` audit.
|
|
6. **Hygiene** — the `.sh` rename, worktree pruning, the branch audit, and the three
|
|
new `panama` subcommands.
|
|
|
|
## Verification
|
|
|
|
Panama is not going to be tested by reinstalling Fedora. Confidence comes from
|
|
three places instead:
|
|
|
|
- **The assets contract**, which encodes each gap found here as a test that fails on
|
|
the broken tree.
|
|
- **The hardware contract**, for the one stage that cannot be verified by running
|
|
it. `install-hardware` installs a proprietary driver and queues a Secure Boot
|
|
enrollment, and the machine Panama is developed on is an AMD desktop; so every
|
|
privileged command is stood in on `PATH` and the contract asserts which answer
|
|
led to which call. That covers the decisions, which is the part that can be
|
|
wrong. It does not cover whether `akmod-nvidia` builds, and does not claim to —
|
|
the first real NVIDIA machine is still the first real test.
|
|
- **`panama doctor` at the end of every install**, which reports what is actually
|
|
running rather than what was attempted.
|
|
- **`panama test`**, which makes the existing 119 contracts runnable in one command
|
|
for the first time.
|
|
|
|
One gap this list did not cover was found while doing phase 4 and is worth
|
|
recording, because it is the exact failure mode the spec opens with. Every list
|
|
in `setup/packages/` is annotated, and `install-packages` passed the whole file
|
|
to dnf, comments included; dnf does not ignore an argument it cannot match, so
|
|
`set -e` ended the stage on the first annotated list. It could not be seen from
|
|
here — on a machine that already has everything, only the comments fail — and
|
|
every contract that reads those lists strips comments before comparing, so the
|
|
tests were reading a file the installer was not. A checker with a blind spot is
|
|
worse than none, and this one had the same blind spot the dependency contract's
|
|
own header warns about.
|
|
|
|
The open risk this leaves is anything that breaks only on a genuinely clean system
|
|
and that none of the three notices — a repository that fails to enable, a package
|
|
renamed between Fedora releases. That risk is accepted; a VM run can settle it later
|
|
if the fixes here prove insufficient.
|