# Onion MC client-perf — handoff (2026-10-15) Self-contained brief for the next agent. Read `.pi/journal.md` (last sections) and `BENCH-MATRIX.md` too, but this file is the live state on this machine. ## Goal Finish the **Phase 2 client-performance loop**: measure the staged configs, decide by `BENCH-MATRIX.md`'s rules, write winners into `proposed-configs/build.py` (`DEFAULT` / `DECK` / `HIGH`), `build.py --ship`, `packwiz refresh`, commit (Conventional Commits) and push. Pushes go live to players on their next Prism launch. ## Repo / pack state - Pack: **217 mods**, MC 1.21.1, NeoForge 21.1.251. Git `HEAD == origin/main == 8e8483d`. - `8e8483d` fixed the one real boot blocker: the Critters & Companions partial spawn config used camelCase keys (`biomeSpec`) but YACL serialises with `FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES`; every entry loaded `biomeSpec = null` and `CACSpawnConfig$SpawnEntry.isTag()` NPE'd in `FMLCommonSetupEvent`, leaving the client in a "broken mod state" (119 refused events). Fixed to snake_case; **already pushed**. - The Alex's Mobs (TOML) and Fowl Play (YACL camelCase) spawn files are correct and were verified applied in-game. Do not commit the mod/server **full re-saves** of `config/*` (the running server rewrites them): always `git checkout -- config/` before staging. - Nothing was shipped this session. Shipped `config/defaultoptions/**` is unchanged from `a01bc3b`. `build.py` was only patched in the **BENCH** layer (below); the tiers are untouched. ## Boot check (client, this machine) — essentially PASS Reached main menu cleanly. `Sound engine started` 01:26:53; ModernFix "Game took 29.3 s to start"; blocks atlas `4096x4096x2`; Default Options correctly seeded `options.txt` (renderDistance 8, maxFps 120, vsync true). No missing deps, no mixin apply failures, no `ftbteams` refs, no fishermans-haven biome errors, no YACL "Failed to deserialize". 22 ERROR lines, all benign (pride access-transformer, Controlify @Shadow, FTB Library legacy textures, 4 GeckoLib molang parses, icys-better-horses pack path, Xaero version expiry, Veil failing to recompile 2 lodestone `nineslice` shaders). **Open boot-adjacent issue (not yet fixed):** an intermittent crash on **world load**: ``` java.io.FileNotFoundException: minecraft:shaders/core/particle.json at com.corosus.watut.ShaderInstanceBlur.(ShaderInstanceBlur.java:27) at GameRenderer.handler$jhl000$watut$onLoadShaders(...) ``` First world load succeeded and measured; the next crashed during "Rendering overlay". WATUT is a LEVERS §5 removal candidate but the owner says **remove no mods** — look for a WATUT config/patch or a reliable retry. Confirm whether real players hit it before shipping. ## Tooling installed on this machine (all user-local, no root) - **Prism Launcher 11.0.3** (`/usr/bin/prismlauncher`). Data root `~/onion-bench/prism`, instance id **`OnionBench`**, game dir `~/onion-bench/prism/instances/OnionBench/.minecraft` (214 jars). A valid Microsoft account is in `~/onion-bench/prism/accounts.json` (device-code login, owner-approved). - **MangoHud 0.8.4** extracted to `~/.local/mangohud`; wrapper **`~/.local/bin/mangohud-local`** (exports `MANGOHUD_CONFIG`, `LD_PRELOAD` shim, `vblank_mode=0`). CSVs land in `~/onion-bench/mangologs/`. The instance has `WrapperCommand=mangohud-local`. - **Bench world**: `~/onion-bench/prism/instances/OnionBench/.minecraft/saves/onionbench` (seed `onionbench`, creative, cheats). S2 Create floor (2304 kinetic BEs) and S3 mob pen (30 villagers/15 cows/15 sheep/10 allays) were placed via RCON and verified. S4 airships NOT built. Datapack lives in the world's `datapacks/onion-bench`. - **Temp server** for worldgen: `~/onion-bench/server-bench` (symlinks repo `mods`/ `libraries`, copies `config`), port 25566 / RCON 25576, currently **stopped**. - **Harness** (this is new, untracked, packwizignored): `analysis/client-perf/harness/` - `rcon.py` — minimal RCON client. - `run_scene.py` — applies a variant, launches Prism into the bench world under MangoHud, drives scenes with xdotool chat, slices the CSV into p50/p95/p99/1%-low. Verified working end-to-end once (C1/S1). ## Measurements so far — NOT decision-grade One run: **C1 / S1** p50 16.72 ms, p99 17.24 ms, peak 17.60 ms, avg 59.8 FPS, 1% low 57.5, n=1889. It was **vsync-locked at ~60 FPS** (tight 16.7 ms floor). `vblank_mode=0` was added afterwards but the next launch crashed on world load, so uncapped data is not collected yet. Treat all of this as pipeline validation only. ## Next steps (in order) 1. Resolve the WATUT world-load crash; re-run one C1/S1 and confirm FPS > 60 (vblank off). 2. Run the matrix in order, per `BENCH-MATRIX.md`: **B0** noise floor (C0/S1 ×3) → **B1** baseline (C0, S1–S6) → **B2** composite (C1, and C1-deck/C1-high) → **B3** DH radius (`dh-r256`, `dh-r192`, `C1`, `dh-r64`, `dh-off` on S1/S5) → **B4** heap/GC (use `jcmd`/ `jstat`, or spark, at 5/6 G and J0–J3) → **B6** ModernFix → **B7** shaders → **B8** entities → **B9** Flywheel → **B10** SPR → **B11** Sodium/blend → **B12a/b** ablation and trials → **B13** spark profile → **B14** spawn counts. 3. Write winners into `build.py`, `python3 build.py --ship`, `~/go/bin/packwiz refresh`, commit. Ship `config/modernfix-mixins.properties` only if B6 passes (see SHIP comment). 4. Update `PLAYER-TUNING.md` (tiers, heap/GC, shader profiles), `LEVERS.md`, `BENCH-MATRIX.md`, and append a journal section. ## Fleet note P0 (Steam Deck), P1 (7700K/1060) and P2 (6700K/1080 Ti) are **not reachable** from this box (no routes / no SSH targets). Everything measured here is a **high-tier proxy** on a Ryzen 9 9900X + RX 7800 XT, 91 GB RAM. Label results as proxies; absolute FPS floors do not map to tier decisions. ## Gotchas learned this session - Prism 11 `--offline` fails a fresh instance with "Required libraries are missing" (`EnsureOfflineLibraries`). Launch **online** once to download libs/assets; after that offline works. - `xdotool windowactivate --sync` **hangs** under kwin; use `windowactivate` + `windowfocus`. - MangoHud needs `MANGOHUD_CONFIG` set explicitly and `LD_PRELOAD` **exported**. - The owner's dedicated server runs from the repo root (`java @user_jvm_args.txt @libraries/.../unix_args.txt`, port 25565). Never kill it; never touch `world/`. The temp bench server used separate ports/paths and is stopped. - `analysis/` is packwizignored (safe to commit); `config/` is server-rewritten (restore before staging).