Drop the extension, and give the test suite a front door

Phase 6, the last of the fresh-install spec.

159 scripts lose their .sh: 110 contracts, 47 Vicinae commands, 2 compositor
contracts. A shebang and the executable bit already select the interpreter. The
extension only ever added something that had to stay in sync, and the rename
proved the point twice over in the space of an hour.

The spec's stated risk was Vicinae's script discovery. One script was renamed and
reloaded on its own before the other 46 followed; it came back as
scripts:panama.capture and all 47 resolve. What the probe turned up instead is
that the extension was never only a filename: Vicinae's command IDs embed it, so
every ID changed. Nothing in this repository refers to them, so nothing breaks.
The only trace is Vicinae's metadata.json, whose visited map had two Panama
entries that are now orphaned -- two commands lost their usage ranking and will
earn it back. Worth knowing before anyone renames these again on a machine that
has a keybind pointing at one.

Rewriting the references by exact filename missed two things it structurally
could not see: a name built from a variable, settings-$page.sh, and a glob,
-name '*.sh'. Both were in the contract that counts the generated commands, which
promptly reported 47 expected and 0 found. The mechanical part of a rename is the
part that looks finished.

The three subcommands. panama doctor fronts a health check that already existed
and already ran at the end of every install but could not be reached from a
terminal. panama upgrade re-runs the installer from anywhere. panama test runs
the suite, which had no entry point at all -- 121 files that were the main safety
net in this repository and were invisible in it.

Writing that runner found three tests nothing was running.
calendar_agenda_bridge_test, home_assistant_bridge_test and kdeconnect_bridge_test
are unittest suites without the executable bit, so no contract invoked them and
the first draft of the runner skipped them silently. All three pass, and have
passed unobserved for weeks. The runner collects *_test.py as well now, because a
runner with a blind spot is worse than no runner for the same reason a dependency
checker with one is: it reports PASS.

Six worktrees pruned. Each was re-checked rather than trusted to the spec's list,
and two needed it: panama-commands is not on feat/panama-commands but on
feat/gnome-tweaks-parity, and fix/panama-displays-review reads [ahead 3] -- ahead
of its remote, not of main, with every commit patch-equivalent to landed work.
roadmap-completion stays; it has five commits that are genuinely unlanded. The
branches are left alone: pruning a worktree costs nothing, deleting a branch is a
decision.

121 contracts pass.

Claude-Session: https://claude.ai/code/session_01NvgBuSWB5sE43yWmg21ozj
This commit is contained in:
Gabriel Brown
2026-08-20 21:55:55 -04:00
parent 47f29f9fa9
commit e1faaf7a76
185 changed files with 533 additions and 377 deletions
+19 -4
View File
@@ -78,7 +78,7 @@ Log in as **"Hyprland (uwsm-managed)"**, not plain "Hyprland".
## Layout ## Layout
``` ```
bin/ Small user-facing commands on PATH bin/ Small user-facing commands on PATH; `panama` is the entry point
config/ config/
bash/ .bashrc, aliases, env (env is gitignored) bash/ .bashrc, aliases, env (env is gitignored)
copy/ Files copied verbatim over / (needs sudo) copy/ Files copied verbatim over / (needs sudo)
@@ -96,11 +96,12 @@ docs/ Settings reference, and the design specs behind the work
## Tests ## Tests
121 of them, under `tests/`, and each is a plain executable you can run on its 121 of them, under `tests/`. Run the lot, or a subset by pattern:
own:
```sh ```sh
bash tests/setup/interview-contract panama test # everything
panama test dock # just the ones matching "dock"
tests/setup/interview-contract # or one directly; they are plain executables
``` ```
They are called contracts rather than unit tests because that is what they are: They are called contracts rather than unit tests because that is what they are:
@@ -116,3 +117,17 @@ tests/setup/ The installer: the interview, package lists, hardware, extras
tests/quickshell/ The shell and its settings pages tests/quickshell/ The shell and its settings pages
tests/hypr/ The compositor config tests/hypr/ The compositor config
``` ```
## The `panama` command
```sh
panama update # review, commit and sync this repo
panama edit # open it in Neovim
panama doctor # what is actually running, not what was installed
panama test # every contract, or a subset by pattern
panama upgrade # re-run ./install from anywhere
```
None of the scripts in this repository carry a `.sh` extension. A shebang and
the executable bit already select the interpreter, and the extension only
becomes something to keep in sync — which it did not stay.
+109
View File
@@ -7,6 +7,9 @@
# Commands: # Commands:
# update Commit & sync local changes (or just pull if clean) # update Commit & sync local changes (or just pull if clean)
# edit Open the Panama repo in Neovim # edit Open the Panama repo in Neovim
# doctor Report what is actually running on this machine
# test Run every contract under tests/
# upgrade Re-run the installer from anywhere
# help Show this help # help Show this help
# #
# Designed to grow: add new subcommands as cmd_<name> functions and # Designed to grow: add new subcommands as cmd_<name> functions and
@@ -62,6 +65,12 @@ ${BOLD}Commands:${RESET}
${GREEN}update${RESET} Review, commit & sync local changes. If the working tree is ${GREEN}update${RESET} Review, commit & sync local changes. If the working tree is
clean it simply runs 'git pull'. clean it simply runs 'git pull'.
${GREEN}edit${RESET} Open the Panama repo in Neovim. ${GREEN}edit${RESET} Open the Panama repo in Neovim.
${GREEN}doctor${RESET} Report what is actually running on this machine, rather
than what was installed. Takes --summary for one line per check.
${GREEN}test${RESET} Run every contract under tests/. Give it a pattern to run
a subset: 'panama test dock' runs the ones matching 'dock'.
${GREEN}upgrade${RESET} Re-run ./install from anywhere. Safe: every stage is
idempotent and this is the documented upgrade path.
${GREEN}help${RESET} Show this help (also -h, --help). ${GREEN}help${RESET} Show this help (also -h, --help).
${BOLD}Options:${RESET} ${BOLD}Options:${RESET}
@@ -71,6 +80,9 @@ ${BOLD}Options:${RESET}
${BOLD}Examples:${RESET} ${BOLD}Examples:${RESET}
$PROGRAM update $PROGRAM update
$PROGRAM edit $PROGRAM edit
$PROGRAM doctor --summary
$PROGRAM test dock
$PROGRAM upgrade
EOF EOF
} }
@@ -205,6 +217,100 @@ cmd_edit() {
exec nvim . exec nvim .
} }
# ----------------------------------------------------------------------------
# Command: doctor
# ----------------------------------------------------------------------------
#
# The health check already exists and the installer already runs it; what it did
# not have was a way to reach it from a terminal. Everything is passed straight
# through, so --summary and anything added later work without this knowing about
# them.
cmd_doctor() {
local doctor="$PANAMA_DIR/config/dot/quickshell/scripts/panama-doctor"
if [[ ! -x "$doctor" ]]; then
err "panama-doctor is missing from $doctor"
exit 1
fi
exec "$doctor" "$@"
}
# ----------------------------------------------------------------------------
# Command: test
# ----------------------------------------------------------------------------
#
# The contracts are the main safety net in this repository and had no entry
# point: 121 executables with no runner and no mention in the README, which is
# most of the way to not having them.
#
# Each runs in its own process and a failure does not stop the rest, because the
# useful output is the whole list of what is broken rather than the first thing
# that broke. The exit code is what a caller can act on.
cmd_test() {
local pattern="${1:-}"
local -a suite=()
# Executables, plus the Python suites. Those are unittest files rather than
# executables, and collecting only what has the executable bit would skip them
# without saying so -- which is how all three came to be run by nothing at all.
# A runner with a blind spot is worse than no runner, because it reports PASS.
while IFS= read -r path; do
[[ -x "$path" || "$path" == *_test.py ]] || continue
[[ -z "$pattern" || "$path" == *"$pattern"* ]] && suite+=("$path")
done < <(find "$PANAMA_DIR/tests" -type f -not -path '*/fixtures/*' -not -path '*__pycache__*' | sort)
if (( ${#suite[@]} == 0 )); then
err "No contracts match '${pattern}'"
exit 1
fi
info "Running ${#suite[@]} contract(s)"
local -a failed=()
local path name
local -a runner
for path in "${suite[@]}"; do
name="${path#"$PANAMA_DIR"/tests/}"
if [[ "$path" == *_test.py ]]; then
runner=(python3 "$path")
else
runner=("$path")
fi
if "${runner[@]}" >/dev/null 2>&1; then
ok "$name"
else
err "$name"
failed+=("$name")
fi
done
header "Result"
if (( ${#failed[@]} == 0 )); then
ok "${#suite[@]} contract(s) passed"
return 0
fi
err "${#failed[@]} of ${#suite[@]} failed:"
printf ' %s\n' "${failed[@]}" >&2
warn "Run one on its own to see why: ${BOLD}${PANAMA_DIR}/tests/<name>${RESET}"
return 1
}
# ----------------------------------------------------------------------------
# Command: upgrade
# ----------------------------------------------------------------------------
#
# ./install is the upgrade path -- every stage is idempotent and re-running is
# the documented way to repair a machine. This only saves remembering where the
# repository lives.
cmd_upgrade() {
local installer="$PANAMA_DIR/install"
if [[ ! -x "$installer" ]]; then
err "The installer is missing from $installer"
exit 1
fi
info "Re-running ${BOLD}${installer}${RESET}"
cd "$PANAMA_DIR"
exec "$installer" "$@"
}
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
# Dispatcher # Dispatcher
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
@@ -213,6 +319,9 @@ main() {
case "$cmd" in case "$cmd" in
update) shift; cmd_update "$@" ;; update) shift; cmd_update "$@" ;;
edit) shift; cmd_edit "$@" ;; edit) shift; cmd_edit "$@" ;;
doctor) shift; cmd_doctor "$@" ;;
test) shift; cmd_test "$@" ;;
upgrade) shift; cmd_upgrade "$@" ;;
help|-h|--help|"") usage ;; help|-h|--help|"") usage ;;
--version) printf '%s %s\n' "$PROGRAM" "$VERSION" ;; --version) printf '%s %s\n' "$PROGRAM" "$VERSION" ;;
*) *)
+2 -2
View File
@@ -88,7 +88,7 @@ entry.
`prefs.lua` never raises. A missing, empty, truncated, malformed, or `prefs.lua` never raises. A missing, empty, truncated, malformed, or
wrong-typed settings file costs you your customizations and nothing else; wrong-typed settings file costs you your customizations and nothing else;
`tests/hypr/prefs-fallback-contract.sh` pins that, including that Hyprland still `tests/hypr/prefs-fallback-contract` pins that, including that Hyprland still
accepts the config in each of those states. accepts the config in each of those states.
### Adding a keybind: use `bind`, not `hl.bind` ### Adding a keybind: use `bind`, not `hl.bind`
@@ -120,7 +120,7 @@ Every `hl.bind` must pass a `description`. Hyprland reports Lua-defined binds
with dispatcher `__lua` and a bytecode offset as the argument, so a bind without with dispatcher `__lua` and a bytecode offset as the argument, so a bind without
one has nothing readable beside its chord, and the Settings app drops it from the one has nothing readable beside its chord, and the Settings app drops it from the
Input & Shortcuts page rather than showing a mystery row. Input & Shortcuts page rather than showing a mystery row.
`tests/quickshell/keybinds-contract.sh` fails if any bind lacks a description, so `tests/quickshell/keybinds-contract` fails if any bind lacks a description, so
this cannot regress silently. this cannot regress silently.
```lua ```lua
+1 -1
View File
@@ -1,5 +1,5 @@
// Exercises Migrations.applyWith against fixture steps and prints a verdict per // Exercises Migrations.applyWith against fixture steps and prints a verdict per
// case. Run by tests/quickshell/migrations-contract.sh. // case. Run by tests/quickshell/migrations-contract.
// //
// Fixture steps rather than the real list: the real one is empty until the // Fixture steps rather than the real list: the real one is empty until the
// first breaking schema change, and a mechanism that has never been run against // first breaking schema change, and a mechanism that has never been run against
@@ -91,7 +91,7 @@ layout.
Mirrors must remain the same schema-backed control, never a second preference Mirrors must remain the same schema-backed control, never a second preference
or a copied default. Additions to this table require a concrete discoverability or a copied default. Additions to this table require a concrete discoverability
reason and an update to `tests/quickshell/settings-ownership-contract.sh`. reason and an update to `tests/quickshell/settings-ownership-contract`.
Window border color follows the same ownership rule. The inactive border is a Window border color follows the same ownership rule. The inactive border is a
**scheme-relative role** owned by `ColorScheme.qml`: it changes only to retain **scheme-relative role** owned by `ColorScheme.qml`: it changes only to retain
@@ -127,7 +127,7 @@ store. A row never needs to know which kind it holds.
the value in a different JSON field per type — `int`, `bool`, `float`, `str`, the value in a different JSON field per type — `int`, `bool`, `float`, `str`,
and `css` for gaps (a four-value box). Declaring the wrong one does not fail and `css` for gaps (a four-value box). Declaring the wrong one does not fail
loudly: it makes every write to that key look *rejected*, and the user sees an loudly: it makes every write to that key look *rejected*, and the user sees an
error for a change that worked. `tests/quickshell/schema-hypr-shape-contract.sh` error for a change that worked. `tests/quickshell/schema-hypr-shape-contract`
asks the compositor for the real shape of every mapped option. asks the compositor for the real shape of every mapped option.
**Never trust an exit code from `hyprctl`.** `keyword` refuses to work on a **Never trust an exit code from `hyprctl`.** `keyword` refuses to work on a
@@ -150,12 +150,12 @@ def build() -> dict[Path, str]:
files: dict[Path, str] = {} files: dict[Path, str] = {}
for page, label in pages(): for page, label in pages():
words = keywords_for(page, routing, schema, extras) words = keywords_for(page, routing, schema, extras)
files[OUTPUT_DIR / f"settings-{page}.sh"] = command_for(page, label, words) files[OUTPUT_DIR / f"settings-{page}"] = command_for(page, label, words)
return files return files
def existing() -> set[Path]: def existing() -> set[Path]:
return {path for path in OUTPUT_DIR.glob("settings-*.sh")} return {path for path in OUTPUT_DIR.glob("settings-*")}
def main(arguments: list[str]) -> int: def main(arguments: list[str]) -> int:
+1 -1
View File
@@ -226,7 +226,7 @@ Singleton {
// A bind with no description cannot be presented usefully -- // A bind with no description cannot be presented usefully --
// the dispatcher is "__lua" and the argument is a bytecode // the dispatcher is "__lua" and the argument is a bytecode
// offset. Showing the chord alone would be worse than omitting // offset. Showing the chord alone would be worse than omitting
// it, and tests/quickshell/keybinds-contract.sh fails the build // it, and tests/quickshell/keybinds-contract fails the build
// if any exist, so this should never be reached in practice. // if any exist, so this should never be reached in practice.
if (description === "") if (description === "")
continue; continue;
@@ -33,8 +33,8 @@
- `config/dot/quickshell/scripts/calendar-agenda` — executable Python bridge; the only code that imports EDS libraries. - `config/dot/quickshell/scripts/calendar-agenda` — executable Python bridge; the only code that imports EDS libraries.
- `config/dot/quickshell/services/CalendarAgenda.qml` — singleton state consumed by shell UI; supervises the bridge and owns date-derived selectors. - `config/dot/quickshell/services/CalendarAgenda.qml` — singleton state consumed by shell UI; supervises the bridge and owns date-derived selectors.
- `tests/quickshell/calendar_agenda_bridge_test.py` — pure normalization and URL-policy tests using synthetic components only. - `tests/quickshell/calendar_agenda_bridge_test.py` — pure normalization and URL-policy tests using synthetic components only.
- `tests/quickshell/calendar-agenda-helper-contract.sh` — executable/probe/live-query contract that redacts live content. - `tests/quickshell/calendar-agenda-helper-contract` — executable/probe/live-query contract that redacts live content.
- `tests/quickshell/calendar-agenda-contract.sh` — live Quickshell IPC/state contract using synthetic in-memory fixtures. - `tests/quickshell/calendar-agenda-contract` — live Quickshell IPC/state contract using synthetic in-memory fixtures.
### Daybook presentation ### Daybook presentation
@@ -67,7 +67,7 @@
**Files:** **Files:**
- Create: `config/dot/quickshell/scripts/calendar-agenda` - Create: `config/dot/quickshell/scripts/calendar-agenda`
- Create: `tests/quickshell/calendar_agenda_bridge_test.py` - Create: `tests/quickshell/calendar_agenda_bridge_test.py`
- Create: `tests/quickshell/calendar-agenda-helper-contract.sh` - Create: `tests/quickshell/calendar-agenda-helper-contract`
**Interfaces:** **Interfaces:**
- Consumes: enabled sources returned by `EDataServer.SourceRegistry.list_enabled(EDataServer.SOURCE_EXTENSION_CALENDAR)`. - Consumes: enabled sources returned by `EDataServer.SourceRegistry.list_enabled(EDataServer.SOURCE_EXTENSION_CALENDAR)`.
@@ -229,7 +229,7 @@ Expected: four tests PASS.
- [x] **Step 5: Add the redacted live helper contract** - [x] **Step 5: Add the redacted live helper contract**
Create `tests/quickshell/calendar-agenda-helper-contract.sh` with: Create `tests/quickshell/calendar-agenda-helper-contract` with:
```bash ```bash
#!/usr/bin/env bash #!/usr/bin/env bash
@@ -265,7 +265,7 @@ Make it executable and run it. Expected: PASS with counts only; no source names,
```bash ```bash
git add config/dot/quickshell/scripts/calendar-agenda \ git add config/dot/quickshell/scripts/calendar-agenda \
tests/quickshell/calendar_agenda_bridge_test.py \ tests/quickshell/calendar_agenda_bridge_test.py \
tests/quickshell/calendar-agenda-helper-contract.sh tests/quickshell/calendar-agenda-helper-contract
git commit -m "Add the EDS calendar bridge" git commit -m "Add the EDS calendar bridge"
``` ```
@@ -275,7 +275,7 @@ git commit -m "Add the EDS calendar bridge"
**Files:** **Files:**
- Create: `config/dot/quickshell/services/CalendarAgenda.qml` - Create: `config/dot/quickshell/services/CalendarAgenda.qml`
- Create: `tests/quickshell/calendar-agenda-contract.sh` - Create: `tests/quickshell/calendar-agenda-contract`
- Modify: `config/dot/quickshell/shell.qml` - Modify: `config/dot/quickshell/shell.qml`
**Interfaces:** **Interfaces:**
@@ -286,7 +286,7 @@ git commit -m "Add the EDS calendar bridge"
- [x] **Step 1: Write the failing live service contract** - [x] **Step 1: Write the failing live service contract**
Create `tests/quickshell/calendar-agenda-contract.sh` that first asserts the IPC target, loads fixture `daybook`, and validates only synthetic state: Create `tests/quickshell/calendar-agenda-contract` that first asserts the IPC target, loads fixture `daybook`, and validates only synthetic state:
```bash ```bash
#!/usr/bin/env bash #!/usr/bin/env bash
@@ -317,7 +317,7 @@ printf 'calendar agenda contract: PASS\n'
- [x] **Step 2: Run the contract and verify RED** - [x] **Step 2: Run the contract and verify RED**
Run `tests/quickshell/calendar-agenda-contract.sh`. Run `tests/quickshell/calendar-agenda-contract`.
Expected: FAIL with `calendar IPC target is missing`. Expected: FAIL with `calendar IPC target is missing`.
@@ -385,8 +385,8 @@ Do not include titles, source names, locations, identifiers, or URLs in status o
Allow Quickshell to hot reload, then run: Allow Quickshell to hot reload, then run:
```bash ```bash
tests/quickshell/calendar-agenda-contract.sh tests/quickshell/calendar-agenda-contract
tests/quickshell/calendar-agenda-helper-contract.sh tests/quickshell/calendar-agenda-helper-contract
qs log -n -t 80 --no-color | rg -i 'calendar|error|warn' qs log -n -t 80 --no-color | rg -i 'calendar|error|warn'
``` ```
@@ -397,7 +397,7 @@ Expected: both contracts PASS; no calendar QML error or bridge restart loop.
```bash ```bash
git add config/dot/quickshell/services/CalendarAgenda.qml \ git add config/dot/quickshell/services/CalendarAgenda.qml \
config/dot/quickshell/shell.qml \ config/dot/quickshell/shell.qml \
tests/quickshell/calendar-agenda-contract.sh tests/quickshell/calendar-agenda-contract
git commit -m "Add live calendar state to Quickshell" git commit -m "Add live calendar state to Quickshell"
``` ```
@@ -410,7 +410,7 @@ git commit -m "Add live calendar state to Quickshell"
- Modify: `config/dot/quickshell/modules/bar/Clock.qml` - Modify: `config/dot/quickshell/modules/bar/Clock.qml`
- Modify: `config/dot/quickshell/shell.qml` - Modify: `config/dot/quickshell/shell.qml`
- Modify: `config/dot/quickshell/modules/datemenu/CalendarGrid.qml` - Modify: `config/dot/quickshell/modules/datemenu/CalendarGrid.qml`
- Modify: `tests/quickshell/calendar-agenda-contract.sh` - Modify: `tests/quickshell/calendar-agenda-contract`
**Interfaces:** **Interfaces:**
- Consumes: `CalendarAgenda.selectDate(date)` and `CalendarAgenda.markersForDate(date)`. - Consumes: `CalendarAgenda.selectDate(date)` and `CalendarAgenda.markersForDate(date)`.
@@ -489,7 +489,7 @@ Month changes call `visibleMonthChanged(viewYear, viewMonth)`. Adjacent-month da
Run: Run:
```bash ```bash
tests/quickshell/calendar-agenda-contract.sh tests/quickshell/calendar-agenda-contract
rg -q 'markersForDate' config/dot/quickshell/modules/datemenu/CalendarGrid.qml rg -q 'markersForDate' config/dot/quickshell/modules/datemenu/CalendarGrid.qml
rg -q 'dateActivated' config/dot/quickshell/modules/datemenu/CalendarGrid.qml rg -q 'dateActivated' config/dot/quickshell/modules/datemenu/CalendarGrid.qml
``` ```
@@ -503,7 +503,7 @@ git add config/dot/quickshell/services/ShellState.qml \
config/dot/quickshell/modules/bar/Clock.qml \ config/dot/quickshell/modules/bar/Clock.qml \
config/dot/quickshell/shell.qml \ config/dot/quickshell/shell.qml \
config/dot/quickshell/modules/datemenu/CalendarGrid.qml \ config/dot/quickshell/modules/datemenu/CalendarGrid.qml \
tests/quickshell/calendar-agenda-contract.sh tests/quickshell/calendar-agenda-contract
git commit -m "Route the interactive Panama date menu" git commit -m "Route the interactive Panama date menu"
``` ```
@@ -519,7 +519,7 @@ git commit -m "Route the interactive Panama date menu"
- Modify: `config/dot/quickshell/modules/datemenu/DateMenu.qml` - Modify: `config/dot/quickshell/modules/datemenu/DateMenu.qml`
- Modify: `config/dot/quickshell/modules/datemenu/MediaCard.qml` - Modify: `config/dot/quickshell/modules/datemenu/MediaCard.qml`
- Modify: `config/dot/quickshell/modules/datemenu/qmldir` - Modify: `config/dot/quickshell/modules/datemenu/qmldir`
- Modify: `tests/quickshell/calendar-agenda-contract.sh` - Modify: `tests/quickshell/calendar-agenda-contract`
**Interfaces:** **Interfaces:**
- Consumes: `CalendarAgenda.selectedEvents`, `nextEventForSelectedDate`, `phase`, and action functions. - Consumes: `CalendarAgenda.selectedEvents`, `nextEventForSelectedDate`, `phase`, and action functions.
@@ -623,7 +623,7 @@ Run:
```bash ```bash
qs ipc call calendar-agenda fixture daybook qs ipc call calendar-agenda fixture daybook
qs ipc call calendar-agenda open qs ipc call calendar-agenda open
tests/quickshell/calendar-agenda-contract.sh tests/quickshell/calendar-agenda-contract
``` ```
Capture a temporary full-screen screenshot with `grim`, inspect the Daybook at original detail, and verify: Capture a temporary full-screen screenshot with `grim`, inspect the Daybook at original detail, and verify:
@@ -641,7 +641,7 @@ Close the panel and reset fixture mode after inspection. Do not add screenshots
```bash ```bash
git add config/dot/quickshell/modules/datemenu \ git add config/dot/quickshell/modules/datemenu \
tests/quickshell/calendar-agenda-contract.sh tests/quickshell/calendar-agenda-contract
git commit -m "Build the Prism calendar Daybook" git commit -m "Build the Prism calendar Daybook"
``` ```
@@ -653,7 +653,7 @@ git commit -m "Build the Prism calendar Daybook"
- Create: `config/dot/quickshell/modules/bar/CalendarIndicator.qml` - Create: `config/dot/quickshell/modules/bar/CalendarIndicator.qml`
- Modify: `config/dot/quickshell/modules/bar/Bar.qml` - Modify: `config/dot/quickshell/modules/bar/Bar.qml`
- Modify: `config/dot/quickshell/services/CalendarAgenda.qml` - Modify: `config/dot/quickshell/services/CalendarAgenda.qml`
- Modify: `tests/quickshell/calendar-agenda-contract.sh` - Modify: `tests/quickshell/calendar-agenda-contract`
**Interfaces:** **Interfaces:**
- Consumes: `CalendarAgenda.capsuleVisible`, `capsuleText`, and `nextEvent`. - Consumes: `CalendarAgenda.capsuleVisible`, `capsuleText`, and `nextEvent`.
@@ -693,8 +693,8 @@ Use a single 120 ms opacity/width entrance tied to visibility. No looping animat
- [x] **Step 4: Run capsule and full shell contracts** - [x] **Step 4: Run capsule and full shell contracts**
```bash ```bash
tests/quickshell/calendar-agenda-contract.sh tests/quickshell/calendar-agenda-contract
for test in tests/quickshell/*.sh; do "$test"; done for test in tests/quickshell/*; do "$test"; done
``` ```
Expected: calendar fixture boundaries PASS and every existing Quickshell contract remains green. Expected: calendar fixture boundaries PASS and every existing Quickshell contract remains green.
@@ -705,7 +705,7 @@ Expected: calendar fixture boundaries PASS and every existing Quickshell contrac
git add config/dot/quickshell/modules/bar/CalendarIndicator.qml \ git add config/dot/quickshell/modules/bar/CalendarIndicator.qml \
config/dot/quickshell/modules/bar/Bar.qml \ config/dot/quickshell/modules/bar/Bar.qml \
config/dot/quickshell/services/CalendarAgenda.qml \ config/dot/quickshell/services/CalendarAgenda.qml \
tests/quickshell/calendar-agenda-contract.sh tests/quickshell/calendar-agenda-contract
git commit -m "Add the quiet calendar capsule" git commit -m "Add the quiet calendar capsule"
``` ```
@@ -745,7 +745,7 @@ Remove `qrencode` from `setup/packages/hyprland-packages` only if `rg -n qrencod
- [x] **Step 2: Run static verification** - [x] **Step 2: Run static verification**
```bash ```bash
bash -n tests/quickshell/*.sh config/dot/quickshell/scripts/screen-intelligence bash -n tests/quickshell/* config/dot/quickshell/scripts/screen-intelligence
python3 -c 'compile(open("config/dot/quickshell/scripts/calendar-agenda", encoding="utf-8").read(), "calendar-agenda", "exec")' python3 -c 'compile(open("config/dot/quickshell/scripts/calendar-agenda", encoding="utf-8").read(), "calendar-agenda", "exec")'
python3 tests/quickshell/calendar_agenda_bridge_test.py python3 tests/quickshell/calendar_agenda_bridge_test.py
desktop-file-validate config/local/share/applications/*.desktop desktop-file-validate config/local/share/applications/*.desktop
@@ -758,7 +758,7 @@ Expected: every command exits 0 and Hyprland reports `config ok`.
- [x] **Step 3: Run every Quickshell contract** - [x] **Step 3: Run every Quickshell contract**
```bash ```bash
for test in tests/quickshell/*.sh; do for test in tests/quickshell/*; do
"$test" "$test"
done done
``` ```
@@ -24,7 +24,7 @@
**Files:** **Files:**
- Create: `config/dot/quickshell/services/StatusEvents.qml` - Create: `config/dot/quickshell/services/StatusEvents.qml`
- Modify: `config/dot/quickshell/shell.qml` - Modify: `config/dot/quickshell/shell.qml`
- Test: `tests/quickshell/status-events-contract.sh` - Test: `tests/quickshell/status-events-contract`
**Interfaces:** **Interfaces:**
- Produces: `publish(event: var)`, `dismiss(): void`, `invoke(): void`, `activeEvent`, `active`, and IPC diagnostics. - Produces: `publish(event: var)`, `dismiss(): void`, `invoke(): void`, `activeEvent`, `active`, and IPC diagnostics.
@@ -61,7 +61,7 @@
- Modify: `config/dot/quickshell/services/Capture.qml` - Modify: `config/dot/quickshell/services/Capture.qml`
- Modify: `config/dot/quickshell/services/NightLight.qml` - Modify: `config/dot/quickshell/services/NightLight.qml`
- Modify: `config/dot/quickshell/services/FocusSession.qml` - Modify: `config/dot/quickshell/services/FocusSession.qml`
- Test: `tests/quickshell/activity-state-contract.sh` - Test: `tests/quickshell/activity-state-contract`
**Interfaces:** **Interfaces:**
- Produces: `PrivacyState.microphoneActive`, `cameraActive`, `screenSharingActive`, `recordingActive`, `activeKinds`, and transition events. - Produces: `PrivacyState.microphoneActive`, `cameraActive`, `screenSharingActive`, `recordingActive`, `activeKinds`, and transition events.
@@ -23,7 +23,7 @@
**Files:** **Files:**
- Modify: `config/dot/quickshell/modules/overview/OverviewBody.qml` - Modify: `config/dot/quickshell/modules/overview/OverviewBody.qml`
- Test: `tests/quickshell/overview-window-actions-contract.sh` - Test: `tests/quickshell/overview-window-actions-contract`
**Interfaces:** **Interfaces:**
- Produces: `addressOf(toplevel)`, `closeToplevel(toplevel)`, `moveToplevel(toplevel, workspaceName)`, and `restoreToplevel(toplevel)`. - Produces: `addressOf(toplevel)`, `closeToplevel(toplevel)`, `moveToplevel(toplevel, workspaceName)`, and `restoreToplevel(toplevel)`.
@@ -53,7 +53,7 @@
**Files:** **Files:**
- Create: `config/dot/quickshell/modules/overview/ScratchpadShelf.qml` - Create: `config/dot/quickshell/modules/overview/ScratchpadShelf.qml`
- Modify: `config/dot/quickshell/modules/overview/OverviewBody.qml` - Modify: `config/dot/quickshell/modules/overview/OverviewBody.qml`
- Test: `tests/quickshell/scratchpad-shelf-contract.sh` - Test: `tests/quickshell/scratchpad-shelf-contract`
**Interfaces:** **Interfaces:**
- Consumes: Hyprland workspace named `special:scratch` and OverviewBody move/restore callbacks. - Consumes: Hyprland workspace named `special:scratch` and OverviewBody move/restore callbacks.
@@ -31,14 +31,14 @@
- `config/dot/quickshell/scripts/panama-home-assistant` — credential-safe catalog, action authorization, brightness parsing, and Home Assistant REST calls. - `config/dot/quickshell/scripts/panama-home-assistant` — credential-safe catalog, action authorization, brightness parsing, and Home Assistant REST calls.
- `tests/quickshell/home_assistant_bridge_test.py` — fake-server unit tests for filtering, normalization, authorization, payloads, and redaction. - `tests/quickshell/home_assistant_bridge_test.py` — fake-server unit tests for filtering, normalization, authorization, payloads, and redaction.
- `tests/quickshell/home-assistant-helper-contract.sh` — live read-only probe/catalog shape check; it never invokes an action command. - `tests/quickshell/home-assistant-helper-contract` — live read-only probe/catalog shape check; it never invokes an action command.
- `config/dot/quickshell/config/HomePreferences.qml` — sole durable owner of initialization state and ordered `{id, alias}` favorites. - `config/dot/quickshell/config/HomePreferences.qml` — sole durable owner of initialization state and ordered `{id, alias}` favorites.
- `config/dot/quickshell/config/qmldir` — registers `HomePreferences` as a singleton. - `config/dot/quickshell/config/qmldir` — registers `HomePreferences` as a singleton.
- `config/dot/quickshell/home-preferences-harness.qml` — isolated IPC surface for preference mutation and restart tests. - `config/dot/quickshell/home-preferences-harness.qml` — isolated IPC surface for preference mutation and restart tests.
- `tests/quickshell/home-preferences-contract.sh` — first-run, empty-state, alias, reorder, remove, and restart-persistence contract. - `tests/quickshell/home-preferences-contract` — first-run, empty-state, alias, reorder, remove, and restart-persistence contract.
- `config/dot/quickshell/services/HomeAssistant.qml` — complete catalog, preference resolution, four-item shelf, fixtures, sequential action queue, and per-entity pending/error maps. - `config/dot/quickshell/services/HomeAssistant.qml` — complete catalog, preference resolution, four-item shelf, fixtures, sequential action queue, and per-entity pending/error maps.
- `config/dot/quickshell/shell.qml` — typed Home Assistant diagnostics/actions for fixture-only testing and Home & Phone routing. - `config/dot/quickshell/shell.qml` — typed Home Assistant diagnostics/actions for fixture-only testing and Home & Phone routing.
- `tests/quickshell/control-center-services-contract.sh` — service-model and per-light action-state contract using fixtures only. - `tests/quickshell/control-center-services-contract` — service-model and per-light action-state contract using fixtures only.
- `config/dot/quickshell/services/SystemSettings.qml` — BlueBubbles installed-state query and fixed allow-listed launch vector. - `config/dot/quickshell/services/SystemSettings.qml` — BlueBubbles installed-state query and fixed allow-listed launch vector.
- `config/dot/quickshell/modules/settings/HomePhonePage.qml` — page composition, connection health, search, selected/available sections, save error, and phone continuity. - `config/dot/quickshell/modules/settings/HomePhonePage.qml` — page composition, connection health, search, selected/available sections, save error, and phone continuity.
- `config/dot/quickshell/modules/settings/HomeFavoriteCard.qml` — editable alias, source name, first-four badge, remove action, and drag handle. - `config/dot/quickshell/modules/settings/HomeFavoriteCard.qml` — editable alias, source name, first-four badge, remove action, and drag handle.
@@ -47,14 +47,14 @@
- `config/dot/quickshell/modules/settings/SettingsShell.qml` — page loader registration. - `config/dot/quickshell/modules/settings/SettingsShell.qml` — page loader registration.
- `config/dot/quickshell/modules/settings/qmldir` — component registrations. - `config/dot/quickshell/modules/settings/qmldir` — component registrations.
- `config/dot/quickshell/services/ShellState.qml``home-phone` settings-page allow-list entry. - `config/dot/quickshell/services/ShellState.qml``home-phone` settings-page allow-list entry.
- `tests/quickshell/settings-pages-contract.sh` — route and single-window behavior. - `tests/quickshell/settings-pages-contract` — route and single-window behavior.
- `tests/quickshell/home-phone-settings-contract.sh` — static and fixture-driven settings-page behavior without writing the user's real preferences. - `tests/quickshell/home-phone-settings-contract` — static and fixture-driven settings-page behavior without writing the user's real preferences.
- `config/dot/quickshell/modules/quicksettings/HomeBrightnessSlider.qml` — local preview and one-shot commit interaction. - `config/dot/quickshell/modules/quicksettings/HomeBrightnessSlider.qml` — local preview and one-shot commit interaction.
- `config/dot/quickshell/modules/quicksettings/HomeTile.qml` — polished power, state, percent, dimmer, busy, and inline-error presentation. - `config/dot/quickshell/modules/quicksettings/HomeTile.qml` — polished power, state, percent, dimmer, busy, and inline-error presentation.
- `config/dot/quickshell/modules/quicksettings/HomeControls.qml` — resting/expanded shelf, setup state, stale state, and Manage in Settings row. - `config/dot/quickshell/modules/quicksettings/HomeControls.qml` — resting/expanded shelf, setup state, stale state, and Manage in Settings row.
- `config/dot/quickshell/modules/quicksettings/PhoneControls.qml` — four equal actions and independent Messages enablement. - `config/dot/quickshell/modules/quicksettings/PhoneControls.qml` — four equal actions and independent Messages enablement.
- `tests/quickshell/control-center-contract.sh` — mapped panel, exclusive expansion, component presence, and approved shelf structure. - `tests/quickshell/control-center-contract` — mapped panel, exclusive expansion, component presence, and approved shelf structure.
- `tests/quickshell/phone-messages-contract.sh` — BlueBubbles detection/allow-list/independent-enable contract; it never invokes the action. - `tests/quickshell/phone-messages-contract` — BlueBubbles detection/allow-list/independent-enable contract; it never invokes the action.
--- ---
@@ -63,7 +63,7 @@
**Files:** **Files:**
- Modify: `config/dot/quickshell/scripts/panama-home-assistant:44-434` - Modify: `config/dot/quickshell/scripts/panama-home-assistant:44-434`
- Modify: `tests/quickshell/home_assistant_bridge_test.py:25-182` - Modify: `tests/quickshell/home_assistant_bridge_test.py:25-182`
- Modify: `tests/quickshell/home-assistant-helper-contract.sh:1-29` - Modify: `tests/quickshell/home-assistant-helper-contract:1-29`
**Interfaces:** **Interfaces:**
- Consumes: `Config(base_url: str, token: str, entity_ids: tuple[str, ...])`, `request_json(config, method, path, payload)` and current URL/token/legacy resolution. - Consumes: `Config(base_url: str, token: str, entity_ids: tuple[str, ...])`, `request_json(config, method, path, payload)` and current URL/token/legacy resolution.
@@ -225,7 +225,7 @@ Do not print the discovery response, request body, URL, or token on action failu
- [x] **Step 6: Make unit and live read-only contracts GREEN** - [x] **Step 6: Make unit and live read-only contracts GREEN**
Update `home-assistant-helper-contract.sh` to call `catalog`, assert the exact seven entity keys, assert `legacyEntityIds` is an array, and report only the count: Update `home-assistant-helper-contract` to call `catalog`, assert the exact seven entity keys, assert `legacyEntityIds` is an array, and report only the count:
```bash ```bash
catalog="$($helper catalog)" catalog="$($helper catalog)"
@@ -242,7 +242,7 @@ Run:
```bash ```bash
python3 tests/quickshell/home_assistant_bridge_test.py -v python3 tests/quickshell/home_assistant_bridge_test.py -v
tests/quickshell/home-assistant-helper-contract.sh tests/quickshell/home-assistant-helper-contract
``` ```
Expected: all unit tests PASS; the live contract prints a redacted light count and performs GET requests only. Expected: all unit tests PASS; the live contract prints a redacted light count and performs GET requests only.
@@ -252,7 +252,7 @@ Expected: all unit tests PASS; the live contract prints a redacted light count a
```bash ```bash
git add config/dot/quickshell/scripts/panama-home-assistant \ git add config/dot/quickshell/scripts/panama-home-assistant \
tests/quickshell/home_assistant_bridge_test.py \ tests/quickshell/home_assistant_bridge_test.py \
tests/quickshell/home-assistant-helper-contract.sh tests/quickshell/home-assistant-helper-contract
git commit -m "Add Home Assistant light catalog and dimming" git commit -m "Add Home Assistant light catalog and dimming"
``` ```
@@ -264,7 +264,7 @@ git commit -m "Add Home Assistant light catalog and dimming"
- Create: `config/dot/quickshell/config/HomePreferences.qml` - Create: `config/dot/quickshell/config/HomePreferences.qml`
- Modify: `config/dot/quickshell/config/qmldir:1-4` - Modify: `config/dot/quickshell/config/qmldir:1-4`
- Create: `config/dot/quickshell/home-preferences-harness.qml` - Create: `config/dot/quickshell/home-preferences-harness.qml`
- Create: `tests/quickshell/home-preferences-contract.sh` - Create: `tests/quickshell/home-preferences-contract`
**Interfaces:** **Interfaces:**
- Consumes: top-level helper field `legacyEntityIds: string[]` after the first successful catalog. - Consumes: top-level helper field `legacyEntityIds: string[]` after the first successful catalog.
@@ -307,7 +307,7 @@ Then remove both records, restart again, call `initialize` with a different lega
Run: Run:
```bash ```bash
tests/quickshell/home-preferences-contract.sh tests/quickshell/home-preferences-contract
``` ```
Expected: FAIL because the singleton and harness do not exist. Expected: FAIL because the singleton and harness do not exist.
@@ -344,7 +344,7 @@ Use a 180 ms single-shot persistence timer. `initialize()` filters IDs through `
Run: Run:
```bash ```bash
tests/quickshell/home-preferences-contract.sh tests/quickshell/home-preferences-contract
``` ```
Expected: PASS for initial migration, trim, reorder, remove, restart persistence, and initialized-empty behavior. The temporary file is valid JSON and contains no credential-like fields. Expected: PASS for initial migration, trim, reorder, remove, restart persistence, and initialized-empty behavior. The temporary file is valid JSON and contains no credential-like fields.
@@ -355,7 +355,7 @@ Expected: PASS for initial migration, trim, reorder, remove, restart persistence
git add config/dot/quickshell/config/HomePreferences.qml \ git add config/dot/quickshell/config/HomePreferences.qml \
config/dot/quickshell/config/qmldir \ config/dot/quickshell/config/qmldir \
config/dot/quickshell/home-preferences-harness.qml \ config/dot/quickshell/home-preferences-harness.qml \
tests/quickshell/home-preferences-contract.sh tests/quickshell/home-preferences-contract
git commit -m "Persist Home accessory preferences" git commit -m "Persist Home accessory preferences"
``` ```
@@ -366,7 +366,7 @@ git commit -m "Persist Home accessory preferences"
**Files:** **Files:**
- Modify: `config/dot/quickshell/services/HomeAssistant.qml:1-185` - Modify: `config/dot/quickshell/services/HomeAssistant.qml:1-185`
- Modify: `config/dot/quickshell/shell.qml:252-272` - Modify: `config/dot/quickshell/shell.qml:252-272`
- Modify: `tests/quickshell/control-center-services-contract.sh:10-90` - Modify: `tests/quickshell/control-center-services-contract:10-90`
**Interfaces:** **Interfaces:**
- Consumes: helper `catalog`, `toggle ENTITY_ID`, and `brightness ENTITY_ID PERCENT`; all `HomePreferences` interfaces from Task 2. - Consumes: helper `catalog`, `toggle ENTITY_ID`, and `brightness ENTITY_ID PERCENT`; all `HomePreferences` interfaces from Task 2.
@@ -394,7 +394,7 @@ Add `missing-selected` and `action-error` fixtures. `missing-selected` retains o
Run: Run:
```bash ```bash
tests/quickshell/control-center-services-contract.sh tests/quickshell/control-center-services-contract
``` ```
Expected: the new catalog counts, selected IDs, brightness fixture action, and per-entity errors are absent. Expected: the new catalog counts, selected IDs, brightness fixture action, and per-entity errors are absent.
@@ -480,8 +480,8 @@ Fixture actions update only in-memory fixture catalog. `clearFixture()` clears f
Run: Run:
```bash ```bash
tests/quickshell/home-preferences-contract.sh tests/quickshell/home-preferences-contract
tests/quickshell/control-center-services-contract.sh tests/quickshell/control-center-services-contract
``` ```
Expected: both PASS; fixture cleanup returns live mode and the durable preference contract remains unchanged. Expected: both PASS; fixture cleanup returns live mode and the durable preference contract remains unchanged.
@@ -491,7 +491,7 @@ Expected: both PASS; fixture cleanup returns live mode and the durable preferenc
```bash ```bash
git add config/dot/quickshell/services/HomeAssistant.qml \ git add config/dot/quickshell/services/HomeAssistant.qml \
config/dot/quickshell/shell.qml \ config/dot/quickshell/shell.qml \
tests/quickshell/control-center-services-contract.sh tests/quickshell/control-center-services-contract
git commit -m "Compose Home catalog with accessory preferences" git commit -m "Compose Home catalog with accessory preferences"
``` ```
@@ -509,8 +509,8 @@ git commit -m "Compose Home catalog with accessory preferences"
- Modify: `config/dot/quickshell/modules/settings/qmldir:1-19` - Modify: `config/dot/quickshell/modules/settings/qmldir:1-19`
- Modify: `config/dot/quickshell/services/ShellState.qml:94-99` - Modify: `config/dot/quickshell/services/ShellState.qml:94-99`
- Modify: `config/dot/quickshell/shell.qml:274-299` - Modify: `config/dot/quickshell/shell.qml:274-299`
- Modify: `tests/quickshell/settings-pages-contract.sh:15-28` - Modify: `tests/quickshell/settings-pages-contract:15-28`
- Create: `tests/quickshell/home-phone-settings-contract.sh` - Create: `tests/quickshell/home-phone-settings-contract`
**Interfaces:** **Interfaces:**
- Consumes: `HomeAssistant.catalog`, `selectedEntities`, `discoveredCount`, phase/stale/error, `refresh()`, `open()`; all `HomePreferences` mutators; `SystemSettings.bluebubblesAvailable` and `openApplication("bluebubbles")`. - Consumes: `HomeAssistant.catalog`, `selectedEntities`, `discoveredCount`, phase/stale/error, `refresh()`, `open()`; all `HomePreferences` mutators; `SystemSettings.bluebubblesAvailable` and `openApplication("bluebubbles")`.
@@ -539,8 +539,8 @@ Using the ready fixture, route Settings to `home-phone` and assert one tiled `Pa
Run: Run:
```bash ```bash
tests/quickshell/settings-pages-contract.sh tests/quickshell/settings-pages-contract
tests/quickshell/home-phone-settings-contract.sh tests/quickshell/home-phone-settings-contract
``` ```
Expected: `home-phone` falls back to Home and the new components are missing. Expected: `home-phone` falls back to Home and the new components are missing.
@@ -629,10 +629,10 @@ Extend settings diagnostics with read-only counts:
Run: Run:
```bash ```bash
tests/quickshell/settings-system-contract.sh tests/quickshell/settings-system-contract
tests/quickshell/settings-pages-contract.sh tests/quickshell/settings-pages-contract
tests/quickshell/home-phone-settings-contract.sh tests/quickshell/home-phone-settings-contract
tests/quickshell/home-preferences-contract.sh tests/quickshell/home-preferences-contract
``` ```
Expected: all PASS; Panama Settings remains one normal tiled client, fixture tests leave real Home preferences unchanged, and no BlueBubbles process starts. Expected: all PASS; Panama Settings remains one normal tiled client, fixture tests leave real Home preferences unchanged, and no BlueBubbles process starts.
@@ -649,8 +649,8 @@ git add config/dot/quickshell/services/SystemSettings.qml \
config/dot/quickshell/modules/settings/qmldir \ config/dot/quickshell/modules/settings/qmldir \
config/dot/quickshell/services/ShellState.qml \ config/dot/quickshell/services/ShellState.qml \
config/dot/quickshell/shell.qml \ config/dot/quickshell/shell.qml \
tests/quickshell/settings-pages-contract.sh \ tests/quickshell/settings-pages-contract \
tests/quickshell/home-phone-settings-contract.sh tests/quickshell/home-phone-settings-contract
git commit -m "Add Home and Phone settings" git commit -m "Add Home and Phone settings"
``` ```
@@ -663,7 +663,7 @@ git commit -m "Add Home and Phone settings"
- Modify: `config/dot/quickshell/modules/quicksettings/HomeTile.qml:1-73` - Modify: `config/dot/quickshell/modules/quicksettings/HomeTile.qml:1-73`
- Modify: `config/dot/quickshell/modules/quicksettings/HomeControls.qml:1-280` - Modify: `config/dot/quickshell/modules/quicksettings/HomeControls.qml:1-280`
- Modify: `config/dot/quickshell/modules/quicksettings/qmldir` - Modify: `config/dot/quickshell/modules/quicksettings/qmldir`
- Modify: `tests/quickshell/control-center-contract.sh:19-72` - Modify: `tests/quickshell/control-center-contract:19-72`
**Interfaces:** **Interfaces:**
- Consumes: `HomeAssistant.visibleEntities`, `selectedEntities`, `isBusy(id)`, `pendingFor(id)`, `errorFor(id)`, `toggleEntity(id)`, `setBrightness(id, percent)`, phase/stale, refresh/open; `ShellState.openSettings("home-phone")`. - Consumes: `HomeAssistant.visibleEntities`, `selectedEntities`, `isBusy(id)`, `pendingFor(id)`, `errorFor(id)`, `toggleEntity(id)`, `setBrightness(id, percent)`, phase/stale, refresh/open; `ShellState.openSettings("home-phone")`.
@@ -689,7 +689,7 @@ Keep the live panel mapping and exclusive expansion assertions. Add ready-fixtur
Run: Run:
```bash ```bash
tests/quickshell/control-center-contract.sh tests/quickshell/control-center-contract
``` ```
Expected: the two-column shelf, slider, and Home & Phone management route are absent. Expected: the two-column shelf, slider, and Home & Phone management route are absent.
@@ -733,8 +733,8 @@ At the expanded list footer add `Manage in Settings`, which closes Control Cente
Run: Run:
```bash ```bash
tests/quickshell/control-center-services-contract.sh tests/quickshell/control-center-services-contract
tests/quickshell/control-center-contract.sh tests/quickshell/control-center-contract
``` ```
Expected: PASS. Opening and expanding Home maps one panel, displays the fixture shelf, and does not invoke the real Home Assistant API. Expected: PASS. Opening and expanding Home maps one panel, displays the fixture shelf, and does not invoke the real Home Assistant API.
@@ -746,7 +746,7 @@ git add config/dot/quickshell/modules/quicksettings/HomeBrightnessSlider.qml \
config/dot/quickshell/modules/quicksettings/HomeTile.qml \ config/dot/quickshell/modules/quicksettings/HomeTile.qml \
config/dot/quickshell/modules/quicksettings/HomeControls.qml \ config/dot/quickshell/modules/quicksettings/HomeControls.qml \
config/dot/quickshell/modules/quicksettings/qmldir \ config/dot/quickshell/modules/quicksettings/qmldir \
tests/quickshell/control-center-contract.sh tests/quickshell/control-center-contract
git commit -m "Build the Home accessory shelf" git commit -m "Build the Home accessory shelf"
``` ```
@@ -756,8 +756,8 @@ git commit -m "Build the Home accessory shelf"
**Files:** **Files:**
- Modify: `config/dot/quickshell/modules/quicksettings/PhoneControls.qml:1-273` - Modify: `config/dot/quickshell/modules/quicksettings/PhoneControls.qml:1-273`
- Create: `tests/quickshell/phone-messages-contract.sh` - Create: `tests/quickshell/phone-messages-contract`
- Modify: `tests/quickshell/control-center-contract.sh:41-72` - Modify: `tests/quickshell/control-center-contract:41-72`
**Interfaces:** **Interfaces:**
- Consumes: `SystemSettings.bluebubblesAvailable`, `SystemSettings.openApplication("bluebubbles")`, and existing KDE Connect capability/reachability/action interfaces. - Consumes: `SystemSettings.bluebubblesAvailable`, `SystemSettings.openApplication("bluebubbles")`, and existing KDE Connect capability/reachability/action interfaces.
@@ -774,7 +774,7 @@ Add a guard that fails if the script contains `openApplication` in an executed `
Run: Run:
```bash ```bash
tests/quickshell/phone-messages-contract.sh tests/quickshell/phone-messages-contract
``` ```
Expected: FAIL because PhoneControls still has three KDE-only actions. Expected: FAIL because PhoneControls still has three KDE-only actions.
@@ -803,9 +803,9 @@ When BlueBubbles is absent, append one quiet detail row: `BlueBubbles is not ins
Run: Run:
```bash ```bash
tests/quickshell/phone-messages-contract.sh tests/quickshell/phone-messages-contract
tests/quickshell/control-center-contract.sh tests/quickshell/control-center-contract
tests/quickshell/control-center-services-contract.sh tests/quickshell/control-center-services-contract
``` ```
Expected: PASS; the offline KDE fixture still exposes an enabled Messages action when BlueBubbles is installed, and no client launches during testing. Expected: PASS; the offline KDE fixture still exposes an enabled Messages action when BlueBubbles is installed, and no client launches during testing.
@@ -814,8 +814,8 @@ Expected: PASS; the offline KDE fixture still exposes an enabled Messages action
```bash ```bash
git add config/dot/quickshell/modules/quicksettings/PhoneControls.qml \ git add config/dot/quickshell/modules/quicksettings/PhoneControls.qml \
tests/quickshell/phone-messages-contract.sh \ tests/quickshell/phone-messages-contract \
tests/quickshell/control-center-contract.sh tests/quickshell/control-center-contract
git commit -m "Add BlueBubbles to Phone controls" git commit -m "Add BlueBubbles to Phone controls"
``` ```
@@ -850,14 +850,14 @@ Run:
```bash ```bash
python3 tests/quickshell/home_assistant_bridge_test.py -v python3 tests/quickshell/home_assistant_bridge_test.py -v
tests/quickshell/home-assistant-helper-contract.sh tests/quickshell/home-assistant-helper-contract
tests/quickshell/home-preferences-contract.sh tests/quickshell/home-preferences-contract
tests/quickshell/control-center-services-contract.sh tests/quickshell/control-center-services-contract
tests/quickshell/home-phone-settings-contract.sh tests/quickshell/home-phone-settings-contract
tests/quickshell/phone-messages-contract.sh tests/quickshell/phone-messages-contract
tests/quickshell/control-center-contract.sh tests/quickshell/control-center-contract
tests/quickshell/settings-system-contract.sh tests/quickshell/settings-system-contract
tests/quickshell/settings-pages-contract.sh tests/quickshell/settings-pages-contract
``` ```
Expected: every command exits 0. The helper contract performs read-only GETs; fixtures perform no real light action; BlueBubbles remains closed unless it was already open. Expected: every command exits 0. The helper contract performs read-only GETs; fixtures perform no real light action; BlueBubbles remains closed unless it was already open.
@@ -867,7 +867,7 @@ Expected: every command exits 0. The helper contract performs read-only GETs; fi
Run: Run:
```bash ```bash
for test in tests/quickshell/*contract.sh; do for test in tests/quickshell/*contract; do
printf 'Running %s\n' "$test" printf 'Running %s\n' "$test"
"$test" "$test"
done done
@@ -34,7 +34,7 @@ correctness bug in shipped behavior and does not depend on any of the
architecture below. architecture below.
**Files:** Modify `config/dot/quickshell/services/SystemSettings.qml`; **Files:** Modify `config/dot/quickshell/services/SystemSettings.qml`;
Test `tests/quickshell/settings-hyprland-write-contract.sh` Test `tests/quickshell/settings-hyprland-write-contract`
- [x] Write a contract that sets a display policy through `SystemSettings`, then - [x] Write a contract that sets a display policy through `SystemSettings`, then
asserts via `hyprctl getoption` that the compositor value actually changed — asserts via `hyprctl getoption` that the compositor value actually changed —
@@ -58,9 +58,9 @@ holds the group/key/option path and allow-list per option, so the UI never names
an option or supplies an unchecked value. Policy is applied as one batch, so the an option or supplies an unchecked value. Policy is applied as one batch, so the
shell cannot come up half-configured. shell cannot come up half-configured.
New: `tests/quickshell/settings-hyprland-write-contract.sh` — flips each policy New: `tests/quickshell/settings-hyprland-write-contract` — flips each policy
to a value it does not hold and reads it back, so a no-op write cannot pass. to a value it does not hold and reads it back, so a no-op write cannot pass.
The pre-existing `settings-system-contract.sh` re-applied the values already in The pre-existing `settings-system-contract` re-applied the values already in
place, which is why it passed throughout the outage. place, which is why it passed throughout the outage.
--- ---
@@ -70,7 +70,7 @@ place, which is why it passed throughout the outage.
**Files:** Create `config/dot/quickshell/config/PreferenceSchema.qml`; **Files:** Create `config/dot/quickshell/config/PreferenceSchema.qml`;
Modify `config/dot/quickshell/config/DesktopPreferences.qml`, Modify `config/dot/quickshell/config/DesktopPreferences.qml`,
`config/dot/quickshell/config/Settings.qml`; `config/dot/quickshell/config/Settings.qml`;
Test `tests/quickshell/preference-schema-contract.sh` Test `tests/quickshell/preference-schema-contract`
Schema entry shape: Schema entry shape:
@@ -93,8 +93,8 @@ Schema entry shape:
file from `Quickshell.stateDir` on first run if present. file from `Quickshell.stateDir` on first run if present.
- [x] Keep `Settings.qml` as the stable public read surface; existing consumers - [x] Keep `Settings.qml` as the stable public read surface; existing consumers
must not change. must not change.
- [x] Run the new contract plus `settings-preferences-contract.sh` and - [x] Run the new contract plus `settings-preferences-contract` and
`settings-pages-contract.sh` to green. `settings-pages-contract` to green.
**Exit criteria:** adding a setting is one schema line; reset is complete by **Exit criteria:** adding a setting is one schema line; reset is complete by
construction; the store lives at a stable, user-visible path. construction; the store lives at a stable, user-visible path.
@@ -116,7 +116,7 @@ absent, and never deletes the original. Verified live: the running shell adopted
all 17 values into `~/.config/panama/settings.json` with the legacy files intact. all 17 values into `~/.config/panama/settings.json` with the legacy files intact.
New: `config/PreferenceSchema.qml`, `preference-schema-harness.qml`, New: `config/PreferenceSchema.qml`, `preference-schema-harness.qml`,
`tests/quickshell/preference-schema-contract.sh`. Full suite green — 6 settings `tests/quickshell/preference-schema-contract`. Full suite green — 6 settings
contracts, 22 other Quickshell contracts, 3 Python bridge tests. contracts, 22 other Quickshell contracts, 3 Python bridge tests.
--- ---
@@ -125,7 +125,7 @@ contracts, 22 other Quickshell contracts, 3 Python bridge tests.
**Files:** Create `config/dot/hypr/prefs.lua`; **Files:** Create `config/dot/hypr/prefs.lua`;
Modify `config/dot/hypr/hyprland.lua`, `looks.lua`, `input.lua`, `monitors.lua`; Modify `config/dot/hypr/hyprland.lua`, `looks.lua`, `input.lua`, `monitors.lua`;
Test `tests/hypr/prefs-fallback-contract.sh` Test `tests/hypr/prefs-fallback-contract`
- [x] Write a contract that verifies `Hyprland --verify-config` passes with the - [x] Write a contract that verifies `Hyprland --verify-config` passes with the
file absent, empty, truncated mid-object, and containing wrong-typed values — file absent, empty, truncated mid-object, and containing wrong-typed values —
@@ -228,7 +228,7 @@ Four things found by building it:
what getoption answers with, not what the setting means, and getting it wrong what getoption answers with, not what the setting means, and getting it wrong
does not fail loudly — it makes every write to that key look rejected. The user does not fail loudly — it makes every write to that key look rejected. The user
saw "Hyprland did not apply Hide pointer after" for a change that worked. saw "Hyprland did not apply Hide pointer after" for a change that worked.
`tests/quickshell/schema-hypr-shape-contract.sh` now asks the compositor for `tests/quickshell/schema-hypr-shape-contract` now asks the compositor for
the real shape of all 23 mapped options. the real shape of all 23 mapped options.
* The Settings window is a normal tiled window, so `implicitWidth: 1120` is only * The Settings window is a normal tiled window, so `implicitWidth: 1120` is only
a hint and rows must survive ~400px. `SliderRow` stacks its control under the a hint and rows must survive ~400px. `SliderRow` stacks its control under the
@@ -244,7 +244,7 @@ Four things found by building it:
## Stage 4 — Shortcuts from the compositor ## Stage 4 — Shortcuts from the compositor
**Files:** Create `services/Keybinds.qml`; Modify `modules/settings/ShortcutsPage.qml`, **Files:** Create `services/Keybinds.qml`; Modify `modules/settings/ShortcutsPage.qml`,
`config/dot/hypr/keybinds.lua`; Test `tests/quickshell/keybinds-contract.sh` `config/dot/hypr/keybinds.lua`; Test `tests/quickshell/keybinds-contract`
- [x] Write a contract asserting the page's bind count matches `hyprctl binds -j` - [x] Write a contract asserting the page's bind count matches `hyprctl binds -j`
exactly, so it can never drift again. exactly, so it can never drift again.
@@ -266,7 +266,7 @@ Grouping is derived from each bind's own description rather than a table here, s
adding a bind puts it in the right section automatically. Hyprland reports adding a bind puts it in the right section automatically. Hyprland reports
Lua-defined binds with dispatcher `__lua` and a bytecode offset as the argument, Lua-defined binds with dispatcher `__lua` and a bytecode offset as the argument,
so a bind without a description has nothing readable beside its chord; the so a bind without a description has nothing readable beside its chord; the
service drops those, and `tests/quickshell/keybinds-contract.sh` fails if any service drops those, and `tests/quickshell/keybinds-contract` fails if any
exist so that dropping can never be silent. exist so that dropping can never be silent.
Input settings are on the same page and are now real controls: keyboard repeat, Input settings are on the same page and are now real controls: keyboard repeat,
@@ -33,14 +33,14 @@
- `config/dot/quickshell/scripts/panama-kdeconnect` — validates device/file inputs, normalizes device/plugin status, and invokes allow-listed actions. - `config/dot/quickshell/scripts/panama-kdeconnect` — validates device/file inputs, normalizes device/plugin status, and invokes allow-listed actions.
- `tests/quickshell/kdeconnect_bridge_test.py` — pure parser, capability, validation, and command tests with fake runners. - `tests/quickshell/kdeconnect_bridge_test.py` — pure parser, capability, validation, and command tests with fake runners.
- `tests/quickshell/kdeconnect-helper-contract.sh` — live read-only status contract with names and IDs redacted. - `tests/quickshell/kdeconnect-helper-contract` — live read-only status contract with names and IDs redacted.
- `config/dot/quickshell/services/KdeConnect.qml` — singleton device, action, transfer, fixture, and recent-exchange state. - `config/dot/quickshell/services/KdeConnect.qml` — singleton device, action, transfer, fixture, and recent-exchange state.
### Home Assistant boundary ### Home Assistant boundary
- `config/dot/quickshell/scripts/panama-home-assistant` — configuration resolution, normalized REST reads, allow-listed toggles, and URL handoff. - `config/dot/quickshell/scripts/panama-home-assistant` — configuration resolution, normalized REST reads, allow-listed toggles, and URL handoff.
- `tests/quickshell/home_assistant_bridge_test.py` — local fake API and credential/configuration precedence tests. - `tests/quickshell/home_assistant_bridge_test.py` — local fake API and credential/configuration precedence tests.
- `tests/quickshell/home-assistant-helper-contract.sh` — live read-only probe/snapshot contract with entity content redacted. - `tests/quickshell/home-assistant-helper-contract` — live read-only probe/snapshot contract with entity content redacted.
- `config/dot/quickshell/services/HomeAssistant.qml` — singleton entities, stale state, per-entity action state, fixture, and inline errors. - `config/dot/quickshell/services/HomeAssistant.qml` — singleton entities, stale state, per-entity action state, fixture, and inline errors.
### Control Center presentation and integration ### Control Center presentation and integration
@@ -58,8 +58,8 @@
- `config/dot/quickshell/services/Ongoing.qml` — append and control one running phone transfer. - `config/dot/quickshell/services/Ongoing.qml` — append and control one running phone transfer.
- `config/dot/quickshell/services/StatusEvents.qml` — open a completed received/sent path through the existing allow-listed action. - `config/dot/quickshell/services/StatusEvents.qml` — open a completed received/sent path through the existing allow-listed action.
- `config/dot/quickshell/shell.qml` — diagnostics/fixture IPC for the two services. - `config/dot/quickshell/shell.qml` — diagnostics/fixture IPC for the two services.
- `tests/quickshell/control-center-services-contract.sh` — deterministic service, activity, and event contract. - `tests/quickshell/control-center-services-contract` — deterministic service, activity, and event contract.
- `tests/quickshell/control-center-contract.sh` — panel geometry, routing, components, and live layer contract. - `tests/quickshell/control-center-contract` — panel geometry, routing, components, and live layer contract.
### Documentation ### Documentation
@@ -73,7 +73,7 @@
**Files:** **Files:**
- Create: `config/dot/quickshell/scripts/panama-kdeconnect` - Create: `config/dot/quickshell/scripts/panama-kdeconnect`
- Create: `tests/quickshell/kdeconnect_bridge_test.py` - Create: `tests/quickshell/kdeconnect_bridge_test.py`
- Create: `tests/quickshell/kdeconnect-helper-contract.sh` - Create: `tests/quickshell/kdeconnect-helper-contract`
**Interfaces:** **Interfaces:**
- Produces: `panama-kdeconnect status` JSON with `available` and `devices`. - Produces: `panama-kdeconnect status` JSON with `available` and `devices`.
@@ -185,7 +185,7 @@ Expected: all cases PASS with no device name, address, or file path printed by t
- [ ] **Step 5: Add and run the redacted live contract** - [ ] **Step 5: Add and run the redacted live contract**
Create `tests/quickshell/kdeconnect-helper-contract.sh` that runs `status` and asserts: Create `tests/quickshell/kdeconnect-helper-contract` that runs `status` and asserts:
```bash ```bash
jq -e ' jq -e '
@@ -203,7 +203,7 @@ Print only `PASS (N paired, N reachable; identities redacted)`.
```bash ```bash
git add config/dot/quickshell/scripts/panama-kdeconnect \ git add config/dot/quickshell/scripts/panama-kdeconnect \
tests/quickshell/kdeconnect_bridge_test.py \ tests/quickshell/kdeconnect_bridge_test.py \
tests/quickshell/kdeconnect-helper-contract.sh tests/quickshell/kdeconnect-helper-contract
git commit -m "Add the Panama KDE Connect bridge" git commit -m "Add the Panama KDE Connect bridge"
``` ```
@@ -214,7 +214,7 @@ git commit -m "Add the Panama KDE Connect bridge"
**Files:** **Files:**
- Create: `config/dot/quickshell/scripts/panama-home-assistant` - Create: `config/dot/quickshell/scripts/panama-home-assistant`
- Create: `tests/quickshell/home_assistant_bridge_test.py` - Create: `tests/quickshell/home_assistant_bridge_test.py`
- Create: `tests/quickshell/home-assistant-helper-contract.sh` - Create: `tests/quickshell/home-assistant-helper-contract`
**Interfaces:** **Interfaces:**
- Produces: `probe`, `snapshot`, `toggle ENTITY_ID`, and `open`. - Produces: `probe`, `snapshot`, `toggle ENTITY_ID`, and `open`.
@@ -348,7 +348,7 @@ The contract runs `probe` and `snapshot`, validates the schema, and prints only
```bash ```bash
git add config/dot/quickshell/scripts/panama-home-assistant \ git add config/dot/quickshell/scripts/panama-home-assistant \
tests/quickshell/home_assistant_bridge_test.py \ tests/quickshell/home_assistant_bridge_test.py \
tests/quickshell/home-assistant-helper-contract.sh tests/quickshell/home-assistant-helper-contract
git commit -m "Add the Panama Home Assistant bridge" git commit -m "Add the Panama Home Assistant bridge"
``` ```
@@ -359,7 +359,7 @@ git commit -m "Add the Panama Home Assistant bridge"
**Files:** **Files:**
- Create: `config/dot/quickshell/services/KdeConnect.qml` - Create: `config/dot/quickshell/services/KdeConnect.qml`
- Create: `config/dot/quickshell/services/HomeAssistant.qml` - Create: `config/dot/quickshell/services/HomeAssistant.qml`
- Create: `tests/quickshell/control-center-services-contract.sh` - Create: `tests/quickshell/control-center-services-contract`
- Modify: `config/dot/quickshell/services/DeviceEvents.qml` - Modify: `config/dot/quickshell/services/DeviceEvents.qml`
- Modify: `config/dot/quickshell/services/Ongoing.qml` - Modify: `config/dot/quickshell/services/Ongoing.qml`
- Modify: `config/dot/quickshell/shell.qml` - Modify: `config/dot/quickshell/shell.qml`
@@ -396,7 +396,7 @@ Cleanup resets both fixture modes and closes Quick Settings.
- [ ] **Step 2: Run the contract and verify RED** - [ ] **Step 2: Run the contract and verify RED**
Run `tests/quickshell/control-center-services-contract.sh`. Run `tests/quickshell/control-center-services-contract`.
Expected: FAIL because the IPC targets do not exist. Expected: FAIL because the IPC targets do not exist.
@@ -456,7 +456,7 @@ Run the repository's established shell reload command, wait for the current
instance to report IPC, then run: instance to report IPC, then run:
```bash ```bash
tests/quickshell/control-center-services-contract.sh tests/quickshell/control-center-services-contract
``` ```
Expected: PASS with fixture state only and no QML warnings in the fresh journal. Expected: PASS with fixture state only and no QML warnings in the fresh journal.
@@ -469,7 +469,7 @@ git add config/dot/quickshell/services/KdeConnect.qml \
config/dot/quickshell/services/DeviceEvents.qml \ config/dot/quickshell/services/DeviceEvents.qml \
config/dot/quickshell/services/Ongoing.qml \ config/dot/quickshell/services/Ongoing.qml \
config/dot/quickshell/shell.qml \ config/dot/quickshell/shell.qml \
tests/quickshell/control-center-services-contract.sh tests/quickshell/control-center-services-contract
git commit -m "Add Control Center integration services" git commit -m "Add Control Center integration services"
``` ```
@@ -483,7 +483,7 @@ git commit -m "Add Control Center integration services"
- Create: `config/dot/quickshell/modules/quicksettings/HomeTile.qml` - Create: `config/dot/quickshell/modules/quicksettings/HomeTile.qml`
- Create: `config/dot/quickshell/modules/quicksettings/PhoneControls.qml` - Create: `config/dot/quickshell/modules/quicksettings/PhoneControls.qml`
- Create: `config/dot/quickshell/modules/quicksettings/RecentExchange.qml` - Create: `config/dot/quickshell/modules/quicksettings/RecentExchange.qml`
- Create: `tests/quickshell/control-center-contract.sh` - Create: `tests/quickshell/control-center-contract`
- Modify: `config/dot/quickshell/config/Theme.qml` - Modify: `config/dot/quickshell/config/Theme.qml`
- Modify: `config/dot/quickshell/modules/quicksettings/QuickSettings.qml` - Modify: `config/dot/quickshell/modules/quicksettings/QuickSettings.qml`
- Modify: `config/dot/quickshell/modules/quicksettings/QuickSettingsPanel.qml` - Modify: `config/dot/quickshell/modules/quicksettings/QuickSettingsPanel.qml`
@@ -514,7 +514,7 @@ Phone leaves only Phone expanded.
- [ ] **Step 2: Run the contract and verify RED** - [ ] **Step 2: Run the contract and verify RED**
Run `tests/quickshell/control-center-contract.sh`. Run `tests/quickshell/control-center-contract`.
Expected: FAIL on the missing geometry tokens and components. Expected: FAIL on the missing geometry tokens and components.
@@ -568,7 +568,7 @@ animation.
- [ ] **Step 7: Restart Quickshell and run the panel contract GREEN** - [ ] **Step 7: Restart Quickshell and run the panel contract GREEN**
Run `tests/quickshell/control-center-contract.sh` and inspect the fresh shell Run `tests/quickshell/control-center-contract` and inspect the fresh shell
journal for `error`, `warning`, `ReferenceError`, and `TypeError` entries from journal for `error`, `warning`, `ReferenceError`, and `TypeError` entries from
the current Quickshell start. the current Quickshell start.
@@ -581,7 +581,7 @@ fixture screenshots to `/tmp`; do not commit screenshots.
git add config/dot/quickshell/config/Theme.qml \ git add config/dot/quickshell/config/Theme.qml \
config/dot/quickshell/modules/quicksettings \ config/dot/quickshell/modules/quicksettings \
config/dot/quickshell/modules/bar/StatusCluster.qml \ config/dot/quickshell/modules/bar/StatusCluster.qml \
tests/quickshell/control-center-contract.sh tests/quickshell/control-center-contract
git commit -m "Build the Panama Control Center" git commit -m "Build the Panama Control Center"
``` ```
@@ -610,10 +610,10 @@ retaining printers and the external RustDesk lock-screen test.
```bash ```bash
python3 tests/quickshell/kdeconnect_bridge_test.py python3 tests/quickshell/kdeconnect_bridge_test.py
python3 tests/quickshell/home_assistant_bridge_test.py python3 tests/quickshell/home_assistant_bridge_test.py
tests/quickshell/kdeconnect-helper-contract.sh tests/quickshell/kdeconnect-helper-contract
tests/quickshell/home-assistant-helper-contract.sh tests/quickshell/home-assistant-helper-contract
tests/quickshell/control-center-services-contract.sh tests/quickshell/control-center-services-contract
tests/quickshell/control-center-contract.sh tests/quickshell/control-center-contract
``` ```
Expected: every command exits 0; live contracts print counts only. Expected: every command exits 0; live contracts print counts only.
@@ -621,7 +621,7 @@ Expected: every command exits 0; live contracts print counts only.
- [ ] **Step 3: Run full Panama verification** - [ ] **Step 3: Run full Panama verification**
Run `hyprctl configerrors` and require empty output. Run every executable Run `hyprctl configerrors` and require empty output. Run every executable
`tests/quickshell/*contract.sh` in sorted order and require zero failures. `tests/quickshell/*contract` in sorted order and require zero failures.
Restart Quickshell from a clean process, verify all IPC targets return, and Restart Quickshell from a clean process, verify all IPC targets return, and
inspect only the new process's journal for QML errors or warnings. inspect only the new process's journal for QML errors or warnings.
@@ -26,7 +26,7 @@
**Files:** **Files:**
- Create: `config/dot/quickshell/config/DesktopPreferences.qml` - Create: `config/dot/quickshell/config/DesktopPreferences.qml`
- Modify: `config/dot/quickshell/config/Settings.qml` - Modify: `config/dot/quickshell/config/Settings.qml`
- Test: `tests/quickshell/settings-preferences-contract.sh` - Test: `tests/quickshell/settings-preferences-contract`
**Interfaces:** **Interfaces:**
- Produces: writable `use24Hour`, `showSeconds`, `showWeekday`, `showCpu`, `showMemory`, `showGpu`, `dockAutohide`, `dockRevealDelayMs`, `dockHideDelayMs`, `focusDurationMinutes`, `autoHdr`, `vrrPolicy`, `directScanoutPolicy`, and `lastPage` properties plus `resetDesktopDefaults(): void`. - Produces: writable `use24Hour`, `showSeconds`, `showWeekday`, `showCpu`, `showMemory`, `showGpu`, `dockAutohide`, `dockRevealDelayMs`, `dockHideDelayMs`, `focusDurationMinutes`, `autoHdr`, `vrrPolicy`, `directScanoutPolicy`, and `lastPage` properties plus `resetDesktopDefaults(): void`.
@@ -41,7 +41,7 @@
**Files:** **Files:**
- Create: `config/dot/quickshell/services/SystemSettings.qml` - Create: `config/dot/quickshell/services/SystemSettings.qml`
- Test: `tests/quickshell/settings-system-contract.sh` - Test: `tests/quickshell/settings-system-contract`
**Interfaces:** **Interfaces:**
- Consumes: `DesktopPreferences`, `NightLight`, `Notifs`, `Caffeine`, `hyprctl`, `systemctl`, and `pgrep`. - Consumes: `DesktopPreferences`, `NightLight`, `Notifs`, `Caffeine`, `hyprctl`, `systemctl`, and `pgrep`.
@@ -66,7 +66,7 @@
- Create: `config/dot/quickshell/modules/settings/DisplaysPage.qml` - Create: `config/dot/quickshell/modules/settings/DisplaysPage.qml`
- Create: `config/dot/quickshell/modules/settings/DesktopPage.qml` - Create: `config/dot/quickshell/modules/settings/DesktopPage.qml`
- Create: `config/dot/quickshell/modules/settings/qmldir` - Create: `config/dot/quickshell/modules/settings/qmldir`
- Test: `tests/quickshell/settings-window-contract.sh` - Test: `tests/quickshell/settings-window-contract`
**Interfaces:** **Interfaces:**
- Consumes: `DesktopPreferences`, `SystemSettings`, `NightLight`, and `ShellState.settingsPage`. - Consumes: `DesktopPreferences`, `SystemSettings`, `NightLight`, and `ShellState.settingsPage`.
@@ -87,7 +87,7 @@
- Create: `config/dot/quickshell/modules/settings/ServicesPage.qml` - Create: `config/dot/quickshell/modules/settings/ServicesPage.qml`
- Create: `config/dot/quickshell/modules/settings/AboutPage.qml` - Create: `config/dot/quickshell/modules/settings/AboutPage.qml`
- Modify: `config/dot/quickshell/modules/settings/SettingsShell.qml` - Modify: `config/dot/quickshell/modules/settings/SettingsShell.qml`
- Test: `tests/quickshell/settings-pages-contract.sh` - Test: `tests/quickshell/settings-pages-contract`
**Interfaces:** **Interfaces:**
- Consumes: existing PipeWire controls, `Notifs`, `FocusSession`, service status from Task 2, and fixed GNOME panel handoffs. - Consumes: existing PipeWire controls, `Notifs`, `FocusSession`, service status from Task 2, and fixed GNOME panel handoffs.
@@ -25,7 +25,7 @@
**Files:** **Files:**
- Create: `config/dot/quickshell/scripts/screen-intelligence` - Create: `config/dot/quickshell/scripts/screen-intelligence`
- Create: `tests/quickshell/screen-intelligence-helper-contract.sh` - Create: `tests/quickshell/screen-intelligence-helper-contract`
- Modify: `setup/packages/hyprland-packages` - Modify: `setup/packages/hyprland-packages`
**Interfaces:** **Interfaces:**
@@ -42,7 +42,7 @@
**Files:** **Files:**
- Create: `config/dot/quickshell/services/ScreenIntelligence.qml` - Create: `config/dot/quickshell/services/ScreenIntelligence.qml`
- Test: `tests/quickshell/screen-intelligence-contract.sh` - Test: `tests/quickshell/screen-intelligence-contract`
**Interfaces:** **Interfaces:**
- Produces: readiness properties, `phase`, `text`, detected-code data, `analyzeRegion`, `analyzeFile`, copy/search/translate/open actions, and `close`. - Produces: readiness properties, `phase`, `text`, detected-code data, `analyzeRegion`, `analyzeFile`, copy/search/translate/open actions, and `close`.
@@ -85,7 +85,7 @@
- Create: `config/local/share/applications/panama-screen-intelligence.desktop` - Create: `config/local/share/applications/panama-screen-intelligence.desktop`
- Modify: `config/dot/hypr/README.md` - Modify: `config/dot/hypr/README.md`
- Modify: `README.md` - Modify: `README.md`
- Modify: `tests/quickshell/settings-pages-contract.sh` - Modify: `tests/quickshell/settings-pages-contract`
**Interfaces:** **Interfaces:**
- Produces: Settings destination `screen-intelligence`, `Super+Shift+S`, and a searchable desktop entry. - Produces: Settings destination `screen-intelligence`, `Super+Shift+S`, and a searchable desktop entry.
@@ -32,11 +32,11 @@
- `config/dot/quickshell/modules/settings/HealthSummary.qml`: stable-height summary hero and primary controls. - `config/dot/quickshell/modules/settings/HealthSummary.qml`: stable-height summary hero and primary controls.
- `config/dot/quickshell/modules/settings/HealthCheckRow.qml`: one accessible check row with one action. - `config/dot/quickshell/modules/settings/HealthCheckRow.qml`: one accessible check row with one action.
- `config/dot/quickshell/modules/bar/HealthIndicator.qml`: degraded-only bar entry point. - `config/dot/quickshell/modules/bar/HealthIndicator.qml`: degraded-only bar entry point.
- `config/local/share/vicinae/scripts/check-system-health.sh`: searchable launcher command. - `config/local/share/vicinae/scripts/check-system-health`: searchable launcher command.
- `tests/quickshell/fixtures/doctor/`: isolated command, config, state, and runtime fixtures containing no real workstation data. - `tests/quickshell/fixtures/doctor/`: isolated command, config, state, and runtime fixtures containing no real workstation data.
- `tests/quickshell/panama-doctor-contract.sh`: schema, status, redaction, timeout, ordering, and repair allow-list contract. - `tests/quickshell/panama-doctor-contract`: schema, status, redaction, timeout, ordering, and repair allow-list contract.
- `tests/quickshell/health-service-contract.sh`: QML state-machine contract. - `tests/quickshell/health-service-contract`: QML state-machine contract.
- `tests/quickshell/health-ui-contract.sh`: Settings, footer, report, indicator, IPC, and Vicinae integration contract. - `tests/quickshell/health-ui-contract`: Settings, footer, report, indicator, IPC, and Vicinae integration contract.
The helper's authored check order is: The helper's authored check order is:
@@ -126,7 +126,7 @@ Add a short `Approved visual: <variant>` note beneath this task after user selec
**Files:** **Files:**
- Create: `config/dot/quickshell/scripts/panama-doctor` - Create: `config/dot/quickshell/scripts/panama-doctor`
- Create: `tests/quickshell/panama-doctor-contract.sh` - Create: `tests/quickshell/panama-doctor-contract`
- Create: `tests/quickshell/fixtures/doctor/bin/systemctl` - Create: `tests/quickshell/fixtures/doctor/bin/systemctl`
- Create: `tests/quickshell/fixtures/doctor/bin/pgrep` - Create: `tests/quickshell/fixtures/doctor/bin/pgrep`
- Create: `tests/quickshell/fixtures/doctor/bin/busctl` - Create: `tests/quickshell/fixtures/doctor/bin/busctl`
@@ -162,7 +162,7 @@ Cover a healthy required service, a missing required executable, an unconfigured
- [ ] **Step 2: Run the contract and verify the helper is absent** - [ ] **Step 2: Run the contract and verify the helper is absent**
Run: `tests/quickshell/panama-doctor-contract.sh` Run: `tests/quickshell/panama-doctor-contract`
Expected: FAIL because `config/dot/quickshell/scripts/panama-doctor` does not exist. Expected: FAIL because `config/dot/quickshell/scripts/panama-doctor` does not exist.
@@ -195,14 +195,14 @@ The top-level `context` contains only an authored session class and an ordered a
- [ ] **Step 4: Run the doctor contract** - [ ] **Step 4: Run the doctor contract**
Run: `tests/quickshell/panama-doctor-contract.sh` Run: `tests/quickshell/panama-doctor-contract`
Expected: `panama doctor contract: PASS`. Expected: `panama doctor contract: PASS`.
- [ ] **Step 5: Commit the read-only engine** - [ ] **Step 5: Commit the read-only engine**
```bash ```bash
git add config/dot/quickshell/scripts/panama-doctor tests/quickshell/panama-doctor-contract.sh tests/quickshell/fixtures/doctor git add config/dot/quickshell/scripts/panama-doctor tests/quickshell/panama-doctor-contract tests/quickshell/fixtures/doctor
git commit -m "Add Panama system health diagnostics" git commit -m "Add Panama system health diagnostics"
``` ```
@@ -211,7 +211,7 @@ git commit -m "Add Panama system health diagnostics"
**Files:** **Files:**
- Create: `config/dot/quickshell/services/Health.qml` - Create: `config/dot/quickshell/services/Health.qml`
- Create: `config/dot/quickshell/health-harness.qml` - Create: `config/dot/quickshell/health-harness.qml`
- Create: `tests/quickshell/health-service-contract.sh` - Create: `tests/quickshell/health-service-contract`
- Modify: `config/dot/quickshell/shell.qml` - Modify: `config/dot/quickshell/shell.qml`
**Interfaces:** **Interfaces:**
@@ -232,7 +232,7 @@ Assert that a valid warning snapshot is accepted, an older generation is ignored
- [ ] **Step 2: Run the contract and verify it fails** - [ ] **Step 2: Run the contract and verify it fails**
Run: `tests/quickshell/health-service-contract.sh` Run: `tests/quickshell/health-service-contract`
Expected: FAIL because `Health.qml` and the harness do not exist. Expected: FAIL because `Health.qml` and the harness do not exist.
@@ -265,8 +265,8 @@ The `health` IPC `status()` returns only the already-redacted summary, busy flag
Run: Run:
```bash ```bash
tests/quickshell/health-service-contract.sh tests/quickshell/health-service-contract
tests/quickshell/settings-window-contract.sh tests/quickshell/settings-window-contract
``` ```
Expected: both PASS. Expected: both PASS.
@@ -274,7 +274,7 @@ Expected: both PASS.
- [ ] **Step 5: Commit the service layer** - [ ] **Step 5: Commit the service layer**
```bash ```bash
git add config/dot/quickshell/services/Health.qml config/dot/quickshell/health-harness.qml tests/quickshell/health-service-contract.sh config/dot/quickshell/shell.qml git add config/dot/quickshell/services/Health.qml config/dot/quickshell/health-harness.qml tests/quickshell/health-service-contract config/dot/quickshell/shell.qml
git commit -m "Add Panama health state service" git commit -m "Add Panama health state service"
``` ```
@@ -288,9 +288,9 @@ git commit -m "Add Panama health state service"
- Modify: `config/dot/quickshell/modules/settings/SettingsSidebar.qml` - Modify: `config/dot/quickshell/modules/settings/SettingsSidebar.qml`
- Modify: `config/dot/quickshell/services/SettingsSearch.qml` - Modify: `config/dot/quickshell/services/SettingsSearch.qml`
- Delete: `config/dot/quickshell/modules/settings/ServicesPage.qml` - Delete: `config/dot/quickshell/modules/settings/ServicesPage.qml`
- Create: `tests/quickshell/health-ui-contract.sh` - Create: `tests/quickshell/health-ui-contract`
- Modify: `tests/quickshell/settings-pages-contract.sh` - Modify: `tests/quickshell/settings-pages-contract`
- Modify: `tests/quickshell/settings-search-contract.sh` - Modify: `tests/quickshell/settings-search-contract`
**Interfaces:** **Interfaces:**
- Consumes: all read-only state and methods from `Health.qml`; route remains the stable internal name `services`. - Consumes: all read-only state and methods from `Health.qml`; route remains the stable internal name `services`.
@@ -315,9 +315,9 @@ The runtime harness must prove warning rows appear before healthy groups, unconf
Run: Run:
```bash ```bash
tests/quickshell/health-ui-contract.sh tests/quickshell/health-ui-contract
tests/quickshell/settings-pages-contract.sh tests/quickshell/settings-pages-contract
tests/quickshell/settings-search-contract.sh tests/quickshell/settings-search-contract
``` ```
Expected: FAIL because the approved Health components are absent. Expected: FAIL because the approved Health components are absent.
@@ -344,9 +344,9 @@ The sidebar footer is a 54 px `TapHandler` target with status text derived from
Run: Run:
```bash ```bash
tests/quickshell/health-ui-contract.sh tests/quickshell/health-ui-contract
tests/quickshell/settings-pages-contract.sh tests/quickshell/settings-pages-contract
tests/quickshell/settings-search-contract.sh tests/quickshell/settings-search-contract
``` ```
Expected: all PASS with zero QML warnings. Expected: all PASS with zero QML warnings.
@@ -354,7 +354,7 @@ Expected: all PASS with zero QML warnings.
- [ ] **Step 5: Commit the Settings experience** - [ ] **Step 5: Commit the Settings experience**
```bash ```bash
git add config/dot/quickshell/modules/settings config/dot/quickshell/services/SettingsSearch.qml tests/quickshell/health-ui-contract.sh tests/quickshell/settings-pages-contract.sh tests/quickshell/settings-search-contract.sh git add config/dot/quickshell/modules/settings config/dot/quickshell/services/SettingsSearch.qml tests/quickshell/health-ui-contract tests/quickshell/settings-pages-contract tests/quickshell/settings-search-contract
git commit -m "Build the System Health settings page" git commit -m "Build the System Health settings page"
``` ```
@@ -363,11 +363,11 @@ git commit -m "Build the System Health settings page"
**Files:** **Files:**
- Create: `config/dot/quickshell/modules/bar/HealthIndicator.qml` - Create: `config/dot/quickshell/modules/bar/HealthIndicator.qml`
- Modify: `config/dot/quickshell/modules/bar/Bar.qml` - Modify: `config/dot/quickshell/modules/bar/Bar.qml`
- Create: `config/local/share/vicinae/scripts/check-system-health.sh` - Create: `config/local/share/vicinae/scripts/check-system-health`
- Modify: `config/dot/quickshell/scripts/panama-action` - Modify: `config/dot/quickshell/scripts/panama-action`
- Modify: `tests/quickshell/health-ui-contract.sh` - Modify: `tests/quickshell/health-ui-contract`
- Modify: `tests/quickshell/panama-action-contract.sh` - Modify: `tests/quickshell/panama-action-contract`
- Modify: `tests/quickshell/panama-commands-contract.sh` - Modify: `tests/quickshell/panama-commands-contract`
**Interfaces:** **Interfaces:**
- Consumes: `Health.actionable`, `Health.status`, and `Health.summary`; existing `panama-action` dispatcher and Settings IPC. - Consumes: `Health.actionable`, `Health.status`, and `Health.summary`; existing `panama-action` dispatcher and Settings IPC.
@@ -379,8 +379,8 @@ Assert the indicator is absent for healthy/unconfigured-only fixtures, visible a
```text ```text
panama-action health -> qs ipc call health open panama-action health -> qs ipc call health open
check-system-health.sh title -> Panama: Check System Health check-system-health title -> Panama: Check System Health
check-system-health.sh exec -> $HOME/.config/quickshell/scripts/panama-action health check-system-health exec -> $HOME/.config/quickshell/scripts/panama-action health
``` ```
- [ ] **Step 2: Run focused tests and verify failure** - [ ] **Step 2: Run focused tests and verify failure**
@@ -388,9 +388,9 @@ check-system-health.sh exec -> $HOME/.config/quickshell/scripts/panama-action he
Run: Run:
```bash ```bash
tests/quickshell/health-ui-contract.sh tests/quickshell/health-ui-contract
tests/quickshell/panama-action-contract.sh tests/quickshell/panama-action-contract
tests/quickshell/panama-commands-contract.sh tests/quickshell/panama-commands-contract
``` ```
Expected: FAIL on the missing indicator and command. Expected: FAIL on the missing indicator and command.
@@ -416,7 +416,7 @@ Expected: all PASS; command count increases from 17 to 18.
- [ ] **Step 5: Commit the entry points** - [ ] **Step 5: Commit the entry points**
```bash ```bash
git add config/dot/quickshell/modules/bar config/local/share/vicinae/scripts/check-system-health.sh config/dot/quickshell/scripts/panama-action tests/quickshell git add config/dot/quickshell/modules/bar config/local/share/vicinae/scripts/check-system-health config/dot/quickshell/scripts/panama-action tests/quickshell
git commit -m "Add quiet System Health entry points" git commit -m "Add quiet System Health entry points"
``` ```
@@ -424,11 +424,11 @@ git commit -m "Add quiet System Health entry points"
**Files:** **Files:**
- Modify: `config/dot/quickshell/scripts/panama-doctor` - Modify: `config/dot/quickshell/scripts/panama-doctor`
- Modify: `tests/quickshell/panama-doctor-contract.sh` - Modify: `tests/quickshell/panama-doctor-contract`
- Modify: `config/dot/quickshell/services/Health.qml` - Modify: `config/dot/quickshell/services/Health.qml`
- Modify: `tests/quickshell/health-service-contract.sh` - Modify: `tests/quickshell/health-service-contract`
- Modify: `config/dot/quickshell/modules/settings/HealthCheckRow.qml` - Modify: `config/dot/quickshell/modules/settings/HealthCheckRow.qml`
- Modify: `tests/quickshell/health-ui-contract.sh` - Modify: `tests/quickshell/health-ui-contract`
**Interfaces:** **Interfaces:**
- Consumes: the fixed repair matrix in this plan and current accepted checks from `Health.qml`. - Consumes: the fixed repair matrix in this plan and current accepted checks from `Health.qml`.
@@ -454,8 +454,8 @@ For runtime links, fixtures must prove only these link names are eligible: `hypr
Run: Run:
```bash ```bash
tests/quickshell/panama-doctor-contract.sh tests/quickshell/panama-doctor-contract
tests/quickshell/health-service-contract.sh tests/quickshell/health-service-contract
``` ```
Expected: FAIL because `--repair` is not implemented. Expected: FAIL because `--repair` is not implemented.
@@ -482,9 +482,9 @@ Handle runtime links, Vicinae command linking, and duplicate inhibitors in dedic
Run: Run:
```bash ```bash
tests/quickshell/panama-doctor-contract.sh tests/quickshell/panama-doctor-contract
tests/quickshell/health-service-contract.sh tests/quickshell/health-service-contract
tests/quickshell/health-ui-contract.sh tests/quickshell/health-ui-contract
``` ```
Expected: all PASS. Expected: all PASS.
@@ -533,11 +533,11 @@ Run:
```bash ```bash
python3 -m py_compile config/dot/quickshell/scripts/panama-doctor python3 -m py_compile config/dot/quickshell/scripts/panama-doctor
bash -n config/dot/quickshell/scripts/panama-action bash -n config/dot/quickshell/scripts/panama-action
tests/quickshell/panama-doctor-contract.sh tests/quickshell/panama-doctor-contract
tests/quickshell/health-service-contract.sh tests/quickshell/health-service-contract
tests/quickshell/health-ui-contract.sh tests/quickshell/health-ui-contract
for test in tests/quickshell/*contract.sh; do "$test"; done for test in tests/quickshell/*contract; do "$test"; done
for test in tests/hypr/*contract.sh; do "$test"; done for test in tests/hypr/*contract; do "$test"; done
``` ```
Expected: every command exits 0. After the latest Settings and installer work, Expected: every command exits 0. After the latest Settings and installer work,
@@ -25,7 +25,7 @@
**Files:** **Files:**
- Create: `config/dot/quickshell/services/AudioStreams.js` - Create: `config/dot/quickshell/services/AudioStreams.js`
- Create: `config/dot/quickshell/audio-streams-harness.qml` - Create: `config/dot/quickshell/audio-streams-harness.qml`
- Create: `tests/quickshell/application-volume-contract.sh` - Create: `tests/quickshell/application-volume-contract`
**Interfaces:** **Interfaces:**
- Consumes: PipeWire-shaped nodes with `id`, `ready`, `type`, `properties`, and `audio`. - Consumes: PipeWire-shaped nodes with `id`, `ready`, `type`, `properties`, and `audio`.
@@ -47,7 +47,7 @@ Also assert Chromium volume `0.6` from fixture values `0.4` and `0.8`, mixed mut
- [ ] **Step 2: Run the contract and verify RED** - [ ] **Step 2: Run the contract and verify RED**
Run: `tests/quickshell/application-volume-contract.sh` Run: `tests/quickshell/application-volume-contract`
Expected: FAIL because `AudioStreams.js` and the IPC target do not exist. Expected: FAIL because `AudioStreams.js` and the IPC target do not exist.
@@ -134,14 +134,14 @@ Use literal property lookups and `Number.isFinite`; do not import PipeWire into
- [ ] **Step 4: Run the contract and verify GREEN** - [ ] **Step 4: Run the contract and verify GREEN**
Run: `tests/quickshell/application-volume-contract.sh` Run: `tests/quickshell/application-volume-contract`
Expected: PASS for grouping, fallback metadata, aggregate volume, mixed mute, and writes. Expected: PASS for grouping, fallback metadata, aggregate volume, mixed mute, and writes.
- [ ] **Step 5: Commit the model** - [ ] **Step 5: Commit the model**
```bash ```bash
git add config/dot/quickshell/services/AudioStreams.js config/dot/quickshell/audio-streams-harness.qml tests/quickshell/application-volume-contract.sh git add config/dot/quickshell/services/AudioStreams.js config/dot/quickshell/audio-streams-harness.qml tests/quickshell/application-volume-contract
git commit -m "Model live application audio streams" git commit -m "Model live application audio streams"
``` ```
@@ -150,7 +150,7 @@ git commit -m "Model live application audio streams"
**Files:** **Files:**
- Modify: `config/dot/quickshell/services/AudioDevices.qml` - Modify: `config/dot/quickshell/services/AudioDevices.qml`
- Modify: `config/dot/quickshell/audio-streams-harness.qml` - Modify: `config/dot/quickshell/audio-streams-harness.qml`
- Modify: `tests/quickshell/application-volume-contract.sh` - Modify: `tests/quickshell/application-volume-contract`
**Interfaces:** **Interfaces:**
- Consumes: `AudioStreams.group(nodes, PwNodeType.AudioOutStream)`. - Consumes: `AudioStreams.group(nodes, PwNodeType.AudioOutStream)`.
@@ -162,7 +162,7 @@ Assert the harness can report real `AudioDevices.applications` without starting
- [ ] **Step 2: Run and verify RED** - [ ] **Step 2: Run and verify RED**
Run: `tests/quickshell/application-volume-contract.sh` Run: `tests/quickshell/application-volume-contract`
Expected: FAIL because `AudioDevices.applications` is undefined. Expected: FAIL because `AudioDevices.applications` is undefined.
@@ -181,14 +181,14 @@ Delegate aggregate reads and writes to the pure model. Preserve `outputs`, `inpu
- [ ] **Step 4: Run and verify GREEN** - [ ] **Step 4: Run and verify GREEN**
Run: `tests/quickshell/application-volume-contract.sh` Run: `tests/quickshell/application-volume-contract`
Expected: PASS with zero or more real live applications and no mutation of the live streams. Expected: PASS with zero or more real live applications and no mutation of the live streams.
- [ ] **Step 5: Commit the service boundary** - [ ] **Step 5: Commit the service boundary**
```bash ```bash
git add config/dot/quickshell/services/AudioDevices.qml config/dot/quickshell/audio-streams-harness.qml tests/quickshell/application-volume-contract.sh git add config/dot/quickshell/services/AudioDevices.qml config/dot/quickshell/audio-streams-harness.qml tests/quickshell/application-volume-contract
git commit -m "Expose live application audio groups" git commit -m "Expose live application audio groups"
``` ```
@@ -198,8 +198,8 @@ git commit -m "Expose live application audio groups"
- Create: `config/dot/quickshell/modules/settings/ApplicationVolumeRow.qml` - Create: `config/dot/quickshell/modules/settings/ApplicationVolumeRow.qml`
- Create: `config/dot/quickshell/modules/settings/ApplicationMixer.qml` - Create: `config/dot/quickshell/modules/settings/ApplicationMixer.qml`
- Modify: `config/dot/quickshell/modules/settings/SoundPage.qml` - Modify: `config/dot/quickshell/modules/settings/SoundPage.qml`
- Modify: `tests/quickshell/application-volume-contract.sh` - Modify: `tests/quickshell/application-volume-contract`
- Modify: `tests/quickshell/sound-page-contract.sh` - Modify: `tests/quickshell/sound-page-contract`
**Interfaces:** **Interfaces:**
- Consumes: one `AudioDevices.applications` group per row. - Consumes: one `AudioDevices.applications` group per row.
@@ -211,7 +211,7 @@ Construct `SoundPage.qml` in the existing isolated Settings harness. Assert no Q
- [ ] **Step 2: Run and verify RED** - [ ] **Step 2: Run and verify RED**
Run: `tests/quickshell/application-volume-contract.sh && tests/quickshell/sound-page-contract.sh` Run: `tests/quickshell/application-volume-contract && tests/quickshell/sound-page-contract`
Expected: FAIL because the mixer components and Applications card are absent. Expected: FAIL because the mixer components and Applications card are absent.
@@ -221,14 +221,14 @@ Expected: FAIL because the mixer components and Applications card are absent.
- [ ] **Step 4: Run and verify GREEN** - [ ] **Step 4: Run and verify GREEN**
Run: `tests/quickshell/application-volume-contract.sh && tests/quickshell/sound-page-contract.sh` Run: `tests/quickshell/application-volume-contract && tests/quickshell/sound-page-contract`
Expected: PASS with no QML warnings. Expected: PASS with no QML warnings.
- [ ] **Step 5: Commit the finished application mixer** - [ ] **Step 5: Commit the finished application mixer**
```bash ```bash
git add config/dot/quickshell/modules/settings/ApplicationVolumeRow.qml config/dot/quickshell/modules/settings/ApplicationMixer.qml config/dot/quickshell/modules/settings/SoundPage.qml tests/quickshell/application-volume-contract.sh tests/quickshell/sound-page-contract.sh git add config/dot/quickshell/modules/settings/ApplicationVolumeRow.qml config/dot/quickshell/modules/settings/ApplicationMixer.qml config/dot/quickshell/modules/settings/SoundPage.qml tests/quickshell/application-volume-contract tests/quickshell/sound-page-contract
git commit -m "Add application volume mixer" git commit -m "Add application volume mixer"
``` ```
@@ -242,9 +242,9 @@ git commit -m "Add application volume mixer"
Run: Run:
```bash ```bash
tests/quickshell/application-volume-contract.sh tests/quickshell/application-volume-contract
tests/quickshell/sound-page-contract.sh tests/quickshell/sound-page-contract
tests/quickshell/settings-pages-contract.sh tests/quickshell/settings-pages-contract
``` ```
Expected: all PASS; runtime enumeration may report zero applications without failing. Expected: all PASS; runtime enumeration may report zero applications without failing.
@@ -26,7 +26,7 @@
**Files:** **Files:**
- Create: `config/dot/quickshell/services/DisplayLayout.js` - Create: `config/dot/quickshell/services/DisplayLayout.js`
- Create: `config/dot/quickshell/display-layout-harness.qml` - Create: `config/dot/quickshell/display-layout-harness.qml`
- Create: `tests/quickshell/display-layout-contract.sh` - Create: `tests/quickshell/display-layout-contract`
**Interfaces:** **Interfaces:**
- Consumes: records `{name,width,height,scale,transform,x,y,primary}`. - Consumes: records `{name,width,height,scale,transform,x,y,primary}`.
@@ -47,7 +47,7 @@ Assert transformed logical sizes, normalized DP-2 position `0,0`, normalized HDM
- [ ] **Step 2: Run and verify RED** - [ ] **Step 2: Run and verify RED**
Run: `tests/quickshell/display-layout-contract.sh` Run: `tests/quickshell/display-layout-contract`
Expected: FAIL because the geometry module and harness do not exist. Expected: FAIL because the geometry module and harness do not exist.
@@ -71,14 +71,14 @@ Assert rejection of duplicate outputs, zero or two primaries, fractional coordin
- [ ] **Step 5: Run and verify GREEN** - [ ] **Step 5: Run and verify GREEN**
Run: `tests/quickshell/display-layout-contract.sh` Run: `tests/quickshell/display-layout-contract`
Expected: PASS for geometry, deterministic snapping, normalization, and invalid cases. Expected: PASS for geometry, deterministic snapping, normalization, and invalid cases.
- [ ] **Step 6: Commit layout geometry** - [ ] **Step 6: Commit layout geometry**
```bash ```bash
git add config/dot/quickshell/services/DisplayLayout.js config/dot/quickshell/display-layout-harness.qml tests/quickshell/display-layout-contract.sh git add config/dot/quickshell/services/DisplayLayout.js config/dot/quickshell/display-layout-harness.qml tests/quickshell/display-layout-contract
git commit -m "Model multi-monitor layout geometry" git commit -m "Model multi-monitor layout geometry"
``` ```
@@ -89,8 +89,8 @@ git commit -m "Model multi-monitor layout geometry"
- Modify: `config/dot/quickshell/displays-harness.qml` - Modify: `config/dot/quickshell/displays-harness.qml`
- Modify: `config/dot/hypr/monitors.lua` - Modify: `config/dot/hypr/monitors.lua`
- Modify: `config/dot/quickshell/config/PreferenceSchema.qml` - Modify: `config/dot/quickshell/config/PreferenceSchema.qml`
- Modify: `tests/quickshell/displays-contract.sh` - Modify: `tests/quickshell/displays-contract`
- Modify: `tests/quickshell/settings-preferences-contract.sh` - Modify: `tests/quickshell/settings-preferences-contract`
**Interfaces:** **Interfaces:**
- Consumes: `hyprctl -j monitors` x/y values and backward-compatible persisted entries. - Consumes: `hyprctl -j monitors` x/y values and backward-compatible persisted entries.
@@ -111,7 +111,7 @@ Assert only one valid persisted primary is honored and DP-2's 10-bit/color polic
- [ ] **Step 2: Run and verify RED** - [ ] **Step 2: Run and verify RED**
Run: `PANAMA_DISPLAYS_STATIC_ONLY=1 tests/quickshell/displays-contract.sh` Run: `PANAMA_DISPLAYS_STATIC_ONLY=1 tests/quickshell/displays-contract`
Expected: FAIL because x/y/primary are neither parsed nor replayed. Expected: FAIL because x/y/primary are neither parsed nor replayed.
@@ -129,14 +129,14 @@ Change the internal `displays` detail to **Resolution, scale, rotation, position
- [ ] **Step 6: Run and verify GREEN** - [ ] **Step 6: Run and verify GREEN**
Run: `PANAMA_DISPLAYS_STATIC_ONLY=1 tests/quickshell/displays-contract.sh && tests/quickshell/settings-preferences-contract.sh` Run: `PANAMA_DISPLAYS_STATIC_ONLY=1 tests/quickshell/displays-contract && tests/quickshell/settings-preferences-contract`
Expected: PASS for old and new records. Expected: PASS for old and new records.
- [ ] **Step 7: Commit extended persistence** - [ ] **Step 7: Commit extended persistence**
```bash ```bash
git add config/dot/quickshell/services/Displays.qml config/dot/quickshell/displays-harness.qml config/dot/hypr/monitors.lua config/dot/quickshell/config/PreferenceSchema.qml tests/quickshell/displays-contract.sh tests/quickshell/settings-preferences-contract.sh git add config/dot/quickshell/services/Displays.qml config/dot/quickshell/displays-harness.qml config/dot/hypr/monitors.lua config/dot/quickshell/config/PreferenceSchema.qml tests/quickshell/displays-contract tests/quickshell/settings-preferences-contract
git commit -m "Persist complete monitor layouts" git commit -m "Persist complete monitor layouts"
``` ```
@@ -145,8 +145,8 @@ git commit -m "Persist complete monitor layouts"
**Files:** **Files:**
- Modify: `config/dot/quickshell/services/Displays.qml` - Modify: `config/dot/quickshell/services/Displays.qml`
- Modify: `config/dot/quickshell/displays-harness.qml` - Modify: `config/dot/quickshell/displays-harness.qml`
- Modify: `tests/quickshell/displays-contract.sh` - Modify: `tests/quickshell/displays-contract`
- Create: `tests/quickshell/display-transaction-contract.sh` - Create: `tests/quickshell/display-transaction-contract`
**Interfaces:** **Interfaces:**
- Consumes: `DisplayLayout.validate/normalize` and complete current monitor records. - Consumes: `DisplayLayout.validate/normalize` and complete current monitor records.
@@ -162,7 +162,7 @@ Assert timeout, explicit revert, non-zero apply exit, wrong readback, and a disc
- [ ] **Step 3: Run and verify RED** - [ ] **Step 3: Run and verify RED**
Run: `tests/quickshell/display-transaction-contract.sh` Run: `tests/quickshell/display-transaction-contract`
Expected: FAIL because `Displays.qml` tracks only one output per operation. Expected: FAIL because `Displays.qml` tracks only one output per operation.
@@ -195,14 +195,14 @@ Keep `apply(output, mode, scale, transform)` by cloning `currentLayout()`, repla
- [ ] **Step 7: Run and verify GREEN** - [ ] **Step 7: Run and verify GREEN**
Run: `tests/quickshell/display-transaction-contract.sh && PANAMA_DISPLAYS_STATIC_ONLY=1 tests/quickshell/displays-contract.sh` Run: `tests/quickshell/display-transaction-contract && PANAMA_DISPLAYS_STATIC_ONLY=1 tests/quickshell/displays-contract`
Expected: PASS for apply, confirm, timeout, all revert paths, disconnect, and stale generations. Expected: PASS for apply, confirm, timeout, all revert paths, disconnect, and stale generations.
- [ ] **Step 8: Commit safe transactions** - [ ] **Step 8: Commit safe transactions**
```bash ```bash
git add config/dot/quickshell/services/Displays.qml config/dot/quickshell/displays-harness.qml tests/quickshell/displays-contract.sh tests/quickshell/display-transaction-contract.sh git add config/dot/quickshell/services/Displays.qml config/dot/quickshell/displays-harness.qml tests/quickshell/displays-contract tests/quickshell/display-transaction-contract
git commit -m "Apply monitor layouts transactionally" git commit -m "Apply monitor layouts transactionally"
``` ```
@@ -211,8 +211,8 @@ git commit -m "Apply monitor layouts transactionally"
**Files:** **Files:**
- Create: `config/dot/quickshell/modules/settings/DisplayArrangement.qml` - Create: `config/dot/quickshell/modules/settings/DisplayArrangement.qml`
- Modify: `config/dot/quickshell/modules/settings/DisplaysPage.qml` - Modify: `config/dot/quickshell/modules/settings/DisplaysPage.qml`
- Create: `tests/quickshell/display-arrangement-contract.sh` - Create: `tests/quickshell/display-arrangement-contract`
- Modify: `tests/quickshell/settings-pages-contract.sh` - Modify: `tests/quickshell/settings-pages-contract`
**Interfaces:** **Interfaces:**
- Consumes: `Displays.currentLayout()`, `Displays.applyLayout()`, `Displays.makePrimary()`, and `DisplayLayout.canvasRects/snap`. - Consumes: `Displays.currentLayout()`, `Displays.applyLayout()`, `Displays.makePrimary()`, and `DisplayLayout.canvasRects/snap`.
@@ -224,7 +224,7 @@ Render two literal monitors at wide and 500 px content widths. Through harness I
- [ ] **Step 2: Run and verify RED** - [ ] **Step 2: Run and verify RED**
Run: `tests/quickshell/display-arrangement-contract.sh` Run: `tests/quickshell/display-arrangement-contract`
Expected: FAIL because no arrangement component exists. Expected: FAIL because no arrangement component exists.
@@ -242,14 +242,14 @@ Show the card only for two or more monitors. Keep the existing connected-display
- [ ] **Step 6: Run and verify GREEN** - [ ] **Step 6: Run and verify GREEN**
Run: `tests/quickshell/display-arrangement-contract.sh && PANAMA_DISPLAYS_STATIC_ONLY=1 tests/quickshell/displays-contract.sh && tests/quickshell/settings-pages-contract.sh` Run: `tests/quickshell/display-arrangement-contract && PANAMA_DISPLAYS_STATIC_ONLY=1 tests/quickshell/displays-contract && tests/quickshell/settings-pages-contract`
Expected: PASS at both widths with no QML warnings. Expected: PASS at both widths with no QML warnings.
- [ ] **Step 7: Commit the canvas** - [ ] **Step 7: Commit the canvas**
```bash ```bash
git add config/dot/quickshell/modules/settings/DisplayArrangement.qml config/dot/quickshell/modules/settings/DisplaysPage.qml tests/quickshell/display-arrangement-contract.sh tests/quickshell/settings-pages-contract.sh git add config/dot/quickshell/modules/settings/DisplayArrangement.qml config/dot/quickshell/modules/settings/DisplaysPage.qml tests/quickshell/display-arrangement-contract tests/quickshell/settings-pages-contract
git commit -m "Add monitor arrangement canvas" git commit -m "Add monitor arrangement canvas"
``` ```
@@ -259,7 +259,7 @@ git commit -m "Add monitor arrangement canvas"
- Create: `config/dot/quickshell/modules/settings/DisplayIdentify.qml` - Create: `config/dot/quickshell/modules/settings/DisplayIdentify.qml`
- Modify: `config/dot/quickshell/modules/settings/DisplayArrangement.qml` - Modify: `config/dot/quickshell/modules/settings/DisplayArrangement.qml`
- Modify: `config/dot/quickshell/shell.qml` - Modify: `config/dot/quickshell/shell.qml`
- Modify: `tests/quickshell/display-arrangement-contract.sh` - Modify: `tests/quickshell/display-arrangement-contract`
**Interfaces:** **Interfaces:**
- Consumes: `Displays.identifying` and each `Quickshell.screens` entry. - Consumes: `Displays.identifying` and each `Quickshell.screens` entry.
@@ -271,7 +271,7 @@ Invoke identify through the fixture harness. Assert screen 1 renders connector/n
- [ ] **Step 2: Run and verify RED** - [ ] **Step 2: Run and verify RED**
Run: `tests/quickshell/display-arrangement-contract.sh` Run: `tests/quickshell/display-arrangement-contract`
Expected: FAIL because identify state and overlays do not exist. Expected: FAIL because identify state and overlays do not exist.
@@ -281,14 +281,14 @@ Expected: FAIL because identify state and overlays do not exist.
- [ ] **Step 4: Run and verify GREEN** - [ ] **Step 4: Run and verify GREEN**
Run: `tests/quickshell/display-arrangement-contract.sh` Run: `tests/quickshell/display-arrangement-contract`
Expected: PASS with a fixed window count and no focus-grab warnings. Expected: PASS with a fixed window count and no focus-grab warnings.
- [ ] **Step 5: Commit identification** - [ ] **Step 5: Commit identification**
```bash ```bash
git add config/dot/quickshell/modules/settings/DisplayIdentify.qml config/dot/quickshell/modules/settings/DisplayArrangement.qml config/dot/quickshell/shell.qml tests/quickshell/display-arrangement-contract.sh git add config/dot/quickshell/modules/settings/DisplayIdentify.qml config/dot/quickshell/modules/settings/DisplayArrangement.qml config/dot/quickshell/shell.qml tests/quickshell/display-arrangement-contract
git commit -m "Add display identification overlays" git commit -m "Add display identification overlays"
``` ```
@@ -298,10 +298,10 @@ git commit -m "Add display identification overlays"
- Modify: `config/dot/quickshell/services/SettingsSearch.qml` - Modify: `config/dot/quickshell/services/SettingsSearch.qml`
- Modify: `config/dot/quickshell/services/SettingsBackup.qml` - Modify: `config/dot/quickshell/services/SettingsBackup.qml`
- Modify: `config/dot/quickshell/modules/settings/README.md` - Modify: `config/dot/quickshell/modules/settings/README.md`
- Modify: `tests/quickshell/settings-search-contract.sh` - Modify: `tests/quickshell/settings-search-contract`
- Modify: `tests/quickshell/settings-backup-live-contract.sh` - Modify: `tests/quickshell/settings-backup-live-contract`
- Modify: `tests/quickshell/settings-commit-reset-contract.sh` - Modify: `tests/quickshell/settings-commit-reset-contract`
- Modify: `tests/quickshell/settings-ownership-contract.sh` - Modify: `tests/quickshell/settings-ownership-contract`
**Interfaces:** **Interfaces:**
- Consumes: the existing internal `displays` preference and complete-layout transaction. - Consumes: the existing internal `displays` preference and complete-layout transaction.
@@ -313,7 +313,7 @@ Assert **arrange displays**, **monitor position**, and **primary display** route
- [ ] **Step 2: Run and verify RED** - [ ] **Step 2: Run and verify RED**
Run: `tests/quickshell/settings-search-contract.sh && tests/quickshell/settings-backup-live-contract.sh && tests/quickshell/settings-commit-reset-contract.sh` Run: `tests/quickshell/settings-search-contract && tests/quickshell/settings-backup-live-contract && tests/quickshell/settings-commit-reset-contract`
Expected: FAIL for missing terms and one-output restore assumptions. Expected: FAIL for missing terms and one-output restore assumptions.
@@ -327,14 +327,14 @@ Document Displays as the sole owner of mode, scale, rotation, arrangement, and p
- [ ] **Step 5: Run and verify GREEN** - [ ] **Step 5: Run and verify GREEN**
Run: `tests/quickshell/settings-search-contract.sh && tests/quickshell/settings-backup-live-contract.sh && tests/quickshell/settings-commit-reset-contract.sh && tests/quickshell/settings-ownership-contract.sh` Run: `tests/quickshell/settings-search-contract && tests/quickshell/settings-backup-live-contract && tests/quickshell/settings-commit-reset-contract && tests/quickshell/settings-ownership-contract`
Expected: PASS with no new duplicated controls. Expected: PASS with no new duplicated controls.
- [ ] **Step 6: Commit integration** - [ ] **Step 6: Commit integration**
```bash ```bash
git add config/dot/quickshell/services/SettingsSearch.qml config/dot/quickshell/services/SettingsBackup.qml config/dot/quickshell/modules/settings/README.md tests/quickshell/settings-search-contract.sh tests/quickshell/settings-backup-live-contract.sh tests/quickshell/settings-commit-reset-contract.sh tests/quickshell/settings-ownership-contract.sh git add config/dot/quickshell/services/SettingsSearch.qml config/dot/quickshell/services/SettingsBackup.qml config/dot/quickshell/modules/settings/README.md tests/quickshell/settings-search-contract tests/quickshell/settings-backup-live-contract tests/quickshell/settings-commit-reset-contract tests/quickshell/settings-ownership-contract
git commit -m "Integrate complete display layouts" git commit -m "Integrate complete display layouts"
``` ```
@@ -343,12 +343,12 @@ git commit -m "Integrate complete display layouts"
- [ ] **Step 1: Run all static display contracts** - [ ] **Step 1: Run all static display contracts**
```bash ```bash
tests/quickshell/display-layout-contract.sh tests/quickshell/display-layout-contract
tests/quickshell/display-transaction-contract.sh tests/quickshell/display-transaction-contract
tests/quickshell/display-arrangement-contract.sh tests/quickshell/display-arrangement-contract
PANAMA_DISPLAYS_STATIC_ONLY=1 tests/quickshell/displays-contract.sh PANAMA_DISPLAYS_STATIC_ONLY=1 tests/quickshell/displays-contract
tests/quickshell/settings-search-contract.sh tests/quickshell/settings-search-contract
tests/quickshell/settings-backup-live-contract.sh tests/quickshell/settings-backup-live-contract
``` ```
Expected: all PASS without touching the physical display. Expected: all PASS without touching the physical display.
@@ -361,7 +361,7 @@ Expected: `config ok`.
- [ ] **Step 3: Defer the live display test** - [ ] **Step 3: Defer the live display test**
Do not run the state-changing portion of `tests/quickshell/displays-contract.sh` here. The master Phase 2 completion gate runs it once after every slice is stable and restores the observed mode, scale, transform, and position. Do not run the state-changing portion of `tests/quickshell/displays-contract` here. The master Phase 2 completion gate runs it once after every slice is stable and restores the observed mode, scale, transform, and position.
- [ ] **Step 4: Review branch state** - [ ] **Step 4: Review branch state**
@@ -58,7 +58,7 @@ Use strict red-green-refactor cycles and the exact commit boundaries in that pla
- [ ] **Step 3: Confirm the slice head** - [ ] **Step 3: Confirm the slice head**
Run: `tests/quickshell/application-volume-contract.sh && tests/quickshell/sound-page-contract.sh && git status --short` Run: `tests/quickshell/application-volume-contract && tests/quickshell/sound-page-contract && git status --short`
Expected: both PASS and no uncommitted files. Expected: both PASS and no uncommitted files.
@@ -80,7 +80,7 @@ Never invoke `panama-lock run` outside its fake-hyprlock fixture.
- [ ] **Step 3: Confirm the slice head** - [ ] **Step 3: Confirm the slice head**
Run: `tests/quickshell/lock-screen-helper-contract.sh && tests/quickshell/lock-screen-service-contract.sh && tests/quickshell/lock-screen-settings-contract.sh && git status --short` Run: `tests/quickshell/lock-screen-helper-contract && tests/quickshell/lock-screen-service-contract && tests/quickshell/lock-screen-settings-contract && git status --short`
Expected: all PASS, no live `hyprlock` test process, and no uncommitted files. Expected: all PASS, no live `hyprlock` test process, and no uncommitted files.
@@ -102,7 +102,7 @@ All apply tests use fake hyprpaper IPC and temporary image files.
- [ ] **Step 3: Confirm the slice head** - [ ] **Step 3: Confirm the slice head**
Run: `tests/quickshell/wallpaper-policy-contract.sh && tests/quickshell/wallpaper-service-contract.sh && tests/quickshell/wallpaper-settings-contract.sh && git status --short` Run: `tests/quickshell/wallpaper-policy-contract && tests/quickshell/wallpaper-service-contract && tests/quickshell/wallpaper-settings-contract && git status --short`
Expected: all PASS and no uncommitted files. Expected: all PASS and no uncommitted files.
@@ -124,7 +124,7 @@ Use fixture monitor JSON for all multi-monitor cases.
- [ ] **Step 3: Confirm the static slice head** - [ ] **Step 3: Confirm the static slice head**
Run: `tests/quickshell/display-layout-contract.sh && tests/quickshell/display-transaction-contract.sh && tests/quickshell/display-arrangement-contract.sh && PANAMA_DISPLAYS_STATIC_ONLY=1 tests/quickshell/displays-contract.sh && git status --short` Run: `tests/quickshell/display-layout-contract && tests/quickshell/display-transaction-contract && tests/quickshell/display-arrangement-contract && PANAMA_DISPLAYS_STATIC_ONLY=1 tests/quickshell/displays-contract && git status --short`
Expected: all PASS and no uncommitted files. Expected: all PASS and no uncommitted files.
@@ -143,11 +143,11 @@ Expected: all PASS and no uncommitted files.
- [ ] **Step 1: Expand the combined restore fixture before the final audit** - [ ] **Step 1: Expand the combined restore fixture before the final audit**
The slice plans already extend `tests/quickshell/settings-backup-live-contract.sh` test-first. Confirm its final fixture now contains lock, slideshow, and two-output layout values and asserts this exact order: preferences reload, display apply/verify, idle apply, lock generate, wallpaper apply/verify, keybind/compositor settle, shell reload. It must also assert bounded failure remains in service state and shell reload waits for the settle cap. The slice plans already extend `tests/quickshell/settings-backup-live-contract` test-first. Confirm its final fixture now contains lock, slideshow, and two-output layout values and asserts this exact order: preferences reload, display apply/verify, idle apply, lock generate, wallpaper apply/verify, keybind/compositor settle, shell reload. It must also assert bounded failure remains in service state and shell reload waits for the settle cap.
- [ ] **Step 2: Run the combined audit** - [ ] **Step 2: Run the combined audit**
Run: `tests/quickshell/settings-backup-live-contract.sh` Run: `tests/quickshell/settings-backup-live-contract`
Expected: PASS. A failure means the independently green hooks conflict and must be debugged before any consolidation. Expected: PASS. A failure means the independently green hooks conflict and must be debugged before any consolidation.
@@ -161,7 +161,7 @@ Run the ownership contract against final pages. Manual search entries may exist
- [ ] **Step 5: Run and verify GREEN** - [ ] **Step 5: Run and verify GREEN**
Run: `tests/quickshell/settings-backup-live-contract.sh && tests/quickshell/settings-search-contract.sh && tests/quickshell/settings-ownership-contract.sh` Run: `tests/quickshell/settings-backup-live-contract && tests/quickshell/settings-search-contract && tests/quickshell/settings-ownership-contract`
Expected: all PASS. Expected: all PASS.
@@ -177,16 +177,16 @@ If Step 2 or Step 5 required corrections, stage only those files and commit them
- [ ] **Step 1: Run new contracts** - [ ] **Step 1: Run new contracts**
```bash ```bash
tests/quickshell/application-volume-contract.sh tests/quickshell/application-volume-contract
tests/quickshell/lock-screen-helper-contract.sh tests/quickshell/lock-screen-helper-contract
tests/quickshell/lock-screen-service-contract.sh tests/quickshell/lock-screen-service-contract
tests/quickshell/lock-screen-settings-contract.sh tests/quickshell/lock-screen-settings-contract
tests/quickshell/wallpaper-policy-contract.sh tests/quickshell/wallpaper-policy-contract
tests/quickshell/wallpaper-service-contract.sh tests/quickshell/wallpaper-service-contract
tests/quickshell/wallpaper-settings-contract.sh tests/quickshell/wallpaper-settings-contract
tests/quickshell/display-layout-contract.sh tests/quickshell/display-layout-contract
tests/quickshell/display-transaction-contract.sh tests/quickshell/display-transaction-contract
tests/quickshell/display-arrangement-contract.sh tests/quickshell/display-arrangement-contract
``` ```
Expected: all PASS. Expected: all PASS.
@@ -194,23 +194,23 @@ Expected: all PASS.
- [ ] **Step 2: Run affected existing contracts** - [ ] **Step 2: Run affected existing contracts**
```bash ```bash
tests/quickshell/sound-page-contract.sh tests/quickshell/sound-page-contract
tests/quickshell/settings-pages-contract.sh tests/quickshell/settings-pages-contract
tests/quickshell/settings-search-contract.sh tests/quickshell/settings-search-contract
tests/quickshell/settings-ownership-contract.sh tests/quickshell/settings-ownership-contract
tests/quickshell/settings-preferences-contract.sh tests/quickshell/settings-preferences-contract
tests/quickshell/settings-commit-reset-contract.sh tests/quickshell/settings-commit-reset-contract
tests/quickshell/settings-backup-live-contract.sh tests/quickshell/settings-backup-live-contract
tests/quickshell/migrations-contract.sh tests/quickshell/migrations-contract
tests/quickshell/panama-doctor-contract.sh tests/quickshell/panama-doctor-contract
tests/quickshell/schema-hypr-shape-contract.sh tests/quickshell/schema-hypr-shape-contract
``` ```
Expected: all PASS. Expected: all PASS.
- [ ] **Step 3: Run the one state-changing display contract** - [ ] **Step 3: Run the one state-changing display contract**
Run: `tests/quickshell/displays-contract.sh` Run: `tests/quickshell/displays-contract`
Expected: PASS and cleanup proves the physical monitor returns to its captured original mode, scale, transform, x, and y. Stop immediately if the preflight reports a dirty display baseline. Expected: PASS and cleanup proves the physical monitor returns to its captured original mode, scale, transform, x, and y. Stop immediately if the preflight reports a dirty display baseline.
@@ -26,7 +26,7 @@
**Files:** **Files:**
- Modify: `config/dot/quickshell/config/PreferenceSchema.qml` - Modify: `config/dot/quickshell/config/PreferenceSchema.qml`
- Create: `config/dot/quickshell/scripts/panama-lock` - Create: `config/dot/quickshell/scripts/panama-lock`
- Create: `tests/quickshell/lock-screen-helper-contract.sh` - Create: `tests/quickshell/lock-screen-helper-contract`
**Interfaces:** **Interfaces:**
- Consumes: `lockBackgroundMode`, `lockBlurLevel`, `lockShowClock`, `lockShowDate`, `lockShowUser`, `lockFadeOnEmpty`, `use24Hour`, `colorScheme`, and wallpaper policy from `settings.json`. - Consumes: `lockBackgroundMode`, `lockBlurLevel`, `lockShowClock`, `lockShowDate`, `lockShowUser`, `lockFadeOnEmpty`, `use24Hour`, `colorScheme`, and wallpaper policy from `settings.json`.
@@ -50,7 +50,7 @@ For light solid mode assert `rgba(245, 246, 250, 1.0)`. For wallpaper mode with
- [ ] **Step 2: Run and verify RED** - [ ] **Step 2: Run and verify RED**
Run: `tests/quickshell/lock-screen-helper-contract.sh` Run: `tests/quickshell/lock-screen-helper-contract`
Expected: FAIL because `panama-lock` does not exist. Expected: FAIL because `panama-lock` does not exist.
@@ -109,14 +109,14 @@ Seed a valid generated file, force generation failure through an unwritable fixt
- [ ] **Step 6: Run and verify GREEN** - [ ] **Step 6: Run and verify GREEN**
Run: `tests/quickshell/lock-screen-helper-contract.sh` Run: `tests/quickshell/lock-screen-helper-contract`
Expected: PASS for modes, visibility, clock format, validation, atomicity, and fallback. Expected: PASS for modes, visibility, clock format, validation, atomicity, and fallback.
- [ ] **Step 7: Commit the generator** - [ ] **Step 7: Commit the generator**
```bash ```bash
git add config/dot/quickshell/config/PreferenceSchema.qml config/dot/quickshell/scripts/panama-lock tests/quickshell/lock-screen-helper-contract.sh git add config/dot/quickshell/config/PreferenceSchema.qml config/dot/quickshell/scripts/panama-lock tests/quickshell/lock-screen-helper-contract
git commit -m "Generate managed lock screen configuration" git commit -m "Generate managed lock screen configuration"
``` ```
@@ -127,8 +127,8 @@ git commit -m "Generate managed lock screen configuration"
- Modify: `config/dot/quickshell/scripts/panama-idle` - Modify: `config/dot/quickshell/scripts/panama-idle`
- Create: `config/dot/quickshell/services/LockScreen.qml` - Create: `config/dot/quickshell/services/LockScreen.qml`
- Create: `config/dot/quickshell/lock-screen-harness.qml` - Create: `config/dot/quickshell/lock-screen-harness.qml`
- Create: `tests/quickshell/lock-screen-service-contract.sh` - Create: `tests/quickshell/lock-screen-service-contract`
- Modify: `tests/quickshell/lock-screen-helper-contract.sh` - Modify: `tests/quickshell/lock-screen-helper-contract`
**Interfaces:** **Interfaces:**
- Consumes: `panama-lock generate/status` and `DesktopPreferences.revision`. - Consumes: `panama-lock generate/status` and `DesktopPreferences.revision`.
@@ -146,13 +146,13 @@ Through the QML harness, change one lock preference three times inside 250 ms an
- [ ] **Step 2: Run and verify RED** - [ ] **Step 2: Run and verify RED**
Run: `tests/quickshell/lock-screen-service-contract.sh` Run: `tests/quickshell/lock-screen-service-contract`
Expected: FAIL because the idle paths still invoke `hyprlock` directly and the service is absent. Expected: FAIL because the idle paths still invoke `hyprlock` directly and the service is absent.
- [ ] **Step 3: Update shipped and generated hypridle commands** - [ ] **Step 3: Update shipped and generated hypridle commands**
Change only `lock_cmd`; preserve blanking, sleep, and lock timing behavior. Keep both shipped/generated idle-command assertions in `tests/quickshell/lock-screen-service-contract.sh`; this repository has no separate idle-lock contract. Change only `lock_cmd`; preserve blanking, sleep, and lock timing behavior. Keep both shipped/generated idle-command assertions in `tests/quickshell/lock-screen-service-contract`; this repository has no separate idle-lock contract.
- [ ] **Step 4: Implement `LockScreen.qml`** - [ ] **Step 4: Implement `LockScreen.qml`**
@@ -160,14 +160,14 @@ Use one `Process` for generation and one for status. Coalesce `DesktopPreference
- [ ] **Step 5: Run and verify GREEN** - [ ] **Step 5: Run and verify GREEN**
Run: `tests/quickshell/lock-screen-helper-contract.sh && tests/quickshell/lock-screen-service-contract.sh` Run: `tests/quickshell/lock-screen-helper-contract && tests/quickshell/lock-screen-service-contract`
Expected: PASS with one coalesced generation and no live locker process. Expected: PASS with one coalesced generation and no live locker process.
- [ ] **Step 6: Commit lock invocation and service state** - [ ] **Step 6: Commit lock invocation and service state**
```bash ```bash
git add config/dot/hypr/hypridle.conf config/dot/quickshell/scripts/panama-idle config/dot/quickshell/services/LockScreen.qml config/dot/quickshell/lock-screen-harness.qml tests/quickshell/lock-screen-helper-contract.sh tests/quickshell/lock-screen-service-contract.sh git add config/dot/hypr/hypridle.conf config/dot/quickshell/scripts/panama-idle config/dot/quickshell/services/LockScreen.qml config/dot/quickshell/lock-screen-harness.qml tests/quickshell/lock-screen-helper-contract tests/quickshell/lock-screen-service-contract
git commit -m "Route session locking through Panama" git commit -m "Route session locking through Panama"
``` ```
@@ -177,8 +177,8 @@ git commit -m "Route session locking through Panama"
- Create: `config/dot/quickshell/modules/settings/LockScreenPreview.qml` - Create: `config/dot/quickshell/modules/settings/LockScreenPreview.qml`
- Modify: `config/dot/quickshell/modules/settings/AppearancePage.qml` - Modify: `config/dot/quickshell/modules/settings/AppearancePage.qml`
- Modify: `config/dot/quickshell/services/SettingsSearch.qml` - Modify: `config/dot/quickshell/services/SettingsSearch.qml`
- Create: `tests/quickshell/lock-screen-settings-contract.sh` - Create: `tests/quickshell/lock-screen-settings-contract`
- Modify: `tests/quickshell/settings-search-contract.sh` - Modify: `tests/quickshell/settings-search-contract`
- Modify: `config/dot/quickshell/modules/settings/README.md` - Modify: `config/dot/quickshell/modules/settings/README.md`
**Interfaces:** **Interfaces:**
@@ -191,7 +191,7 @@ Construct the real Appearance page in an isolated QML harness for screenshot, wa
- [ ] **Step 2: Run and verify RED** - [ ] **Step 2: Run and verify RED**
Run: `tests/quickshell/lock-screen-settings-contract.sh && tests/quickshell/settings-search-contract.sh && tests/quickshell/settings-ownership-contract.sh` Run: `tests/quickshell/lock-screen-settings-contract && tests/quickshell/settings-search-contract && tests/quickshell/settings-ownership-contract`
Expected: FAIL because the preview, card, and group route are absent. Expected: FAIL because the preview, card, and group route are absent.
@@ -209,14 +209,14 @@ Map `lockAppearance` to `appearance`; add manual terms **lock screen background*
- [ ] **Step 6: Run and verify GREEN** - [ ] **Step 6: Run and verify GREEN**
Run: `tests/quickshell/lock-screen-settings-contract.sh && tests/quickshell/settings-search-contract.sh && tests/quickshell/settings-ownership-contract.sh` Run: `tests/quickshell/lock-screen-settings-contract && tests/quickshell/settings-search-contract && tests/quickshell/settings-ownership-contract`
Expected: PASS with zero QML warnings and no additional mirrors. Expected: PASS with zero QML warnings and no additional mirrors.
- [ ] **Step 7: Commit the lock-screen Settings experience** - [ ] **Step 7: Commit the lock-screen Settings experience**
```bash ```bash
git add config/dot/quickshell/modules/settings/LockScreenPreview.qml config/dot/quickshell/modules/settings/AppearancePage.qml config/dot/quickshell/services/SettingsSearch.qml config/dot/quickshell/modules/settings/README.md tests/quickshell/lock-screen-settings-contract.sh tests/quickshell/settings-search-contract.sh git add config/dot/quickshell/modules/settings/LockScreenPreview.qml config/dot/quickshell/modules/settings/AppearancePage.qml config/dot/quickshell/services/SettingsSearch.qml config/dot/quickshell/modules/settings/README.md tests/quickshell/lock-screen-settings-contract tests/quickshell/settings-search-contract
git commit -m "Add lock screen appearance settings" git commit -m "Add lock screen appearance settings"
``` ```
@@ -225,10 +225,10 @@ git commit -m "Add lock screen appearance settings"
**Files:** **Files:**
- Modify: `config/dot/quickshell/services/SettingsBackup.qml` - Modify: `config/dot/quickshell/services/SettingsBackup.qml`
- Modify: `config/dot/quickshell/scripts/panama-doctor` - Modify: `config/dot/quickshell/scripts/panama-doctor`
- Modify: `tests/quickshell/settings-backup-live-contract.sh` - Modify: `tests/quickshell/settings-backup-live-contract`
- Modify: `tests/quickshell/settings-commit-reset-contract.sh` - Modify: `tests/quickshell/settings-commit-reset-contract`
- Modify: `tests/quickshell/panama-doctor-contract.sh` - Modify: `tests/quickshell/panama-doctor-contract`
- Modify: `tests/quickshell/lock-screen-service-contract.sh` - Modify: `tests/quickshell/lock-screen-service-contract`
**Interfaces:** **Interfaces:**
- Consumes: `LockScreen.regenerate()` and `panama-lock status`. - Consumes: `LockScreen.regenerate()` and `panama-lock status`.
@@ -240,7 +240,7 @@ Restore a fixture snapshot with non-default lock values and assert regeneration
- [ ] **Step 2: Run and verify RED** - [ ] **Step 2: Run and verify RED**
Run: `tests/quickshell/settings-backup-live-contract.sh && tests/quickshell/settings-commit-reset-contract.sh && tests/quickshell/panama-doctor-contract.sh` Run: `tests/quickshell/settings-backup-live-contract && tests/quickshell/settings-commit-reset-contract && tests/quickshell/panama-doctor-contract`
Expected: FAIL because restore and Health do not know the lock generator. Expected: FAIL because restore and Health do not know the lock generator.
@@ -250,14 +250,14 @@ Inject `regenerateLock` into `SettingsBackup.qml`, start it after preference rel
- [ ] **Step 4: Run and verify GREEN** - [ ] **Step 4: Run and verify GREEN**
Run: `tests/quickshell/settings-backup-live-contract.sh && tests/quickshell/settings-commit-reset-contract.sh && tests/quickshell/panama-doctor-contract.sh && tests/quickshell/lock-screen-service-contract.sh` Run: `tests/quickshell/settings-backup-live-contract && tests/quickshell/settings-commit-reset-contract && tests/quickshell/panama-doctor-contract && tests/quickshell/lock-screen-service-contract`
Expected: PASS with restore ordering and redacted status. Expected: PASS with restore ordering and redacted status.
- [ ] **Step 5: Commit integration** - [ ] **Step 5: Commit integration**
```bash ```bash
git add config/dot/quickshell/services/SettingsBackup.qml config/dot/quickshell/scripts/panama-doctor tests/quickshell/settings-backup-live-contract.sh tests/quickshell/settings-commit-reset-contract.sh tests/quickshell/panama-doctor-contract.sh tests/quickshell/lock-screen-service-contract.sh git add config/dot/quickshell/services/SettingsBackup.qml config/dot/quickshell/scripts/panama-doctor tests/quickshell/settings-backup-live-contract tests/quickshell/settings-commit-reset-contract tests/quickshell/panama-doctor-contract tests/quickshell/lock-screen-service-contract
git commit -m "Integrate managed lock screen recovery" git commit -m "Integrate managed lock screen recovery"
``` ```
@@ -266,14 +266,14 @@ git commit -m "Integrate managed lock screen recovery"
- [ ] **Step 1: Run all lock contracts once** - [ ] **Step 1: Run all lock contracts once**
```bash ```bash
tests/quickshell/lock-screen-helper-contract.sh tests/quickshell/lock-screen-helper-contract
tests/quickshell/lock-screen-service-contract.sh tests/quickshell/lock-screen-service-contract
tests/quickshell/lock-screen-settings-contract.sh tests/quickshell/lock-screen-settings-contract
tests/quickshell/settings-search-contract.sh tests/quickshell/settings-search-contract
tests/quickshell/settings-ownership-contract.sh tests/quickshell/settings-ownership-contract
tests/quickshell/settings-backup-live-contract.sh tests/quickshell/settings-backup-live-contract
tests/quickshell/settings-commit-reset-contract.sh tests/quickshell/settings-commit-reset-contract
tests/quickshell/panama-doctor-contract.sh tests/quickshell/panama-doctor-contract
``` ```
Expected: all PASS and no process named `hyprlock` is started by the tests. Expected: all PASS and no process named `hyprlock` is started by the tests.
@@ -26,7 +26,7 @@
- Modify: `config/dot/quickshell/config/PreferenceSchema.qml` - Modify: `config/dot/quickshell/config/PreferenceSchema.qml`
- Create: `config/dot/quickshell/services/WallpaperPolicy.js` - Create: `config/dot/quickshell/services/WallpaperPolicy.js`
- Create: `config/dot/quickshell/wallpaper-policy-harness.qml` - Create: `config/dot/quickshell/wallpaper-policy-harness.qml`
- Create: `tests/quickshell/wallpaper-policy-contract.sh` - Create: `tests/quickshell/wallpaper-policy-contract`
**Interfaces:** **Interfaces:**
- Consumes: mode, global path, collection, per-monitor map, connected outputs, valid candidates, and shuffle bag. - Consumes: mode, global path, collection, per-monitor map, connected outputs, valid candidates, and shuffle bag.
@@ -46,7 +46,7 @@ Assert missing assignments fall back to the global path, invalid collection entr
- [ ] **Step 2: Run and verify RED** - [ ] **Step 2: Run and verify RED**
Run: `tests/quickshell/wallpaper-policy-contract.sh` Run: `tests/quickshell/wallpaper-policy-contract`
Expected: FAIL because the policy module and harness are missing. Expected: FAIL because the policy module and harness are missing.
@@ -90,14 +90,14 @@ Use `group: "wallpaper"` for every key. Keep the existing `wallpaperPath` patter
- [ ] **Step 5: Run and verify GREEN** - [ ] **Step 5: Run and verify GREEN**
Run: `tests/quickshell/wallpaper-policy-contract.sh` Run: `tests/quickshell/wallpaper-policy-contract`
Expected: PASS for validation, fallback maps, ordered wrap, and shuffle-without-repeat. Expected: PASS for validation, fallback maps, ordered wrap, and shuffle-without-repeat.
- [ ] **Step 6: Commit policy model** - [ ] **Step 6: Commit policy model**
```bash ```bash
git add config/dot/quickshell/config/PreferenceSchema.qml config/dot/quickshell/services/WallpaperPolicy.js config/dot/quickshell/wallpaper-policy-harness.qml tests/quickshell/wallpaper-policy-contract.sh git add config/dot/quickshell/config/PreferenceSchema.qml config/dot/quickshell/services/WallpaperPolicy.js config/dot/quickshell/wallpaper-policy-harness.qml tests/quickshell/wallpaper-policy-contract
git commit -m "Model wallpaper display policies" git commit -m "Model wallpaper display policies"
``` ```
@@ -106,8 +106,8 @@ git commit -m "Model wallpaper display policies"
**Files:** **Files:**
- Modify: `config/dot/quickshell/services/Wallpaper.qml` - Modify: `config/dot/quickshell/services/Wallpaper.qml`
- Create: `config/dot/quickshell/wallpaper-service-harness.qml` - Create: `config/dot/quickshell/wallpaper-service-harness.qml`
- Create: `tests/quickshell/wallpaper-service-contract.sh` - Create: `tests/quickshell/wallpaper-service-contract`
- Modify: `tests/quickshell/settings-pages-contract.sh` - Modify: `tests/quickshell/settings-pages-contract`
**Interfaces:** **Interfaces:**
- Consumes: `WallpaperPolicy.effectiveMap(...)` and hyprpaper `listactive` output. - Consumes: `WallpaperPolicy.effectiveMap(...)` and hyprpaper `listactive` output.
@@ -127,7 +127,7 @@ Assert preferences are written only after exact readback, wrong readback leaves
- [ ] **Step 2: Run and verify RED** - [ ] **Step 2: Run and verify RED**
Run: `tests/quickshell/wallpaper-service-contract.sh` Run: `tests/quickshell/wallpaper-service-contract`
Expected: FAIL because `Wallpaper.qml` only tracks one active path and persists after exit status. Expected: FAIL because `Wallpaper.qml` only tracks one active path and persists after exit status.
@@ -157,14 +157,14 @@ Keep `set(path)` as `return root.setSingle(path)` so SettingsBackup and existing
- [ ] **Step 6: Run and verify GREEN** - [ ] **Step 6: Run and verify GREEN**
Run: `tests/quickshell/wallpaper-service-contract.sh && tests/quickshell/settings-pages-contract.sh` Run: `tests/quickshell/wallpaper-service-contract && tests/quickshell/settings-pages-contract`
Expected: PASS for exact argv, readback gating, old API compatibility, and failure copy. Expected: PASS for exact argv, readback gating, old API compatibility, and failure copy.
- [ ] **Step 7: Commit verified application** - [ ] **Step 7: Commit verified application**
```bash ```bash
git add config/dot/quickshell/services/Wallpaper.qml config/dot/quickshell/wallpaper-service-harness.qml tests/quickshell/wallpaper-service-contract.sh tests/quickshell/settings-pages-contract.sh git add config/dot/quickshell/services/Wallpaper.qml config/dot/quickshell/wallpaper-service-harness.qml tests/quickshell/wallpaper-service-contract tests/quickshell/settings-pages-contract
git commit -m "Verify wallpaper policy application" git commit -m "Verify wallpaper policy application"
``` ```
@@ -174,8 +174,8 @@ git commit -m "Verify wallpaper policy application"
- Modify: `config/dot/quickshell/services/Wallpaper.qml` - Modify: `config/dot/quickshell/services/Wallpaper.qml`
- Modify: `config/dot/quickshell/services/WallpaperPolicy.js` - Modify: `config/dot/quickshell/services/WallpaperPolicy.js`
- Modify: `config/dot/quickshell/wallpaper-service-harness.qml` - Modify: `config/dot/quickshell/wallpaper-service-harness.qml`
- Modify: `tests/quickshell/wallpaper-policy-contract.sh` - Modify: `tests/quickshell/wallpaper-policy-contract`
- Modify: `tests/quickshell/wallpaper-service-contract.sh` - Modify: `tests/quickshell/wallpaper-service-contract`
**Interfaces:** **Interfaces:**
- Consumes: validated slideshow collection, interval, shuffle flag, and `Quickshell.screens`. - Consumes: validated slideshow collection, interval, shuffle flag, and `Quickshell.screens`.
@@ -187,7 +187,7 @@ Use a harness-adjustable interval measured in milliseconds while production deri
- [ ] **Step 2: Run and verify RED** - [ ] **Step 2: Run and verify RED**
Run: `tests/quickshell/wallpaper-policy-contract.sh && tests/quickshell/wallpaper-service-contract.sh` Run: `tests/quickshell/wallpaper-policy-contract && tests/quickshell/wallpaper-service-contract`
Expected: FAIL because no slideshow state or screen-set coalescing exists. Expected: FAIL because no slideshow state or screen-set coalescing exists.
@@ -201,14 +201,14 @@ Bind a sorted screen-name signature and restart a 350 ms single-shot Timer when
- [ ] **Step 5: Run and verify GREEN** - [ ] **Step 5: Run and verify GREEN**
Run: `tests/quickshell/wallpaper-policy-contract.sh && tests/quickshell/wallpaper-service-contract.sh` Run: `tests/quickshell/wallpaper-policy-contract && tests/quickshell/wallpaper-service-contract`
Expected: PASS without rapid retry or durable writes during rotation. Expected: PASS without rapid retry or durable writes during rotation.
- [ ] **Step 6: Commit runtime policy** - [ ] **Step 6: Commit runtime policy**
```bash ```bash
git add config/dot/quickshell/services/Wallpaper.qml config/dot/quickshell/services/WallpaperPolicy.js config/dot/quickshell/wallpaper-service-harness.qml tests/quickshell/wallpaper-policy-contract.sh tests/quickshell/wallpaper-service-contract.sh git add config/dot/quickshell/services/Wallpaper.qml config/dot/quickshell/services/WallpaperPolicy.js config/dot/quickshell/wallpaper-service-harness.qml tests/quickshell/wallpaper-policy-contract tests/quickshell/wallpaper-service-contract
git commit -m "Add event-driven wallpaper rotation" git commit -m "Add event-driven wallpaper rotation"
``` ```
@@ -219,8 +219,8 @@ git commit -m "Add event-driven wallpaper rotation"
- Modify: `config/dot/quickshell/modules/settings/WallpaperPicker.qml` - Modify: `config/dot/quickshell/modules/settings/WallpaperPicker.qml`
- Modify: `config/dot/quickshell/modules/settings/AppearancePage.qml` - Modify: `config/dot/quickshell/modules/settings/AppearancePage.qml`
- Modify: `config/dot/quickshell/services/SettingsSearch.qml` - Modify: `config/dot/quickshell/services/SettingsSearch.qml`
- Create: `tests/quickshell/wallpaper-settings-contract.sh` - Create: `tests/quickshell/wallpaper-settings-contract`
- Modify: `tests/quickshell/settings-search-contract.sh` - Modify: `tests/quickshell/settings-search-contract`
**Interfaces:** **Interfaces:**
- Consumes: Wallpaper modes, connected displays, collection membership, assignments, and transaction state. - Consumes: Wallpaper modes, connected displays, collection membership, assignments, and transaction state.
@@ -232,7 +232,7 @@ Render Appearance in all three modes. Assert Single tile activation calls `setSi
- [ ] **Step 2: Run and verify RED** - [ ] **Step 2: Run and verify RED**
Run: `tests/quickshell/wallpaper-settings-contract.sh && tests/quickshell/settings-search-contract.sh` Run: `tests/quickshell/wallpaper-settings-contract && tests/quickshell/settings-search-contract`
Expected: FAIL because only single-image tile activation exists. Expected: FAIL because only single-image tile activation exists.
@@ -250,14 +250,14 @@ Place `WallpaperControls` in the existing wallpaper card above `WallpaperPicker`
- [ ] **Step 6: Run and verify GREEN** - [ ] **Step 6: Run and verify GREEN**
Run: `tests/quickshell/wallpaper-settings-contract.sh && tests/quickshell/settings-search-contract.sh && tests/quickshell/settings-ownership-contract.sh` Run: `tests/quickshell/wallpaper-settings-contract && tests/quickshell/settings-search-contract && tests/quickshell/settings-ownership-contract`
Expected: PASS with no new mirrors or QML warnings. Expected: PASS with no new mirrors or QML warnings.
- [ ] **Step 7: Commit the wallpaper UI** - [ ] **Step 7: Commit the wallpaper UI**
```bash ```bash
git add config/dot/quickshell/modules/settings/WallpaperControls.qml config/dot/quickshell/modules/settings/WallpaperPicker.qml config/dot/quickshell/modules/settings/AppearancePage.qml config/dot/quickshell/services/SettingsSearch.qml tests/quickshell/wallpaper-settings-contract.sh tests/quickshell/settings-search-contract.sh git add config/dot/quickshell/modules/settings/WallpaperControls.qml config/dot/quickshell/modules/settings/WallpaperPicker.qml config/dot/quickshell/modules/settings/AppearancePage.qml config/dot/quickshell/services/SettingsSearch.qml tests/quickshell/wallpaper-settings-contract tests/quickshell/settings-search-contract
git commit -m "Add wallpaper mode controls" git commit -m "Add wallpaper mode controls"
``` ```
@@ -265,8 +265,8 @@ git commit -m "Add wallpaper mode controls"
**Files:** **Files:**
- Modify: `config/dot/quickshell/services/SettingsBackup.qml` - Modify: `config/dot/quickshell/services/SettingsBackup.qml`
- Modify: `tests/quickshell/settings-backup-live-contract.sh` - Modify: `tests/quickshell/settings-backup-live-contract`
- Modify: `tests/quickshell/settings-commit-reset-contract.sh` - Modify: `tests/quickshell/settings-commit-reset-contract`
**Interfaces:** **Interfaces:**
- Consumes: `Wallpaper.applyCurrentPolicy(false)`. - Consumes: `Wallpaper.applyCurrentPolicy(false)`.
@@ -278,7 +278,7 @@ Restore slideshow and per-monitor fixture snapshots. Assert the restored policy
- [ ] **Step 2: Run and verify RED** - [ ] **Step 2: Run and verify RED**
Run: `tests/quickshell/settings-backup-live-contract.sh && tests/quickshell/settings-commit-reset-contract.sh` Run: `tests/quickshell/settings-backup-live-contract && tests/quickshell/settings-commit-reset-contract`
Expected: FAIL because restore calls `Wallpaper.set(path)` only. Expected: FAIL because restore calls `Wallpaper.set(path)` only.
@@ -288,14 +288,14 @@ Inject `applyWallpaperPolicy: function() { return Wallpaper.applyCurrentPolicy(f
- [ ] **Step 4: Run and verify GREEN** - [ ] **Step 4: Run and verify GREEN**
Run: `tests/quickshell/settings-backup-live-contract.sh && tests/quickshell/settings-commit-reset-contract.sh && tests/quickshell/wallpaper-service-contract.sh` Run: `tests/quickshell/settings-backup-live-contract && tests/quickshell/settings-commit-reset-contract && tests/quickshell/wallpaper-service-contract`
Expected: PASS for both policy modes and shipped reset. Expected: PASS for both policy modes and shipped reset.
- [ ] **Step 5: Commit restore integration** - [ ] **Step 5: Commit restore integration**
```bash ```bash
git add config/dot/quickshell/services/SettingsBackup.qml tests/quickshell/settings-backup-live-contract.sh tests/quickshell/settings-commit-reset-contract.sh git add config/dot/quickshell/services/SettingsBackup.qml tests/quickshell/settings-backup-live-contract tests/quickshell/settings-commit-reset-contract
git commit -m "Restore complete wallpaper policies" git commit -m "Restore complete wallpaper policies"
``` ```
@@ -304,12 +304,12 @@ git commit -m "Restore complete wallpaper policies"
- [ ] **Step 1: Run all wallpaper contracts once** - [ ] **Step 1: Run all wallpaper contracts once**
```bash ```bash
tests/quickshell/wallpaper-policy-contract.sh tests/quickshell/wallpaper-policy-contract
tests/quickshell/wallpaper-service-contract.sh tests/quickshell/wallpaper-service-contract
tests/quickshell/wallpaper-settings-contract.sh tests/quickshell/wallpaper-settings-contract
tests/quickshell/settings-backup-live-contract.sh tests/quickshell/settings-backup-live-contract
tests/quickshell/settings-commit-reset-contract.sh tests/quickshell/settings-commit-reset-contract
tests/quickshell/settings-search-contract.sh tests/quickshell/settings-search-contract
``` ```
Expected: all PASS. The live desktop wallpaper is never changed by fixture tests. Expected: all PASS. The live desktop wallpaper is never changed by fixture tests.
@@ -31,8 +31,8 @@ verification gate is recorded in the integrating commit history.
- Create: `config/dot/quickshell/services/DefaultApps.qml` - Create: `config/dot/quickshell/services/DefaultApps.qml`
- Create: `config/dot/quickshell/modules/settings/ApplicationsPage.qml` - Create: `config/dot/quickshell/modules/settings/ApplicationsPage.qml`
- Create only if needed for a safe parser/writer boundary: `config/dot/quickshell/scripts/panama-default-apps` - Create only if needed for a safe parser/writer boundary: `config/dot/quickshell/scripts/panama-default-apps`
- Create: `tests/quickshell/default-apps-contract.sh` - Create: `tests/quickshell/default-apps-contract`
- Create: `tests/quickshell/applications-settings-contract.sh` - Create: `tests/quickshell/applications-settings-contract`
**Interfaces:** **Interfaces:**
- Consumes: `DesktopEntries.applications.values`, `SettingsPage`, `SettingsCard`, `SettingRow.activatable`, `ActionRow`, `TextRow`, and Claude-owned routing for page id `applications`. - Consumes: `DesktopEntries.applications.values`, `SettingsPage`, `SettingsCard`, `SettingRow.activatable`, `ActionRow`, `TextRow`, and Claude-owned routing for page id `applications`.
@@ -47,8 +47,8 @@ The page contract must require `DesktopEntries.applications.values`, page id/obj
- [x] **Step 2: Run focused contracts to verify RED** - [x] **Step 2: Run focused contracts to verify RED**
```bash ```bash
tests/quickshell/default-apps-contract.sh tests/quickshell/default-apps-contract
tests/quickshell/applications-settings-contract.sh tests/quickshell/applications-settings-contract
``` ```
Expected: fail because the service/page and behavior do not exist. Expected: fail because the service/page and behavior do not exist.
@@ -60,9 +60,9 @@ All process commands use argument arrays. Validate roles against a fixed map and
- [x] **Step 4: Verify and commit** - [x] **Step 4: Verify and commit**
```bash ```bash
tests/quickshell/default-apps-contract.sh tests/quickshell/default-apps-contract
tests/quickshell/applications-settings-contract.sh tests/quickshell/applications-settings-contract
tests/quickshell/settings-pages-contract.sh tests/quickshell/settings-pages-contract
``` ```
Commit subject: `Add application and autostart settings`. Commit subject: `Add application and autostart settings`.
@@ -81,8 +81,8 @@ Commit subject: `Add application and autostart settings`.
- Modify: `config/dot/quickshell/modules/settings/ScreenIntelligencePage.qml` - Modify: `config/dot/quickshell/modules/settings/ScreenIntelligencePage.qml`
- Modify: `config/dot/quickshell/modules/settings/ServicesPage.qml` - Modify: `config/dot/quickshell/modules/settings/ServicesPage.qml`
- Modify: `config/dot/quickshell/modules/settings/AboutPage.qml` - Modify: `config/dot/quickshell/modules/settings/AboutPage.qml`
- Modify: `tests/quickshell/settings-pages-contract.sh` - Modify: `tests/quickshell/settings-pages-contract`
- Create: `tests/quickshell/settings-hardcoded-values-contract.sh` - Create: `tests/quickshell/settings-hardcoded-values-contract`
**Interfaces:** **Interfaces:**
- Consumes: Claude-owned schema keys `temperatureUnit`, `weatherRefreshMinutes`, `vitalsIntervalMs`, `notificationTimeoutMs`, `notificationTimeoutCriticalMs`, `notificationHistoryLimit`, `maxVisibleToasts`, `screenshotDir`, `recordingDir`, and `recorderArgs`; shared Settings rows; existing services and system handoffs. - Consumes: Claude-owned schema keys `temperatureUnit`, `weatherRefreshMinutes`, `vitalsIntervalMs`, `notificationTimeoutMs`, `notificationTimeoutCriticalMs`, `notificationHistoryLimit`, `maxVisibleToasts`, `screenshotDir`, `recordingDir`, and `recorderArgs`; shared Settings rows; existing services and system handoffs.
@@ -95,8 +95,8 @@ Require all ten `Settings.qml` properties to use `DesktopPreferences.get()` exac
- [x] **Step 2: Run contracts to verify RED** - [x] **Step 2: Run contracts to verify RED**
```bash ```bash
tests/quickshell/settings-hardcoded-values-contract.sh tests/quickshell/settings-hardcoded-values-contract
tests/quickshell/settings-pages-contract.sh tests/quickshell/settings-pages-contract
``` ```
Expected: fail on hardcoded properties and copied page scaffolds. Expected: fail on hardcoded properties and copied page scaffolds.
@@ -108,12 +108,12 @@ Use `ChoiceRow` for `temperatureUnit`, `screenshotDir`, `recordingDir`, and `rec
- [x] **Step 4: Run focused and full suite, then commit** - [x] **Step 4: Run focused and full suite, then commit**
```bash ```bash
tests/quickshell/settings-hardcoded-values-contract.sh tests/quickshell/settings-hardcoded-values-contract
tests/quickshell/settings-pages-contract.sh tests/quickshell/settings-pages-contract
tests/quickshell/settings-preferences-contract.sh tests/quickshell/settings-preferences-contract
tests/quickshell/settings-search-contract.sh tests/quickshell/settings-search-contract
``` ```
Then run every `tests/quickshell/*.sh`, every `tests/hypr/*.sh`, and all three `tests/quickshell/*_test.py` files sequentially. Then run every `tests/quickshell/*`, every `tests/hypr/*`, and all three `tests/quickshell/*_test.py` files sequentially.
Commit subject: `Complete Panama settings controls`. Commit subject: `Complete Panama settings controls`.
@@ -28,8 +28,8 @@
- Modify: `config/dot/quickshell/modules/settings/HomePhonePage.qml` - Modify: `config/dot/quickshell/modules/settings/HomePhonePage.qml`
- Modify only if required for shared vocabulary compatibility: `config/dot/quickshell/modules/settings/HomeFavoriteCard.qml` - Modify only if required for shared vocabulary compatibility: `config/dot/quickshell/modules/settings/HomeFavoriteCard.qml`
- Modify only if required for shared vocabulary compatibility: `config/dot/quickshell/modules/settings/AvailableLightRow.qml` - Modify only if required for shared vocabulary compatibility: `config/dot/quickshell/modules/settings/AvailableLightRow.qml`
- Modify: `tests/quickshell/home-preferences-contract.sh` - Modify: `tests/quickshell/home-preferences-contract`
- Modify: `tests/quickshell/home-phone-settings-contract.sh` - Modify: `tests/quickshell/home-phone-settings-contract`
**Interfaces:** **Interfaces:**
- Consumes: `SettingsPage { title; lede; default content }`, existing `SettingsCard`, `SettingRow`, `ActionRow`, `TextRow`, `HomeAssistant`, `SystemSettings.bluebubblesAvailable`, and writable `HomePreferences` adapter state. - Consumes: `SettingsPage { title; lede; default content }`, existing `SettingsCard`, `SettingRow`, `ActionRow`, `TextRow`, `HomeAssistant`, `SystemSettings.bluebubblesAvailable`, and writable `HomePreferences` adapter state.
@@ -37,13 +37,13 @@
- [ ] **Step 1: Write failing contracts** - [ ] **Step 1: Write failing contracts**
Add `reset()` to the isolated `home-pref-test` IPC harness. Extend `home-preferences-contract.sh` to seed aliases/order, invoke reset, and require both IPC state and `panama-home.json` to become exactly `{"initialized":false,"favorites":[]}` without waiting for the 180 ms debounce interval. Extend `home-phone-settings-contract.sh` to require `SettingsPage {`, `title: "Home & Phone"`, and the existing lede through `lede:`, while rejecting the copied root `Flickable` scaffold. Add `reset()` to the isolated `home-pref-test` IPC harness. Extend `home-preferences-contract` to seed aliases/order, invoke reset, and require both IPC state and `panama-home.json` to become exactly `{"initialized":false,"favorites":[]}` without waiting for the 180 ms debounce interval. Extend `home-phone-settings-contract` to require `SettingsPage {`, `title: "Home & Phone"`, and the existing lede through `lede:`, while rejecting the copied root `Flickable` scaffold.
- [ ] **Step 2: Run contracts to verify RED** - [ ] **Step 2: Run contracts to verify RED**
```bash ```bash
tests/quickshell/home-preferences-contract.sh tests/quickshell/home-preferences-contract
tests/quickshell/home-phone-settings-contract.sh tests/quickshell/home-phone-settings-contract
``` ```
Expected: the preference contract fails because `reset` is missing; the page contract fails because the page still owns a copied `Flickable` scaffold. Expected: the preference contract fails because `reset` is missing; the page contract fails because the page still owns a copied `Flickable` scaffold.
@@ -79,11 +79,11 @@ Use shared `ActionRow` or `TextRow` only where their single-action/read-only con
- [ ] **Step 4: Run focused contracts to GREEN** - [ ] **Step 4: Run focused contracts to GREEN**
```bash ```bash
tests/quickshell/home-preferences-contract.sh tests/quickshell/home-preferences-contract
tests/quickshell/home-phone-settings-contract.sh tests/quickshell/home-phone-settings-contract
tests/quickshell/settings-pages-contract.sh tests/quickshell/settings-pages-contract
tests/quickshell/settings-rows-contract.sh tests/quickshell/settings-rows-contract.sh
tests/quickshell/settings-commit-reset-contract.sh tests/quickshell/settings-commit-reset-contract
``` ```
Expected: every command exits 0; no test launches BlueBubbles or changes a real Home Assistant entity. Expected: every command exits 0; no test launches BlueBubbles or changes a real Home Assistant entity.
@@ -96,8 +96,8 @@ git add config/dot/quickshell/config/HomePreferences.qml \
config/dot/quickshell/modules/settings/HomePhonePage.qml \ config/dot/quickshell/modules/settings/HomePhonePage.qml \
config/dot/quickshell/modules/settings/HomeFavoriteCard.qml \ config/dot/quickshell/modules/settings/HomeFavoriteCard.qml \
config/dot/quickshell/modules/settings/AvailableLightRow.qml \ config/dot/quickshell/modules/settings/AvailableLightRow.qml \
tests/quickshell/home-preferences-contract.sh \ tests/quickshell/home-preferences-contract \
tests/quickshell/home-phone-settings-contract.sh \ tests/quickshell/home-phone-settings-contract \
docs/superpowers/plans/2026-08-18-settings-home-phone-completion.md docs/superpowers/plans/2026-08-18-settings-home-phone-completion.md
git commit -m "Finish Home and Phone settings cohesion" git commit -m "Finish Home and Phone settings cohesion"
``` ```
@@ -16,7 +16,7 @@ notification server, and a Settings application with thirty-odd pages. Almost al
of it was verified against a running system. Almost none of it was verified against 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. a system where Panama had just been installed for the first time.
The existing `tests/quickshell/declared-dependencies-contract.sh` was written for The existing `tests/quickshell/declared-dependencies-contract` was written for
exactly this class of bug and reports PASS, because it checks only commands that 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 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 handoffs are invisible to it. A dependency checker with a blind spot is worse than
@@ -314,8 +314,17 @@ this way:
- `panama doctor` — front `panama-doctor` from a terminal, not only from Settings - `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 - `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 suite had no entry point and no mention in the README; it is the main safety net
main safety net and it is currently invisible. and it was invisible.
Building the runner found three tests that nothing was running.
`calendar_agenda_bridge_test.py`, `home_assistant_bridge_test.py` and
`kdeconnect_bridge_test.py` are `unittest` suites without the executable bit, so
no contract invoked them and the first draft of this runner skipped them in
silence. All three pass, and have presumably passed unobserved for weeks. The
runner now collects `*_test.py` as well, because a runner with a blind spot is
worse than no runner for the same reason a dependency checker with one is: it
reports PASS.
- `panama upgrade` — re-run `./install` from anywhere - `panama upgrade` — re-run `./install` from anywhere
### Dropping the `.sh` extension ### Dropping the `.sh` extension
@@ -324,7 +333,7 @@ this way:
`config/local/share/vicinae/scripts`, 2 under `tests/hypr`. All are already `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 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 three comment references and two lines in `panama-settings-commands`, which
generates the Vicinae command files and globs for `settings-*.sh`. generates the Vicinae command files and globs for `settings-*`.
The one real risk is Vicinae's script discovery. Its documentation states a script 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 command needs a plain text file, the three `@vicinae.*` directives, a shebang, and
@@ -334,6 +343,19 @@ to act on, but not close enough to skip verifying: after the rename, reload with
before the change is considered done. If discovery does key off the extension, the before the change is considered done. If discovery does key off the extension, the
Vicinae directory is exempted and the reason recorded here. Vicinae directory is exempted and the reason recorded here.
**Verified, and discovery does not.** One script was renamed first and reloaded on
its own; it came back as `scripts:panama.capture`, so the whole set followed and
all 47 resolve.
What the probe did turn up is that the extension was never only a filename:
Vicinae's command IDs embed it, so every ID changed — `scripts:panama.capture.sh`
became `scripts:panama.capture`. Nothing in this repository refers to those IDs,
so nothing breaks. The only trace is Vicinae's own `metadata.json`, whose
`visited` map had two Panama entries that are now orphaned; the effect is that two
commands lost their usage ranking and will earn it back. Worth knowing before
renaming these files again, and worth checking for a keybind or deeplink first on
a machine that has one.
### Machine-specific configuration ### Machine-specific configuration
Monitor layout, keybinds and input differences stay in gitignored local state — Monitor layout, keybinds and input differences stay in gitignored local state —
@@ -422,10 +444,17 @@ installer. They remain recoverable from sunhat's git history.
hardening, with its own spec and plan. It does not conflict with this work — it 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 *depends* on it, since its lock generator falls back to the shipped wallpaper this
spec makes exist. Rebasing it is its own task. spec makes exist. Rebasing it is its own task.
- Six worktrees remain on branches already merged to `main` - **Done.** Six worktrees remained on branches already merged to `main`
(`home-accessories-customization`, `panama-commands`, `panama-displays-review`, (`home-accessories-customization`, `panama-commands`, `panama-displays-review`,
`panama-settings-home-phone`, `settings-notification-rules`, `settings-ownership`). `panama-settings-home-phone`, `settings-notification-rules`, `settings-ownership`),
They are clutter, not risk; pruning them stays in phase 6. and all six are pruned. Each was re-checked rather than trusted to this list:
`git cherry main <branch>` reported nothing unique and every working tree was
clean. Two needed the check. `panama-commands` is not on `feat/panama-commands`
at all but on `feat/gnome-tweaks-parity` — the directory name and the branch had
drifted apart. And `fix/panama-displays-review` reads `[ahead 3]`, which is ahead
of its *remote*, not of `main`; all three commits are patch-equivalent to work
already landed. The branches themselves are left alone: pruning a worktree costs
nothing, and deleting a branch is somebody's decision rather than tidying.
- Guard the `.cargo/env` source in `config/bash/.bashrc` and remove the Codex block. - 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. - Rewrite the README: one desktop, the real install stages, and the test suite.
- **Done, and it needed nothing.** `docs/settings.md` is generated from - **Done, and it needed nothing.** `docs/settings.md` is generated from
+1 -1
View File
@@ -2,7 +2,7 @@
# Every asset Panama's desktop names must be something Panama installs. # Every asset Panama's desktop names must be something Panama installs.
# #
# This is the sibling of declared-dependencies-contract.sh, and it exists because # This is the sibling of declared-dependencies-contract, and it exists because
# that contract has a structural blind spot. It checks commands that scripts # that contract has a structural blind spot. It checks commands that scripts
# invoke -- so it reports PASS on a machine where the shell's icon font, the # invoke -- so it reports PASS on a machine where the shell's icon font, the
# pointer theme, the wallpaper and four GUI applications are all missing, because # pointer theme, the wallpaper and four GUI applications are all missing, because

Some files were not shown because too many files have changed in this diff Show More