PROCITY/docs/LANES/LANE_E_NOTES.md
m3ultra 0c12dacb6d Lane E round 7 (E2): GODVERSE stock-pack pipeline (parody + atlas + index), proven
pipeline/build_stock_pack.py builds C's ?stock=real pack offline (nothing queries the
dataset at runtime): recordgod (dealgod discogs_release) → curate → parody-transform
title/artist (deterministic, shares no source token — no real trademarks) → atlas WebPs
+ JSON index {id,title,artist,price,price_band,atlas,uv}. Proven end-to-end with
--sample 24 (synthetic sleeves); sample pack staged to web/assets/models/ so Lane C
wires ?stock=real against the real index format now. Real 200-400 pack blocked on
GODVERSE_DSN (dealgod Postgres creds — flagged to Fable) + C's schema confirmation;
one command (--from-db --count 300) once they land.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 00:43:08 +10:00

154 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# LANE E — cross-lane notes
## Round 7
**→ Lane D (D1 — the flip gate): merged peds ready to validate.** `web/models/peds/*.glb` (19 rigs)
are merged to **ONE draw each** (1 primitive + 1 atlased material) — fleet **92→19 draws**, at the
24-rig near cap **116→24**. Method: Blender join + UV-pack + EMIT-bake all materials into one 1024
atlas (`pipeline/merge_ped.py`). **Skinning + skeleton preserved** — 65 joints intact on all 19,
`walk`/`idle` untouched, so clips retarget unchanged. I verified in the vendored GLTFLoader: all 19
load as SkinnedMesh + bind walk; `man_suit` poses to byte-identical dims vs the original (skin
deforms unchanged); `man_athletic` (3-mat) atlas eyeballed correct. Please do the full pass
(silhouettes/materials/impostor bake/identity variety) + the **full-density draws/tris numbers** for
F's flip. Pre-merge peds backed up (gitignored) at `pipeline/.peds_r6/` if you need a diff; per-ped
in `pipeline/_peds_merge.json`. **If any ped's atlas/silhouette reads wrong, name it — I re-run that
one** (per-ped `atlas` size is tunable; a couple with dense detail could go 2048).
**→ Lane C (E2 — stock pack): pipeline built + PROVEN, sample staged for you now.**
`pipeline/build_stock_pack.py` produces the pack (parody-transform → atlas WebPs + JSON index). A
**24-sleeve sample pack is staged at `web/assets/models/stock_record_{index.json,atlas_00.webp}`**
wire `?stock=real` against it NOW (real index format, synthetic covers), and the real covers drop in
unchanged. **Proposed index schema** (I built to this — confirm/adjust in LANE_C_NOTES and I'll match
`INDEX_FIELDS`):
```json
{ "version":1, "atlas_px":2048, "cell":256, "atlases":["stock_record_atlas_00.webp"],
"items":[ {"id":"rec_0000","title":"Neon Suburbs","artist":"Trev Wollemi","price":39,
"price_band":"collector","atlas":"stock_record_atlas_00.webp","uv":[0,0,0.125,0.125]} ] }
```
`uv` = [u0,v0,u1,v1] into the named atlas (origin top-left); price_band ∈ bargain/standard/collector/grail.
Seeded pick per bin is yours (same shop.seed → same crate). Fail-soft: pack missing → parody canvas.
**→ Fable (E2 blockers — flagging mid-round per your schedule-harness note):** the real 200-400 pack
needs two things I can't self-serve: (1) **`GODVERSE_DSN`** — the dealgod Postgres dsn/creds (Postgres
is up on :5432; I read it from env, don't hunt creds) → `--from-db --count 300`; (2) **C's schema**
confirmation. Both external. The pipeline + parody law + atlas are done and proven on `--sample`; the
real pack builds in one command once the DSN lands. Not blocking C's consumer wiring (sample staged).
## Round 6
**E1 done**`publish.py` now merges into `_published.json` (no more R5 clobber); `--verify` +
post-publish drift-check vs the live depot; `validate_manifest.py` fails if a manifest GLB isn't in
`_published.json`. Record verified 27==depot. All 27 procity GLBs stay live + recorded.
**→ Lane B / Lane C — I'm on-call for the props I shipped:**
- **B:** if `bus_shelter` / `bin` need a scale, origin, or facing tweak once placed on the street
graph, tell me the exact issue (current: bus_shelter 2.33×1.41 m / 2.4 m, bin 0.57×0.68 m / 1.0 m,
both base-origin minY=0). I can re-normalize + re-publish same-name (idempotent, merge-safe now).
- **C:** if `glass_case` / `magazine_rack` / `crate_stack` read wrong in-room (scale, the fal
glass_case's interior clutter, the magazine_rack density), flag it. A *broken*-prop fal re-gen is
pre-authorized ≤2 attempts (decision #5) — I'll log any spend in AUDIT. Footprints in the manifest;
all base-origin. Mapping guidance for the 3 orphans is in the Round-5 → Lane C section below.
## Round 5
### → Lane C: hero props BAKED to ≤8k tris — re-measure the record interior
The 6 heavy TRELLIS props are re-baked and **live on the depot** (same filenames, footprints
unchanged, so **no re-map needed** — they upgrade in place):
| prop | tris before → after |
|---|---|
| drinks_fridge | 77k → 8.0k |
| milkshake_mixer | 73k → 8.0k |
| listening_booth | 54k → 8.0k |
| counter_till | 32k → 8.0k |
| novelty_record | 26k → 8.0k |
| arcade_cabinet | 25k → 8.0k |
**Fleet 288k → 48k tris.** Method: voxel-remesh → decimate → Cycles base-colour bake (see
`pipeline/bake_lowpoly.py`, AUDIT R5). Verified loading in the vendored GLTFLoader; base colour
baked (no separate metallic/normal maps → also dodges the record_crate dangling-texture class).
**Please re-measure the record interior** (was ~273k tris in your R4 note) and record the new
number in LANE_C_GLB_VALIDATION.md — it should drop by ~most of the prop weight.
### → Lane C: 3 new fittings LIVE (fal Hunyuan) — glass_case + magazine_rack
The two remaining primitive-only fittings are now real GLBs on the depot (≤8k, base-colour baked):
- **`glass_case`** (`procity_fit_glass_case_01.glb`, 1.08×1.42 m, 1.0 m tall) — timber base + glass
panels + items inside. Registry ids `glass_case` (toy/dept) + `glass_cabinets` (pawn) both alias
to it. → add `glass_case`/`glassCase` (+ your pawn cabinet kind) → `'glass_case'` in `KIND_TO_GLB`.
- **`magazine_rack`** (`procity_fit_magazine_rack_01.glb`, 0.54×0.44 m, 1.2 m tall) — tiered timber
rack w/ magazines (milkbar/pawn). Registry `magazine_rack` aliases to it. → map your kind → `'magazine_rack'`.
- Both base-origin, verified loading in the vendored GLTFLoader. `manifest.fittingAliases` also maps
`fridge`→`drinks_fridge` and `listening_corner`→`listening_booth` if you iterate registry ids.
### → Lane B: new street props — `bus_shelter` + `bin`
- `procity_street_bus_shelter_01.glb` (`furniture.bus_shelter`, 2.33×1.41 m, 2.4 m, ≤8k, base-origin).
Solid painted-steel shelter (back wall + roof + bench) — place at bus-stop spots along the footpath.
- `procity_street_bin_01.glb` (`furniture.bin`, 0.57×0.68 m, 1.0 m, 3k) — red council wheelie bin, an
obvious town-furniture gap. Map `bin` in your furniture GLB-upgrade path if you want it on footpaths.
- **B3 resolved:** `novelty_record` is now **8k** (was 26.5k) via the E1 bake — re-measure the busy view.
All furniture GLBs base-origin + footprint-accurate; fail-soft as usual.
### → Lane C also: `crate_stack` for floor piles / dig
`procity_fit_crate_stack_01.glb` (`fittings.crate_stack`, 0.71×0.72 m, 0.9 m, 3k) — a stack of 3
plastic milk crates, good for record-store floor dressing or the dig scene. Optional; map a kind to
`'crate_stack'` if useful.
### → Fable: E1 (bake) + E3 (fal) status
- **E1 bake DONE + committed** — 6 props ≤8k, published. Feeds C's re-measure + your v1.1 tag.
- **E3 fal DONE** — glass_case + bus_shelter + magazine_rack generated on fal Hunyuan v2, **~$0.64
total** (log in AUDIT R5), ≤2 attempts each, all baked ≤8k + published. Guardrail held (nothing
else on fal). `validate --depot` 0 err. Last two primitive-only fittings retired.
- **E2 depot growth** next (v2-serving library props).
---
## Round 4
## → Lane D (task D2): decimated peds ready to validate
The 19 ped rigs in `web/models/peds/` are decimated and staged (committed `518678d`, ref
`lane-e/round4-peds`). Please validate rig binding + animation:
- **≤3k tris each** (range 15642805; per-ped before/after in `pipeline/_peds_decim.json`).
Fleet total **924k → 46.5k tris** (48.6k → 2.45k avg). At the 24-rig near cap ≈ **≤67k**.
- **Skinning preserved**: `JOINTS_0`/`WEIGHTS_0` intact; **skeleton unchanged** (nodes + 65
joints identical to source on every ped I checked), so the shared `walk.glb`/`idle.glb`
clips retarget unchanged. **`walk.glb`/`idle.glb` were NOT touched.**
- Method: `gltf-transform weld``simplify --ratio 0.05 --error 0.12` (meshoptimizer — works
because these are manifold skinned meshes, not R3 TRELLIS shell-soup). Contact sheet:
`docs/shots/laneE/peds_decimated.png` (silhouettes/textures clean at street distance; fingers
merge + faces flatten as expected at 3k, no melting).
- Originals backed up (gitignored) at `pipeline/.peds_orig/` if you need a before/after diff.
If any rig fails to bind/animate or a silhouette reads badly, tell me the file(s) and I'll
re-run that one with a gentler error (0.08 keeps ~50% more tris but still <5k). Then F re-measures
gate 3 after your sign-off.
## → Lane C: E2 asset re-exports
1. **`procity_fit_record_crate_01.glb` FIXED.** Root cause of your `undefined 'uri'` crash: the
material's `metallicRoughnessTexture` + `occlusionTexture` both pointed at a **sourceless
texture** (the packed AO/roughness map failed to encode to WebP during normalize; base-colour
+ normal were fine). Fix: `pipeline/fix_glb_textures.py` strips material slots that reference a
sourceless texture (orphaning it three.js loads textures lazily, so no crash). **Verified it
loads in the real vendored `GLTFLoader`** (meshes=1, tris=5000, textures ok) alongside a
bookshelf control. Re-published to the depot re-map `record_crate`/`recordBin` in `glb.js`
(they should already be mapped) and it'll upgrade instead of falling back.
2. **counter-with-till — LIVE.** New fitting `counter_till` (`procity_fit_counter_till_01.glb`):
**1.61 × 0.64 m footprint, 1.15 m tall**, timber counter + cabinet doors + period beige till on
top (flux_local concept trellis_mac, on-device). Fixes the R3 4 m till-less counter that
squashed. **Verified it loads in the vendored `GLTFLoader`** (32k tris TRELLIS shell-soup floor,
within decision-#2's 2577k for focal props) and **live on the depot** (`validate --depot` 0 err).
**In `glb.js` re-add `counter` to `KIND_TO_GLB` mapping to `'counter_till'`** (NOT the old
`counter` = balcao, which is a 4 m long bar counter kept for shops that want it). The manifest
`fittingAliases.counter` `counter_till` too. It's base-origin (minY=0), so your footprint-fit +
floor-plant works unchanged; at a 1.42.0 m counter slot it scales to a believable ~1.01.4 m
tall counter.
## → Fable: status
- **E1 (gate-3 critical path): DONE.** Peds 3k, committed + pinned. Unblocks D2 F3.
- **E2a record_crate: DONE + verified** (loads in vendored GLTFLoader). Re-published.
- **E2b counter: in progress** (local, on-device no fal spend per decision #3).
- Not doing: fal.ai spend (glass-case/bus-shelter stay parked), hero-prop bake-to-lowpoly.