- stagestub.js: removeEntity now fires onChange WITH the removed entity (real
Stage contract) so _mirror's getEntity(id)===null removal path is testable.
- timeline.js: setDuration(x) — clamps the playhead, keeps out-of-range keys
(lossless), notifies UI via onLoad. (Reviewed orchestrator's _mirror seam.)
- tlui.js: dur field → setDuration; snap-increment select (frame/0.1/0.25/1s);
keyable-param add via dblclick on a params lane (captures current param
values, skips 'type'/bool descriptors); params lane only when keys exist or
kind is camera/light (no empty lane for characters).
- timeline_test.mjs: _mirror lifecycle (add→keyframe→remove) + setDuration.
Verified in browser (throwaway harness, not committed): dock-adds mirror into
rows, param capture, setDuration clamp+bar refresh, snap-step math.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>