3.5.3 (2026-08-06)
Internal Improvements
core/log: add deferred-format haply_* macro shape (cf7dbfc), closes #271core: add pivot and compose/inverse transform primitives (01080f6), closes #283devices: cache 0xE4 body orientation and route trigger_mode (#265) (4864700)devices: compensate the 0xE4 IMU sensor frame service-side (#286) (e6d877c), closes tapi-prototype-firmware#87devices: refresh body_orientation on inkwell calibration (#268) (89b190b), closes #286 #286 #286devices: split live (0x0C) vs reference (0xE4) body orientation (#286 #315) (638487a), closes #268 #266 #268http: align unsupported-protocol responses on 422 (e0e7638), closes #293 #293 #295http: migrate transform echoes and sdf inputs to euler-capable patches (#279, #280, #291) (bb29404)http: reset the device mount on Delete scope=device (#265) (f6bf26b), closes #286modules::navigation: add clutch mode on the motion lock (gated, default off) (4b69eed), closes #308 #308 #283 #308modules::navigation: button inputs with prevent_default; clutch force_scale; bubble hold-to-navigate (fb216aa), closes #317 #318 #316 #317 #318modules::navigation: clutch max_motion/force_scale ceilings (a946088), closes #316modules::navigation: mirrored feature kill switches, both on by default (b6ee0c0), closes #318modules::navigation: per-input settings patches on inputs[]; bubble emits status.engaged (ba2058f), closes #318protocol: capability file split, damping gate, base hoist (30d7d5d), closes #293protocol: capability table + single unsupported emitter (289382e), closes #293 #295protocol: gate home_return + pen_attached via table (8a05d20), closes #293protocol: introduce fw_version and migrate version checks (38c2cae), closes #293serialization: apply the grip button mask in the v3.1 session passes (7b93e35), closes #316serialization: emit euler on config.mount rotations under euler.output (#268) (f6b54a2)serialization: emit euler on transform rotations under euler.output (96c6cc9), closes #283serialization: expose workspace zoom-about-pivot on set_transform (#309) (c1d08fc), closes #280serialization: flatten config/body_orientation trigger_mode (#265) (8781b8a), closes #268serialization: promote transform knobs into per-session serial_options (#280) (03b2fd6)serialization: split config/mount into scope + body_orientation (#265) (5618839), closes #280serialization: thread session options through outputs and gate the nested reshape (#279, #280) (59984ce), closes #265serialization: unify ws and http configure decoding (#280) (6076917)sessions: add generic motion-lock mechanism with disengage bake (c8d2a93), closes #304sessions: add live_motion per-tick motion-lock advance (gated) (d29013c), closes #308 #304 #308sessions: add manager-level session observers with main-loop delivery (83e76ef), closes #284sessions: add mount reparent and workspace zoom-about-pivot (294d6e8), closes #265 297/#272 #304sessions: add namespaced config.body_orientation event scope; warn on legacy 'values' input (3f70047), closes #320sessions: add preview config/mount source + trigger routing (#265) (5d11dbf), closes #268sessions: device mount store/load in mount space (#265) (4cec178), closes #292sessions: generalize set_workspace_transform_around with pivot echo (0b242a2), closes #309sessions: grip button mask + force_scale overlay mechanisms (836ef2f), closes #316sessions: label Tracy session plots with client profile (72a8f34), closes #258sessions: mount scope routing + storage virtuals (#265) (9a4e7f4), closes post-#286 #293sessions: per-session force_scale ducking (preview) (bff66ad)Bug Fixes
ci: pin release toolchain to restore changelogs (72c6773), closes #313compilation fix with new glaze (e2c53d3)deps: update rust crate nix to 0.31 (b3b9a84)devices: gate the safety-config protocol at the send chokepoint (b8e8401), closes #295devices: guard safety-config writes on fw version and calibration (5ad5128), closes #295devices: keep inverse3 wire alive during wakeup settle window (4afed45)devices: keep inverse3 wire alive during wakeup settle window (79c2b66)devices: suppress [secure] battery notification on wired verse grips (ea54a1a), closes #314http: check calibration on session-scoped safety writes (89f9cd7), closes #295 #293http: fold euler rotations under session conventions (#288) (97cf203)inverse_ux: restrict calibration_notifier processing to Minverse (418913f)lifetime cleanup to prevent crashes (e7b3785)modules::inverse-ux: always emit calibration-failed when firmware blocks (3841d06)modules::inverse-ux: re-pair after swapping one paired device (cf85707), closes #278modules::sdf: fold sdf transform euler under session conventions (#291) (9741ac6)modules::sdf: orient SDF shapes in the client coordinate frame (c29e4f2), closes #276protocol: eliminate timer lifetime races that crash or hang the service (0cb019b), closes #303protocol: flush serial buffers on port open to recognize hot-swapped devices (b8724d9)protocol: guard firmware client callbacks against device destruction races (3d795bb), closes #303protocol: rewrite 0xE4 IMU orientation API with typed enum and correct wire format (8733ec0)return to home for inverse3x enable/disable bia hub (f435454)service: adaptive dispatch disabled by default (9415638)service: make service teardown ordered, bounded, and race-free (ff888d7), closes #303sessions: center *_centered presets on the real reachable center (ad6e726), closes #321sessions: drop siggraph workspace-boundary auto-push on mount change (2df1654)sessions: skip closing-session force drain for a device still driven by a live session (e1f9ff7), closes #324sessions: stop start() wiping connect-time negotiated serial_options (#290) (27e27d8)sessions: zero workspace transform velocity after set_transform (133c3ad), closes #280websocket: decode commands under the sender session's conventions (#289) (1b24049), closes #265Performance Improvements
core/log: gate haply_* macros so fmt::format is skipped when off (672a87a), closes #270modules::sdf: bake SDF once at creation instead of per tick (15350c5), closes #277