diff options
Diffstat (limited to 'working/hyprland-lua-port/README.org')
| -rw-r--r-- | working/hyprland-lua-port/README.org | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/working/hyprland-lua-port/README.org b/working/hyprland-lua-port/README.org new file mode 100644 index 0000000..42779e5 --- /dev/null +++ b/working/hyprland-lua-port/README.org @@ -0,0 +1,131 @@ +#+TITLE: Hyprland .conf → Lua port — staged, not deployed +#+AUTHOR: Craig Jennings + +* Status + +Built and verified in a nested compositor. *Not deployed.* I deployed it to the +dotfiles tree on 2026-08-24 and then rolled it back the same afternoon, because +the switch had not been checked on real hardware and the machine needs to stay +usable. The dotfiles repo is untouched at =8f692f5=; the live config is the +original =hyprland.conf=. + +The port goes live only after the hardware check in =todo.org= under "Manual +testing and validation" passes. + +* What is here + +| File | What it is | +|----------------------------+---------------------------------------------------------------| +| =hyprland.lua= | The deliverable, 788 lines. Shared config. | +| =velox-local.lua= | velox host overrides, for =velox/.config/hypr/conf.d/=. | +| =ratio-local.lua= | ratio host overrides, for =ratio/.config/hypr/conf.d/=. | +| =reader-changes-for-lua.patch= | dotfiles-side: the four readers, ported and mutation-tested. | +| =test-desktop-for-lua.patch= | archsetup-side: the post-install desktop checks. | +| =hyprland.lua.generated= | Raw =hyprlang2lua= output, merging mode. Derivation evidence. | +| =nomerge.lua= | Same converter with =--no-merge=. Derivation evidence. | + +The two patches are the part that is easy to lose and expensive to redo. Both +were mutation-tested — every ported assertion was confirmed to go red when the +property it guards was removed — so replay them rather than rewriting the +assertions from scratch. + +* Redeploy, when the port is ready + +1. =cp hyprland.lua ~/.dotfiles/hyprland/.config/hypr/hyprland.lua= +2. =cp velox-local.lua ~/.dotfiles/velox/.config/hypr/conf.d/local.lua= +3. =cp ratio-local.lua ~/.dotfiles/ratio/.config/hypr/conf.d/local.lua= +4. Move the three =.conf= files out of their stow packages. Do NOT merely leave + them beside the =.lua=: with both present Hyprland 0.56.2 loads the =.lua= + (proven — see below), so leaving the =.conf= in place buys no rollback and + only creates ambiguity about which file is live. +5. =cd ~/.dotfiles && git apply <path>/reader-changes-for-lua.patch= +6. =cd ~/code/archsetup && git apply <path>/test-desktop-for-lua.patch= +7. Restow. Expect two traps, both hit on 2026-08-24 and both documented in + =todo.org=: =make restow hyprland= aborts on the pre-existing + =obsbot-wb-guard.service= conflict in =common= (restow =hyprland= and the host + package individually instead), and the running Hyprland rewrites a stub + =hyprland.conf= within a second of the symlink vanishing. Silence the stub with + =hyprctl keyword misc:disable_autoreload 1=, do the stow, then set it back to 0. +8. *Push the dotfiles change before committing archsetup.* The installer clones + the dotfiles *remote* (=archsetup:1481=), so until the push lands a fresh VM + stows a tree with only =hyprland.conf= and the post-install checks fail. + +* Two things already proven, so nobody re-derives them + +*With both files present, the =.lua= wins.* Tested in a nested Hyprland 0.56.2 +with a fixture whose =.conf= set =gaps_in=11= and whose =.lua= set =77=. Result +was 77, and the log read "[cfg] Using lua config found at ...hyprland.lua". This +is why step 4 moves the =.conf= out rather than leaving it as a fallback. + +*The converter is a draft, not an answer.* =hyprlang2lua= +(github.com/EIonTusk/hyprlang2lua) reported 100% coverage and still produced +three functional defects, two of which would have broken the desktop. The two +generated files are kept as evidence: both still carry the unfixed bind defect +(="CTRL" .. mod .. " + S"=, which collapses to an unparseable =CTRLSUPER + S=), +and the merging-mode file shows the source glob emitted mid-file where it silently +reverses every per-host override. =--no-merge= fixed the ordering structurally; +the rest were hand-fixed. + +* Review findings folded in (2026-08-24) + +An isolated review of the deployed diff, before the rollback. Four were fixed in +the files here; the rest are gates on redeploying, not on the port's correctness. + +** Fixed here + +- =hl_source_glob= now surfaces all three failure modes and survives them. A + host override that fails to parse was warned about and skipped, which on velox + means coming up with no =force_zero_scaling= and no monitor scale — looking + like the whole port failed rather than one file. A runtime error inside the + chunk was unprotected and would have taken the entire config down over a single + host file. Now: parse failure says SKIPPED, runtime failure says PARTIAL and is + caught with =pcall=, and a glob matching nothing says NO MATCH. hyprlang did + none of this. +- The =col.nogroup_border*= rationale sat *below* the =col= table, reading as a + preamble to =layout=. Moved above the two keys it explains — the same defect + the file header says was fixed for autostart. +- =Generated by hyprlang2lua. Review TODOs before reloading Hyprland= removed + from all three files. No TODOs exist, and in =ratio-local.lua= it had landed + mid-paragraph, splitting the DP-4 rationale from the =hl.monitor= call it + explains. +- =ratio-local.lua='s usage examples were still hyprlang syntax + (=monitor=DP-1,...=, =bind = $mod, L, ...=), which are syntax errors in a Lua + file, and the second named =$mod= — a variable a sourced chunk cannot see. + Rewritten in Lua, with a note on the scoping. Verified rather than assumed: + =loadfile= gives the chunk globals only, and both =mod= and =at_start= are + locals, so both read =nil= inside a sourced file. + +** Refuted by measurement + +- *Duplicate chords append; they do not replace.* The config binds Super+Z twice + on purpose (=exec pypr zoom= plus =submap zoom=), and the same for Escape + inside the submap — if the Lua API replaced rather than appended, Super+Z would + enter the submap without zooming and the pairing the config's own comment + relies on would be broken. Tested in a nested Hyprland 0.56.2 with exactly that + shape: both binds register. The live =.conf= session registers the same pair, + so behaviour matches. No action needed; recorded so nobody re-derives it. + +** Gates on redeploy — do these as part of the switch + +1. *Do not put the =.conf= files in a =retired/= directory inside the repo + without also excluding them from =dotfiles-validate=.* Its find uses + =-path '*/.config/hypr/*.conf'=, which globs across slashes and would match + the retired copies — 81 of 228 checked references came from the dead config + when this was tried. The validator would then fail pointing at a file kept + precisely because nothing loads it. Add =-not -path "$root/retired/*"= to both + finds, or park the =.conf= files outside the repo entirely. +2. *Add tests for the new =dotfiles-validate= Lua branch.* The 25 new lines ship + with none. Proven vacuous: replacing both new awk regexes with =NEVERMATCHES= + still leaves =tests/dotfiles-validate/= reporting 15 tests OK. An extractor + that matches nothing prints nothing and exits 0 — the same false-pass shape + the three ported test suites got vacuity guards for. This one has no guard. +3. *Guard the override ordering.* Nothing asserts =hl_source_glob= is the last + statement in =hyprland.lua=, and it is the single invariant the whole per-host + layer rests on. An edit that moves it above the =hl.config= blocks silently + reverses every host override — converter defect 1, the one that would have + reverted the Qt scaling fix. archsetup's VM suite structurally cannot catch + it, because the VM stows no host tier. The guard belongs in the dotfiles repo. +4. *Sweep the prose comments that still name =hyprland.conf=.* About fifteen + across live scripts. =hyprland/.local/bin/waybar-reserve:12= is the one that + matters: it documents "Wired as =exec = waybar-reserve= in hyprland.conf", + which is exactly the mechanism the port replaces with =at_reload=. |
