aboutsummaryrefslogtreecommitdiff
path: root/working/hyprland-lua-port/README.org
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-08-24 14:27:57 -0600
committerCraig Jennings <c@cjennings.net>2026-08-24 14:27:57 -0600
commit8b5e438d787ff73c3344b4c5ea1141cf8b23ef69 (patch)
tree25f64dea1f918117648a6e0a383da208b2e2018e /working/hyprland-lua-port/README.org
parent1bb5955b121d650302ba3eab08e44cc004470a91 (diff)
downloadarchsetup-8b5e438d787ff73c3344b4c5ea1141cf8b23ef69.tar.gz
archsetup-8b5e438d787ff73c3344b4c5ea1141cf8b23ef69.zip
chore: stage the Hyprland Lua port with its redeploy kitHEADmain
Hyprland 0.57 drops the .conf format. The port is built and measured identical to the current config in a nested compositor — 38 settings, 103 binds, the host-override chain — but it is not deployed. I put it live this afternoon and took it back out the same hour, because it had not been run on real hardware and the machine has to stay usable until it has. working/hyprland-lua-port/ carries what the switch needs, including the two reader changes as replayable patches. Those matter more than the config itself: four things read hyprland.conf as a source of truth, and dotfiles-validate globs hypr/*.conf, so with the .conf gone it finds nothing and reports a clean tree. Two facts not worth re-deriving: with both files present 0.56.2 loads the .lua, so keeping the .conf beside it buys no rollback; and a running compositor rewrites a stub config within a second of the file vanishing, which is what fights a restow. Also archives finished tasks and folds in several sessions of task-review edits.
Diffstat (limited to 'working/hyprland-lua-port/README.org')
-rw-r--r--working/hyprland-lua-port/README.org131
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=.