# Lane A log — append-only, newest at bottom Format per session: ## session N DONE: … DECISIONS: … BLOCKED/REQUESTS: … NEXT: … (no sessions yet) ## 2026-07-18 session 1 DONE: M1 shipped and verified end-to-end in a browser. - `web/room3d.js` — ported the rigroom retarget as a pure ES module (no DOM/globals). Exports parseAny/canon/boneMap/captureRest/bakeRetarget/disposeRoot/stats + `_selftest`. bakeRetarget is now `(clip, srcRoot, srcRest, tgtRoot, tgtRest, opts?)` — target is a parameter instead of the closed-over `char`. Algorithm kept byte-for-byte (30fps world-delta bake, hips-height ratio, quat sign continuity, dup-hierarchy dedupe). Added `.bvh` to parseAny. - `web/stage.js` — `class Stage` per PLAN §4.2. IBL (RoomEnvironment+PMREM), grid+circle floor, OrbitControls director cam, TransformControls gizmo (W/E/R), raycast select, shadow-casting. addEntity handles character/prop/backdrop(plane|corner|dome)/camera/light; wrapper-Group holds all transforms, loaded root normalized+grounded underneath. prepareClip caches parse-per-path and bake-per-(entity,path,index). captureState/applyState round-trip entities. - `web/dock.js` — asset dock (Characters/Props/Backdrops/Animations tabs from `/assets/tree`, offline→file-drop) + inspector (transform/params editors, ⏺key dispatches `scenegod:capturekey`, delete). Local drop: image→backdrop, mesh→character, clip-onto-selected-character→bake+play. - `web/index.html` + `web/style.css` — CSS-grid layout (dock/view/inspector/timeline), rigroom importmap (three 0.160.0), `?selftest=1` badge. Timeline loaded via guarded dynamic import so the page never breaks when Lane B's file is absent. VERIFICATION (browser, in-app): - `?selftest=1`: PASS — two 3-bone skeletons, different rests+namespaces, baked 1s clip, world-delta match maxErr=6.4e-12, srcMoved=0.224rad (guard against a silently-frozen source). - Real end-to-end (Female_mixamo.fbx char + "Running.fbx" clip + a jpg backdrop, served from a throwaway scratchpad harness): char loaded (65 bones, 18.6k tris, normalized), gizmo-moved, clip retargeted (66 tracks) and animating live. Screenshot: `logs/shots/m1-lady-running.png`. - Page boots with zero console errors with BOTH timeline.js and the server absent. DECISIONS: - selftest uses underscore namespaces (`mixamorig1_`/`mixamorig4_`), not colon — a colon in a bone name breaks three's PropertyBinding so the source clip wouldn't bind (silent pass). canon() still collapses both to the same key, which is the thing under test. - Added `Stage.prepareClipUpload(id, buf, name, idx)` (bake from in-memory bytes) so the offline file-drop path can retarget without a server. `Stage.setMixerAuto(false)` lets Lane B take over mixer stepping at SYNC 1 (default true so dropped clips preview standalone now). - backdrop param edits (mode/image/width) don't rebuild the mesh yet — marked M2. fov/light color/intensity are live. BLOCKED/REQUESTS: - @Lane C: please confirm the item shape inside `/assets/tree` arrays. dock.js tolerates both a bare path string and `{path,name,files:[{path,ext}]}` (rigroom-style) for now — tell me the real one and I'll drop the fallback. Also confirm the page is served such that absolute `/web/*.js` imports resolve (I used `/web/...` to be URL-independent). NEXT (M2, do not start until orchestrator flips the milestone line): - multiple cameras + PiP overlay via renderActiveCamera, light entity param plumbing polish, backdrop rebuild-on-param-change, drag-from-dock onto viewport (currently click-to-add).