Skip to content

fix-live: live production fixes for 54 (viewer AI refusal, ghost peers, guest auto-admit notice, report seams) - #448

Merged
AlexZ005 merged 13 commits into
feat/60from
feat/60-fix-live
Oct 25, 2026
Merged

AlexZ005 merged 13 commits into
feat/60from
feat/60-fix-live

Conversation

@AlexZ005

Copy link
Copy Markdown
Collaborator

Lane fix-live (roadmap 55 "Fixes for 54" + plans-review additions; owner yes 2026-10-24). Merges into the 60 union.

What changes

  • F-1 — a viewer's AI tool call returns a view-only refusal instead of reporting created (read-only tools such as list_scene / control_simulation still work).
  • F-3 — ghost peers: an ICE link held disconnected 4 s closes; a getStats watch closes a link whose consent checks go unanswered 7 s; a redial answered "peer-unavailable" is not toasted; leave/drop-time WebRTC noise is logged, not toasted ("Connection error" no longer shows on a normal leave). Fixes the unavailable-id regex that matched "Could".
  • F-5 — every automatic admission gives the host a toast + a Notifications entry with Turn off / Remove (Remove drops the roster row, closes the link and refuses re-dials while the tab is open). New seams authProvider.admitNotice and cloudApi.setConnectBadge ("Public · guests join", also on the connected chip).
  • Reports seam — cloudApi.setPeerMenuItems (plugin entries in the Users peer menu); typed mute menu.
  • Floor — getproject / getasset / getmatpreset join ALWAYS_ALLOWED (viewers' Explorer fills in; replies stay gateable).
  • F-4 — AI create_objects is static unless the request asks for physics (physics: 'dynamic' or a mass); the Add menu default is unchanged.
  • F-2 — showToast(msg, actions, {keep: true}) / cloudApi.toast keep the buttons on the Notifications entry (role offers stay answerable).
  • Private deletions — localOnly rows are withheld from outboundManifest; a merge keeps our localOnly rows when a peer's newer document wins.
  • OPEN-CORE.md documents the new seams.

Verification

  • vitest: 215 files / 2637 tests green; npm run build rc 0 on the tip; svelte-check 297/39 (baseline 299 — improved, not --updated here, int may ratchet).
  • e2e tests/e2e/fix-live.test.cjs (2–3 peers, every fix): ALL PASS. Crash probe A/B: base never pruned a crashed peer (still in Users at 90 s); this branch prunes in 17.7–21.7 s when the host has the lower id, 27–31.5 s when higher (the remainder is the B5 reconnect window).
  • A/B regressions: connect-decision lane ALL PASS. deleted-folders ("idb delete timed out") and shared-library ("Settings has an Explorer section") fail identically on the base union. Open: scene-rooms-matrix fails 1 premise on this branch ("P is private in "Secret""); the base comparison is still unclassified (the first base run hit another lane's server, the re-run was stopped for low memory before it started) — run scene-rooms-matrix on the union base before merging.

Cloud counterpart: theprototype-app/cloud fix-live (reports for rooms / peers, plugin UI). It is inert on an engine without these seams, and this branch is inert without the plugin.

🤖 Generated with Claude Code

AlexZ005 and others added 13 commits October 24, 2026 10:56
…reated

Viewers' creations stay local and their edits are dropped by every receiver, so
executeAiTool answered { created } for work nobody else would see (test flight T1).
Scene-changing tools now return a view-only refusal; list_scene and local
simulation playback still work.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…sts Connection error

- ICE held 'disconnected' past 5 s closes the conn ourselves, so a peer that died
  without closing its channel goes through the reconnect window instead of
  staying a ghost (test flight T5).
- A redial answered 'peer-unavailable' is not toasted; three answers in a row end
  the window at once. The id is read from the end of the message (the old regex
  answered 'Could').
- Peer-level webrtc/disconnected noise right after a leave, drop or redial is
  logged, not toasted.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…etting shows on Connect

- Every auto-admitted peer gives the host a toast AND a notification-history entry
  that keeps its buttons until answered: Remove (session-local door: roster row
  dropped, link closed, re-dials refused while the tab is open) and the provider's
  Turn off (test flight T14: a remembered 'Allow guests' admitted silently).
- authProvider.admitNotice(peerId, cloudMeta) supplies the line + switch-off;
  cloudApi.setConnectBadge puts e.g. 'Public · guests join' on the Connect pill.
- OPEN-CORE.md documents both seams.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A connected pill collapses to its chip, which is exactly when a host forgets a
remembered 'guests join' setting; the badge was gated off there.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…tems)

cloudApi.setPeerMenuItems([{id, label, run(peerId, {name})}]) appends up to 8
entries under Mute voice when a peer is right-clicked in Users; the cloud
plugin's 'Report…' rides it. Inert with no plugin.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… the host

Plans review #5 (roadmap 49 follow-up): the last three get* requests off the
cloudHooks ALWAYS_ALLOWED floor, so a cloud viewer's Explorer never filled in and
a shared texture or big material preset stayed missing. Requests only; their
replies stay gateable. A unit test now walks every get* the dispatcher answers;
gettransport, getgame, getkitentities and getpatch are still off the floor and
listed there for a separate look.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…physics

The Add menu stamps standard primitives dynamic (mass 1), so a scene an AI built
from boxes fell apart the moment Play started a sim (test flight T8).
create_objects now writes static through setPhysicsFor (replicated, undoable)
unless an object asks physics: 'dynamic' or a mass; the schema and set_physics
description say so. The Add-menu default is unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…{keep})

showToast(message, actions, { keep: true }) (and cloudApi.toast) leaves the
buttons on the notification-history entry until one is pressed — the role offer
sat there as 'Accept?' with nothing to click. Plain action toasts are unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… 295)

The plugin-items spread read muteMenu inside a closure, which svelte-check
flagged; typing the $state fixes that and four older errors on the same menu.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…session

Plans review #6 (R22 round 36 'known and left'): a localOnly deletion row carries
the file's name, folder path and thumbnail, and the deleted log replicates whole.
outboundManifest now withholds localOnly rows (both branches), and the merge keeps
OUR localOnly rows when a peer's newer document wins, so the bin is not stranded;
applyRemoteManifest compares without them so an otherwise-identical document
still installs quietly under the sender's stamp.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… server'

Measured on two Chromium peers with one renderer crashed: the server answers a
dial to a vanished id only when the offer expires (~5 s), so three answers could
not land inside the 15.5 s reconnect window and the crashed peer stayed ~27 s.
A link WE closed for ICE silence (grace now 4 s) needs one answer; a channel that
closed by itself still needs three.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… seen at ~9 s)

ICE's own 'disconnected' took ~15 s after a peer's renderer crashed (and the base
never pruned that peer at all: 90 s probe). getStats every 2 s: when consent
requests keep going out and no response arrives for 7 s, the link is closed as
silent, which runs the reconnect window. Crash probe on a local slot: pruned in
17.7 s when the host redials, 27.2 s when it is the higher id (the B5 window).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
F-1 viewer AI refusal + editor counterfactual; F-4 static by default, replicated,
a dynamic one falls in a sim while the static one stays; the capability floor
(viewer getproject/getasset answered, a mutation still gated); a private
deletion never reaches the host and survives its newer manifest; F-5 badge,
toast, history buttons, Turn off, Remove + re-dial refused; F-2 Accept from the
bell; F-3 graceful leave and a crashed renderer (CDP Page.crash); the Users
peer-menu plugin item. Local slot: ALL PASS.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@AlexZ005
AlexZ005 merged commit 84637ff into feat/60 Oct 25, 2026
9 checks passed
@AlexZ005
AlexZ005 deleted the feat/60-fix-live branch October 25, 2026 18:37
@AlexZ005

Copy link
Copy Markdown
Collaborator Author

In main via 60-int: released in v1.44.0 (#476).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant