- web: all URLs relative (imports ./web/..., fetches assets/...) so the app serves at / locally and under /scenegod/ behind nginx; esc() on dock innerHTML interpolations (ship-check XSS class) - server: capped_body on every POST (scenes 5MB, frames 25MB, meta/director 256KB-1MB), render begin sanity (fps<=60, dims<=4096, frame idx<=20000) - deploy/: Dockerfile (slim+ffmpeg), compose (project 'scenegod' — avoids the shared-'deploy'-project orphan trap with meshgod), nginx location (suite basic-auth), deploy.sh (rsync model, meshgod-style) - live: digalot.fyi/scenegod/ -> 401 unauthed, app healthy on dealgod_default Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
84 lines
5.0 KiB
Markdown
84 lines
5.0 KiB
Markdown
# 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<X>.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 <paths>`) — 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`.
|