8156fc47cae823168771f88c93fbc90c6758e459
4
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
1f62256024 |
Make a fresh install actually produce a working desktop
Two things stood between this repository and a machine that could install it. The installer aborted on its own first question. The hostname prompt defaults to N, and the N branch ran `exit` -- so pressing Enter, the obvious answer when you do not want to rename your machine, skipped the entire installation and said nothing about it. Declining now just declines. The installer is also safe to re-run, which is the upgrade path too: it reports which stages failed instead of scrolling the failure past twenty minutes ago, and restores the idle settings on every exit path rather than only on success. The package lists had drifted badly from what the configs and helpers actually use. jq alone has thirty-one call sites across the helpers and the contracts; kitty has a full shipped config and a dock pin; tmux and btop have shipped themes the colour scheme switches; ddcutil, qrencode and orca back features added today. None were declared. Neither were fontconfig, pciutils, libselinux-utils, libnotify, wireplumber, fwupd or python3-dnf, all of which shipped scripts invoke by name. A fresh machine following this repository's own instructions would have got a desktop whose features quietly were not there -- the helpers report "not installed" rather than crashing, which is good behaviour and completely silent. So the lists are corrected and a contract now checks that every external command Panama's scripts invoke is installed by Panama's packages. Writing it was instructive about its own blind spots. The first version reported `then`, `esac` and `done` as missing packages, burying the real findings. The second passed while jq was undeclared, because the pattern required three characters and jq is two -- a dependency checker with a blind spot for short names is worse than none, since it reports PASS. The third missed ddcutil, which is only ever invoked as `timeout 10 ddcutil` and so never appears statement-initial. It now also reads `command -v X`, which is how these helpers probe for a tool and therefore the clearest statement of a dependency there is. Verified it catches jq, ddcutil and qrencode individually. Also replaced a fixed 0.3s sleep in the write contract with a bounded wait. It was failing about one run in three with "a rejected value did not surface an error" when the error had simply not arrived yet, which reads as a missing guard rather than a slow one. Claude-Session: https://claude.ai/code/session_01BRvzt4H8XXLPVH5MyYdk9L |
||
|
|
5562323eb8 |
Stop the live shell clobbering the write contract
This contract failed intermittently with "a typed batch did not reach the compositor", reporting Panama's shipped defaults, and passed on retry. The earlier guard against a lingering harness was not the cause -- no instance was alive. Adding the writer's own error to the failure message settled it: the writer reports NO error while the compositor holds defaults. A rejected write leaves an error behind; a write that succeeded and was then overwritten does not. Both this contract and the LIVE shell write to the same compositor, and the running Panama re-applies its own preferences on any store change -- landing exactly the values that were being mistaken for "the write never happened". So the apply is re-issued periodically while waiting, which makes the test survive being overwritten without weakening what it asserts, and the failure message now distinguishes the two cases instead of describing both as a write that never arrived. The wait is also 10 seconds rather than 4. The write path verifies every option by reading it back and retries a refused batch, so a loaded machine legitimately takes longer -- and this runs in a suite alongside other tests driving the same compositor. Claude-Session: https://claude.ai/code/session_01BRvzt4H8XXLPVH5MyYdk9L |
||
|
|
3ff414fb1b |
Stop two contracts from driving each other's shell
settings-hyprland-write-contract failed in full suite runs and passed on its own, reporting "a typed batch did not reach the compositor" with every value at its default. Both it and settings-commit-reset-contract drive the same harness file, and Quickshell identifies an instance by its config path -- not by the environment it was launched with. So when one run's instance has not fully exited, the other's wait for `ipc show` is satisfied by that instance's target, and the whole contract then talks to a shell it did not start. The two directions fail differently, and the second is the alarming one: The write contract lands on the isolated instance, whose compositor write seam is deliberately stubbed. Its writes go nowhere, which is exactly the symptom above. The commit/reset contract lands on the non-isolated instance and drives the DAILY DESKTOP's real compositor while believing it is isolated. Both now refuse to start while another instance of that harness is alive, and say which hazard they are avoiding rather than failing on an assertion much later. One trap worth naming, since it bit me writing this: `rg -c` prints nothing at all when there are no matches, so an unguarded command substitution yields "" and not "0" -- the first version of the guard fired on a perfectly clean machine. Claude-Session: https://claude.ai/code/session_01BRvzt4H8XXLPVH5MyYdk9L |
||
|
|
00a81edadd |
Make Panama settings one shared source of truth
Panama had grown into three configuration surfaces that only agreed because they had been typed to agree: looks.lua hardcoded values, DesktopPreferences independently defaulted the same values, and SystemSettings replayed them at startup. Nothing kept them in sync, and the Lua side read no shared state at all. This lands the first three stages of docs/superpowers/plans/2026-08-17-panama-cohesion.md. Fix silently failing Hyprland writes. On a Lua-configured Hyprland, hyprctl keyword refuses the write, prints the refusal to stdout, and still exits 0, so the HDR, VRR, and direct-scanout toggles persisted their value and reported success while the compositor never changed. Writes now go through hyprctl eval, which has the same hazard on syntax and runtime errors, so success is defined as reading the value back and finding it equal. The existing contract passed throughout the outage because it re-applied the values already in place; the new one flips each value to something it does not hold. Derive preferences from a schema. Every setting used to be restated four times -- a property alias, a JSON adapter property, a change handler, and a line in reset -- where omitting any one failed silently. PreferenceSchema.qml is now the single source, and persistence, validation, reset, and the Hyprland mapping all derive from it. Unknown keys on disk survive a write so a rollback does not discard a newer build's settings, and a corrupt file falls back to shipped defaults. The store moved to ~/.config/panama/settings.json, migrating from the old state directory without deleting it. Share that file with Hyprland. prefs.lua reads it at config time with every shipped literal kept as the fallback, so the config still stands alone. The Lua is the default, the JSON is the truth, and Settings is the editor. The compositor-adjustable surface goes from 3 keys to 23. Also fixes two test-hygiene bugs found by running the suite end to end for the first time: settings-pages-contract could see the window settings-window-contract leaves behind, and the new write contract was persisting its deliberately-wrong values into the user's real store. Claude-Session: https://claude.ai/code/session_01BRvzt4H8XXLPVH5MyYdk9L |