Files
Panama/.claude/skills/panama/SKILL.md
T

134 lines
8.3 KiB
Markdown

---
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 <file>` 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.
Successful stdout stays quiet. Successful stderr is surfaced as a warning.
- 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 first. Migrations already follow the rule.
## Initial bootstrap trust
Use the complete command in `README.md` for a new machine. It downloads `boot`
from the documented commit URL into a private temporary directory, enforces the
documented curl time and byte limits, verifies the committed blob with
`sha256sum -c`, and passes both pins to the verified script. Desktop and server
bootstrap use the same commit and digest. Never substitute a branch URL, pipe a
response into Bash, or invent a newer pin from an uncommitted file.
`boot` validates the full lowercase commit and SHA-256 before Git or install. A
fresh destination fetches only that revision and creates a tracked local `main`
after HEAD matches. An existing checkout must be clean and an ancestor of the
requested revision; it advances with fast-forward only. Dirty, divergent,
fetch-failed, or mismatched checkouts stop without reset or install. Once Panama
exists, use `panama update` for normal updates.
`boot --server` is the one exception where a new Fedora VPS may begin as root.
Before it offers SSH hardening, it copies a safe root key when possible or
verifies the target key. The target user's `.ssh` must be owned by that user at
`0700`, and `authorized_keys` must be owned by that user at `0600`. Without a
verified target key, SSH hardening is unavailable and the bootstrap continues.
Every non-comment key line must parse with `ssh-keygen`. Root-key destination
creation and writing run as the target UID, followed by the same owner, mode,
and key checks. Do not replace that with root writes or assume the user's
primary group matches the username.
Accepted hardening uses atomic same-directory `00-panama.conf` with exactly
`PermitRootLogin no`, `PasswordAuthentication no`, and
`KbdInteractiveAuthentication no`. A pre-existing symlink or non-regular
object makes hardening unavailable, as does a missing SSH unit. Panama runs
`sshd -t`, then checks effective root and target-user policy with `sshd -T -C`
before reloading the detected unit. Validation or reload failure restores a
prior regular file with its metadata before it retries validation and reload.
Failed recovery stops the handoff with instructions that distinguish a prior
file from no prior file. The fixture contracts also cover declined hardening
and interrupted preparation. `panama test --safe` never reloads a live daemon,
so it is not live-host proof.