--- name: panama description: Use when working on the Panama repository itself — editing anything under config/, setup/, bin/, tests/, or the Quickshell shell and Hyprland Lua it ships. Covers the live-desktop hot-reload rules, the contract-test discipline, the fixture seams, and where the real documentation lives. --- # panama You are editing a running desktop, not a codebase that gets deployed later. Every dotfile in this repository is symlinked into `~/.config`, so a save is live the moment it lands. That single fact drives every rule below. Read before large work, in this order: - `README.md` — layout, the `panama` command, how installing and updating work - `config/dot/hypr/README.md` — the compositor config is **Lua, not hyprlang**; read "The one thing to know first" and "Never use `hyprctl keyword`" before touching it - `config/dot/quickshell/modules/settings/README.md` — adding a setting, setting ownership, "Things that will bite you", and where state lives; the most load-bearing document here - `docs/settings.md` — generated reference for every settings key (never edit by hand) ## The live-desktop covenant Editing `config/dot/quickshell/**` hot-reloads the live shell on every save. 1. Every save must leave valid QML. An intermediate broken save is a broken desktop, not a broken build. Convert a component and its body in ONE edit, never two. 2. After each batch of saves, check the journal for errors AND "Unable to assign" warnings: `journalctl --user -u panama-quickshell.service --since '-2 minutes' --no-pager` 3. Every `.qml` file in `config/dot/quickshell/modules/*` must be registered in that directory's `qmldir` in the same save batch. An unregistered component fails the whole configuration and takes down the bar, dock, and settings together. `tests/quickshell/qmldir-registration-contract` is pure file inspection — run it before the change lands. 4. Never `qs kill` from a copied configuration: Quickshell derives the shell ID from config content, so a content-identical harness can share the live shell's ID and kill the desktop. Harnesses use a distinct entry file, `qs -p`, the PID from `qs list --all`, and `kill` that PID. 5. Never `hyprctl keyword` — Lua-configured Hyprland refuses it, prints to stdout, and exits 0. `hyprctl eval` also exits 0 on errors. The only proof a write landed is `hyprctl getoption` reading it back. Batch `hyprctl reload` to one per verified change-set, and say when you do it. 6. IPC: annotate every parameter and return type or Quickshell silently skips registration; never duplicate an `IpcHandler` target — one silently shadows the other. 7. In `config/dot/quickshell/config/PreferenceSchema.qml`, `readAs` describes the compositor's ANSWER shape, not the setting's; a wrong one makes every successful write look rejected. 8. No continuously repainting animations (pulse, shimmer, spinners) — they peg the GPU on high-refresh displays. 9. `hyprlock.conf`, `hypridle.conf`, `hyprpaper.conf`, `hyprtoolkit.conf` never moved to Lua. Do not "fix" them. Do not install a notification daemon — the shell is one. 10. Scripts carry no `.sh` extension (shebang + `chmod +x`), with one deliberate exception: `migrations/*.sh`, which `bin/panama-migrate` globs. No secrets under `user/` — it is world-readable and `tests/setup/user-content-contract` greps for key material. ## The contract discipline Every executable contract under `tests/` is classified in `tests/contracts.manifest`. The rules: - `panama contracts ` names the contracts that mention a file; run those after touching it. - During a desktop session, run `panama test --safe [pattern]`. `--safe` selects only contracts classified as `hermetic`. - A plain full run prompts in a terminal before any selected non-hermetic contract starts. In automation, grant every required capability with repeatable flags, for example `panama test --allow live-compositor --allow live-desktop keybinds`. - Each contract has a 180-second outer timeout by default. Override it with a positive `PANAMA_TEST_TIMEOUT_SECONDS` value. Failures print the contract's captured stdout and stderr. - Contracts run directly too: `tests/setup/interview-contract`. - After changing `PreferenceSchema.qml` or `services/SettingsRoutes.qml`, regenerate: `config/dot/quickshell/scripts/panama-settings-docs` (writes `docs/settings.md`) and `config/dot/quickshell/scripts/panama-settings-commands` (writes the launcher deep links). Both take `--check`; `tests/quickshell/settings-docs-contract` fails when stale. - `README.md` pins the contract count and the `panama` subcommand list (`tests/setup/readme-contract`); adding a contract or subcommand means updating it. ## Seams for testing Helpers are built hermetic: validated inputs, JSON out, secrets on stdin only (never argv). Contracts reach them through env seams — `PANAMA_NETWORK_HELPER`, `PANAMA_FINGERPRINT_FIXTURE`, `PANAMA_EXTRAS_DIR`, and the `PANAMA_*_STATIC_ONLY` family that cuts a contract to its file-inspection half. Prefer exercising a helper through its contract's stubbed PATH over running it against the real system. ## Safety idioms (contract-enforced) - Destructive actions are two-stage: `ConfirmAction` with a unique `actionId`, arbitrated through `ShellState.armedConfirm` — one armed confirm app-wide. Danger tone marks only the confirming press. - Failures render through `ErrorRow`; honest empty states through `NotMeasuredRow` with a `because:`; paragraph-length notes through `SettingsNote`. - Stored user actions (custom shortcuts, gestures, window rules) are DATA — an enum kind and a validated target resolved through whitelist tables in `config/dot/hypr/actions.lua`. Nothing in `~/.config/panama/settings.json` may ever be an executable command; the contracts (`tests/quickshell/settings-idiom-contract`, `tests/quickshell/keybind-rebind-contract`) pin all of this. ## Root work Never bare `sudo` — load the `panama-sudo` skill. Migrations already follow the rule.