Skip to content

editor: host select/frame/unit exports; the plan frames a node alone and lights what a chat points at - #1040

Open
Aymericr wants to merge 6 commits into
mainfrom
feedback/entities
Open

Aymericr wants to merge 6 commits into
mainfrom
feedback/entities

Conversation

@Aymericr

@Aymericr Aymericr commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

What does this PR do?

Lets a host surface select and show a scene node the way the editor's own lists do. The plan frames a node when it is the only view on screen, and it lights what a host's chat points at.

  • selectZoneOrRoom, frameViewerNode, enterUnitFocus and PLUGINS_VIEW_ID are exported from @pascal-app/editor.
    • selectZoneOrRoom selects a zone by the Rooms list's rule: an enclosed room as the room, anything else as the zone.
    • frameViewerNode is the navigation's framing (the node's saved view, else its box in the scene).
    • enterUnitFocus focuses a unit as the site panel does.
    • PLUGINS_VIEW_ID is the plugin directory's view, for openEditorView.
  • FloorplanPanel answers camera-controls:frame itself while no 3D view is visible.
    • The request waits for the selection it came with to render, so a node on another floor or in another building is placed with that building's transform, after the floor change has reset the view.
    • After a floor change the glide starts from the new floor's view, so the plan never shows the whole floor for a frame and then snaps.
    • It fits the node's box to the pane at the current turn and aspect: the box's rotated corners against both dimensions, plus the plan's usual 2 m padding.
    • A saved view with no box centres on its target at the current zoom.
    • With a 3D view on screen nothing changes: the plan keeps following the framed camera's pose.
  • A frame request now carries the node's box as well as its saved view. The 3D camera still frames the saved view; the plan frames the box.
  • Under reduced motion, framing jumps to its pose in 3D and in the plan (framingAnimates).
  • What a host's chat points at (useViewer.pointedIds, Bundle 2's slot for chat chips) now lights beyond the 3D outline.
    • The plan's registry entries draw a pointed node as they draw a hovered one.
    • A single pointed zone shows the room outline a hovered zone does (room-highlight.tsx). With zones hidden a zone draws nothing of its own, so the point outline had nothing to trace.
  • wiki/architecture/selection-managers.md and point-and-ask.md describe all of it.

Why

The hosted Architect chat now draws the nodes a reply names as references (pascalorg/private-editor#900, slice H-entities). Hover lights the node, and a click selects and frames it. The owner's feedback of 2026-10-12, verbatim:

C10: "introduce rich message text with interactive and icon rich highlighted entities (see image examples): tool calls, scene graph node mentions, project version mentions, and more"

S5: "rich clickable icon highlighted text intead of unreadable low contrast inline code"

C23: "here are renders example of interactive highlighted mentions, we should make the right abstractions so we can change the style over time if we need." (renders: tooltip "Highlight & focus camera"; footnote "Click an entity to highlight it and focus the camera.")

Each export closes a gap the running app showed:

  • Without selectZoneOrRoom, a host could only set selection.zoneId, which opened a room as a bare zone.
  • A box a host computes from the graph misses saved views and a moved or turned building. frameViewerNode has neither problem.
  • A unit is not selectable on its own; without enterUnitFocus a host put its id in selectedIds, where no selection manager acts on it.
  • The plugin directory is a view, not a sidebar panel. Setting the sidebar to plugins showed nothing.

The plan change is the 2D half of the same click (E-006). Before it, a node clicked in a list while only the plan was on screen stayed wherever it was, often off screen. This applies to camera-controls:frame only: the scene tree's double-click focuses through camera-controls:focus, which the plan does not answer, so it keeps its current behaviour.

The pointedIds change is the 2D half of a chat's hover. The host now lights every chat chip through that one slot (references, Point and ask's elements, step cards), so they never fight the editor's own hoveredId. Before this, a pointed node lit only in 3D, and a pointed room not at all.

How to test

  1. Open a project with a few rooms and show the plan alone (2D, no split).
  2. Zoom into a corner, then select a far room from a host surface that frames (the hosted chat's reference, or frameViewerNode(id, source)). The plan glides to the room and fits it, at the same rotation.
  3. Do the same for a door: the plan centres on it with about 2 m around it.
  4. Turn on the OS's reduced motion and repeat: the plan and the 3D camera jump instead of gliding.
  5. Split 2D + 3D and repeat. The 3D camera frames the node and the plan follows it, as before.
  6. Hover a wall's reference in the hosted chat with the plan on screen: the wall is stroked in the plan. Hover a room's reference in 3D: its outline shows.

Checks run (from the hosted worktree root, at 0610e66a):

  • bunx turbo run check-types --filter='./editor/packages/*': 9/9.
  • Biome on the changed files, with the editor's config.
  • bun test on viewer-selection, components/editor (the floorplan and room-routing tests), the viewer store and the point-ask components: 354 pass.
  • The editor packages' full suites were not run locally; CI runs them.

Screenshots / screen recording

Checked in the hosted app (pascalorg/private-editor#900 at b4be51583, local dev server, scripted turns), in dark and in light (the host's theme, #1041 / private-editor #901). Screenshots are in /tmp/feedback-work/entities/reconciled/ on the author's machine:

  • desktop/plan-hover-garage-*.png, desktop/plan-hover-wall-*.png: with the plan alone, a hovered room's reference lights the room and a wall's strokes the wall.
  • desktop/plan-click-kitchen-*.png, floors/plan-ground-kitchen-*.png: a click on a room selects it and fits the plan to it.
  • floors/plan-upper-study-*.png: a click on a room on the other floor switches the plan to that floor, selects the room and fits it. Read every frame, the viewBox starts at the new floor's view and glides in (width 13.47 → 12.20 over about 0.5 s), with no snap.
  • desktop/hover-room-*.png, desktop/click-kitchen-3d-*.png: in 3D a hovered room's reference shows its outline, and a click selects and frames it.
  • mobile/tap-kitchen-*.png (390 × 844): a tap selects the room.

Reconciled with Bundle 2

Rebased onto editor main c69d1d33: #1024 (Bundle 2), #1042, #1043, #1048 (which carries the H-sidebar commits) and #1041 (light chrome). No conflicts.

  • Dropped: the feedback/entities-pin merge with the H-sidebar pin. Those commits are on main, so the hosted gitlink is this branch's head.
  • Kept: the exports, next to Bundle 2's (isTypingTarget and others).
  • Added: the plan and the room outline read Bundle 2's pointedIds. That gives one hover path for every chat chip.

Review

From the review of b90ec70e (Claude and GPT-6 Astra):

Fixed

  • The plan converted the frame request with the previous building's transform when the click changed building. It now waits for the selection to render.
  • Twice the diagonal did not fit a wide or tall pane. The box is now fitted against both dimensions at the current turn.
  • Framing ignored reduced motion in both views. It now jumps.
  • A unit host reference had no unit focus. enterUnitFocus is exported.
  • The wiki paragraphs were re-wrapped to the page's width.

Fixed after Bugbot's review of the reconcile

  • A frame on another floor flashed: the floor change nulled the view before the frame applied, so the glide started at its own destination and the plan showed the whole floor for a frame before snapping. It now starts from the new floor's view (0610e66a).

Corrected

  • The earlier body said the scene tree's 2D framing was fixed too. That was wrong: the tree uses camera-controls:focus. The "fully visible" and "never closer than 4 m" claims were replaced by what the code does.

Not changed

  • A saved view keeps the current zoom in the plan only when the node has no box to fit. Every node the chat frames has one.

Deployment notes

  • Merge this PR first (D-006). Then re-bump pascalorg/private-editor#900's gitlink (now 0610e66a, this branch's head) to the merge commit.
  • No env vars, no migrations, no schema change.

Checklist

  • I've tested this locally with bun dev (tested through the hosted Community dev server, not the editor's bun dev)
  • My code follows the existing code style (run bun check to verify)
  • I've updated relevant documentation (if applicable)
  • This PR targets the main branch

🤖 Generated with Claude Code


Note

Medium Risk
Touches shared framing events and public selection APIs used by hosted chat; behavior changes when 2D-only or reduced-motion, but scope is viewer/navigation rather than auth or data.

Overview
Hosts can drive scene UX like the built-in navigation: new public APIs include selectZoneOrRoom, frameViewerNode, enterUnitFocus, and PLUGINS_VIEW_ID.

Framing now sends both bounding box and saved camera pose on camera-controls:frame (3D still prefers the saved view; the plan can fit the box). framingAnimates() respects prefers-reduced-motion for 3D setLookAt / fitToSphere. When only the 2D plan is visible, FloorplanPanel handles the same frame event—waiting for the selection to render, then fitting rotated bounds or centering a pose-only target.

Chat / host references use pointedIds in 2D: floorplan registry entries treat a pointed node like hover, and a single pointed zone gets the room outline (including when zones are hidden). Wiki architecture notes were updated.

Reviewed by Cursor Bugbot for commit 0610e66. Bugbot is set up for automated code reviews on this repo. Configure here.

@Aymericr Aymericr changed the title editor: hosts select and frame nodes like the lists; the plan frames alone editor: host select/frame exports; the plan frames a node alone Oct 12, 2026
@Aymericr Aymericr changed the title editor: host select/frame exports; the plan frames a node alone editor: host select/frame/unit exports; the plan frames a node alone Oct 13, 2026
@Aymericr
Aymericr force-pushed the feedback/entities branch 2 times, most recently from 0f18a46 to 0e60590 Compare October 13, 2026 16:15
@Aymericr Aymericr changed the title editor: host select/frame/unit exports; the plan frames a node alone editor: host select/frame/unit exports; the plan frames a node alone and lights what a chat points at Oct 13, 2026

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 0e60590. Configure here.

Comment thread packages/editor/src/components/editor/floorplan-panel.tsx
Aymericr and others added 6 commits October 13, 2026 12:46
…EW_ID for hosts

A host surface that names scene nodes (the hosted chat's chips) selects and
shows them the way the editor's own lists do:
- selectZoneOrRoom: a zone by the Rooms list's rule, an enclosed room as the
  room, anything else as the zone. A host could only set selection.zoneId,
  which opened a room as a bare zone.
- frameViewerNode: the navigation's framing, the node's saved view else its
  box in the scene. A host computing its own box missed saved views and a
  moved or turned building.
- PLUGINS_VIEW_ID: the plugin directory's view, for openEditorView.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A frame request (camera-controls:frame, from the navigation or a host's
"show me this node") moves the 3D camera, and the plan follows its pose.
With the plan alone on screen nothing carries that pose over, so a node
selected from a list stayed wherever it was, often off screen. The plan now
answers the request itself while no 3D view is visible: it centres on the
node's box (or its saved view's target) at the current turn, wide enough for
the box at any rotation and never closer than 4 m. With a 3D view on screen
nothing changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A host's reference to a unit focuses it the way the site panel does, instead
of putting the unit in the selection.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ed to the pane

- With no 3D view on screen, a frame request now waits for the selection it
  came with to render. A node on another floor or building is placed with that
  building's transform, after the floor change has reset the view, instead of
  the previous building's.
- The node's box is fitted to the pane at the current turn and aspect (its
  rotated corners against both dimensions), not twice its diagonal.
- A frame request carries the node's box as well as its saved view; the 3D
  camera still prefers the saved view, the plan frames the box.
- Under reduced motion, framing jumps to its pose in 3D and in the plan.
- selection-managers.md re-wrapped and updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nts at

A host's chat lights nodes through the viewer's `pointedIds` (Point and
ask's chips, a step's card, and now every reference in a message), but only
the 3D outline read it.

- The plan draws a pointed node as it draws a hovered one, so a chat light
  shows in 2D as well as 3D.
- A single pointed zone shows the room outline a hovered zone does. With
  zones hidden a zone draws nothing of its own, so the point outline had
  nothing to trace.
- point-and-ask.md says so.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…loor

The floor change resets the plan's view before the frame applies, so the
glide started at its own destination: the plan showed the whole floor for a
frame, then snapped to the node. It now starts from the floor's fitted view.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
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