- gen_shader_profiles.py + shader-profiles/: Iris per-pack option files
resolved from each pack's profile.* lines (Iris has no profile key)
- bench.py: flag rows shader_not_loaded when Iris falls back to vanilla
rendering (analyze.py treats it as invalid)
- matrix: shader_options session key, trial jar globs pinned to the
downloaded Modrinth builds, post-join settle 45 s (B0 v1 showed rep 1
still warming at 10 s)
- bench.py: gamescope-headless display (default, 1920x1080; ~2% cost vs
desktop for isolation from the shared Wayland desktop), --shader,
--dh, --disable-mods/--add-mods, --world-zip, crash-safe restore
journal, spectator mode in the plan (elevated cameras fell to the
sea floor and S4 measured underwater darkness)
- matrix.toml/matrix.py: declarative, resumable B0-B14 runner keyed on
mods hash (warns when B0 must be re-run)
- build.py: bench-only resource-pack variants (C1-fa, C1-fa-ext,
emf-lod*-fa, C1-bl); every bench variant pins resourcePacks so packs
don't leak between sessions; shipped tier output unchanged
- analyze.py: tagged labels use their own block's baseline
xdotool chat injection silently fails under KDE Wayland/Xwayland, so the
v1 harness recorded runs whose scene commands never executed. v2 drives
scenes from a generated world datapack, detects crashes, aligns MangoHud
CSVs by file birth time, flags vsync/backup/low-n windows, and records
full run metadata to JSONL; analyze.py applies the BENCH-MATRIX win rule.
Fright's Delight jar-in-jars MidnightLib 1.9.2, whose MidnightConfig.init
races during NeoForge parallel mod construction (ConcurrentModificationException).
The broken mod state left mod_resources unloaded, so WATUT's reloadShaders
mixin crashed on particle.json - WATUT was the victim, not the cause.
1.10.0 synchronizes the entries map (upstream 1fe69729); FML selects it over
the JiJ copy. Verified: 10/10 clean cold launches to world join.
Also adds analysis/state/ (Phase 2 state capture).
The client now boots cleanly on the bench machine (the CAC spawn-key
crash was fixed in 8e8483d). Add the harness used to drive bench scenes
and capture frametimes, the bench-world generation workflow, and a
self-contained handoff brief. All files live under analysis/ (packwizignored),
so nothing player-facing changes.
- harness/rcon.py: minimal RCON client for the temp worldgen server
- harness/run_scene.py: apply variant -> launch Prism under MangoHud ->
xdotool scene commands -> p50/p95/p99/1%-low from the CSV
- HANDOFF.md: state, gotchas, next steps
- build.py: disable DH autoUpdater for bench variants (suppress modal)
Everything the next agent needs to run the Phase 2 optimisation loop on a
machine that can launch the client:
- analysis/client-perf/: LEVERS (ranked levers + corrections), BENCH-MATRIX
(world, scenes, config IDs, blocks B0-B14 with decision rules),
PLAYER-TUNING, SPAWN-TUNING, research briefs, the jar scanner and its
output, observed default configs, and proposed-configs/ (build.py
generates tiers and bench variants and fails on unknown keys;
apply_variant.py applies a variant and merges options.txt).
- analysis/client-perf/bench/onion-bench/: bench-world datapack (scene
teleports, Create grid, mob pen, sound storm, 120 s teleport tour).
- analysis/audit/: the static recipe/dependency audit, including gen_fixes.py,
which generates the shipped Paxi datapack and was never tracked.
- phase0/: per-machine measurement harness (Steam Deck, 7700K/1060,
6700K/1080 Ti).
- .pi/journal.md: running work log; read it first.
All of it is packwizignored, so nothing here ships to players.
Move the completed 2026-09 candidate review (MODLIST-REVIEW/-GROUPS,
CANDIDATE-APPENDIX, PACK-CONTEXT), FINDINGS.md and the shipped FTB Chunks swap
write-up into analysis/archive/, with a README mapping their old paths. The
review's build pieces, subagent intermediates and Modrinth API dumps are
deleted: the assembled reports carry their content. MODLIST-GROUPS.md was a
byte-for-byte duplicate of analysis/groups-table.md.
Also: drop the now-pointless FINDINGS/MODLIST packwizignore lines (analysis/
covers the archive), and gitignore *.tar.gz so the 650 MB map-migration world
tarball can't be committed by accident.
FTB Teams was the only thing holding FTB Quests down -- FTB Quests' 1.21.1
build requires it, and its bytecode references dev/ftb/mods/ftbteams in 14
classes including the event handler, so it breaks at runtime without it. With
quests unused, the whole block goes. XMod Compat only bridged
Quests/Chunks/Ranks, all of which are now gone.
FTB Library stays because FTB Backups 3 builds its config UI on it
(Panel/Theme/Widget/ConfigGroup/ConfigValue/SNBTCompoundTag, 13 classes, and
it does not bundle them despite declaring only neoforge). Architectury API
stays because FTB Library references it in 47 classes.
Verified before removing: FTB Library and FTB Backups 3 reference ftbteams,
ftbquests and ftbxmodcompat in zero classes each, and nothing else in the pack
references them.
CurseForge-sourced mods drop from 9 to 5; pack is 146 mods. OPAC's built-in
party system is now the only one, so primaryPartySystem should be left at its
default rather than pointed at ftbteams.
The swap does not carry players' explored terrain across. FTB Chunks stores no
rendered map (its region zips hold chunks.dat plus five data PNGs, one of which
packs height into an image channel), and Xaero's region format is closed and now
version 6 with per-pixel NBT blobs, so the community converters no longer work.
Rather than convert pixels, prune a copy of the world save down to exactly the
chunks a player revealed and let Xaero's own generator map it.
Validated against real data: extracting the 167-region / 98,170-chunk mask
cross-checks clean against FTB's own pixel data, and Anvil pruning round-trips
byte-identically (15.7 MB -> 471 KB on a live region file, slot-to-chunk mapping
confirmed against 1024 chunk NBT headers).
Deferred for now: needs the world save and one singleplayer pass per player.
See analysis/FTB-XAERO-MAP-MIGRATION.md.