From 54f51c5671b069a0c76f4594c0a92f973f56596a Mon Sep 17 00:00:00 2001 From: server2 Date: Sat, 10 Oct 2026 03:22:56 +0200 Subject: [PATCH] AGENTS.md: full handoff for a new session where everything lives (repo, library, skill, desktop and its Hyprland setup), the user's ground rules, the current state (master, the three open glass branches with benchmark numbers, what runs on the desktop), architecture including hover, instant transport, monitors, theme and idle pill, Hyprland 0.56 pitfalls, performance rules, develop and test workflow, open threads --- AGENTS.md | 157 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 102 insertions(+), 55 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 6a4a2fc..10600f0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,65 +1,109 @@ # AGENTS.md -Notes for agents continuing work on the Magic Island shell. Read README.md first for what it does and how it's laid out. +Handoff for agents continuing work on the Magic Island shell (Hermes, Claude Code, Codex, a new session). Read README.md first for what the shell does and how to use it; this file is how it's built, how to work on it, and where things stand. Last updated 2026-10-10. + +## Where things are + +- **This repo:** `/root/amane-config` on the dev host; remote `git@server1:fabolous005/amane-config.git`. +- **Amane library and docs:** `/root/amane` (`docs/src/*.md`, source in `src/`). The desktop has its own copy at `~/git/amane`. +- **Hermes skill `amane`** (`~/.hermes/skills/software-development/amane/`): distilled Amane docs plus lessons. `references/recipe-media-island.md` and `references/remote-visual-testing.md` cover this project; `scripts/` holds copies of `tools/` (keep them in sync). +- **Desktop:** `ssh -o BatchMode=yes fabian@192.168.2.169`. Hyprland 0.56.2 with a **Lua** config (`~/.config/hypr/*.lua`; API stubs in `/usr/share/hypr/stubs/hl.meta.lua`). Intel Xe iGPU (Raptor Lake). Four monitors: eDP-1 1920×1200 at 1920,620; HDMI-A-1 at 0,620; DP-2 at 3840,0; HDMI-A-4 at 5760,0. `~/.config/amane` on the desktop is a git checkout of this repo. ## Ground rules from the user -- **Branch per big change, and ask before merging.** Create a new branch for each big change, show the result, and merge into `master` only after the user explicitly approves. Small follow-ups the user asks for in the same breath can go on the same branch. -- **Never touch the user's real players' sound.** Cider and Firefox are real; their volume, equalizer and output are the user's. Before any `island preset|output` call or volume change, run `amane ipc call island status` and make sure `player=` is a fake test player. Test audio goes to inaudible null sinks (see Testing). -- **The desktop is reached only by `ssh -o BatchMode=yes fabian@192.168.2.169`** (Hyprland, Intel iGPU, monitors DP-2 and eDP-1). Don't probe the network, SSH keys or other hosts; if SSH fails, report it and wait. -- **Leave the desktop clean:** stop fake players and null sinks after testing, and restart the shell without frame logging (see "After testing"). -- Be honest in summaries about what was and wasn't checked on the real desktop. +- **Branch per big change, ask before merging.** New branch for each big change; merge into `master` only after explicit approval. "In main branch" or "merge directly to main" means commit straight to master. Small follow-ups in the same request can share a branch. **Push only when the user asks.** +- **Never touch the user's real players' sound** (Cider, Firefox). Before any `island preset|output` call or volume change, check `amane ipc call island status` names a fake test player. Test audio goes to the inaudible null sinks. +- **The user's own amane:** they sometimes run it from a terminal. Don't kill it without asking; `tools/amane-remote.sh start` refuses when it finds a shell it didn't start. +- **Desktop access is SSH only.** Don't probe the network, SSH keys or other hosts. If SSH fails, report it and wait (the user once had to restart sshd). +- **Leave the desktop clean** after testing: fake players and null sinks stopped, shell running without the frame log (see "After testing"). +- **Edit files with the patch/write tools, not scripts that rewrite files.** The user installs missing tools themselves. Scripts take instance values (hosts, names) as arguments. +- Hermes approval prompts are switched off; edits to AGENTS.md may still prompt (`security.protected_instruction_files`). +- Report honestly what was and wasn't checked on the real desktop. + +## Current state + +**master** (pushed): the island (pill, card, CD ring, EQ, output and player switching, hover animations, instant transport buttons), an idle pill when no player is open, one island per monitor (card on one monitor, live bars only on the focused one), a workspace pill per monitor, and wallpaper colours through matugen. + +**Open design branches** (pushed, not merged; the user is reviewing them): + +| Branch | What it is | +|---|---| +| `glass-base` | `glass` (0.05 to 1, default 1 = solid) in `shell.conf`; new `src/surface.rs` with `shell()`, which draws the island, idle pill and workspace pill; with glass below 1 the open/close fade uses `.opacity()` (a veil can't hide content on see-through glass). README "Glass" section with the Hyprland layer rule. | +| `design-frosted` | glass-base plus an Apple-style surface: default glass 0.62, thin tint, hairline white rim (accent when hovered), white sheen along the top third, soft low black shadow instead of the accent glow. | +| `design-liquid` | glass-base plus clear glass: default 0.4, denser toward the bottom right, specular gradient (bright top left, faint bottom right), 1.5 px light rim warming to `flame` when hovered, keeps the accent glow. | + +Each branch has review images in `docs/design/`. A `blur` value was added to `shell.conf` on all three and then reverted: **the user wants the blur strength set only in Hyprland** (`~/.config/hypr/looks.lua` has `decoration.blur.size = 3`). When the user picks a design, merge `glass-base` plus that design into master. + +Measured 2026-10-09 with the silent "Synth Test" player playing, 4 monitors (Amane GPU time per frame, CPU of amane-shell): + +| | Pill | Open card | Open/close | +|---|---|---|---| +| master (solid) | 1.6 ms, 12% | 3.3 ms, 25% | 2.5 ms | +| glass-base at 0.5 | 1.7 ms, 13.5% | 3.0 ms, 25.5% | 2.4 ms | +| design-liquid at 0.4 | 2.2 ms, 16% | 3.3 ms, 23.5% | 2.9 ms | +| design-frosted at 0.62 | 2.9 ms, 22% | 3.3 ms, 24% | 2.9 ms | + +Hyprland's CPU stayed at about 9.5% in every run, blur rule on or off. All builds, master included, had 25–40 stutter frames (20–500 ms gaps) per 3 opens and closes, against 0–1 measured earlier with fewer monitors; the cause wasn't found (Cider and Firefox were running). + +**On the desktop right now:** the agent-started shell runs the `design-frosted` build (pid in `~/.cache/amane-remote-test/shell.pid`, no frame log). `~/.config/amane` is on master with design-frosted's `src/` deployed over it, so `git status` shows changed files. `shell.conf` has `glass = 0.70` (set by the user). amane is not autostarted by Hyprland: after a reboot the user starts it. + +**Theme pipeline:** Skwd-wall v2's matugen integration `amane` renders `~/.config/amane/matugen/amane.colors` into `~/.config/amane/theme` (Skwd scheme: `scheme-fidelity`). `~/.config/hypr/windowrules.lua` has the glass layer rule (`^magic-.*$`, blur, `ignore_alpha = 0.5`). ## Constraints of Amane itself -- The shell can only depend on `amane` and the Rust standard library: `amane compile` generates `Cargo.toml` and no other crates can be added. External tools run as processes (`std::process::Command`, `amane::output`). -- Amane docs: `/root/amane/docs/src/*.md` on the dev host; library source in `/root/amane/src/`. -- Amane redraws the whole window every frame, so every effect in the view is paid at the frame rate. +- Only `amane` and the Rust standard library: `amane compile` generates `Cargo.toml`, so no crates. External tools run as processes (`std::process::Command`, `amane::output`). +- Amane redraws the whole window every frame, so every effect is paid at the frame rate. +- Amane can only blur what the shell draws itself; frosting the desktop behind the shell needs a Hyprland layer rule. +- `amane compile` saves `~/.cache/amane/amane-shell`; `amane run` starts it. ## Architecture | Piece | Kind | Job | |---|---|---| -| `island.rs` `Island` | input-only Service | `open: Animation` (0 pill, 1 card), `expanded`, `selected` player (bus name, `None` follows the playing one), open dropdown, time-bar scrub. Also the view and the `island` IPC handler (`command`). | +| `island.rs` `Island` | input-only Service | `open: Animation` (0 pill, 1 card), `expanded`, `selected` player (bus name; `None` follows the playing one), open `menu`, time-bar `scrub`, `hover` (per-`Spot` animations), `opened_on` / `pointer_on` (monitors), `playing_now` (a clicked play/pause until the player answers). Also the view and the `island` IPC handler (`command`). | | `sound.rs` `Sound` | Service, 1 s poll | `pactl list sinks` + `sink-inputs` → each player's streams (matched by process ancestry, then app name), volume, mute, output, equalizer. Curves saved by player identity to `~/.config/amane/island-eq`. | -| `spectrum.rs` `Spectrum` | Service, 200 ms check | While the shown player plays: `pw-record --target \| cava -p $XDG_RUNTIME_DIR/magic-island/cava.conf` → 24 levels. Stops when it pauses. | -| `art.rs` `Art` | Service, 250 ms poll | Cover URL → local file (curl for https), copied to `palette-cover`, which `Palette` (opened in `main.rs`, 8 colours) watches. | -| `parse.rs` | plain functions, no amane | pactl/cava/proc parsing, filter-chain config, `pw-cli` params, EQ store, middle ellipsis, `key = value` settings and `#rrggbb`. Unit-tested on its own. | -| `theme.rs` | `Theme` Service, `amane::watch_file` (inotify on the folder, so rename-over saves count) | The shell's 10 colours from `~/.config/amane/theme` (rendered by Skwd-wall from `matugen/amane.colors`) and `shell.conf` (`cover_colors`, `transition_ms`), faded together on one `Animation`. Every view starts with `theme::begin()` (reads Theme, so it redraws on a change; returns `cover_colors`) and draws with `theme::now()`. No theme file: the original pink on purple. | -| `workspaces.rs` | view + input-only `Hover` Service | Workspace pill per monitor (namespace `magic-workspaces`, top left): `Workspaces` filtered by `output() == monitor.name`, special workspaces skipped, click = `hyprctl dispatch 'hl.dsp.focus({ workspace = N })'` (Hyprland 0.56 with a Lua config rejects the `dispatch workspace N` that amane's `Workspaces::focus` sends). Draws with `theme::now()`, reuses the island's `backdrop()` and `HOVER_MS`. Redraws only on Hyprland events and hover. | +| `spectrum.rs` `Spectrum` | Service, 200 ms check | While the shown player plays: `pw-record --target \| cava -p $XDG_RUNTIME_DIR/magic-island/cava.conf` → 24 levels. On start it `pkill -KILL`s cava left by an earlier shell (cava ignores SIGTERM). | +| `art.rs` `Art` | Service, 250 ms poll | Cover URL → local file (curl for https), copied to `palette-cover`, which `Palette` (opened in `main.rs`, 8 colours) watches. Only used for `cover_colors`. | +| `theme.rs` `Theme` | Service, `amane::watch_file` | 10 colours from `~/.config/amane/theme` and `shell.conf` (`cover_colors`, `transition_ms`; `glass` on the glass branches), faded together on one `Animation`. Every view starts with `theme::begin()` (subscribes, returns `cover_colors`) and draws with `theme::now()`. No theme file: the original pink on purple. `watch_file` watches the folder, so matugen's rename-over saves count (55–68 ms to redraw). | +| `workspaces.rs` | view + input-only `Hover` | Workspace pill per monitor (namespace `magic-workspaces`, top left): `Workspaces` filtered by `output() == monitor.name`, special workspaces skipped. Click runs `hyprctl dispatch 'hl.dsp.focus({ workspace = N })'` on a thread. | +| `parse.rs` | plain functions | pactl/cava/proc parsing, filter-chain config, `pw-cli` params, EQ store, middle ellipsis, `key = value` settings, `#rrggbb`. Unit-tested on its own. | -The equalizer: one `setsid -f pipewire -c eq-.conf` process per player with `libpipewire-module-filter-chain`, 10 biquads (low shelf 31 Hz, peaking 63 Hz–8 kHz, high shelf 16 kHz). The player's streams are moved into sink `magic_island_eq.`; gains change live with `pw-cli set-param magic_island_eq. Props '{ params = [ "b1:Gain" 6.0 ... ] }'`. A player only gets one when its curve or output is first changed, or it has a saved non-flat curve. +The equalizer: one `setsid -f pipewire -c eq-.conf` per player with `libpipewire-module-filter-chain`, 10 biquads (low shelf 31 Hz, peaking 63 Hz–8 kHz, high shelf 16 kHz). The player's streams move into sink `magic_island_eq.`; gains change live with `pw-cli set-param magic_island_eq. Props '{ params = [ "b1:Gain" 6.0 ... ] }'`. A player only gets one when its curve or output first changes, or it has a saved non-flat curve. ### The view (island.rs `view`) -- One `LayerWindow` per monitor (`window_per_monitor`, namespace `magic-island`, `Layer::Overlay` because the user's windows are fullscreen) sized for the open card; an `InputArea` lets clicks outside the island through. -- **Never `visible(false)`.** Hyprland 0.56 configures a layer surface before its first commit, so a window that starts hidden gets a size, Amane logs "no child to draw" and the window stays blank forever. With nothing to show, return `window.click_through().child(Rectangle::new().width(0.0).height(0.0))`. -- All windows share the `Island` state. `opened_on` names the monitor the card is open on (others show their pill), `pointer_on` the monitor whose pill is hovered. Only the focused monitor's window (and the one with the card) reads `Spectrum`, so the others don't redraw for every cava frame: with music, pill ~11% of a core and open card ~21%, as with one island. `focused_monitor()` comes from `Workspaces`, which follows the mouse on Hyprland. -- `Spectrum::listen` first `pkill -KILL -f`s any cava running our `cava.conf`: a stopped shell leaves its cava behind, and cava ignores SIGTERM. -- `phases(open)` splits the one linear 560 ms timeline: pill fades out over 0–0.18, the empty shape grows over 0–0.6 (cubic ease-out), the card fades in over 0.6–1 (smoothstep). Closing runs it backwards. At most one face (pill or card) is built per frame. -- `veiled()` fades a face by laying the backdrop gradient over it with alpha `1 - shown` instead of `.opacity()`: same picture, no GPU layer. -- `backdrop_colors()` / `backdrop()`: one 150° three-stop gradient from the palette (dominant, `colors()[1]`, `background()`), each darkened by `deepen()` to a max brightness of 0.22 / 0.15 / 0.07. -- `pill_levels()`: 7 bars, bar *i* = loudest of spectrum slice *i* of 7, × 1.4, linear, drawn up and down from the middle line. -- `ring()`: 40 candles around the CD, levels from `mirrored()` (bass at the top, highs down both sides), `powf(0.75)`. Drawn as 3 paths (glow, body, flame tips). -- Moving the pointer off the island collapses it (`on_hover`). +- One `LayerWindow` per monitor (`window_per_monitor`, namespace `magic-island`, `Layer::Overlay` because the user's windows are fullscreen), sized for the open card; an `InputArea` lets clicks outside the island through. +- No player: `idle()`, a static click-through pill with a drawn note and "Nothing playing". +- Monitors: `tap(monitor)` opens the card where it was clicked, `expand()` (IPC) on the focused monitor; `open_on` restarts the animation when the card moves. Other monitors render `phases(0.0)`, their pill. Only the focused window and the one with the card read `Spectrum` (reading a Service is what subscribes a window), so the rest stay idle. +- `phases(open)` splits one linear 560 ms timeline: pill fades out over 0–0.18, the empty shape grows over 0–0.6 (cubic ease-out), the card fades in over 0.6–1 (smoothstep). At most one face is built per frame. `veiled()` fades a face with a backdrop-coloured veil instead of `.opacity()`. +- Background: the wallpaper surfaces as one 150° three-stop gradient (`backdrop()`); with `cover_colors` the card's background blends to `backdrop_colors(Palette)` (dominant, `colors()[1]`, `background()`, darkened by `deepen()` to 0.22 / 0.15 / 0.07 brightness) as it opens. White-alpha overlays (`CHIP`, `TRACK`, `CHIP_HOVER`, `CLEAR`) stay unthemed. +- Hover: `hovering(spot)` returns the `on_hover` closure easing that `Spot` to 0/1 over 220 ms; the view reads `island.lit(spot)`. Amane matches hover targets by their index in the last frame, so a vanished button never hears the pointer leave: entering a spot fades all others, and `collapse()`/`set_menu()` drop stale highlights. Effects are colour blends and `.scale()`/`.translate()`; transport buttons go bold (`bold_icon`: the glyph's own outline, 0–2 px). +- Transport: play/pause flips at once through `playing_now`; after any transport click `refresh_soon()` re-reads Media at 150 and 600 ms (Media polls once a second). `island play-pause` over IPC takes the same path. +- `pill_levels()`: 7 bars, bar *i* = loudest of spectrum slice *i*, ×1.4, linear, drawn up and down from the middle. `ring()`: 40 candles, levels from `mirrored()`, 3 paths (glow, body, flame tips). +- Moving the pointer off the open card collapses it. -## Performance rules (measured on the Intel iGPU) +## Hyprland 0.56 (Lua config) pitfalls -Current numbers: card open with music 60 fps, about 3.1 ms GPU per frame; pill with music 60 fps, about 1.7 ms GPU, about 9% of one core for shell + cava; paused, about 1 frame a second. Opening has 1 frame over 20 ms (where the card first appears), closing 0. +- **Never return `visible(false)` from a layer view.** Hyprland configures a layer surface before its first commit, so a hidden-at-start window gets a size, Amane logs "`` has no child to draw" and the window stays blank forever. With nothing to show, return `window.click_through().child(Rectangle::new().width(0.0).height(0.0))`. +- **`Workspaces::focus` does nothing:** it sends `dispatch workspace N`, which the Lua config rejects. Use `hl.dsp.focus({ workspace = N })`. Test dispatches harmlessly on the already-focused workspace. +- `hyprctl eval` / `hyprctl repl` run Lua in one shared state; globals (e.g. a layer rule kept in a variable) vanish when Hyprland reloads its config. +- Layer-rule `match.namespace` is a full match: `^magic-` matches nothing, `^magic-.*$` works. Layer rules can only switch blur on; blur strength (`decoration.blur.size`, `passes`) is global. +- `$XDG_RUNTIME_DIR/hypr/` keeps folders of dead instances; the live one has `.socket.sock` (`amane-remote.sh` picks it). A shell started with a dead signature gets an empty `Workspaces` list. +- `hyprctl layers` lists hidden layer windows too (alpha 0); filter on `alpha > 0`. -- **Measure before and after every visual change** with `tools/amane-remote.sh HOST fps` and `anim island`, baseline first. +## Performance rules + +- **Measure before and after every visual change**, baseline first, with the same player and monitor. The GPU-busy counter (`gt0/gtidle/idle_residency_ms`) reads 100% even with the shell paused, so compare Amane's per-frame `gpu` time and `top` CPU instead. - Don't resize a shape with the full card inside it; grow the empty shape, then fade the content in. -- `.clip()` and `.opacity(<1)` each add a GPU layer. A clip over the whole card once took the iGPU from 47 to 9 fps. -- Gradients are expensive in numbers: a gradient background plus 10 gradient slider fills halved the frame rate; the single backdrop gradient is affordable. -- A veil over a gradient must be the same gradient at the same size as the shape (inset 1 px for the rim): Amane places a gradient by each rectangle's own bounds, so a smaller veil shows patches. -- Blurred shadows cost every frame: the drop shadow only exists on the pill and during the animation. -- Many shapes cost: draw repeated marks (candles, bars) as one `Path` per look. -- Streaming data needs `amane::request_frame()` in the view while levels are live; a Service write alone only got about 11 redraws a second from Hyprland. +- `.clip()` and `.opacity(<1)` each add a GPU layer (a clip over the whole card once took the iGPU from 47 to 9 fps). A shadow is two layers per frame: halos only while hovered. +- Gradients cost: a gradient background plus 10 gradient fills halved the frame rate; one backdrop gradient is affordable. A veil over a gradient must be the same gradient at the same size (Amane places gradients by each rectangle's own bounds). +- Draw repeated marks (candles, bars) as one `Path` per look. +- Streaming data needs `amane::request_frame()` in the view while levels are live; a Service write alone got about 11 redraws a second from Hyprland. - `Rectangle::child` holds one child; stack layers with `Stack`. ## Develop -1. Type-check on the dev host without the desktop. A scratch crate outside the repo (don't commit a `Cargo.toml`, Amane generates its own): +1. Type-check on the dev host without the desktop, in a scratch crate outside the repo (don't commit a `Cargo.toml`). Scratch at `/root/.hermes/cache/scratch/amane-check/` (pruned after 24 h idle; recreate it): ```toml [package] @@ -77,35 +121,35 @@ Current numbers: card open with music 60 fps, about 3.1 ms GPU per frame; pill w [workspace] ``` - Then `cargo clippy` in that crate. (It is at `/root/.hermes/cache/scratch/amane-check/` on the dev host.) - -2. Unit tests: `rustc --edition 2024 --test src/parse.rs -o /tmp/parse_test && /tmp/parse_test` (5 tests). + Then `cargo clippy` there. The first build takes minutes. +2. Unit tests: `rustc --edition 2024 --test src/parse.rs -o /tmp/parse_test && /tmp/parse_test` (6 tests). ## Testing on the desktop -`tools/amane-remote.sh HOST COMMAND`; the full command list is in the comment at the top of the script. The main ones: +`tools/amane-remote.sh HOST COMMAND`; the full list is at the top of the script. ```sh H=fabian@192.168.2.169 tools/amane-remote.sh $H deploy src # back up the remote src once, then replace it tools/amane-remote.sh $H build # amane compile -tools/amane-remote.sh $H start # runs the shell WITH frame logging (AMANE_FRAMES=1) +tools/amane-remote.sh $H start # stop the shell it started earlier, start one WITH frame logging tools/amane-remote.sh $H fps 3 # frames, average gap, gpu wait -tools/amane-remote.sh $H anim island # open/close 3x, every frame gap +tools/amane-remote.sh $H anim island # open/close 3x; stutter = 20-500 ms gaps tools/amane-remote.sh $H shot magic-island out.png tools/amane-remote.sh $H sinks start # null sinks island_test_a/_b -tools/amane-remote.sh $H players start 4 # fake MPRIS players (tools/fake_mpris.py), "Synth Test" makes real sound into island_test_a +tools/amane-remote.sh $H players start 4 # fake MPRIS players; "Synth Test" plays a synth into island_test_a tools/amane-remote.sh $H ipc island status tools/amane-remote.sh $H sh 'COMMAND' # anything inside the graphical session's environment ``` -- Pick a fake player with `ipc island next` until `status` names it, before anything that changes sound. -- The island follows the focused monitor: read its geometry from `hyprctl layers -j` (namespace `magic-island`) right before each `grim` capture. -- With one window per monitor, `fps` and `anim` count every window's frames together; resting windows add ~1000 ms gaps (one frame a second for the time bar). Those aren't stalls. -- The desktop's `$XDG_RUNTIME_DIR/hypr/` keeps folders of dead Hyprland instances; the live one is the one with `.socket.sock`, which `amane-remote.sh` now picks. A shell started with a dead signature gets an empty `Workspaces` list. -- Once, a fresh shell exited with "lost the gpu (Device is lost)" (Mesa warns the Xe driver is experimental); starting it again worked. -- The user's pointer may be over the island and open or collapse it during a test; check `status` and capture right after `open`. -- To tune a visualiser, sample the real levels read-only (`pw-record --target | cava`, with `timeout -s KILL` on each stage; a plain `timeout` on a pipeline orphans cava) and look at the distribution first. Typical music sits at 0.15–0.35. +- Pick a fake player with `ipc island next` until `status` names it, before anything that changes sound; stopping the fake players lets the island fall back to the user's player. +- `ipc island open` opens on the **focused** monitor (the user's, if they're at the desk). Read the geometry from `hyprctl layers -j` on that monitor right before each `grim` capture. The user's pointer can open or collapse the island mid-test. +- With one window per monitor the frame log mixes windows; resting ones show ~1000 ms gaps. +- Design screenshots: set `glass` in the remote `shell.conf` (applies live), wait ~1 s, capture pill, workspace pill and the card (`ipc island open`, wait ~2.5 s). +- Hover can't be tested with `hyprctl dispatch movecursor` (no motion events reach the surface); real motion needs a virtual pointer and moves the user's mouse, so ask first. +- Before trusting timings, check `uptime`: a background Gentoo build once made every build look broken. +- A fresh shell once exited with "lost the gpu (Device is lost)" (Mesa warns Xe is experimental); starting again worked. +- To tune a visualiser, sample real levels read-only (`pw-record --target | cava`, `timeout -s KILL` on each stage; a plain `timeout` on the pipeline orphans cava) first. Typical music sits at 0.15–0.35. - In `pkill -f` patterns over SSH, use `[p]ython3 ...` so the pattern doesn't match the remote shell itself. ### After testing @@ -113,13 +157,16 @@ tools/amane-remote.sh $H sh 'COMMAND' # anything inside the graphical sessi ```sh tools/amane-remote.sh $H players stop tools/amane-remote.sh $H sinks stop -tools/amane-remote.sh $H sh 'kill $(cat shell.pid); sleep 0.5; rm -f shell.log - setsid -f sh -c "echo \$\$ > shell.pid; exec ~/.cache/amane/project/target/debug/amane-shell" > /dev/null 2>&1' +tools/amane-remote.sh $H sh 'kill $(cat shell.pid); for i in $(seq 50); do pgrep -F shell.pid > /dev/null || break; sleep 0.1; done + rm -f shell.log; setsid -f sh -c "echo \$\$ > shell.pid; exec ~/.cache/amane/amane-shell" > /dev/null 2>&1' ``` -The desktop's `amane` CLI is older than the docs: no `~/.cache/amane/amane-shell` is saved and `amane run` doesn't apply, so the shell runs from `~/.cache/amane/project/target/debug/amane-shell`. - ## Open threads -- The candle ring is still mirrored (`mirrored()`); the user had the pill bars unmirrored and may want the same for the ring. +- The user picks a glass design; then merge `glass-base` plus that design into master and update README/AGENTS.md. +- The candle ring is still mirrored (`mirrored()`); the pill's bars aren't. +- The Amane library could fix the two Hyprland 0.56 issues upstream (handle a configure on a hidden layer window; use the Lua dispatch in `Workspaces::focus`). Not started. +- `island-eq` is tracked in git but rewritten live by the island, so the desktop checkout always shows it changed; untracking it was proposed, no answer yet. +- Leftovers offered for deletion, no answer yet: `src.before-test/` on the desktop, seven merged local branches on the dev host. +- The open/close stutter rise (25–40 slow frames per 3 opens and closes on every build) is unexplained. - See README "Known limits".