Journey event  ·  10 Sep 2026

Placement is data: every instance in the twin can be moved without an edit and a rebuild

plan-spatial-layout-2026-09-10.md S4, shipped in commit d58a9e6. The rig's layout was source code: 36 hand-written calls with literal offsets and rotations, so nothing cou

  state copied from the tracker, never improved

  event date 2026-09-10

Event date 2026-09-10
Version found
Version fixed
Expected kit firmware
Release file
SHA-256
Served count
Source https://app.notion.com/3d62b4cda370819aaf5adcd28142fbe8

plan-spatial-layout-2026-09-10.md S4, shipped in commit d58a9e6. The rig’s layout was source code: 36 hand-written calls with literal offsets and rotations, so nothing could be moved without an edit and a rebuild. APPROACH: rather than rebuilding the scene from a flat list — which would mean reconstructing the parent/child nesting the JSX tree already expresses correctly, and touching all 36 sites — the override is consulted by Placed ITSELF, keyed on the id it already has. One intercept covers every placement in the rig; the literals stay as defaults; the diff is four lines in the component that was already the single door into the scene. The stored shape is the shape Placed consumes (at = parent+anchor OR position, plus rotation/self/scale), so persisting and rendering cannot drift into a translation layer. Details worth keeping: – at refuses to carry both a parent and a position — one would render and the other be silently ignored with no way to tell which. – Absent optionals stay absent: the scene’s own default and an explicit [0,0,0] are different statements. – Only OVERRIDES are stored. An empty table renders the rig exactly as it always did; moving something back is deleting a row. – resolvePlacement merges FIELD BY FIELD, not all-or-nothing: an override carrying only an at must not drop the rotation the scene gave the model, or a fan snapped to a new port comes back lying on its side. – anchors.ts gains a DEV-only window.__dscAnchors() listing where every instance actually ended up — the twin draws on a frame loop and the registry is module-scope, so there was previously no way to ask. – placements added to API_FIRST_SEGMENTS; without it the SPA catch-all would serve index.html for an unknown /placements path (caught by test_api_segments_cover_every_route). VERIFIED: 23 brain tests, placement smoke tests, /placements reachable from the SPA, empty by default, demo mode refuses writes (403), contradictory at refused over HTTP (400). Brain suite 698 pass. NOT VERIFIED : that an override VISIBLY relocates a model. The preview pane mounts the canvas but never advances the twin’s frame loop (frameloop=”never” + rAF-driven advance), so no model settles and no anchors register — __dscAnchors() returns {} there. NEEDS A REAL BROWSER: open #/twin, PUT a placement, reload, and check window._dscAnchors().heater.origin has moved. Also not deployed to the Pi.

All events  ·  DSC  ·  CannaLib  ·  Site  ·  Firmware releases

Empty rows are honest

A blank cell means the tracker has no value for it. Nothing on this page is filled in to look complete.