From a40f99e417697f471d3e151378cd51fde987575a Mon Sep 17 00:00:00 2001 From: Bernardo Magri Date: Thu, 16 Jul 2026 09:23:10 +0100 Subject: [PATCH] =?UTF-8?q?docs(agent):=20file=20#137=E2=80=93#141=20from?= =?UTF-8?q?=20the=20T14s=20round=20(three=20root-caused=20live)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bernardo's 2026-07-16 observations, filed with the diagnosis done on the machine rather than as symptoms: - #137 plymouth: unindexed Window.Get* → whole splash placed on head 0's geometry; off-centre on any second monitor (LUKS prompt included). - #138 [human] Meet claims no mic/speakers: audio graph + Flatpak sandbox ruled out live; needs the browser named and the failure in front of us. - #139 terminal floats full-screen: % size rules silently no-op on Hyprland 0.55.4 (absolute px applies), and Kitty replays its remembered window size — the second half is the Ghostty regression from #95. - #141 waybar updates click dead: whole-swaps use $TERMINAL, which is absent from Waybar's env; 4 jsonc lines, a parity break not a bug. - #140 PROPOSED: Ask Claude → web chat instead of the claude-code REPL. Also gives #127 its "if diagnosis fails" branch: a screensaver while docked, which is the panel-protection consolation prize, not a new item. Co-Authored-By: Claude Opus 4.8 --- agent/BACKLOG.md | 144 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) diff --git a/agent/BACKLOG.md b/agent/BACKLOG.md index fed1ab4..08b252f 100644 --- a/agent/BACKLOG.md +++ b/agent/BACKLOG.md @@ -80,6 +80,15 @@ stays lit under hyprlock (journal: `dpms-off skipped: docked`); undocked still blanks at 10 min and wakes on input. Full original pass (wake after DPMS-while-docked) deferred to the LATER revisit. +**Fallback if the cause resists (Bernardo 2026-07-16):** diagnosing stays the +preference — DPMS when docked is the outcome we want. But the mitigation as +shipped holds a near-static lock screen on the externals indefinitely, so if +the cause cannot be pinned down, a **screensaver while docked** is the +consolation prize: it protects the panels (burn-in — the same cost #135 +names) without re-entering the blanking path that bricked the session. Not a +new item: it is the "if diagnosis fails" branch of this one, and #135's state +key is where it would land. + ## NEXT ### 135. Give the #127 DPMS mitigation a state key (and a way back) @@ -181,6 +190,111 @@ migration (state.json created + git-staged, legacy `git rm`'d). Proven by hand 2026-07-15 (drvPaths identical across the rename) — this just keeps it 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. + +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. + +### 138. `[human]` Google Meet reports no mic or speakers; Zoom is fine + +Bernardo 2026-07-16 (T14s, docked): Meet insists there is no microphone or +speaker even with the browser permission granted; Zoom calls work. What I +could rule out from the live session, so the fix pass does not re-tread it: + +- The audio graph is healthy — PipeWire 1.6.5 with 4 sinks and 5 sources + (`wpctl status`), and a live `Chromium input` client was already attached. +- Not a Flatpak sandbox: Chromium is the **native** nixpkgs build from the + template's `home.packages`. (Zoom, the app that works, is the Flatpak. + Brave — also Flatpak — holds `pulseaudio` + `xdg-run/pipewire-0` + + `devices=all`, so it would not fail this way either.) +- One oddity worth checking first: the default source is **`OBSBOT Meet SE + Digital Stereo (IEC958)`** — an S/PDIF *passthrough* profile on the webcam, + a strange default for a mic. A device that enumerates but cannot open is a + plausible route to Meet's "no devices" wording. + +`[human]` because it needs the failure in front of us: **which browser** were +you in (native Chromium, or the Brave Flatpak?), and with it open on Meet, +`chrome://media-internals` plus the device list under `chrome://settings/content/microphone` +would separate "Chromium enumerates nothing" from "Meet rejects what it is +offered". Until then there is no way to tell a Nomarchy defect from a +device-profile accident, and guessing costs more than asking. + +### 139. Terminal floats open full-screen — % size rules are ignored, and Kitty remembers + +Bernardo 2026-07-16: calcurse and nomarchy-doctor float but fill the screen — +the reduced size we had under Ghostty is gone. Reproduced and root-caused live +on the T14s (Hyprland 0.55.4, single 2560×1440 head), and it is **two** faults +stacked, which is why it looks like the float rules are dead when they are not: + +1. **Percentage sizes silently no-op.** `com.nomarchy.calendar` came up + `floating=true` but `size=[2526,1360]` — the full work area, not the + `size 60% 65%` in `modules/home/hyprland.nix:1064`. A runtime rule with + **absolute** pixels (`size 1400 900`) applied perfectly and even centred + itself, so `size` works and the matcher works: it is the `%` form that this + Hyprland drops. No `hyprctl configerrors` — it fails silently, which is + how it survived the rule-syntax rewrite. +2. **Kitty remembers its last window size.** With the rule not applying, + nothing overrides Kitty's own request, and Kitty defaults to + `remember_window_size yes` — `~/.cache/kitty/main.json` literally holds + `{"window-size": [...]}` and is replayed into every new OS window. So the + float inherits whatever the last Kitty was, which after any tiled window is + ~full-screen. **This is the Ghostty regression** (#95, Kitty-only): Ghostty + kept no such memory, so fault 1 was invisible — fault 2 exposed it. + +Both need fixing, and fixing either alone is a trap: absolute pixels alone +stop being right on the 1366-wide Acer (#131's machine) or any scaled head, +and pinning Kitty alone leaves the `%` rules rotting for the next window we +float. Likely shape: `-o remember_window_size=no` (plus +`initial_window_width/height`) in the `nomarchy-calendar` / doctor launchers +so Kitty stops fighting us, and either the working syntax for `%` or a +documented note that this Hyprland wants absolute px. Affects every rule using +`%` — today calendar (`:1064`) and doctor (`:1070`). Pass = both sheets open +centred at their intended fraction on the dev box **and** on the Acer. + +_(My probes wrote `{"window-size": [1400, 900]}` into your Kitty cache — it is +a self-updating cache, harmless, and any resize overwrites it.)_ + +### 141. Waybar's update module is dead in the whole-swap themes (`$TERMINAL` is unset) + +Bernardo 2026-07-16: clicking the Waybar updates module does nothing. +Confirmed live and it is a **Waybar parity break** (CONVENTIONS § whole-swaps), +not an updates bug. The generated module bakes the terminal in — +`"${config.nomarchy.terminal} -e nomarchy-updates upgrade"` +(`modules/home/waybar.nix:356`) — but the four whole-swap themes hand-write +`"sh -c '$TERMINAL -e nomarchy-updates upgrade'"`, and **Waybar's environment +has no `TERMINAL`**: its 55 vars contain zero matches (pid 1688, `/proc/*/environ`). +`TERMINAL` is a `home.sessionVariables` entry (`modules/home/default.nix:104`), +so login shells get it and the Hyprland-spawned bar does not. The click expands +to `sh -c ' -e nomarchy-updates upgrade'` → nothing, no error, no toast. You +are on **boreal**, a whole-swap, which is why you see it. + +Affected, one line each: `themes/{boreal,summer-day,summer-night,executive-slate}/waybar.jsonc` +(`custom/updates.on-click` — grep says this is the *only* `$TERMINAL` use left +in any whole-swap, so the blast radius is exactly these 4 lines). Fix = drop +the env dependency the way calendar/doctor already do — name `kitty` outright, +Kitty being sole supported since #95 — or, better and one place instead of +five, give `nomarchy-updates` a subcommand that opens its own terminal so +every caller stops needing `$TERMINAL`. Worth a check against the class of +bug, not the instance: nothing today asserts that a whole-swap's on-click +survives Waybar's actual environment, so the next hand-written jsonc can +reintroduce it silently. + ### 120. A netinstall ISO, next to the fat offline one Bernardo 2026-07-14, after seeing the measured size: **keep the current ISO @@ -297,6 +411,36 @@ high-ROI, etc.) live in the journal + ROADMAP — not here.* ### Product / day-2 +### 140. Ask Claude should hand off to a web chat, not open a coding agent + +Bernardo 2026-07-16: "opening claude-code is too disruptive" — he would prefer +the query go to a **web interface** (Gemini or Claude) instead. Today +SUPER+CTRL+A → `nomarchy-menu ask` (`modules/home/rofi.nix:899–905`) takes the +free-text line and does `${cfg.terminal} -e npx --yes @anthropic-ai/claude-code@latest "$q"`: +a terminal window, an npm fetch on first run, and a REPL that stays open — a +coding agent answering "what's the syntax for…". The prompt surface is right; +the destination is wrong for the question the surface invites. + +Cheap version: URL-encode `$q` and `xdg-open` a prefill URL +(`https://claude.ai/new?q=…`, `https://gemini.google.com/app?q=…`), landing in +the default browser (Chromium, per Decisions). That is a handful of lines and +deletes the `npx`/network/REPL cost — plus `pkgs.nodejs`, carried in +`home.packages` (`:1685`) **only** for this feature, so the closure shrinks +with it. To settle before building: +- **Which destination, and is it a choice?** Bernardo named Claude *or* + Gemini. A `settings.ask.provider` key keeps it in-flake and menu-writable + (the convention) and stops us hardcoding a vendor into a vendor-neutral + distro; a fixed default is cheaper. Prefill-URL support is per-vendor and + can be changed by them unilaterally — worth verifying each still prefills, + since a silently-ignored `?q=` degrades to "opens a blank chat", which is + survivable but should be a known cost, not a surprise. +- **Keep the CLI at all?** A second row (Ask ▸ web / Ask ▸ agent) preserves + today's behaviour for whoever wants it; deleting it is the simpler surface + and the one the complaint argues for. Bernardo's call. +- Renaming: "Ask Claude" is the keybind desc (`keybinds.nix:57`) and shows in + the generated cheatsheet — if the destination becomes configurable, the + label should stop naming one vendor. + ### 134. `unstable.` in the downstream — a newer app without a second flake Bernardo 2026-07-15, wanting a newer LM Studio (pinned 0.4.15-2 vs unstable