diff --git a/agent/BACKLOG.md b/agent/BACKLOG.md index db9ba47..394e9c6 100644 --- a/agent/BACKLOG.md +++ b/agent/BACKLOG.md @@ -180,23 +180,54 @@ proven. Delete together with the shim + the `nomarchy-theme-sync` alias. ### 137. Plymouth splash draws on head 0's geometry, so it is off-centre when docked Bernardo 2026-07-16 (T14s, docked): the boot **and** shutdown logo is not -centred on the external monitor. Cause is in the theme script, not the -hardware: `modules/nixos/plymouth/nomarchy.script` calls `Window.GetWidth()` -/ `Window.GetHeight()` with **no head index**, which returns head 0, while -sprite coordinates live in a device-wide space spanning every head. So every -element is placed at "head 0's centre" measured from the union origin — right -on a single monitor, wrong the moment a second one exists, and wrong in a -different direction depending on which head is 0 and how they are arranged. +centred on the external monitor. -It is the whole splash, not just the logo: the same unindexed call places the -logo (`:9`, `:15–16` — note the 15%-of-height *scale* also tracks the wrong -head), the password entry (`:129`), the lock, the bullets, and the progress -box/bar (`:210`, `:219`). Fix shape is the standard Plymouth one: loop -`Window.GetX(i)` / `GetY(i)` / `GetWidth(i)` / `GetHeight(i)` over the heads -and give each its own sprite set, so each monitor gets a centred, correctly -scaled splash — the LUKS prompt especially, since a passphrase box half off -the panel is the failure that matters. Pass = docked boot + shutdown centred -on both heads; undocked unchanged. +**The first diagnosis here was wrong — do not act on it.** It claimed +`Window.GetWidth()` returns head 0 and that the fix was per-head sprites. Both +are false, and per-head sprites would have been a *regression* (duplicate +logos). Read from plymouth's own source (`plymouth.src`, the build nixpkgs +ships) rather than from a summary: + +- `Window.GetWidth()` **without an index returns `data->max_width`** + (`script-lib-sprite.c:227`) — the widest head, not head 0. +- The script plugin builds a virtual canvas of `max_width × max_height` and + **centres every display inside it**: `display->x = (max_width - width) / 2` + (`:536`). Sprites are drawn per display at `sprite->x - display->x` (`:452`). +- Therefore a canvas-centred sprite **is** centred on every head, and today's + `Window.GetWidth()/2 - w/2` is *correct at the instant it runs*. Note the DRM + renderer sets every head's `area.x = 0` (`renderers/drm/plugin.c:612`) — the + origins that matter are the plugin's computed ones, not the crtc's. + +**The real bug is time, not geometry.** `nomarchy.script` computes every +position as a **top-level statement at parse time** (`:9`, `:15–16`, `:129`, +`:210`, `:219`), i.e. once, against whatever canvas existed at that moment. +When a display arrives or leaves *during* the splash — which is exactly +"booting up / shutting down **with** an external" — `max_width/max_height` +change, the plugin re-centres each display (`:532-537`), but the sprite's frozen +canvas coordinate does not move with it. Every element then sits off by +`(new_max - old_max) / 2` **on every head**. A single monitor never changes the +canvas, which is precisely why this has never been seen undocked. + +**Fix shape:** hoist the position math into a `reposition()` and call it from +the existing `refresh_callback` (already running at 50 fps) whenever +`Window.GetWidth()/GetHeight()` differ from the last canvas — logo (scale +included), entry, lock, any live bullets, progress box/bar. Keep it a +canvas-change check, not an every-frame recompute. + +**Testing — the rig exists, and it needs root.** nixpkgs' plymouth ships +`x11.so`, and plymouth has a built-in fake dual-head mode: +`PLY_CREATE_FAKE_MULTI_HEAD_SETUP=1` (`renderers/x11/plugin.c:294`) creates +800×600 + 640×480 heads, so the splash can be rendered in a window with no +DRM and no reboot. Caveat: that fake path builds both heads up front, so it +proves *rendering and centring*, not the canvas-change bug itself — for that, +plug/unplug while the splash is up, or compare a boot with and without the +external. `plymouthd` wants root and its theme comes from +`/etc/plymouth/plymouthd.conf`, so this needs a sudo session. + +**Do not ship this blind:** the same script draws the **LUKS passphrase box**, +this machine is encrypted, and a script that fails to parse leaves a prompt you +cannot see. Pass = with the rig, a two-head render centred on both; then a real +docked boot + shutdown, undocked unchanged. ### 143. Rofi keeps the selected *row number* when the search changes, so the highlight lands on an unrelated entry diff --git a/agent/JOURNAL.md b/agent/JOURNAL.md index f9fddec..8f02290 100644 --- a/agent/JOURNAL.md +++ b/agent/JOURNAL.md @@ -19,6 +19,38 @@ Template: --- +## 2026-07-16 — "fix the rest": #140, #142, #144 shipped; #137 re-diagnosed +- **Task:** the T14s round's remainder. Bernardo picked configurable-provider + + drop-the-CLI for #140 (and asked for chatgpt/grok in the list). +- **Did:** **#140** Ask → web chat; `settings.ask.provider` read at run time + (switching needs no rebuild), claude-code + `pkgs.nodejs` deleted, query also + copied to the clipboard because vendor prefill is undocumented and fails + *silently*. **#142** dock mode is now an intent (`settings.display.dockMode`) + written at the transition choke point and re-asserted by the watcher as a + **tick invariant** — reconcile diffs `monitors all`, which lists disabled + outputs, so it is blind to a panel switching back on. **#144** MIGRATION.md + gets the Mozilla `profiles.ini` bullet. +- **Verified:** V0 on each. #140: drove the generated script — bad state values + all fall back, hostile query encodes right. #142: **9/9 gates** unit-tested by + extracting the real generated `enforce_dock_intent` and stubbing the session + (incl. *no external → never re-dock*, the #127 brick), plus the state + write/read round-trip on a scratch checkout so the live flake stayed clean. +- **#137 — read the entry before touching it.** My own first diagnosis was + **wrong** and is now corrected in place: `Window.GetWidth()` returns + `max_width`, not head 0, and the plugin *centres every display in the canvas* + — so per-head sprites (what I originally proposed) would duplicate the logo. + The real cause is that the script computes positions **once at parse time**, + so a display arriving/leaving mid-splash re-centres the displays while the + sprites keep their stale canvas coords. Fix = reposition on canvas change from + the existing refresh callback. Not shipped: it draws the **LUKS box** on an + encrypted machine, and the render rig (`x11.so` + + `PLY_CREATE_FAKE_MULTI_HEAD_SETUP`) needs root. +- **Pending:** V3 queue now holds #138 (dock audio), #139 (Acer sheets), #131 + (Acer menu width), #142 (rebuild while docked — **relogin first**). Bernardo + must `nomarchy-home` + relogin to get any of today's session work. +- **Next suggestion:** #137 with a sudo session for the rig, or #143's upstream + (rofi#2317) — nothing to do there until they answer. + ## 2026-07-16 — #139 + #141: the quick ones from the T14s round - **Task:** #139 (terminal sheets open full-screen) and #141 (Waybar updates click does nothing) — Bernardo: "let's do the quick ones first".