Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
8ce56af
[docs] claude.md: the UI redesign design-system section + the every-i…
AlexZ005 Oct 5, 2026
2e2299b
[feat] redesign tokens: SPEC 1 semantic variables, Tailwind @theme, .…
AlexZ005 Oct 5, 2026
16bc737
[feat] redesign primitives in components/ui + the dev-only /kit page …
AlexZ005 Oct 5, 2026
9687164
Merge remote-tracking branch 'origin/main' into feat/38-tokens
AlexZ005 Oct 5, 2026
53d7720
[feat] material presets core: payload, starter set, library + peer br…
AlexZ005 Oct 5, 2026
5a11d21
[feat] prefab sync core: keyed instances and the override-keeping mer…
AlexZ005 Oct 5, 2026
d0a4e68
[docs] settings inventory for the R21 redesign (37-settings step 1, u…
AlexZ005 Oct 5, 2026
1d623d2
[feat] 37 R1 P1: a multi-object edit is ONE replicated batch; Inspect…
AlexZ005 Oct 5, 2026
9fa12a8
[feat] race touch pedals + in-car VR seat (21-C slipped row, 37-slipp…
AlexZ005 Oct 5, 2026
39a3761
[feat] material presets swatch row in the Inspector (37 R5 phase 2, e…
AlexZ005 Oct 5, 2026
ff7cc7b
[feat] R14 named workspace layouts (save/apply/rename/delete)
AlexZ005 Oct 5, 2026
85fb261
[feat] prefab instances: linked placement, revisions, "Update N insta…
AlexZ005 Oct 5, 2026
00f3b89
[fix] a module-declared touch stick stays live under the module's own…
AlexZ005 Oct 6, 2026
2992887
[test] R14 e2e workspace-layouts (save/apply live, mounted windows re…
AlexZ005 Oct 6, 2026
5d35e78
[feat] 37 R1 P2: drag a whole selection onto a group or parent in the…
AlexZ005 Oct 6, 2026
2da0b75
[feat] prefab library: folders, tags and a tag filter in the Prefabs …
AlexZ005 Oct 6, 2026
c9573bd
[feat] 37 R1 P3: pivot point on the toolbar and in VR; a VR grip carr…
AlexZ005 Oct 6, 2026
34dddf7
[test] material-presets waits on the store, not a fixed sleep
AlexZ005 Oct 6, 2026
b4a4d2c
[feat] module seams: registerPointerHandler, onClickMiss, camera, onP…
AlexZ005 Oct 6, 2026
b107794
[test] 37 R1 P4 (WIP): multiselect-v2 e2e suite
AlexZ005 Oct 6, 2026
287332b
[fix] prefab graph propagation reaches the instance root; prefab-expl…
AlexZ005 Oct 6, 2026
9574d87
Merge remote-tracking branch 'origin/feat/38-tokens' into feat/37-set…
AlexZ005 Oct 6, 2026
ec7ea6d
[feat] --speaking token (NOTES-38 #12): calm green ring for voice spe…
AlexZ005 Oct 6, 2026
bce8369
[test] 37 R1 P4: multiselect-v2 - wait for the wb:1 handshake, drive …
AlexZ005 Oct 6, 2026
7ba1905
[test] material-presets re-reads the host peer id after its reload
AlexZ005 Oct 6, 2026
a386ae0
[test] race-touch-vr 38/0 and module-pointer-seam green; Race terrain…
AlexZ005 Oct 6, 2026
f02e63a
Merge remote-tracking branch 'origin/feat/38-tokens' into feat/37-mat…
AlexZ005 Oct 6, 2026
d62c926
[test] R14 workspace-layouts: drag the chat header where it is really…
AlexZ005 Oct 6, 2026
7671cd6
[feat] material presets row on the 38 redesign kit
AlexZ005 Oct 6, 2026
9220937
[feat] density token switch + public /kit for module authors (NOTES-3…
AlexZ005 Oct 6, 2026
0fe9a26
[fix] NavRow follows Compact density too (--nav-row-pad-y)
AlexZ005 Oct 6, 2026
e8fbdeb
Merge remote-tracking branch 'origin/feat/38-tokens' into feat/37-mul…
AlexZ005 Oct 6, 2026
82bf0de
[ui] 37 R1: the lane's new UI on the 38 kit rules (merged origin/feat…
AlexZ005 Oct 6, 2026
1957eab
Merge remote-tracking branch 'origin/feat/38-tokens' into feat/37-set…
AlexZ005 Oct 6, 2026
5dfdf8a
[fix] prefab graph replacement replicates per node, so an undo lands …
AlexZ005 Oct 6, 2026
6256c42
[fix] R18 four small fixes: Z cycles view mode, live edit-wire tint, …
AlexZ005 Oct 6, 2026
419d087
[feat] R25 Undo toast after destructive actions: Clear scene, delete …
AlexZ005 Oct 6, 2026
453664e
[feat] R15 chat v2: @mentions in peer colours, emoji shortcodes, unre…
AlexZ005 Oct 6, 2026
5f1ea9d
[feat] R20 report a problem: a screenshot, boxes round what is wrong,…
AlexZ005 Oct 6, 2026
319c509
[feat] R16 threaded note replies + an 'annotation' history kind (note…
AlexZ005 Oct 6, 2026
f56bd7f
Merge origin/feat/38-tokens; prefab tag bar + details rebuilt on the …
AlexZ005 Oct 6, 2026
3a1ec3e
[feat] characters stand on the floor, get knocked off when idle, fly …
AlexZ005 Oct 6, 2026
a59dbc1
[feat] settings redesign on the roadmap-38 kit: grouped window, every…
AlexZ005 Oct 6, 2026
7868535
[fix] material presets read past the selection tint (37 R5)
AlexZ005 Oct 6, 2026
45373ab
[fix] 37 R1: a typed value + Enter no longer applies twice (a selecti…
AlexZ005 Oct 6, 2026
c6e8c76
[fix] settings: the bound search input starts null (props_invalid_val…
AlexZ005 Oct 6, 2026
25f5092
[fix] 37 lane e2e round 1: Z cycles synchronously, Escape closes the …
AlexZ005 Oct 6, 2026
9977ee1
[fix] 37 light-theme contrast: a chat @mention keeps the bubble's tex…
AlexZ005 Oct 6, 2026
a0ece82
[feat] material presets: one edit toolbar for the picked swatch
AlexZ005 Oct 6, 2026
89c6f6a
[fix] settings: nav groups entries (no duplicate each-key before labe…
AlexZ005 Oct 6, 2026
0361741
[fix] settings (phone): the nav bar's back clears the app logo, wide …
AlexZ005 Oct 6, 2026
5069292
[fix] star eyes sit on the face (ray-cast eye depth), feet shot after…
AlexZ005 Oct 6, 2026
11a0cec
[test] 37 R1: controls-roster counts the nine-button default bar (Piv…
AlexZ005 Oct 6, 2026
205f6e9
[test] 37 R1: controls-roster reorder walk - Rotate is hidden there, …
AlexZ005 Oct 6, 2026
d7e615a
[fix] settings: Esc reaches Settings after a pressed control unmounts…
AlexZ005 Oct 6, 2026
1b6bc72
[fix] settings: a segmented row stacks on a phone; Density in the inv…
AlexZ005 Oct 6, 2026
b7d57c7
[fix] settings: phone rows stack any wide control; the inventory walk…
AlexZ005 Oct 6, 2026
689ad5d
[test] undo-toast presses Undo with force: the toast stack reflows wh…
AlexZ005 Oct 6, 2026
d50f3ed
[fix] R25 Undo offers sit ABOVE modals: the Undo after Settings ▸ Res…
AlexZ005 Oct 6, 2026
8341296
[test] undo-toast widens the offer through undoTiming (load average 3…
AlexZ005 Oct 6, 2026
14f5ffe
[fix] settings: the window paints its own surface (light showed a gre…
AlexZ005 Oct 7, 2026
200a93a
Merge remote-tracking branch 'origin/feat/37-multiselect' into feat/3…
AlexZ005 Oct 7, 2026
ad402e1
Merge remote-tracking branch 'origin/feat/37-prefabs' into feat/37-in…
AlexZ005 Oct 7, 2026
6947d82
Merge remote-tracking branch 'origin/feat/37-materials' into feat/37-…
AlexZ005 Oct 7, 2026
41e24f0
Merge remote-tracking branch 'origin/feat/37-editor-small' into feat/…
AlexZ005 Oct 7, 2026
c9a5544
Merge remote-tracking branch 'origin/feat/37-slipped' into feat/37-in…
AlexZ005 Oct 7, 2026
30d07b4
Merge remote-tracking branch 'origin/feat/37-avatar-fix' into feat/37…
AlexZ005 Oct 7, 2026
7a85a97
Merge remote-tracking branch 'origin/feat/37-settings' into feat/37-i…
AlexZ005 Oct 7, 2026
be0d5e0
[chore] svelte-check baseline 318 → 306 on the 1.26 union
AlexZ005 Oct 7, 2026
bea0507
[test] touch-actions: the blank scene allows flying first (37 R24 mad…
AlexZ005 Oct 7, 2026
1679d7b
[fix] 1.26 union: no Pivot cell on a bar narrower than 440 px (the de…
AlexZ005 Oct 7, 2026
671cf5a
[test] avatars-rigged 1.3 reads head + feet in one frame and waits (t…
AlexZ005 Oct 7, 2026
91b24a5
[chore] perf budget reads scenes@preview-1-26-r37 (the 1.26 race re-a…
AlexZ005 Oct 7, 2026
f8814cd
[test] ui-kit PropRow: Esc after typing restores the focus value now …
AlexZ005 Oct 7, 2026
743c22b
[test] undo-toast: a used card fading out (Svelte 5 marks the outro i…
AlexZ005 Oct 7, 2026
6cf1e85
[fix] Reset all settings' Undo toast keeps 37 R25's wording ('Setting…
AlexZ005 Oct 7, 2026
b83dd98
[test] undo-toast: restore checks wait 60 s (the Undo's session re-ap…
AlexZ005 Oct 7, 2026
2b0a2d4
1.26.0 changelog (Edit many at once: prefabs that update, material pr…
AlexZ005 Oct 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ jobs:
# the subscriber for the session.
- name: no bare localStorage
run: node scripts/check-storage.cjs
# 38 R2: colours come from the redesign tokens. WARNING mode while the redesign
# migrates area by area — it only fails when a token-CLEAN file (its CLEAN list)
# grows a raw colour. R11 switches this to --strict.
- name: redesign tokens (warning mode)
run: node scripts/check-tokens.cjs

# 34 B3: scene-lint over every scene core ships (the seed) and every scene of the scenes ref
# the perf budget is about (perf/budgets.json), with the packs checkout for the kit rules.
Expand Down
63 changes: 63 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,69 @@
per release, newest first. HTML comments like this one are stripped before
rendering, so maintainer notes stay out of the user-facing window. -->

## 1.26.0 — Edit many at once: prefabs that update, material presets and a new Settings 🧰

### 🎯 Selections

- 🧮 **The Inspector edits a whole selection.** Rows that differ show a dash (checkboxes go indeterminate, lists show
—); one edit is ONE undo step and reaches everyone as one change. Visibility, shadow, render-order and culling flags
and every Light row are now undoable, and Light rows edit all selected lights at once.
- 📍 **Pivot point: Median, Active or Individual** — in the Inspector, the object menu, a new **Pivot** button on the
toolbar (after Scale) and VR Settings ▸ Editing. In VR, grip any member of a selection to move the whole set; twist
or push the stick to rotate and scale it about the pivot.
- 🗂️ **Drag a selection onto a group or any object** in the object list to put it inside; drop it on the list to
bring it back to the top.

### 🧱 Prefabs and materials

- 🔁 **Prefabs update their copies.** Editing a prefab (Update from selection, or an instance's Prefab ▸ Apply
changes) offers **Update N instances** — each copy keeps its own changes unless you pick Reset overrides; one undo,
and everyone in the room sees it. Right-click a placed copy for **Prefab ▸ Update / Reset / Unlink / Select all**.
Prefabs carry their objects' node graphs.
- 📁 **Folders and tags in the Library's Prefabs tab**: New folder, Move to folder, drag onto a folder card, a
breadcrumb, tags in Properties and a tag filter + tag search.
- 🎨 **Material presets**: save, rename and share named looks. A starter set (wood, metal, plastic, glass, stone,
rubber, neon) is one click away at the top of Inspector ▸ Material; your presets stay on your device and everyone
in the session can use them.
- 🩹 Texture maps no longer vanish when a multi-slot material change is undone or reaches a peer.

### 🪟 Workspace, chat and notes

- 🧭 **Settings, redesigned**: a grouped menu (General · Workspace · Devices & services, About & what's new pinned),
cards with one control per row, toggles, segmented controls and sliders with readouts, "This device" badges,
sub-pages with a breadcrumb (push navigation on a phone), search results that show their path and jump to the row,
a per-category **Reset … to defaults** that asks first, and **Interface ▸ Density** (Comfortable / Compact).
Clear saved session and Reset all settings moved to About ▸ Danger zone. No stored setting changed.
- 🗔 **Workspace layouts**: save the windows you have open (panels, docked or floating, sizes, docks, tab groups)
under a name and switch in one click — menu ▸ Layouts, or Settings ▸ Interface ▸ Windows & chrome.
- 💬 **Chat v2**: @mentions in each person's colour, emoji shortcodes (`:tada:`), an unread badge, and the chat so far
for people who join late or reopen a saved session.
- 🧵 **Reply to a note** in a thread; adding, editing and resolving notes is undoable.
- ↩️ **Undo after destructive actions**: Clear scene, Delete selection, Remove module and Reset all settings show a
toast with **Undo** for about 8 seconds — for everyone in the session for scene changes, on this device for modules
and settings.
- 🐞 **Report a problem** (menu, and in VR): a screenshot, boxes around what is wrong and a note, sent to the team
with your consent when you are signed in — or kept on your device.
- 🔧 Small fixes: **Z** cycles your view mode (Shaded → Shaded + AO → Wireframe), the edit-mode wireframe re-tints
the moment a colour changes, VR note pins stay on their objects while you grab the world, and dropdowns open
correctly inside a full-screen dialog.

### 🧍 Characters

- 🦶 **Characters stand on the floor** in Play and keep their feet planted.
- 💫 **Knocked off, not spinning**: an idle character now sees stars — orbiting stars, a woozy sway, star eyes —
instead of spinning its head (Settings ▸ Interface ▸ Avatars ▸ Knocked-off idle: Off / 10 / 20 / 60 s).
- 🕊️ **Flying in Play is opt-in per game**: off unless a game wants it, and a scene can remove it (Configure Scene ▸
Physics ▸ Play mode ▸ Flying). Football, Marble maze, Target toss and Stars Room now walk on desktop.

### 🏎️ Race and modules

- 📱 **Race on phones and in VR**: on a phone the stick steers and Gas/Brake sit under your right thumb; in a headset
you sit in the car and the left stick drives (a VR player could not drive before).
- 🏔️ The Race mountains get grass, rock and snow by slope and height.
- 🧩 Module SDK: `api.registerPointerHandler`, `api.onClickMiss`, `api.camera()`, `api.onPlayMode` / `api.inGame()`,
`api.vrSeat` / `api.vrUnseat`, `api.input().touch` and the `drive` touch preset; Untangle aims with `api.camera()`.

## 1.25.0 — Your feedback, fixed: panels that keep their keys, water that behaves 🌊

### ⌨️ Panels and windows
Expand Down
27 changes: 22 additions & 5 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2632,6 +2632,21 @@ loadable play content. Everything a user does must be visible to connected peers
pushes/pulls a one-grip world, as Edit does an object); `addSetting({onLevels: true})` draws a choice as tabs on the
VR Levels page, which now lists every level.

## UI design system (redesign epic)

- All UI follows the redesign spec kept in the `cloud` repo: `docs/design/redesign/SPEC.md`
(mockups in `docs/design/redesign/mockups/`). Locally that is
`../cloud/docs/design/redesign/` from this checkout (`theprototype-app/cloud`).
- Build UI only from `src/components/ui` primitives (WindowChrome, Tabs, Segmented, Chips,
Toggle, Button, Badge, SettingRow, PropRow, NavRow, EmptyState, Sheet). Add a primitive
there before inventing a one-off.
- Colours, radii, spacing and type come from the semantic tokens in `app.css` only — no raw
hex, no ad-hoc Tailwind palette colours in components (`npm run check:tokens`).
- Every icon goes through `ui/Icon.svelte` (sizes 16 or 20 only).
- A redesign change must not alter behaviour: DragRow scrubbing, modifiers, click-to-type,
shortcuts, undo grouping, peer sync, storage keys and defaults. The behaviour-lock e2e
suites must stay green.

## Replication golden rules

1. Every mutation = apply locally + `$peers.send({type, ...})`; receivers apply WITHOUT
Expand Down Expand Up @@ -4943,11 +4958,13 @@ loadable play content. Everything a user does must be visible to connected peers
`error during build: undefined` (svelte-check never runs; vite dev 500s too).
Same trap in any non-TS component: JSDoc for types, never TS syntax (#13-B3).
- **Icons = `@lucide/svelte` SVG components** (Font Awesome fully REMOVED post-1.0.1
— never add `fa-` classes). Static markup imports named components
(`import { Play } from '@lucide/svelte'`; sizes 16 inline/menu, 18-20 toolbar/
header, 24 the play FAB; `aria-hidden="true"` when decorative); DATA-DRIVEN icon
names (Explorer KIND_ICONS, menu-item defs) render via `components/ui/Icon.svelte`
(kebab lucide names). Icons inherit `currentColor` — never hardcode grays;
— never add `fa-` classes). **Redesign (SPEC §7): EVERY icon goes through
`components/ui/Icon.svelte`** — data-driven names (Explorer KIND_ICONS, menu-item defs)
AND static markup (`<Icon name="play" />`, kebab lucide names; add the name to its MAP,
an unmapped name silently renders a box). Sizes 16 (inline/menu/rows) or 20 (toolbar/
header) only, stroke ~1.75 at 16; `aria-hidden="true"` when decorative. Older code still
imports named components from `@lucide/svelte` directly — R10 migrates it; new code
never does. Icons inherit `currentColor` — never hardcode grays;
semantic colors come from the `--icon-*` theme tokens. TWO TRAPS: a `class` passed
to a lucide component lands on the CHILD-scope `<svg>`, so scoped CSS targeting it
needs `:global(...)` (bit cx-chevron/tp-toast-icon/role-caret — silent style loss,
Expand Down
16 changes: 16 additions & 0 deletions OPEN-CORE.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export function register(api) {
api.camera.pose() / setPose(p) / bookmarks() / recall(id)
api.startPlay() / api.stopPlay()
api.setCommunityProvider(p) // swap the Templates ▸ Community source (null restores GitHub)
api.setProblemReporter(r) // 37 R20: where "Report a problem" sends ({submit, account}) — typeof-probed

api.toast(message)
}
Expand Down Expand Up @@ -257,6 +258,21 @@ Promise<{liked, likeCount} | null>` puts a heart on every card (`[data-card-hear
A play link's frame may carry `&src=play|embed&b=v<n>` (read once with `embed=1`;
`playMode.embedSource` / `embedBuild`) — the badge inside counts them.

#### 37 R20: "Report a problem" — `setProblemReporter(reporter | null)` — additive, no bump

Core draws the whole report — the screenshot taken at the press, boxes drawn round what is
wrong, the note, an explicit consent box — and calls the reporter only when the person
presses **Send** with the box ticked. Without a reporter (no plugin, or an older plugin) the
report is kept on this device as a Profiler recording and the card offers no Send.

| member | contract |
|---|---|
| `reporter.submit(report)` | `report = {note, marks: [{x, y, w, h}] (fractions of the picture, ≤ 12), meta: {version, build, scene, device, url (no query), viewport, xr, peers, at}, perf: T1 light window \| null, shot: Blob (JPEG) \| null}` → `Promise<{ok, id?, reason?, error?}>`. `reason: 'signin'` = the card keeps itself open and says where to sign in |
| `reporter.account()` | `{signedIn, name?}` — read when the card opens and every 1.5 s while it is open; Send is off until `signedIn` |

In a headset (VR menu ▸ Profile ▸ Report a problem) there are no boxes: the VR keyboard's
title says that Enter sends the report, which is the consent.

#### Deep links: `?s=<id>`

Published scenes deep-link through the **query string** (`/?s=<id>[&play=1][&remix=1]`)
Expand Down
4 changes: 2 additions & 2 deletions check-baseline.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"comment": "27-I: the svelte-check floor, read ONLY by scripts/check-ratchet.cjs. It used to be hardcoded in release.yml's shell block, where it went stale (362 while the tree measured 359). Ratchet it DOWN whenever a change legitimately removes errors - that is the project convention, and --update does it in one command.",
"errors": 318,
"errors": 306,
"warnings": 47,
"measured": "2026-10-05"
"measured": "2026-10-07"
}
Loading
Loading