Repository navigation
Conversation
… back and forth - 40 F12: on a phone Aquarium's water refraction switched off and on by itself. The governor walked 6 -> 5 after 10 s of cheap frames at "post off", level 5 brought the screen-space water pass back and overloaded 3 s later; doubling the recovery hold only slowed the flap (10/20/40/80 s) - a step back UP to the level a recovery just left (within flapWindowMs) now locks that level as the lowest recovery may reach, until clearFlapLock: a new scene (load end), releaseQuality / keepFullQuality, or the auto-quality switch. Every auto toggle (water, fluid, HDRI tier, shadows, resolution, AO, post, particles) derives from the level, so all of them get the rule. A scene that becomes light still walks back - keepFullQuality(): full quality and no automatic step for the rest of the page session (not saved; the Settings auto switch stays on) - unit: qualityFlapLock (10-minute phone simulation, counterfactual: >8 refraction switches without the lock, <=3 with it), the old flap test now ends in the lock Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…elocity, body wave (40 F15) - motion/motionCore.js (pure, unit-tested): centripetal Catmull-Rom paths with arc length, loop/pingpong/once + offset, signed curvature, bank roll, seeded smooth bounded noise with an analytic rate, the body-wave envelope/drive/offset - motion/motionNodes.js (three leaf): Follow Path rides a drawn Spline, a Flow path or its own waypoints in world space, faces along it and banks into turns; Wander drifts inside an area object's box (or a box around its base), seeded per object; Orient to Velocity faces the frame's motion with smoothed turning + bank and holds while still; Body Wave bends any mesh subtree with a vertex-shader travelling wave whose amplitude/frequency follow speed and whose bend follows turn rate (per-mesh material clones keeping the original uuid, put back when the wave stops) - flowRuntime applies the followers after the movers (stable sort, graphs without them unchanged) and prunes waves that stopped - catalog (Animation group), sockets (path/area take an object), cards, doc lines - tests/unit/motionCore.test.js: 23 tests incl. the bank-direction counterfactual Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…s remember their image - setObjectsTexture no longer refuses files over 8 MB: the path already downscales to 1024 px, so the cap only refused photos it was built to shrink (roadmap 40 F13, image-large). The one limit left is a 64 MB decode-safety cap. - material.userData.mapSource = the content hash of the Explorer image a texture was made from (Explorer drop, UV slot drop). It rides the `map` message as an additive `source` field, the `materials` payload as `mapSources`, and a material-type switch. Any write without one (paint, undo, a file from disk, an older peer) drops the link. - texturesFromSource(hash) / linkTextureSource(uuid, slot, hash): the seams the Image editor's Save uses to re-texture every material made from an image. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…(40 F16) - material presets carry the thin film (iridescence, its IOR and thickness range) and the transmission volume; three's [min, max] range maps both ways - a new starter "Fish scales": an iridescent physical look over a procedural, tileable scale relief (scales hang like shingles, lower row in front), a light clear coat and a hint of transmission; the swatch shows the film as a hue sweep - materialTiersCore (pure) + materialTiers (runtime): every physical material is drawn at this device's tier, the water rule (headset or post off = low, a phone's start = mid): mid drops transmission (the extra full-scene pass), low also drops the thin film and sheen. LOCAL only; the authored numbers ride as userData.lookTierAuthored, written only when a device draws less, so a desktop save stays byte-identical and a headset's save restores the full look elsewhere; an edit made since is the new look - debug hooks: materialTiers, motionNodes - tests: materialTiers.test.js (10, incl. a save on a low device reloading at full look), the starter list grew by one Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… full quality" per toggle - 40 F12: when the device lowers a quality toggle on its own it says so once per toggle per session, batched per drop: "Lowered water quality and the scene look to keep it smooth" with a "Keep full quality" action (keepFullQuality: full quality for the rest of the page session, the Settings auto switch untouched) - the rule is pure (qualityNoticeCore: which toggles, newly lowered, the words); the AutoQualityNotice component watches qualityOverrides + simplifiedWater, counts only automatic drops (frames / long tasks / the phone's lighter start, never a game preset or the headset floor), holds a drop made in Play or a headset until you are back, and judges in a microtask because publish writes the overrides before the reason - replaces the object list's first-step toast (gone whenever that window was closed) and SimplifiedWaterNotice; the quality chip says "stays this way for this scene" while held - governorForTest: setLevel on a synthetic clock, flapLock / clearFlapLock - e2e auto-quality-notice (phone 390x844 touch + desktop 1440x900: the drop, one retry, held for 10 min, counterfactual 15 switches, scene load clears the lock, Play deferral, tap Keep full quality, shadows on desktop); fb-water-phone part 3 asserts a game preset is not announced; unit qualityNotice Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- F6 docked tab strip: the bar paints from a non-scrolling wrapper, so every tab (not just the first three) sits on it when scrolled and the edge fade masks only the tabs; one shared scroll position survives a tab pick (each panel mounts its own strip, which used to start at 0) - F7 window header names: one line + ellipsis, full name on hover and touch long-press ($lib/ui/fullName.js, on WindowChrome titles and the docked .tp-dock-sub which had no rule); a phone-narrow Animation moves the name out of the control row - F8 docked windows carry no close or undock button (tabs carry the close, the dock code workspace keeps its unsaved-tabs ask through registerDockCloser); the undock button sits left of "minimize the dock" and undocks the active tab, or every tab as one tabbed group (Settings > Interface > Windows & chrome > Undock button); a floating tab group gets a dock-all button left of "close all tabs" - F9 phone "+" (floating windows off) opens a sheet of every window with show/hide switches; with floating windows on it is the desktop menu - F10 a docked tab dropped onto/into a floating window joins it as a tab (windowTabs.windowAt + queueMerge); dragWindow's size watch and window-resize re-clamp stand down for tab members, which threw a revealed member off its group - F11 the Layouts popover is the kit ModalDialog (it painted with a theme var most themes no longer define); own desktop width because the kit width prop loses to the layered !important frame rule - bottomDock.armDockModes queues several dock-mode arms (the slot is write-once) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…swimming with the motion nodes (40 F14) - lodGroupCore: an additive `fallback: true` group — LOD0 (the object itself) is a STAND-IN, drawn only while the real model's levels are loading or unreachable; the pick runs over levels 1..n (pickFallbackLevel, hysteresis kept). Unit tests incl. the counterfactual. - lodGroup: a pack level that does not pair with the object (or any level of a fallback group) is a TREE level, cloned per object, casting shadows; lodTrees.js (a leaf) lists the substitutes so Body Wave bends the real model and the look tier reaches its film - Body Wave: each mesh set (the object's own, each substitute) bends in its own frame, from the local matrix chain - author-templates: a `lod` object field; the card builds every fallback level first and draws each object's finest real model - the Aquarium: six reef fish (clownfish Wander + Orient to Velocity, tangs and angelfish Follow Path loops with banking, every fish a Body Wave), a reef rock arch (was the torus), staghorn coral, eelgrass and Amazon swords — all aquarium-kit models over the old primitives as stand-ins wearing the thin film - tests: e2e aquarium-reef (motion, fallback LOD, saves, tier, offline counterfactual); select-inside-36 / fb-water-probe find the fish the loaded Aquarium has Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…enu taps (F2) - F1: $lib/ui/sheetDrag (the shared drag/flick/keyboard gesture) + sheetSnap.settleSheet (free-height rest rule: snap to min/max, swipe down to the end closes) + ui/SheetGrip (the sticky grab bar). Wired into the shell's framed sheets, ui/Sheet, the Inspector / Configure Scene, the main menu, the profile menu, every phone context menu (Add), the notes sheet, toolboxes, Customize character and the dock (grab bar drawn by PhoneShell; swipe-away minimizes the dock). Heights remembered under each sheet's existing key. - phoneSheetMax / --ps-sheet-max: no sheet rises into the top bar or pushes the selection strip under it; the bar + strip rise over every open sheet so Play is never covered (cover-play-and-handle). The notification centre's desktop click-catcher stands down on the phone. - F2: the profile menu inherited pointer-events:none from the top-right corner chrome on the phone, so Customize character / Profile settings never got the tap. On the phone it is a plain sheet above the bar (no top layer), tappable. - e2e phone-sheets (104, real touch events, F2 counterfactual); mobile-map and mobile-ui-fixes assert the new above-the-bar contract; vitest sheetSnap +4. - svelte-check 300/40 (baseline ratcheted from 300/41). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ersions (WIP) - src/lib/image/imageOps.js: pure raster maths (crop/rotate/flip/area+bilinear resize/ brightness-contrast-saturation), vitest imageOps (19 green) - src/lib/image/imageVersions.js: per-image version history in idb (Original always kept, cap 20) - src/lib/image/imageEditor.js: open/close, decode/encode, saveImage (same record, version kept, linked textures re-textured as one undo), restoreImageVersion, saveImageCopy, editMaterialTexture - ImageEditorWindow.svelte: WindowShell canvas + right sidebar (Edit / Versions), zoom/pan/pinch, crop drag, editor-local undo, phone sheet above Play - entry points: Explorer "Edit image...", preview #preview-edit, Inspector #texture-edit - storage breakdown: "Image versions" category - e2e image-editor (WIP: sections 1-8 pass; save is slow on a janky page, being profiled) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…g fixes - dock-chrome-40 (45 checks, phone touch + desktop mouse), green; counterfactual: keepScroll neutered -> F6.3/F6.5 red - suites that clicked the removed docked close/undock buttons now use the tab x ([data-dock-tab-close]) and #dock-undock - phone '+' sheet ends at the phone bar (Play visible) and its switches fit - Layouts dialog: Escape in the window capture phase (the menu tree stops keydown) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…n, toolbar strip (40 F3) - $lib/ui/touchHold: touch hold opens an Explorer item's menu (the phone action sheet); the browser's touch contextmenu / native dragstart are swallowed on Explorer items only. File cards: hold-and-lift = menu, hold-then-move = the existing touch pick-up. - the inline rename field's ::selection uses --accent-fill / --on-accent. - docked Explorer toolbar is a ui/ScrollStrip on the phone shell (#explorer-dock-strip). - e2e explorer-phone: 20 PASS / 8 FAIL — remaining failures are TEST sequencing (the folder menu has no "Open" row and Escape does not close the action sheet, so the later sections run with a menu open), see the STATUS handover. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… reef suite test fixes (40 F14) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- lod.js afterRender and the water runtime's afterSceneRender returned early on a nested render BEFORE calling the hook they wrap, while their before-hooks always call theirs: every water reflection pass leaked one depth into the wrapped hook, so the LOD group pass was skipped forever after the first frames (pre-existing, seen on the 1.31 Aquarium too). Both now always hand on to prevAfter. - vitest lodHookChain (counterfactual: depth 5 / 0 passes with the old hook); aquarium-reef 2.0 asserts the pass keeps running with water in the scene. - GroupEntry typedef carries the lastWant debug field (svelte-check back to 300/41). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…erty (40 F14) - the tang loop is an ellipse (1.45 x 0.5 m), so two fish half a lap apart are never closer than its minor diameter, 1.0 m: the old > 1.2 m threshold could not pass. The check now asserts their midpoint stays on the loop centre (measured 0.00 m); with a broken offset it would be 0.5-1.45 m off. - suite 32/32 green with the packs reachable. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…on, toolbar strip (40 F3) - finishes the wip commit: e2e explorer-phone 28/28 (real CDP touch, dark + light). - an action sheet closes on a tap on its backdrop (a phone has no Escape); the folder menu's rows are Share folder / Properties / ... (no "Open"). - counterfactuals: no folder onhold -> the folder-sheet check reds; touchHold's swallow removed -> a touch contextmenu opens a second menu before the hold (menus 1). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…d Play; suite green - the phone shell's top bar (64 px) covered the editor's header and close button: the sheet now starts under it and ends at the bottom bar (--ps-bar-h), so Play stays tappable - canvas and sidebar no longer squeeze side by side at 390 px (232 px canvas, a sidebar clipping its own labels): the Edit/Versions panel stacks under a full-width canvas, its tabs a row of 44 px touch targets - image-editor suite: GPU backend (on software GL two pages + the 14 MB photo starved the compositor, ~1 s per round trip, profiled: JS idle), wider post-Save waits, diagnostic logging removed, the phone section finds the shell's #ps-play and asserts the close button and the stacked panel (counterfactual: both red with the CSS removed) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- cause (measured with an instrumented ResizeObserver): ui/ScrollStrip watched every child and never stopped watching a REMOVED one. The docked Explorer's header measures itself inside a resize pass, finds it is narrow and unmounts its storage chip (a strip child) in that pass; a detached node's 0x0 notification cannot be delivered in the same pass, so the browser raised "loop completed with undelivered notifications" and the crash toast showed it (the user's phone had Explorer + Animation docked: feedback-1.31/resizeobserver.jpg). - the strip un-watches a child in its MutationObserver, which runs at the same microtask checkpoint as the removal, before the next gather. Every ScrollStrip inherits it. - e2e resize-observer-loop (14): 350x716 touch, dark + light, Explorer + Animation (Graph) docked, tab switches, a real-touch dock resize; desktop open + resize. Counterfactual: the old ScrollStrip reds 6 checks (1 loop error + the toast, per theme). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ct (40 F3) - section 5 asserted the docked header TRUNCATES the project chip at 520px; at <= 640px the phone shell is up and F3 made that toolbar a sideways strip on purpose (the name was cut to "Unt..." on a phone). The truncation contract moves to 660px (narrow, not phone) unchanged, and 520px asserts the strip: search keeps its width, the name shows whole, a scroll brings the chip fully into view, the page does not overflow. 71/71. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… view - the sidebar's scroller is shared by Edit and Versions, so after scrolling down in Edit the short Versions list opened scrolled out of sight and read as empty (measured on a phone: the list 525 px above the visible area). Each panel resets the scroller when it mounts. - on a phone the stacked panel showed Apply crop half under the bottom bar after Crop...; entering crop mode scrolls it into the panel's view - suite: phone checks for both, the touch drag's crop box asserted directly, the first-draw canvas read polls instead of sampling once (counterfactual run15: three checks red) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…0 repro - windowTabs.tabbable: a header press that never travels (4px) is a click that raises the window, not a merge. Latent before: it only stopped hiding once F10 kept group members on their group rect, which put a member's header band under a window that overlaps the strip (tab-group-stacking went red: a raised object list joined the group) - dock-chrome-40 F10: the joining window's own remembered spot is parked off the right edge first, plus F10.5 (a browser resize and two more tab switches). With the dragWindow tab-member guards removed F10.3 now goes red (it did not before) - dock-splits / docking / layout: #flow-undock -> #dock-undock (the docked window has no undock button of its own since F8). Their remaining reds are identical on 1.31.0 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
# Conflicts: # src/components/editors/Explorer.svelte
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ranking (window-header-ranking 220/190 px overflow) 40-image added #preview-edit after the ranking was set; at 220 px and below the row overflowed. It now gives way with the up-a-folder button (Edit image… stays on the Explorer menu and the Inspector texture row). The suite tracks it in the ranking. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…act (hold = action sheet, hold+move = pick up) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…0 F3) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…Undock button' (40 F8), 'scale' finds the Fish scales preset (40 F16) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…reloads (41-editors' suite meets 41-modals' G16) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…scope chip (the breadcrumb sits above the pane now) 41 G15 moved the crumbs into the layout flow but FIT_PADDING kept its 56px top, so a short docked pane (270px, minimap on) framed below minZoom and clamped at 0.2. node-ux-notes clicks nodes by their own middle and re-reads c after Align (it used to hit another member by luck). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…d in the same frame
- $lib/ui/bottomEdge.js: ONE live bottom edge — the bottom bar and whatever is open along it
(framed sheet, Inspector, notes sheet + note card, toolbox sheet, dock + its tab row, Add list),
read once per animation frame; `followBottomEdge(fn)` calls back only on change.
- PhoneShell: the strip sits at bottom 0 and is lifted by a TRANSFORM written in that rAF (no
layout), replacing a 120 ms poll that moved `bottom` — the strip held a stale place for frames,
then jumped ("inspect toolbar stutter when I resize drawers").
- strip-follow-41b (new): CDP touch drags of the dock grip, a framed sheet's handle and the
Inspector's grab bar with a per-frame sampler. Counterfactual on feat/41-int: 95-102 of ~169
frames more than one frame behind and 17-18 jumps per drag (7 reds); after: 0 / 0, 16 pass.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… is room; no avatar in the profile sheet - H4 (refines G21): the chip shows "Connected" / "Connecting…" / "Offline" (connectionLabel(tone), $lib/connectionStatus) beside its dot when the chip's slot between the logo and the right-hand chrome has room, and drops to the dot alone only when it is crowded (the peers button and a call's mic narrow it) — a ResizeObserver container-width rule, not a device rule. The label's natural width comes from an always-laid-out hidden copy (a hidden label measures 0). The full sentence stays the tooltip and accessible name. Phone only: the screenshots and G21's complaint are phone. - H11: the phone profile sheet drops the notch avatar from its header (the avatar is already top right); the name takes the row. Desktop keeps the notch circle. - signaling-reconnect: its "the chip carries no text" check follows H4 (one state word; the chip fits its slot). vitest connectionLabel. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ay's own menu; Play defaults to Play
- H6: More may leave the bar ($lib/ui/phoneBar: no forced More; More comes back at the end). The
first removal opens a kit modal "To get More back, press and hold any item on the bottom bar"
("Keep More" undoes it; one-time, `phoneBarMoreHint`). The editor's header reads
"More ▸ Edit bar…" and "More" returns to the More menu.
- H6: a long press on Play opens PLAY'S OWN phone menu instead of forwarding to the desktop
toolbar's (whose Move left/right walked a bar a phone does not draw, plus Always on top / Move
toolbar / Collapse / Customize): the shared "Play as" rows, Test play in a game, Move left /
Move right (Play walks along the bar, `phoneBarPlayAt`; the middle is forgotten) and Edit bar…
(so a bar emptied down to Play stays editable). Reset to default also re-centres Play.
- H7: `vrOverride` is three-state — 'true' / 'false' are a choice, absent is the DEVICE default
(sceneStore `readVrOverride`; inputDevice `handheldDevice` = a coarse pointer that is not a
headset browser): a phone plays on its screen like desktop, a headset still enters VR.
`choosePlayAs` / `playAsItems` ($lib/playMode) are the one write for both play buttons'
menus; Settings ▸ VR writes OFF as 'false'; resetting VR settings returns to the device default.
The phone Play glyph follows the choice like desktop (triangle / headset / headset with A R).
- Suites: phone-bar-41b (new, 34: H4 / H6 / H7 / H11 on the folded N6 + desktop parity);
mobile-map's "More cannot be taken off" follows H6; play-mode-menu counts the menu it gets (41 G1
grew the toolbar tail — red on feat/41-int before this, A/B'd). vitest phoneBar.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…r on a phone - Desktop / unfolded N6: the panel is the notification centre's tool window (ui/WindowChrome: "Connected" + count + the All|Rooms switch + close — same 40 px header), 320 px at least and as wide as its rows up to 420 px. Each peer is ONE row: avatar · name (ellipsis, full name as the tooltip) over one muted line (where they are, their role, mode / mute / VR / quality, the short id — the place ellipsizes first, nothing wraps) · actions on the right (role picker, Watch / Go to / Join / Request access). - Phone: `peersPanelOpen` (appStore) replaces the component's own flag, so PhoneShell frames the panel like the notification centre: the shell's sheet with its grab bar, a scrim, swipe down to close (G5); the desktop click-catcher stands down there; the selection strip hides under it (G20). - peers-panel-41b (new, 25): four long-named peers in long-named scenes with roles, on desktop, the unfolded and the folded N6 (real touch swipe). Counterfactual on feat/41-int: 288 px, every row's second line wraps, no full-name tooltip, no header — then no drawer. peers-popover reads the new header. Shot drivers peersShots41b / phoneShots41b (evidence, not suites). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…s stay on the label's row - $lib/ui/rowFit.js: each row measures its control's max-content (an invisible, absolutely-positioned clone — the live row never reflows) against the row and keeps it beside the label when the text column keeps >= 150 px (no one-word columns, G19's narrow-width fix). One ResizeObserver + a MutationObserver per control, batched; verdicts land a frame later from inside the observer so a row-height flip cannot raise a ResizeObserver loop error - ui/SettingRow: G19's container queries (every segmented / two-piece control under 560 px, all but a lone switch under 420 px) replaced by the measured verdict (`sr-fit-stack`); a stacked segmented / slider / text field / `wide` row stretches, the rest keep their width; a stacked segmented wider than its row wraps to two columns (`sr-seg-wrap`, "Double-click action" on a phone); an empty `extra` snippet takes no room (the shortcut rows' dead gap) - folded N6: shortcut keys, Light helper length, Length, colour swatches + Reset, Grid size/colour, Version, Diagnostics Copy, Clear saved session, Reset all settings, Session size, voice-typing Test back on one row (the 1.31 look); unfolded N6: Node editor mouse/opens and Ping sound too - tests: settings-row-fit (new, 47; counterfactual red on feat/41-int — every folded row stacks); settingsNarrowShared floor 180 -> 150 + a description-less one-line label (Version) counts as fine Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…tions, a setting to roll back - the user's FINAL burger decision (feedback-1.32b): COMPACT = a strict two-column grid at list-row height, icons beside labels — [New from template…] / [Load][Save ▾] / [Import][Export…]. Save saves with the last-used options, ▾ opens "Save options", Export… opens Publish / Export. LIST = the 1.32 rows; its ⚙ opens the same Save options. The action ids (#open-templates, #open-publish-export) move with their action; the cloud slot still follows Save in both - Save options (SaveOptionsModal.svelte, the kit's ModalDialog + Segmented + Toggles): format (Project / Scene, GLTF / JSON once offered), what a .tpscene / .tp includes, the two optional formats — a DRAFT: Save remembers and saves, Cancel forgets. It replaces the cog's small popup. $lib/saveOptions.js holds the options under the SAME localStorage keys (saveFormat, showGltfFormat, showJsonFormat, tpscene*, tpProjectVersions), so a device keeps its choices - Settings ▸ Interface ▸ Lists & menus ▸ Project actions = Auto / Compact / List ($lib/projectActions, `ui:projectActions`, absent = Auto = List on the phone shell, Compact on desktop + unfolded N6), keywords for settings search (burger, main menu, compact grid…), Reset Interface resets it - tests: burger-project-actions (new: both device defaults, the grid's geometry, Save ▾ -> Save downloads the chosen format + remembers it, one-press Save, Export…, instant rollback, search, the fold/unfold posture); files-format-row / project-open-import / scene-versions-in-file / tpscene / community-seams pin the List layout and drive Save options; modal-layering measures the modal; text-selection reads either label Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…(41b H10) - the overlay thumb is a CHILD of the scroller, placed at scrollTop + inset, so it was part of the scrollable overflow: content that shrank under a scrolled view kept its old scrollHeight through the thumb, and every scroll event moved the thumb up by its 2 px inset - the view drained 2 px a frame for seconds with the content above it (Modules: Browse scrolled down, then Core = "a huge scrollbar that shrinks, then the items appear") - place() measures with the thumb out of layout, so the offset clamps on the first frame; fixed once in the primitive, every redesigned scroller inherits it Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…pens at its top (41b H8 H9 H10) - H8: a module row is a grid - name/description on the left, the management controls on its RIGHT on every width (Core: download + switch, User: Remove + switch, Browse: Install), the module's own actions (Button & door "+ Button", Pong spawn/remove, Update) under the text; the dev URL row wraps so "Auto" never leaves the card (clipped at 360 css px before) - H8: a clamped description is a tap target with a chevron - expands in place, a second tap collapses it (no tooltip: touch has no hover); nothing to tap when the text fits - H9: Browse installs are per-module JOBS ($lib/moduleInstallJobs: a per-id promise map, a second click joins the running install) - the old single galleryBusy id was overwritten by the next click, so earlier cards went back to "Install" mid-download (the Waves report); installUrl takes an onStatus reporter so a job never writes the shared status line - H9: a failed install stays on its card: the reason in words, Retry, and Details with the raw message (it used to land on the User tab's one status line, overwritten by the next install) - H10: switching tab scrolls the modal body to the top (with the minimalScroll fix, Core is at its final height from the first painted frame) - suite modules-phone-jobs (37): folded N6 + desktop, routed slow/failing module fetches, rapid clicks on four modules incl. Waves; 14 red on feat/41-int, all green here Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… them - Properties (the Inspector's selection view), Objects, Notes, Layouts and Configure Scene are tabs of the bottom dock on a phone, through the G22 registry: bottomDock PHONE_DOCK_TABS (+ titles/icons, DOCK_KEYS for the strip order), dockMenu PHONE_DOCK_WINDOWS (phone-only rows of the "+" sheet/menu) with registerDockOpener/registerDockCloser; no undock for them. - $lib/phoneDock: occupancy while the phone posture is on; the ONE Inspector element as two tabs (an outside close is read after a 120 ms settle, since showSidebar closes and reopens on a kind switch); the posture memory (folded <-> unfolded/desktop: each panel to its wider-screen home and back, the tab in front kept; opens/closes carry over; session memory only); Inspect opens or focuses Properties; phoneBarTap (H5: a tap on the view on screen minimizes the dock, a floating window with undocking on toggles); Objects stays a floating window when undocking on touch is on (41 G6). - PhoneDockHost.svelte: the dock frame (.tp-dock-panel + DockTabs, the shell's grab bar) that re-seats #inspector / #object-list / #notes-drawer via [data-pd-host]; renders the Layouts list and a "Nothing selected" state. - The note card sits under the phone bar (it was on --z-popover and covered the raised Play circle) and is a page of the Notes tab when it is in front, its grab bar resizing the dock. - appStore seams: setInspectorRevealer (showSidebar / openSceneSection on a covered tab bring it to the front) and setPanelsHook (Settings / spectating give back the tab that was in front, and nothing reopens while hidden). - The dock's swipe-away puts the height back to where the gesture started (the live drag left flowDockHeight at 0 and every later tab 27 px tall). - Suites adapted to the tab model (their intent kept): phone-sheets, sheet-handoff, notes-phone-drillin, drawer-layering, mobile-map, dock-add-registry, dock-chrome-40 F11, select-41 reset. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…e only The main menu closes as Configure Scene opens on a phone (it is a dock tab under the menu sheet); on a wider screen it stays open beside the drawer. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Real touch on a folded N6: Inspect = the Properties tab (and focuses it over the Explorer), Objects/Notes/Configure Scene/Layouts tabs, the kind follows the tab, tab close, the "+" sheet rows, no undock, Play never covered (Notes tab + note card), H5 minimize/restore + floating toggle, H2 on phone vs desktop, the posture round trip 390 -> 770 -> 390 -> 1440 -> 390. 58/0 on the lane; red on feat/41-int (counterfactual). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
# Conflicts: # src/components/phone/PhoneShell.svelte
… svelte-check to 299/39 41b H1 made Objects and the Inspector dock tabs on a phone, so 41b-bar's strip-follow rows for "a framed sheet (Objects)" and "the Inspector sheet" no longer open a sheet. The framed-sheet row drives Chat (still a framed sheet); the Inspector's grip is the dock's now, covered by the dock row. The union is one svelte-check error below the baseline (41b-bar). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The 41 section gains the phone dock tabs, the bottom-bar changes, the burger Project grid + Save options, the Modules window and install jobs, the peers panel; the pill and settings-row lines now say what round 2 made of them. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…) in settings search; a phone's 'Play on the screen' default is ON (H7) - lock-search: re-recorded on the union; the only change is the new Settings ▸ Interface ▸ Project actions row in 7 queries (2 of which now also land in Interface). - lock-settings: one value edited by hand, the 390x844 VR ▸ "Play on the screen, even in a headset" default false → true (H7: absent vrOverride = the device default, and a phone plays on its screen). A full LOCK_RECORD re-shuffles ~3k lines of probe output, so it was not kept. - Battery round 2: image-editor touch crop red identically on pristine 353dfea; notes-v2 and fb-water-phone green on rerun. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…a built app (preview proof) The H10 minimalScroll probe imports '/src/lib/ui/minimalScroll.js', which exists on a dev server only; against preview-1-32c the import threw and took the H8 layout checks after it down (24/0 then SCRIPT FAILED). On a build the probe is skipped with a SKIP line; the Core-frame H10 checks above it still run. Dev server: unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…lected offers the whole scene), matching B1.2 Sidebar #format-gltf and SAVE_FORMATS gltf still said "Exports the scene as glTF"; fileHandler exports the selection and asks before exporting everything. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This was referenced Oct 13, 2026
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Release 1.32.0 — roadmap 40 (the 1.31 review) + roadmap 41 (review of preview-1-32, round 1) + roadmap 41b (round 2). Integrators 40-int → 41-int → 41b-int.
[test]lock fixtures follow round 2 (ab66862), modules-phone-jobs skips its /src probe on a built app (8a26e5a),[fix]GLTF tooltips say it exports the selection (6ff5e32, wording only).format-1retagged + purged. Scenes: [scenes] aquarium: the reef (roadmap 40 F14) — for core 1.32.0 scenes#22 (aquarium reef) merges with the release,format-2retag after. Modules unchanged.User approved preview-1-32c (app ab66862) on device 2026-10-14 ("ANSWERED: OK").
Gates: svelte-check 299/39 (baseline ratcheted), vitest 175 files / 2014, check:tokens/storage/zindex, build, scene-lint 33 scenes 0 errors. e2e battery 191 suites in two slots: every red identical on the round-1 head (A/B) or pre-existing. Perf budget gate green; draw calls/triangles unchanged for all 13 games. Preview proof on preview-1-32c: H rows 243/0, G rows 683/0, roadmap-40 104/0.
🤖 Generated with Claude Code