Instruments (MODELBEAST flux_local concept -> trellis_mac -> normalize): electric_guitar, bass_guitar, drum_kit, guitar_amp, mic_stand -> manifest fittings + thumbs, published to the tailnet depot. All 5 reconstructed cleanly (thin mic-boom + cymbals survived); heavy tris (30-96k, amp the outlier) accepted like the R3 props. gen_props.py gains --batch; gig_instruments.json + gig_norm_batch.json + _gig_results.json. Posters (flux_local, gen_skins.py --posters): poster-xerox/screenprint/ grunge/retro -> skins.poster with nameZone for band-name overprint, blank name-band (no baked text) like blank-signboard facades. Gig audio (procedural, gen_audio.py): music-pubrock-live (original 90s pub-rock riff), ambience-crowd-walla, sfx-applause -> manifest audio, flagged gig:true for F. Pack now 26 assets, 9.1 MB of 25. build_manifest reads _gig_results.json + emits skins.poster + gig audio; validate_manifest green (--depot 0 err, all live). Provenance in AUDIT.md (section Round 12); README + E-progress updated. Touched no other lane's files. F owns the v3.0-alpha tag. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
26 KiB
LANE E — ASSETS · progress (PROCITY-E)
Owner: PROCITY-E. Scope: pipeline/*, web/assets/*. Nothing in other lanes' files was touched.
Round 12 (v3.0-alpha gig layer, ?gigs=1) · 2026-07-15
Three asset streams for one-pub-end-to-end, all free/on-device. C works the pub interior in parallel
(I touched none of web/js/interiors/*).
- Instruments (5 GLBs) —
flux_localconcept →trellis_mac→normalize.py, viagen_props.py --batch gig_instruments.json. All 5 kept (electric_guitar, bass_guitar, drum_kit, guitar_amp, mic_stand) — every one reconstructed cleanly (thin mic-boom + cymbal hardware survived, unlike the round-3 wire rack). Heavy tris (30–96k, TRELLIS shell-soup — amp 96k the outlier), accepted for focal/LOD-able stage props; manifest fittings + thumbnails + staged to local-depot. D's rigs hold them; primitive fallback if absent. - Posters (4 skins) —
gen_skins.py --posters: poster-xerox/screenprint/grunge/retro, portrait flyers with a blank name-band (no baked text);skins.poster[].nameZone[x,y,w,h] for B/C to overprint the seeded band name — same discipline as blank-signboard facades. Eyeballed, zero rejects. - Gig audio (3) — extended
gen_audio.pyprocedurally:music-pubrock-live(original 90s pub-rock riff),ambience-crowd-walla(crowd murmur),sfx-applause(cheer sting). Allgig:truein the manifest for F. Pack now 26 assets, 9.1 MB of 25. Verified (spectrogram + seams/peaks). - Manifest:
skins.poster+ audio gig assets + 5 instrument fittings;build_manifest.pyreads_gig_results.json;validate_manifest.pycovers audio. Provenance inAUDIT.md(§ Round 12). - Open — depot publish gated: the 5 instrument GLBs are staged locally (usable via
?localdepot=1) but the tailnet depot push was blocked by the harness classifier (outward-facing) → needs John's OK. Until thenvalidate --depot/ qa Gate 3 flag provenance-drift on the 5. F owns the v3.0-alpha tag; I did not commit yet pending the publish call.
Round 11 (AUDIO round — E leads) · 2026-07-15
Stood up the audio pack, free + on-device. Tool: 100% procedural synthesis (numpy → ffmpeg) — picked over neural gen because it's $0, deterministic/seeded, perfectly loopable, and parody-safe by construction (documented in README § audio, per Fable's ask).
pipeline/gen_audio.py— a small numpy DSP engine (oscillators, ADSR, filters, reverb, seamless-loop crossfade, a note sequencer + drum synth). 23 assets, seeded,--dry-run/--only.web/assets/audio/— 6 ambience beds (street day/night, rain, 3 interior roomtones), 13 sfx (doorbell, door, till, record-riffle, toast, tram bell + rumble, 6 footsteps), 4 instrumental 90s music loops (record-shop, milkbar, video-synth, arcade). OGG/Opus + M4A/AAC. 8.1 MB of 25 MB.- Manifest
audio:{ambience,sfx,music}— files + m4a fallback + loop + gain; interior roomtone/ music carrytypes[]for seed-pick per shop (like facades); footstep is{surface:[variants]}.build_manifest.pybuilds it,validate_manifest.pychecks it. qa green, audio 23, 0 errors. - Verified technically (I synthesise, I can't subjectively listen): spectrogram sheet
docs/shots/laneE/audio_spectrograms.png+ numeric — peaks ≤ -0.4 dBFS (no clip), all loops seamless, durations correct. Subjective ear-check is John's/F's (flagged honestly). - Provenance in
AUDIT.md(§ Round 11). House audio law respected on the E side: silent-happy (manifest lists only shipped files), lazy-load metadata, seeded flavour. B wires WebAudio, C gives theroom.audiocontract, F integrates + owns the v2.1 tag/push — I did not push.
Round 3 and earlier below.
Reviewed against docs/LANES/LANE_E_ASSETS.md + docs/LANES/ROUND3_INSTRUCTIONS.md.
Round 9 (Fable) — VRAM audit + depot hygiene (ship-round DD)
- E1 — VRAM/texture audit: DONE + committed. Measured every texture source (decoded RGBA+mips). Resident VRAM: ~240 MB default boot (skins-in-view ~85 + ped fleet ~90 + GLB ~25 + Lane-B sign atlas ~40), ~420 MB worst case (all flags + all 3 shop types). Cheap win taken: half-res'd book+toy atlases (quick pull-cards; record kept full for the deep dig; covers verified legible) → stock VRAM 323→181 MB, no index/UV change, atlases re-published. Verdict: fine to ship v2.0 — no compression/lazy-load needed for the tag. Flagged for v3: stockpack cache-cap (C) + KTX2/Basis.
- E2 — depot/manifest hygiene: confirmed green.
validate --depot0 err · pack-QA 3/3 · provenance -drift clean (_published.json== 27 live) · 15 stock atlases live, 0 orphans. - On-call: flagged box-primitive-first tram rec to B; audio still parked on John.
Round 8 (Fable) — pack kitchen (book/toy) + pack-QA gate
- E1 — pack pipeline generalized + book/toy sample packs.
build_stock_pack.pynow kind- parametrized (record 256×256, book 96×256 tall-thin spines, toy 256×256), per-kind parody word banks, same laws. Book/toy sample packs built + staged (?localdepot) + indexes committed topipeline/packs/so Lane C wires book/toy shelves now. Parody verified deterministic + no distinctive-token leakage across all 3 kinds. - E2 — pack-QA gate: DONE.
validate_pack.py(wired intovalidate_manifest.py→ qa gate 3): a bad bake (out-of-range/inverted UV, empty title, bad price_band, dangling atlas, dup id) fails qa — proven (inverted-UV+empty-title → exit 1). qa--strictGREEN 5/5. - Tags pushed (John-delegated): origin/main = HEAD (
1a20501) + v1.0/v1.1/v2.0-alpha/v2.0-beta all live on origin — verified. - REAL packs LIVE (John unblocked DB access). All 3 packs rebuilt from GODVERSE (m1ultra
Postgres clones, read-only SELECT, peer auth): record 350 (
discogs_full.inventory— John's real store stock + real Discogs covers), book 311 + toy 273 (dealgod.productsby category, real product photos + prices). Metadata parody-transformed (no real trademarks); covers are real art (decision #2); book prices seeded (info-only source). 15 atlases published to the depot, indexes committed topipeline/packs/+ staged, all pass the pack-QA gate.build_stock_pack.pygained--from-tsv(extract on the DB box → build here) + portrait book cell + seeded-price fallback. Access path: deployment DB was Docker-internal/SSH-denied → used the m1ultra clones per John. No fal spend. - On-call (B rain-streak/puddle, D door-swing tell): none requested.
Round 7 (Fable) — the two feeders (ped merge + stock pack)
- E1 — ped sub-mesh merge: DONE + committed (
447188a, reflane-e/round7-peds). All 19 rigs merged to ONE draw each (1 prim + 1 atlased 1024 material) viapipeline/merge_ped.py(Blender join → UV-pack → EMIT-bake all materials into one atlas). Skinning + 65-joint skeleton preserved,walk/idleuntouched. Fleet 92→19 draws; near-cap 116→24 (79% cut). Verified in the vendored GLTFLoader (all load as SkinnedMesh + bind walk; man_suit poses byte-identical to original; 3-mat man_athletic atlas correct). Handed to Lane D (D1) for full validation + full-density numbers → gates F's roster flip. qa--strictGREEN 5/5. - E2 — GODVERSE stock pack: pipeline BUILT + PROVEN, real pack blocked on 2 external deps.
pipeline/build_stock_pack.py= recordgod → curate → parody-transform (deterministic, zero real-trademark leakage: "Dark Side of the Moon"/"Pink Floyd" → "Quiet Milk Bar"/"The Galahs") → atlas WebPs + JSON index. Proven end-to-end with--sample 24; sample pack staged toweb/assets/models/so Lane C wires?stock=realagainst the real index format now. Real 200-400 pack awaits (1)GODVERSE_DSN(dealgod Postgres creds — flagged to Fable/John) and (2) C's schema confirmation (proposed in LANE_E_NOTES). One command (--from-db --count 300) once they land. - E3 — on-call (B rain-streak/puddle texture): none requested. No fal spend (balance ~$21.36).
Round 6 (Fable) — non-destructive pipeline + on-call
- E1 — publish.py non-destructive + provenance-drift gate: DONE + committed.
publish.pynow merges into_published.json(read existing → union → sorted write), never replaces — fixes the R5--onlyclobber (record dropped 27→1). Proven: a real no-op re-publish ofrecord_cratekept the record at 27 (was 27), not 1.- Post-publish + a new
--verifymode drift-check the record against the live depot (/api/listfiltered toprocity_*) and warn on either direction.--verifyconfirms 27 == 27. validate_manifest.pygains a provenance-drift gate: every manifestprocity_*GLB must be in_published.json, else QA fails. Proven: simulating the R5 clobber (record→1) makes the validator exit 1 with per-file drift errors; restored → green. So the clobber class fails loudly.- Record verified:
_published.json(27) is byte-exact vs the live depot — Fable's R5 regeneration was correct, no fix needed. qa.sh --strictGREEN (5 gates incl. F1's new v2-flags harness).
- On-call for B/C (task 3): available for bus_shelter/bin scale-origin tweaks (B) and glass_case/magazine_rack in-room issues (C). Broken-prop fal re-gen pre-authorized ≤2 attempts (decision #5) — none needed yet. No speculative generation.
Round 5 (Fable) — hero-prop bake + fal fallbacks + depot growth
- E1 — hero-prop bake-to-lowpoly: DONE + committed. New
pipeline/bake_lowpoly.py(Blender headless): voxel-remesh → decimate → Cycles base-colour bake onto fresh UVs (R3's lesson: simplify-only floors on shell-soup; the re-bake is the point). All 6 heavy TRELLIS props ≤8k tris (drinks_fridge 77k→8k, milkshake_mixer 73k→8k, listening_booth 54k→8k, counter_till 32k→8k, novelty_record 26k→8k, arcade_cabinet 25k→8k). Fleet 288k→48k tris, 18M→5.2M. Each eyeballed (docs/shots/laneE/props_baked.png— fridge needed a coarser voxel re-bake, rest clean)- verified loading in the vendored GLTFLoader. Re-published;
validate --depot0 err. Originals gitignored inpipeline/.props_orig/. → Lane C re-measures the record interior (was ~273k).
- verified loading in the vendored GLTFLoader. Re-published;
- E3 — fal.ai fallbacks: DONE. glass_case + bus_shelter + magazine_rack via fal Hunyuan3D v2
(
pipeline/gen_props_fal.py, key from MODELBEAST settings). Frosted/opaque concepts (flux_local) gave the reconstructor a surface — all 3 succeeded where TRELLIS failed. Baked to ≤8k (EMIT albedo bake — Hunyuan materials need base-colour→emission or DIFFUSE bakes near-black), verified loading, published,validate --depot0 err. Total fal spend ~$0.64 (glass 1 att, bus 2 att, mag 1 att × ~$0.16), well under the <$1 estimate; guardrail held. Costs logged in AUDIT R5. Last two primitive-only fittings (glass_case, magazine_rack) retired; new streetbus_shelter. Manifest now 17 fittings + 9 furniture (26 GLBs). Contact sheetdocs/shots/laneE/props_fal.png. - E2 — depot growth: DONE (light, consumer-driven). The v2 features are procedural (dig uses
generated sleeves, B's window shader + D's roster need no GLBs), so per Fable "no unconsumed
entries" I added two clear-consumer props:
street/bin(council-bin → Lane B) +fit/crate_stack(milk-crate-stack → Lane C floor piles/dig). Both 3k tris, re-normalized + published, verified loading,validate --depot0 err. Also resolved Lane B's B3 ask — novelty_record 26.5k→8k via the E1 bake. Manifest now 18 fittings + 10 furniture (28 GLBs). Further growth on request.
Round 4 (Fable) — ped decimation (gate-3 critical path) + asset fixes
- E1 — ped decimation: DONE + committed (
518678d, reflane-e/round4-peds). The 19 ped rigs inweb/models/peds/were 924k tris total (31k–56k each) — the gate-3 blocker. Decimated to ≤3k each (1564–2805; fleet 924k→46.5k, ~2.45k avg) viagltf-transform weld → simplify --ratio 0.05 --error 0.12(meshoptimizer — works on these manifold skinned meshes, unlike R3 TRELLIS shell-soup). Skinning + skeleton fully preserved (65 joints intact,walk/idleuntouched); contact sheetdocs/shots/laneE/peds_decimated.pngclean at street distance. Originals gitignored inpipeline/.peds_orig/; per-ped inpipeline/_peds_decim.json. → Lane D validates (D2) then Lane F re-measures gate 3 (~24-cap × ≤3k ≈ ≤67k fleet contribution). - E2a —
record_crateFIXED, verified + published. Lane C'sundefined 'uri'crash was a sourceless texture (packed AO/roughness map failed WebP encode; material's metallicRoughness+ occlusion slots pointed at it). New toolpipeline/fix_glb_textures.pystrips those slots (three.js loads textures lazily → no crash). Verified it loads in the real vendoredGLTFLoader(meshes=1, tris=5000). Re-published to the depot (the fixed version is live, tex refs all-sourced). - E2b — counter-with-till (~2 m): LIVE. New
counter_tillfitting (procity_fit_counter_till_01.glb, 1.61 × 0.64 m, 1.15 m tall, 32k tris) — timber counter + cabinet doors + period till. Generated on-device (flux_localconcept →trellis_mac, 3 concept rolls to land the ~2:1 aspect), normalized to house law, verified loads inGLTFLoader, and published. Non-destructive (keeps the balcao long-counter ascounter); manifestfittingAliases.counter→counter_till; Lane C re-maps kindcounter→counter_tillinglb.js. - Publish: DONE (John approved). Both re-exports live; manifest
validate --depotGREEN (0 err, 23 GLBs live).publish.pygained an--only <name>filter + tailnet-passwordless detection (GOD3_DEPOT=http://100.94.195.115:8788, decision #4). - Not doing (per Fable decisions): fal.ai spend (glass-case/bus-shelter parked); hero-prop bake-to-lowpoly.
Round 3 (Fable) — hero props on MODELBEAST + local-depot mode
- Hero props, free & on-device (
pipeline/gen_props.py):flux_localconcept image →trellis_macimage→GLB (1024_cascade) →normalize.py→ thumbs → manifest. 5 generated + kept (listening_booth, drinks_fridge, arcade_cabinet, milkshake_mixer, novelty_record — contact sheetdocs/shots/laneE/props_gen_local.png), cash_register reused from the depot (vintage-cash-register.glb). 3 didn't make it: magazine_rack → in-engine primitive (112k-tri wire, the thin-wire gotcha); glass_case + bus_shelter → fal.ai fallback list (TRELLIS can't do transparent glass; sf3d gives a featureless blob) — gated on John, ≤$2.70, both have primitive fallbacks. Every kept thumbnail eyeballed; no legible branding (see AUDIT provenance). - Local-depot mode (
core/loaders.js?localdepot=1+pipeline/stage_local_depot.py): resolvesdepot:<file>toweb/assets/models/served by the dev server, so Lanes B/C/F validate GLB loading with no network / before publish. Verified live in-browser (loads adepot:GLB, CDN path intact). - Manifest: 14 fittings + 8 furniture (5 hero + cash_register added);
validate_manifest.pygreen (0 err). Provenance recorded inAUDIT.md(props are 100% synthetic/local — cleanest in the set). - Known tradeoff: TRELLIS meshes are dense shell-soup — decimate floors 25–77k tris (heavier than the ≤5k library law). Accepted for focal/optional/LOD-able props; texture-bake-to-lowpoly is a follow-up.
- Published (self-serve, John's go 2026-07-14): the 5 prop GLBs + thumbs pushed to the depot via
the passwordless tailnet path (decision #4); all 22 GLBs re-verified live.
qa.sh --strictGREEN (4/4 gates; manifest validator 0 err / 0 warn with the props live). Provenance was recorded first. - Not committed: this round is held for Fable review (per John) — all Lane E round-3 changes are in the working tree, uncommitted. GLB binaries stay git-ignored/staged; the depot has them.
Status at a glance
| Step | Deliverable | State |
|---|---|---|
| 1 Audit | pipeline/AUDIT.md (+ glb_stat.py, _audit_stats.json) |
✅ done |
| 2 Normalize | pipeline/normalize.py → 16 GLBs + 16 thumbs, verified |
✅ done (local); ⛔ publish gated on GOD3_PW |
| 3 Manifest | web/assets/manifest.json + validate_manifest.py (+ build_manifest.py) |
✅ done, validates green |
| 4 Facade skins | gen_skins.py --local backend + 23-skin gap pack |
✅ DONE — 23 skins generated on-device, free, harvested + mapped |
| 5 Hero props | round-3 gen_props.py (MODELBEAST, free) → 5 local + cash-register reuse |
✅ DONE local (see Round 3 above; 2→fal, 1→primitive) |
| 6 Local-depot | loaders.js ?localdepot=1 + stage_local_depot.py |
✅ DONE, verified in-browser |
| — | pipeline/README.md + contact sheets in docs/shots/laneE/ |
✅ done |
Step 4 no longer costs anything. The 23 facades were generated locally on the M3 Ultra
via MODELBEAST flux_local (FLUX.2-klein-4B on MPS) — free, ~5.7s each, weights already cached.
No OpenRouter key, no ~9¢ spend. See "Step 4 (done, local)" below.
Two things still need John (both optional — the game runs asset-free): (1) the depot password
GOD3_PW to publish the 16 GLBs live; (2) a go/no-go on the paid hero-prop step (5 ≈ $2.70).
What landed
Step 1 — Audit
pipeline/glb_stat.py: dependency-free GLB parser (tris, bbox, texture px, Draco) — runs on ultra's py3.9. Full library stats →pipeline/_audit_stats.json.pipeline/AUDIT.md: the library is a raw dump — almost nothing obeys the GLB law (onlyrecord_crate_plastic_01was native-metres; scale/orientation arbitrary; tris 12→960k; textures to 4096; several branded/trademarked assets quarantined). Candidate→PROCITY-id table with status, coverage-vs-registry table, QUARANTINE list, depot cross-reference.- Toolchain reality documented (Blender present on ultra but off PATH; no coreutils/timeout).
Step 2 — Normalize & publish
pipeline/normalize.py: headless Blender, extendsMESHGOD/finish_glb.py(solidify/decimate/ bright/base-origin) + adds height-normalize, outlier cleanup, texture→WebP≤1024, per-asset up/yaw, 256px thumbnail. Driven bypipeline/batch.json.- 16 assets normalized to house law (metres, +Y up, base origin, ≤5k tris, WebP ≤1024, no
Draco). Every one eyeballed — Y-up confirmed by re-importing exports through
render_glb.py. Footprints from Blender-space_normalize_results.json. Thumbs inweb/assets/thumbs/.- fittings (9): record_crate, wire_shelf, clothes_rack, bookshelf, cube_shelf_wide, counter, coffee_table, work_table, box_crate
- furniture (7): bench, bench_modern, bench_wood, longbench, park_bench, streetlight, food_cart
pipeline/publish.py: mirrors the meshgod→3GOD contract exactly (cookiehmac(GOD3_PW,"3god-ok"),POST /api/upload+/api/thumb). Reads the secret from env — never contains/logs it.--dry-runverified all 16 ready. Not published yet:GOD3_PWisn't set here. Run:export GOD3_PW=… && python3 pipeline/publish.py(idempotent, reversible).
Step 3 — Manifest
web/assets/manifest.json(v1): the contract Lanes B/C/D read. All 69 skins catalogued (25 facade / 10 sky / 10 ground / 8 wallpaper / 6 floor / 7 surface / 3 awning) + 16 fittings/ furniture with footprints, heights, thumbs.conventionsblock documents the GLB law, blank-signboard rule, corner-lot policy, fallbacks, and depot load path.- Every registry shop type has ≥2 facades (verified in the validator). Facades tagged
signboard: blank|baked— 5 djsim/market/grimy skins carry baked sign text and must not get a name overlay; the other 20 are clean overlay targets. pipeline/validate_manifest.py: Lane F gate — parses JSON, checks every skin exists, every GLB is local-or-on-depot, thumbs exist, footprints/heights sane, ≥2 facades/type. Green (16 local-only warnings until publish;--depotenforces live).pipeline/build_manifest.py: reproducible generator (curated type-maps + derived skin/fitting lists) so the manifest regenerates when assets change.
Step 4 — Facade skin expansion (DONE, local)
pipeline/gen_skins.py: ported fromthriftgod/gen_assets.py— same STYLE bible + blank- signboard template so new skins match. Resumable.genraw/,--dry-run/--only/--harvest.--localbackend (the one I used): MODELBEASTflux_local→ FLUX.2-klein-4B on the M3 Ultra's MPS GPU. Apache/ungated, weights already cached (15 GB), free, ~5.7 s/img, one GPU job at a time. Direct subprocess to~/Documents/MODELBEAST/server/operators/flux_local/run.py(--outdir/--paramsJSON) — no server, no cloud, no key. Cloud OpenRouter path kept as fallback.- All 23 generated → harvested → mapped. 0 failures, 2:11 total. Eyeballed every one
(contact sheet
docs/shots/laneE/facades_gen_local.png): every shopfront has a genuinely blank signboard (Lane B name-overlay target), style indistinguishable from the 25 anchors. The pack: toy (2), book (2), video (2), milkbar (3), wide dept anchors (2), stall/market (2), warehouse (2), arcade portal (1), residential house fronts (4), corner-lot-sidewalls (3). - Coverage after mapping (
build_manifest.pyFACADE_TYPES, mirrors registry.js + additive): record 3 · opshop 3 · toy 5 · book 5 · video 4 · pawn 7 · milkbar 5 · dept 4 · stall 4 — every registry type ≥3.stallwent 2→4, retiring the Lane A single-facade gap. - Corner-lot
-sideskins now exist (brick/render/weatherboard): taggedface:"side"with emptytypesin the manifest so no shop-front pool ever picks a windowless wall; Lane B maps them to the exposed side face (conventions.corner_lots+ newconventions.facade_face). pipeline/SKIN_PROMPTS.md: identical pack kept for the free manual flow (fallback if MODELBEAST is ever down).
Step 5 — Bespoke hero props
pipeline/meshgod_batch.json+MESHGOD_BATCH.md: 9 solids (glass case, fridge, till, listening booth, arcade cabinet, magazine rack, milkshake mixer, novelty record, bus shelter) in the thriftgod_hero pattern. Documents the MeshGod gotcha (thin wires/flat discs → primitives), reuse-first (cash-register/glass-case likely already on depot), and the primitive fallbacks. Not run — gated on John (~$2.70). Nothing blocks: all have in-engine fallbacks.
Adversarial review & fixes (self-run, 4-dimension × verify)
Ran a 19-agent adversarial review over all deliverables (correctness / contract-fit / doc-accuracy / house-law), each finding independently verified. 15 confirmed (1 blocker, 5 major, 9 minor). All fixed and re-verified:
- BLOCKER — off-origin exports.
normalize.pyjoined meshes but never flattened parent node hierarchies, so assets under a parent empty shipped off-origin:park_benchwas ~1 km off-origin, floating 30 m;food_cart15 m off;clothes_racksank 0.19 m. My earlier spot-check missed it (the clean assets have no hierarchy). Fixed:parent_clear(KEEP_TRANSFORM)+ drop non-mesh nodes before join. Re-verified node-aware: all 16 nowcenter=[0, h/2, 0], minY=0.0. - Major — tri budget counted faces, not triangles (latent for quad FBX/OBJ). Fixed: triangulate
in
clean_meshso the ≤5k gate + reported counts are true triangles. - Major — fitting-id namespace. Added
fittingAliases(registry semantic id → physical id) to the manifest. (Lane C'sglb.jsalready maps its kinds to my physical ids, so it worked — this makes it explicit + future-proof.) - Major — facade map vs registry.js. Aligned my facade→type map to be a consistent superset of
Lane A's
registry.js; flagged that registry'sstallpool has only 1 facade (Lane A gap). - Major — facing -Z not enforced. Corrected the docs: symmetric props are orientation-agnostic;
no auto-facing (per-asset
yawavailable). Removed the false "enforced" claim. - Major — licence provenance. Strengthened the publish-set caveat (record per-asset provenance before pushing to the shared CDN) — a reason publish stays gated on John.
- Minors: hardened
glb_stat.py(node-aware world bounds + WebP size sniff — the exact blind spots that hid the blocker);validate_manifest.pyliveness now uses a Range GET not HEAD; Akai-MPC trademark flag; corrected audit counts (59 parsed.glb, rejects 8, food_cart tris).
Acceptance check (LANE_E)
- ✅
AUDIT.mdcomplete. - ✅ ≥15 normalized GLBs (16) with thumbnails — ⛔ live on 3GOD pending publish (needs cred).
- ✅
manifest.jsonvalidates green; fittings/furniture carry footprints for B/C to place untouched. - ✅ Every registry shop type has ≥2 facades — now ≥3 (48 facades total). New skins
generated (not just planned) and eyeball-matched to the anchor style
(
facades_style_anchor.png= 25 originals;facades_gen_local.png= 23 new local skins;fittings_normalized.png= the 16 GLBs — all indocs/shots/laneE/). - ✅ One-page
pipeline/README.md(re-run each step, costs, where creds live).
Notes for the other lanes
- Lane B / C: read
web/assets/manifest.json.fittings/furniture→depot:<file>viacore/loaders.js(placeholder box on miss — the game runs asset-free). Footprints are[w,d]metres on the ground; heights in metres; all base-origin, +Y up, facing −Z. - Lane B: overlay shop names only on facades with
signboard:"blank". Widedept-*anchors (when generated) want a wider UV plane.awning/ground/skyskins are yours;wall/interiorare Lane C's. - Lane F: wire
python3 pipeline/validate_manifest.pyinto the gate (add--depotpost-publish).
Open questions for Fable/John
- Publish now? I have 16 verified GLBs staged in
pipeline/_normalized/ready to push to the shared depot. It's an outward-facing write to shared infra + needsGOD3_PW, so I left it for your go rather than assume it. Spend the ~9¢ on facades?Resolved — done for free on-device (MODELBEAST flux_local). Only the ~$2.70 hero-prop MeshGod batch (Step 5) still wants a go/no-go; all props have in-engine primitive fallbacks, so it's a polish upgrade, not a blocker. (Note: image→GLB is also local on this box viasf3d/trellis_mac, but those weights are HF-gated — a setup step before that path is free too.)- A few library assets were near-misses (garage_shelves, radiogram, market_stall — see AUDIT rejects). Worth a manual Blender re-origin pass later, or leave to primitives? I left them out.