docs: client-perf analysis, bench harness and work journal

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.
This commit is contained in:
logan committed 2026-10-14 18:15:32 -04:00
1 parent d80f85b3f6
commit 611a1a5952
102 files changed
+25853

No files matched your search

+413
View File
@@ -0,0 +1,413 @@
# Onion MC — work journal
## Session 2026-10-06 — 60-mod expansion, integration review
### What this is
**Onion MC**, a curated Minecraft modpack managed with **packwiz**.
- Minecraft **1.21.1**, NeoForge **21.1.251**
- **209 mods** (was 149 four commits ago)
- packwiz lives at `~/go/bin/packwiz` — **not on PATH**
- Remote: `ssh://git.ljones.me:2222/logan/onion-mc.git`, branch `main`
- Commit style: Conventional Commits, imperative subject, body explains *why*
- The repo **doubles as a server directory** (`.packwizignore` excludes `libraries/`,
`world*/`, `logs/`, `crash-reports/`, `*.jar`, `run.sh`). Never blanket-un-ignore
anything there — you will index runtime junk.
### Environment (checked 2026-10-06)
- This machine is **NixOS**: no `java` on PATH; use `nix shell nixpkgs#jdk21` for
anything server-side. No server is installed in the repo yet (no `libraries/`,
`run.sh`, or NeoForge jar).
- Client = Prism instance `~/.local/share/PrismLauncher/instances/Onion MC/`. Its
pre-launch hook runs `packwiz-installer-bootstrap` against
`https://git.ljones.me/logan/onion-mc/raw/branch/main/pack.toml`, so launching it
pulls the pushed pack. Last launch (`logs/latest.log`) is **2026-09-24**, i.e.
before all five commits below — confirms the expansion has never been booted.
- `.pi/` is in `.packwizignore`, so this journal never ships.
### State
Five commits, all pushed to `main`, HEAD = `e36bff8`:
| Commit | Contents |
| --- | --- |
| `455e398` | 14 client-side mods + 12 libraries |
| `b6ebdb8` | 11 Farmer's Delight addons + 4 decoration + 4 pet/mob |
| `e371e51` | 15 gameplay/media/social |
| `387ee1e` | config policy change + PetProtect default |
| `e36bff8` | Akashic Tome whitelist config |
Verified after each stage: mod set matches intent exactly (nothing auto-added by
packwiz, nothing missing, nothing removed), `index.toml` hash matches `pack.toml`.
**Two configs ship** (new capability — see policy in gotchas):
- `config/petprotect.json`
- `config/akashictome-common.toml`
### Goal
A **working, well-integrated 209-mod pack**:
1. **Boots clean** on client and dedicated server — no mixin failures, no missing deps.
2. **No duplicate systems** — the pack has a history of removing them (FTB Chunks →
Open Parties and Claims; FTB Quests/Teams/XMod Compat deleted). New mods must not
reintroduce overlapping mechanics without a reason.
3. **No broken recipe chains** — every consumed item stays obtainable.
4. **Performance held** — Sodium, Iris, ImmediatelyFast, EntityCulling, ModernFix,
FerriteCore, Distant Horizons mandatory, C2ME/Noisium server-side, Dynamic FPS.
5. **Tested, not assumed** — nothing has been booted yet.
### Decisions made — do not relitigate without cause
**Excluded candidates:**
- `sable_beyond` — every 1.21.1 build is alpha; wide Create/Aeronautics sublevel-mass
mixin surface. Owner's call.
- `expanded-delight` — beta-only, built against FD 1.2.4 (pack runs 1.3.4); sweet
potato / cranberry / peanut / chili / cinnamon / salt duplicate kept mods.
- `hearth-and-harvest` — no per-crop config, so corn/peanut/cotton/salt/blueberry
dupes couldn't be trimmed. Dropping it also removed two cutting-board collisions
(wheat, sunflower).
- `display-delight` — zero risk but ~250 plate items incl. dishes from Delight mods
we don't run. Could be added any time.
**Rustic Delight dedupe declined.** Its flags are whole content-family switches:
- `enable_cotton` — only dupe partner was hearth-and-harvest (not added).
- `enable_coffee` — real dupe vs extradelight, but cascades into coffee-braised beef,
Haste potions, cherry-blossom/syrup chains.
- `squids_drop_calamari` — also strips calamari from creative tab and villager
trades; `enable_fried_foods` depends on it.
Remaining "duplicates" are tag-merged (`c:crops/coffee_beans` etc.) and benign.
**Kept after being flagged:**
- Grassier Grass — reported shader breakage is Rethinking Voxels-specific; issue
lists Complementary Reimagined (what we ship) as working. BSL bug is separate.
- Perception — OctoLib/ShatterLib is a maintained zero-dep lib; trails are particles,
shake is camera; jar has no shader/post-process assets.
### Open questions for the owner
1. **Potato cutting-board collision → needs a datapack loader.** Only real
unresolved defect. `c:crops/potato` + knife matches both
`extradelight:cutting/sliced_potato` (4×) and `moredelight:cutting/diced_potatoes`
(1×). Neither output is obtainable otherwise; they feed 4 and ~10 recipes. The
losing chain breaks permanently. Fix: rewrite both recipes to emit the combined
output via a datapack loader reading from `config/` (**Paxi** or **Global Packs**)
— a new mod, awaiting approval.
2. **Keep PetProtect?** With both protection flags off it only stops pets being
provoked into fights. Dropping it + config restores vanilla retaliation; Pet
Cemetery works alone.
3. **Keep `mystical-oak-tree`?** Costs Moonlight (2.3 MB) for a 1-in-280-chunk
feature — near-zero value on a pre-generated map. Offered to exclude.
4. **Rustic Delight coffee flag** — one line, if the second coffee should go.
5. **`display-delight`** — add later, or not.
### Known and potential conflicts
| Area | State |
| --- | --- |
| **PetProtect ↔ Pet Cemetery** | Resolved *only* by the shipped config. `isInvulnerableTo` gates on `prevent_pet_damage` alone, so disabling `prevent_pet_death` alone leaves pets immortal. Both flags `false`. Delete the config and Pet Cemetery is dead weight. |
| **extradelight recipe overrides** | 169 files under `data/farmersdelight/recipe/`, ~25 path-colliding with FD's own. Live, ungated. FD recipe book changes noticeably. |
| **Twilight Forest stripping (16 pairs)** | `farmers-cutting-twilight-forest` and `twilight-delight` both cut TF logs into `stripped_X` + `tree_bark`. Identical outputs — harmless. Pre-existing. |
| **Curios slot merging** | `artifacts`, `too-many-bows`, `tarotcards-remastered`, `mermod` define player slots, no `replace`. Should merge — **verify in game once**. |
| **Sophisticated Core disc handlers** | Verified clean: first-supports-wins, predicates disjoint. |
| **`dungeons_delight`** | **29 vanilla mixins** incl. `BlockBehaviourMixin`/`LevelRendererMixin`. Broadest surface added. Untested vs ModernFix/Sodium. |
| **`fowlplay` spawning** | ~13 bird species via `NaturalSpawnerMixin` — spawns in already-generated chunks. Watch tick time. |
| **`fishermans-haven`** | Lighthouse spacing 9/separation 6 (dense); several biome modifiers use **bare un-namespaced biome IDs** (may log errors / silently not spawn). Salt lakes in every biome via `neoforge:any`. |
| **`extradelight` legacy `forge/` biome modifiers** | Inert on NeoForge (working `neoforge/` copies exist). Harmless. |
| **`etched` ↔ `music-disc-maker`** | No code conflict (mixin points re-verified), but duplicate content: two blank discs, two boomboxes, two 9-disc albums, two recording pipelines. Design decision. |
| **Tag merges** | Several mods write the same `c:` crop tags (3 garlics, 3 peanuts, 3 salts, 2 corns…). Benign. **Bell pepper and citrus NOT merged** (`crops/bellpepper` vs `crops/bell_pepper`, `crops/lemon` vs `foods/fruits/lemon`). |
### Not verified — nothing has been booted
All findings are static analysis (jars, bytecode, data files, Modrinth API). Untested:
- Whether the pack **boots at all**, client *and* server.
- `dungeons_delight`'s 29 mixins vs the perf stack.
- Grassier Grass vs **Complementary Reimagined** and **MakeUp Ultra Fast** (MakeUp
untested by anyone).
- Whether Terralith biomes carry `#c:is_*` / `#minecraft:is_overworld` tags that
wild-crop/tree biome modifiers key off (generation density only).
- Whether `fishermans-haven`'s bare-ID biome modifiers parse.
- Whether `extradelight`'s inline-feature `neoforge:` biome modifiers place.
- Whether `extradelight`'s cookbook opens (ships `patchouli_books/cookbook2/` dirs but
**no `book.json`**). The item itself is real.
- `room-for-two` (beta; compat untested by author) and `petprotect` (beta).
- PetProtect edge case: logging out while downed may lose items (upstream #184,
1.19.2, never fixed).
- Curios slot merge rendering all four mods' slots.
### Method notes and gotchas
- **packwiz `side` quirk**: only client-only mods are special-cased; mods with
`client_side: unsupported` still get `side = "both"`. `petprotect` manually set to
`side = "server"` (as `c2me-neoforge` and `noisium` already were).
**`packwiz update` rewrites metafiles and resets these.**
- **Config policy is opt-in.** `.packwizignore` ignores `config/*` and
`defaultconfigs/*`; shipping a file needs `!config/<file>` at the **bottom** (last
match wins), after the blanket `*.json` rule.
- **Duplicate `version_number` traps**: `tarotcards-remastered`, `room-for-two`,
`too-many-bows` reuse version strings across 1.21.1 / 1.21.11 / 26.x. Pin exact
filenames by hand.
- **Undeclared deps on Modrinth**: `perception` → `shatterbyte-lib` (OctoLib),
`dungeons_delight` → `runiclib`. `mystical-oak-tree` → `moonlight` is declared in
the jar but not the API.
- **cdn.modrinth.com returns HTTP 501 to Range requests** — download whole jars.
`unzip` is not installed; use `python3 -c "import zipfile..."`.
- **`lodestonelib`** is the real slug; `lodestone` has no 1.21.1 build.
- `FINDINGS.md`, `MODLIST-GROUPS.md`, `MODLIST-REVIEW.md` are untracked,
packwizignored, and **~60 mods stale**. They hold the FTB-swap reasoning, OPAC
config decisions and the original per-mod compat audit — refresh, don't re-derive.
### Next steps, in order
1. **Boot the pack.** Client first (launch the Prism instance — it self-updates from
the pushed `pack.toml`), then the dedicated server.
2. Check logs for: missing deps, mixin apply failures, `fishermans-haven`
biome-modifier parse errors, anything referencing `dev/ftb/mods/ftbteams`
(soft-dep risk from the FTB removal).
3. Smoke-test: Grassier Grass + Complementary Reimagined, `dungeons_delight` mixins,
curios slots, Pet Cemetery death→collar loop.
4. Watch tick time and entity counts (fowlplay, fishermans-haven, mooblooms).
5. Bring open questions to the owner, potato collision first.
## Static audit 2026-10-06 (all 209 jars + vanilla + NeoForge data)
Scripts/output: `analysis/audit/` (jars cached in `/tmp/onion/jars`, ephemeral).
Deps clean (no missing/out-of-range/incompatible; lambdynlights_runtime is a
false positive — nested under META-INF/jars). No item-tag load failures.
Corrections to the handoff:
- Potato board collision is **3-way**: + `rusticdelight:potato_slices` (81
consuming recipes, board-only source). Vanilla `getRecipesFor` sorts by result
translation key, so `extradelight:sliced_potato` likely wins; rustic + moredelight
lose. moredelight diced potatoes/bread slices still reachable via Create saw.
- New: bread + knife → extradelight vs moredelight bread slice.
- rusticdelight tags `potato_slices` as `c:crops/potato` (re-cut/dupe loop);
veggiesdelight tags sweet potato there too. rustic coffee beans sit in both
`c:crops/coffee` and `c:crops/coffee/cooked`.
- extradelight *disables* 14 FD recipes (relocated to oven/mixing bowl/feast/
chiller — all still obtainable); FD beef_stew is rustic-live vs
extradelight-disabled → load order decides.
Crafting-grid collisions (one output uncraftable): dungeonsdelight vs
twilightdelight TF knives (×4); dungeonsdelight vs frightsdelight crates (×2);
extradelight vs fruitsdelight apple crate, vs hamsterpets cucumber crate; coffee
bag/sack/crate; comforts sleeping bag (vertical) vs handcrafted sheet; fishermans
worms can → own worm vs aquaculture worm. Pre-existing: handcrafted wood plate vs
17 TF drying racks; create vs TF copper nugget (tag-unified, harmless).
## Fix pass 2026-10-06 — pushed as `fc649b4` (on top of `e7d6691`)
- Added **Paxi** 5.1.3 (only dep YUNG's API, already present; injects packs at TOP).
- Datapack `config/paxi/datapacks/onion-fixes/` (43 files), generated by
`analysis/audit/gen_fixes.py` — edit the script, not the JSON. Shipped via a
dir-by-dir re-include chain at the bottom of `.packwizignore` (packwiz's
matcher needs negations *without* trailing slashes or it SkipDirs the parent).
- Re-audit with the pack on top: all real collisions gone. Remaining flags are
benign (dough shaping UI, mixing-bowl fluid variants, Aquaculture Delight
neptunium tiering, Create/TF copper nugget).
- Correction: rustic potato_slices has 3 direct consumers, not 81 (81 was via
the polluted `c:crops/potato` tag).
- `c:crops/potato` and `c:crops/coffee/cooked` now use `replace: true` — any
future mod adding to them must be added to gen_fixes.py.
- Orphaned on purpose (uncraftable, still uncraftable-from): dungeonsdelight TF
knives + crates, hamster cucumber crate, fruitsdelight apple crate. Consider
hiding them in JEI.
- Needs in-game check: `/datapack list` shows onion-fixes (pink), recipes in JEI.
- Rebased over upstream `0adfb6c` (Icy's Better Horses + Modonomicon, 212 mods);
re-audit clean. Note: Better Horses' modId is `icys_better_horses` but it
registers under `icys-better-horses` — the audit's absent-mod check flags it
falsely.
## Session 2026-10-14 — client performance analysis, Phase 1 (static baseline)
HEAD `aa1d273` (212 mods), unchanged. **Nothing committed, nothing changed in the
pack.** All output is in `analysis/client-perf/` (untracked; `analysis/` is
packwizignored).
### What exists now
- `analysis/client-perf/LEVERS.md` — **the deliverable**: ranked levers (Tier 1–3),
meta-levers, add/remove candidates, Phase 2 test order, corrections to the
subagent research. Read this first.
- `analysis/client-perf/README.md` — index and method.
- `scripts/jarscan.py` + `scripts/report.py` → `data/jarscan.json`,
`data/jarscan-report.md`. Parses class-file annotations for real `@Mixin` targets
and injector kinds, per-frame/tick event refs, atlas px (one frame per animated
texture), models, shaders, sounds and entities. It skips the Fabric-only nested
jars of multi-loader jars (DH, LambDynamicLights). Runs in ~35 s over
`/tmp/onion/jars` (ephemeral; refetch with `analysis/audit/fetch.py`; resource
and shader packs were also dropped there).
- `data/observed-default-configs/`: generated configs copied from the Prism
instance's last launch (2026-09-24, the older 110-mod pack). They are the
real-default reference (DH, Sodium, EMF, ModernFix, Flywheel, Sable, SPR…).
- `research/r1..r9-*.md`: nine subagent briefs with confidence tags and URLs.
### Key facts established (verified)
- 951 per-frame mixin classes (121 Overwrite/Redirect); top: Sable 127, Iris 114,
Controlify 84 (GUI), Sodium 48, EMF 42.
- Handcrafted + Chipped + Rechiseled = 58% of the block atlas and 62% of the 69k
models.
- Flywheel 1.0.x disables both GPU backends when *any* shaderpack is active
(checked in `Backends.java`). The pack has no Iris Flywheel Compat.
- DH defaults: LOD radius 256, SSAO and AA on, 2 worker threads. EMF
`animationFrameSkipDuringIrisShadowPass` is already true. ModernFix
`dynamic_resources` is off by default. Flywheel `lightSmoothness = SMOOTH`.
- Sable renders each sub-level by re-driving Sodium's chunk renderer.
`sub_level_skylight_shadows=false` by default; Iris #3164 (sub-level corruption
with shadows) is open.
- Chipped requires Athena and Rechiseled requires Fusion, so neither CTM engine is
removable. Lodestone is required *only* by Miner's Delight.
- Puzzles Lib 21.1.64 has an event-dispatch caching fix; the pack pins 21.1.62.
- Shaders and resource packs are opt-in in practice (the last launch had none
enabled). The pack ships no perf config, and JVM/heap is per-player Prism (old
instance: 8 GB, stock G1).
### Decisions pending (owner)
1. Delivery mechanism for tuned defaults: **Default Options** mod (Balm is already
present) vs packwiz `preserve = true` (semantics with `packwiz refresh`
unverified).
2. Shader policy: default off / opt-in per machine?
3. Server-side spawn tuning (Alex's Mobs #62, Fowlplay #214, Critters &
Companions datapack).
4. Removal candidates: Miner's Delight (drops Lodestone), Fowlplay, Charta, WATUT,
Emojiful.
5. Add candidates: Default Options, Sodium Extra + Reese's Sodium Options,
Particle Core, BadOptimizations; trials: Gnetum, Better Block Entities,
Flerovium, Super Resolution (Deck), Ixeris (P1), Iris Flywheel Compat.
### Next steps
- Phase 2 = benchmark per `LEVERS.md` §6 using the `phase0/` harness (P0 Deck, P1
7700K/1060, P2 6700K/1080 Ti with 8 GB RAM free). Capture the atlas size, heap and
startup time at baseline.
- Before benchmarking: the pack has never booted at this mod count (see the
2026-10-06 session), so do a boot/log check first.
- Free change regardless of benchmarks: bump Puzzles Lib to 21.1.64.
## Session 2026-10-14 (b) — client perf Phase 1b: delivery, staged configs, bench matrix
HEAD `aa1d273`, unchanged. **Nothing committed; zero tracked-file changes; no mods
added/removed.** All output is under `analysis/client-perf/` (untracked, packwizignored).
### Produced
- `proposed-configs/` — `build.py` generates player tiers (`out/T-default|deck|mid|high`)
and 32 bench variants (`out/C0`, `C1`, `dh-*`, `fw-*`, …) from same-version observed
defaults or source-verified templates. **The build fails if an override names a key
that isn't in the base**, so key confirmation is enforced. README §1 = M1 decision,
§2 = tier table, §3 = key provenance.
- `BENCH-MATRIX.md` — replaces LEVERS §6: bench world recipe, scenes S1–S6, JVM sets J0–J3,
blocks B0–B13 with decision rules and budget (~25 h machine time).
- `bench/onion-bench/` — datapack (pack_format 48): scene teleports, `/fill` Create grid
(2,304 kinetic BEs), mob pen, a 24-sounds/tick storm, and a 120 s teleport tour.
**Never run in game**: syntax unverified, and the S2 `/fill`-placed kinetic network may
need motors re-placed by hand (checklist in matrix §2).
- `PLAYER-TUNING.md` — tiers, heap/GC, shader and RP guidance, Deck env vars.
- `proposed-changes/puzzles-lib-21.1.64.patch` — `git apply --check` passes on HEAD.
It touches only `puzzles-lib.pw.toml` + index/pack hashes. A single-mod
`packwiz update puzzles-lib` does **not** reset the side fields on petprotect, c2me or
noisium; only those three are at risk, from bulk updates. Its only dependent is
HeldItemTooltips, range `[21.1.1,)`.
### Verified this session (don't re-derive)
- **packwiz `preserve`** (packwiz `ef87d96` = the installed binary; installer v0.5.14 =
the Prism jar): settable only by hand-editing `index.toml`. It survives refresh, content
change and unrelated `update` (tested). It is **silently dropped** if a refresh runs
while the file is absent or ignored. The installer writes the file only if it's absent.
A skipped file re-logs "invalidated" every launch, and removing a file the installer
wrote deletes the player's copy. Index files have no `side`, so they also land on the
server (this repo *is* the server dir).
- **Default Options 21.1.8**: copy-if-absent for `config/defaultoptions/options.txt`
(`key_` lines stripped) and `config/defaultoptions/extra/**`. Runs at `GameConfig.<init>`:
before NeoForge constructs mods (`ClientModLoader.begin` is inside `Minecraft.<init>`),
but after mixin bootstrap, so too late for `modernfix-mixins.properties`. Balm
`[21.0.39,)`; the pack has 21.0.66.
- Observed defaults come from the **same jar versions as the current pins** (DH 3.3.2,
Sodium 0.8.13, EMF 3.3.9, Create 6.0.10 / Flywheel 1.0.6, Sable 2.0.5, SPR 1.5.1).
All 172 DH values match `Config.java` @ 3.3.2, except DH `numberOfThreads`: the true
default is ceil(nproc/2) = **4** on the fleet (the observed 2 came from this 4-thread
box). `serverId` is per-install random and is stripped from shipped files.
- SSRD 1.8.7 config = `config/ssrd-common.toml` (COMMON; the server reads it too).
`physicsRenderDistance` defaults to 128, slider floor 16.
- LambDynamicLights 4.8.11 = `config/lambdynlights.toml`; `mode` is lowercase
off/fastest/fast/fancy; `[light_sources] entities`.
- SPR merges a partial `sound_rates.properties` over its generated defaults. Sounds over
the cap play without physics; they are not dropped.
- **Puzzles Lib 21.1.64 has no perf change on NeoForge**: `FabricEventFactory` isn't in the
NeoForge jar. The 62→64 diff is access transformers plus one class. LEVERS #14 is
corrected.
- r6's `-XX:ShenandoahGCMode=iu` aborts JDK 21 without UnlockExperimentalVMOptions
(tested). GenZGC and the brucethemoose G1 set parse cleanly.
### Owner decisions pending (presented 2026-10-14)
1. Approve **Default Options** as the delivery mechanism, plus enforced
`modernfix-mixins.properties`. This is a mod add plus 3 `.packwizignore` lines (drafted in
proposed-configs README §1).
2. Apply the Puzzles Lib patch (bugfix only).
3. Shader policy (B7 produces the data).
4. Server spawn tuning (Alex's Mobs / Fowlplay / Critters & Companions).
5. Removal candidates (Miner's Delight → Lodestone, Fowlplay, Charta, WATUT, Emojiful).
6. Add candidates (Sodium Extra + RSO, Particle Core, BadOptimizations; trials). These gate
B12.
### Next steps
1. Boot check (matrix §0). Nothing else can proceed until the pack boots.
2. Build the bench world on P2 (matrix §2); fix any datapack parse errors on `/reload`.
3. Run B0 → B13; write the winners into `build.py`; regenerate; then ship via the approved
mechanism. Existing players need the file-reset step in PLAYER-TUNING §1.
## Session 2026-10-14 (c) — owner decisions applied, pushed for the client machine
The owner answered the pending list; this session acted on it, committed, and pushed.
**The next agent works on a machine that can run the client.** This machine is NixOS with
no `java`, no client and no `unzip`. Those notes are machine-specific; check what the new
machine has.
### Owner decisions (2026-10-14), now settled
1. Delivery = **Default Options** (+ enforced `modernfix-mixins.properties` after B6).
Done.
2. Puzzles Lib → 21.1.64. Done (bugfix only).
3. Shaders: **opt-in** (already the case: packwiz downloads them, nothing enables them).
4. Spawn tuning allowed if not detrimental to gameplay. Done, moderate (below).
5. **Remove no mods.** LEVERS §5 is reference only.
6. Add any helpful mods. Added the five "Add" verdicts. Trials are left to bench B12b, and
the agent may add trial winners.
### Commits (all pushed to `main`; Prism instances self-update from it)
- `a01bc3b` feat(perf): Default Options + `config/defaultoptions/` (8 provisional
mid-tier files from `build.py --ship`); Sodium Extra 0.9.4, Reese's Sodium Options 2.2.4,
BadOptimizations 2.4.1, Particle Core 0.3.3 (all `side = "client"`; deps already present);
Puzzles Lib 21.1.64. **217 mods.**
- `5919955` chore: stale reviews archived to `analysis/archive/` (README maps old paths);
intermediates and API dumps deleted; `*.tar.gz` gitignored.
- `d80f85b` feat(config): spawn tuning, enforced partial files
`config/alexsmobs-common.toml`, `config/fowlplay.json5`,
`config/crittersandcompanions-common.json5`. See `analysis/client-perf/SPAWN-TUNING.md`.
- docs commit: `analysis/client-perf/` (minus the generated `out/`), `analysis/audit/`
(incl. `gen_fixes.py`, which builds the shipped Paxi datapack and was never tracked
before), `phase0/`, and this journal.
### Rules of the road for the iteration
- Change tuned defaults **only** through `analysis/client-perf/proposed-configs/build.py`
(`DEFAULT` / `DECK` / `HIGH`), then `build.py --ship`, then `~/go/bin/packwiz refresh`
(wherever packwiz lives on that machine), then commit.
- Shipped defaults are copy-if-absent. Changing them reaches **fresh installs only**;
existing players use PLAYER-TUNING §1.
- `modernfix-mixins.properties` ships only after B6 passes. Instructions are in the `SHIP`
comment in `build.py`.
- Any new mod: verify its NeoForge 1.21.1 build and its `neoforge.mods.toml` ranges against
the pins, check `side`, rerun B0. **More Culling is unusable**: its NeoForge build
declares `minecraft [1.21,1.21.1)`.
- `packwiz update` (bulk) resets the hand-set `side = "server"` on petprotect, c2me-neoforge
and noisium. A single-mod update is fine.
- On first boot, the mods re-save the partial spawn files in full. Don't commit those
expansions by accident (`git diff config/`).
- `sp-world.tar.gz` (650 MB, untracked, gitignored) is a world save from the map-migration
work. Leave it alone.
### Next steps
1. BENCH-MATRIX §0 boot check (now covers Default Options seeding, the RSO/SSRD video
screen, YACL spawn-config loading, and the Iris↔Sodium report).
2. Build the bench world (§2), then run B0 → B14. Write the winners into `build.py`, ship,
refresh, commit.
3. Report shader-policy data (B7) and any trial-mod verdicts (B12b) to the owner.