# SCENEGOD — machinima director's sandbox (iClone/SFM UX, GODVERSE stack) Drop characters + animation clips + image backdrops on a 3D stage, keyframe transforms/cameras/lights on a timeline, render mp4. Web app: FastAPI + three.js, same conventions as MESHGOD (`~/Documents/MESHGOD`). ## Deploy model (digalot.fyi suite) - Prod: dealgod VPS `root@100.94.195.115`, `/opt/scenegod` — NOT a git checkout: `./deploy/deploy.sh` rsyncs from a dev Mac and rebuilds (`deploy/docker-compose.yml`, project name `scenegod` — do NOT drop the `name:` key; meshgod+scenegod both compose from dirs called "deploy" and would otherwise share a project and orphan each other). Container joins the external `dealgod_default` net; data volumes under `/opt/scenegod-data/`. - nginx: `deploy/nginx-scenegod.conf` block lives in the digalot.fyi server in `/opt/dealgod/nginx/dealgod-servers.conf` (dealgod-nginx container) — suite basic-auth (`meshgod.htpasswd`). Live: digalot.fyi/scenegod/. - Frontend is PREFIX-AGNOSTIC: all web URLs are relative (module imports `./web/...`, fetches `assets/...`) so the app works at `/` locally AND under `/scenegod/`. Never reintroduce a leading `/` in a web-side URL. - VPS env keeps `SCENEGOD_LLM_URL`/`SCENEGOD_MB` UNSET (features 503/hide; they shell to tailnet boxes — ultra-only). rhubarb not in the image. - Server has ship-check hardening: `capped_body` on every POST (frames 25MB, scenes 5MB), render dims ≤4096/fps ≤60/frame index ≤20000, `esc()` on all dock innerHTML interpolations. Keep new endpoints behind the same rules. ## You are one of THREE parallel lane agents 1. **Read, in order:** this file → `PLAN.md` → your lane file in `lanes/` → your log in `logs/`. Your lane file is your source of truth — the orchestrator (Fable) updates it between your sessions. Re-read it at the start of EVERY session; instructions may have changed since your last one. 2. **Only touch files your lane owns** (ownership map in PLAN.md §3). If you need a change in another lane's file, write the request in your log under BLOCKED/REQUESTS — do not edit it yourself. 3. **Log protocol** — append (never rewrite) to `logs/lane.md` at the end of every session, and mid-session when you make a design decision: ``` ## 2026-07-18 session N DONE: what shipped, with file:line pointers DECISIONS: choices made + why (schema tweaks, deps, algorithms) BLOCKED/REQUESTS: what you need from another lane or the orchestrator NEXT: what you'd do next session ``` 4. **Commit early, commit often**, on `main`, prefixed `[laneA]`/`[laneB]`/ `[laneC]`. `git pull --rebase` before every commit — other lanes commit to the same branch. File ownership makes conflicts near-zero; if you hit one anyway, resolve only your own files and log it. **Stage your own files explicitly (`git add `) — never `git add -A`/`.`**: another lane's uncommitted work may be sitting in the shared working dir, and -A sweeps it into your commit (happened once; attribution mess). 5. **Don't exceed your lane's current milestone.** Milestones and sync points are in PLAN.md §5. Finishing early = polish + tests + log, not starting the next milestone uninvited. ## Stack rules - Python 3.11 stdlib + `fastapi` + `uvicorn` only (requirements.txt). No other server deps without logging a REQUEST first. - Frontend: vanilla ES modules + three.js via importmap (copy the pattern from `/Users/johnking/Documents/MESHGOD/meshgod/web/rigroom.html`). No bundler, no npm, no framework. - Server: `uvicorn scenegod.server:app --port 8020`, binds 127.0.0.1 by default (local tool on ultra; VPS deploy is a later problem). - Secrets/env in `.env` (gitignored). Never commit tokens. - Reference code you may READ (never edit): the MESHGOD repo, especially `meshgod/web/rigroom.html` (retarget bake), `meshgod/library.py` (folder scanning), `meshgod/ops.py` (MODELBEAST submit contract), `scripts/glb2fbx.py` (headless Blender pattern). ## Gotchas inherited from MESHGOD (learned the hard way — do not relearn) - trimesh/some GLBs omit `metallicFactor` → glTF default 1.0 → renders black. Viewer must use an IBL environment (`RoomEnvironment` + PMREM), not just lights. - Serve HTML **no-cache** — a stale cache once hid UI buttons for a day. - Mixamo rig quirks (all already solved in rigroom's `bakeRetarget` — port, don't reinvent): namespaces differ per download (`mixamorig4Hips`), FBX files carry duplicate hierarchies, quaternion sign continuity must be enforced, Blender-exported GLB rest poses differ from FBX rests → retarget = world-space rotation-delta bake at 30fps, never raw track copy. - Rigged GLBs must NEVER be sent through any Blender join/decimate "finish" path — it spawns phantom joint meshes and mauls the armature. - Path traversal: every endpoint that takes a path must resolve + verify it stays inside its root (ship-check rule). - Verbose commands (installs, test runs, ffmpeg): pipe through `| lm -l 2`.