Skip to content

editor: integrate local plugins, surface stairs and deck railings - #1001

Open
sudhir9297 wants to merge 32 commits into
pascalorg:mainfrom
sudhir9297:t3code/link-local-plugins
Open

sudhir9297 wants to merge 32 commits into
pascalorg:mainfrom
sudhir9297:t3code/link-local-plugins

Conversation

@sudhir9297

@sudhir9297 sudhir9297 commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

What does this PR do?

  • Integrate Bath Space, Landscape, Pool, Streetscape and WebXR through plugin discovery and host panels, with immutable GitHub package revisions and portable bundler configuration. Installs use the published GitHub packages and require no sibling checkout.
  • Add registered surface snapping for straight stair placement and movement in 2D and 3D, live flight previews, inspector controls and curved-boundary transitions. Keep stair authoring in the node definition and respect visible snapping modes.
  • Draw fences as deck railings with inward edge/corner snapping, deck-top elevation and active-floor tracking. Remap support references when cloning, strip preset host references, and clear deleted hosts.
  • Preserve wall-mounted object grab offsets and face placement, support alpha-cutout selection outlines, repair GLB export cloning, and integrate Pool controls and plugin styling.
  • Add documented connected-move hooks, inspector extension composition and room-boundary opt-outs. Increase the portable runtime size budget for the integrated catalogs.
  • Pin the published Bath Space guided UI package. Widen the editor sidebar to 360 px and collapse secondary tool hints under More shortcuts.
  • Prevent autosave SSE echoes from resetting active tools and selection. Accept namespaced attachment slot IDs at the API boundary while continuing to validate asset URLs.

Includes the maintainer fixes for Streetscape identity, stair elevation and fence drawing sessions, retaining the project dashboard and navbar.

  • Publish the Bath Space card picker in subtree 70cffa9a6878122acf6e3fdbde5725db4908f737: shared mounting cards and attached style panels in Guided and Catalog, sharp top pointers, responsive style grids, and one active category/style at a time. Clicking a category selects its first style; switching categories clears the previous selection.

Removed the local Bath Space symlink and bundler override. The installed package now comes from the published subtree commit above. Frozen installation, editor lint and all 13 workspace typecheck tasks passed after this cleanup. The installed package source matches the local Bath Space source.

How to test

  1. Run bun install --frozen-lockfile in a clean checkout. No sibling plugin checkout is required.
  2. Start the standalone editor on port 3004, open a saved project from the dashboard, and check Bath Space Guided/Catalog, Pool, Landscape, Streetscape and WebXR panels. Switch between 2D and 3D. Catalog thumbnails should load.
  3. Open a bathroom containing a wall-mounted tap, edit it and reload. Autosave should succeed with a generated wall-point:<node-id> slot ID, and save echoes should preserve tools and selection.
  4. Draw a fence on a raised deck on the active floor. Check inward edge/corner snaps and deck-top elevation, then change floors and verify the old drawing chain clears.
  5. Place and move a straight stair against a supported surface in 2D and 3D. Check the snapped high end, rise and flight dimensions, mode-driven snapping, and a single undo step per move.
  6. Duplicate a level containing a surface and its fence/stair, then check copied host references. Delete and undo a host, and check wall-mounted movement and alpha-cutout selection outlines.
  7. Expand and collapse More shortcuts. Confirm the primary action and active hints remain visible when collapsed.

Current review-fix verification:

  • bun install --frozen-lockfile --dry-run, bun run check, bun run skills:validate, and all 13 workspace typecheck tasks passed.
  • The editor package passed 2,543 tests and the node package passed 4,850 tests. Core passed 4,948 tests, viewer 684, MCP 1,127, IFC converter 92, geometry script 36, and app library tests 67.
  • New regression coverage exercises railing inset/corner/floor behavior, support-reference cloning, wall grab tracking, cutout masks, plugin LOD cloning, pending save echoes, surface-parented stairs and legacy stair field migration.
  • Landscape attachment/irrigation suites passed 102 tests; its additional raised-source attachment/detachment test and typecheck passed.
  • The portable production build, runtime staging and packed CLI smoke passed, including digest validation and a scene round-trip between MCP and the CLI. Browser checks loaded Bath Space, Landscape and the canonical Streetscape panel and verified its layout styles.
  • PASCAL_PORTABLE_BUILD=1 bun run ci now passes end to end: check, skills validation, all 13 typecheck tasks, all 15 test tasks and all 9 build tasks. The CLI passes 107 tests, including activation, rollback and stopped-editor updates. A published-layout regression test reproduces the pin override on the previous code and passes with the fix.

Review follow-up

  • Shared distribution authoring moved to @pascal-app/editor/distribution; builtin consumers and the published Landscape plugin use that entry. External plugins no longer need @pascal-app/nodes for these tools.
  • Stairs now use destinationSurfaceId / autoSurfaceSnap, with migration of the former fields. Curved transitions read the registered boundary rather than Landscape's private shape. Surface-parented snapping uses a common level frame. Raised-source previews and Landscape reparenting preserve the source elevation.
  • Inspector subscriptions select the node type and primary extension ID. Move cleanup clears previews without rewriting a committed pose, eliminating sameStairMoveStillActive. The temporary fence alias migration was removed. Public DEFAULT_STAIR_* exports are restored through core-owned constants.
  • The four open bug findings are addressed: reject unsafe URL schemes in attachment slot IDs, scan the canonical Streetscape styles, preserve raised stair bases, and reject explicit fence hosts on another level.
  • E-017 and the plugin authoring guide document connected movement, primary inspectors, independent child frames, preserved elevation, surface boundaries and room topology opt-outs.
  • Landscape is pinned to d60ee247334dad037e02a432a50bed9264193402 on the stable packages/landscape publishing branch. Bath Space is now pinned to 357338ddb7e042498fca7b6e6ee2054edbeb70b7, published on packages/bath-space; its 370 tests and two thumbnail checks pass. Streetscape remains the maintainer's org pin.
  • Explicit runtime activation and rollback now boot their selected runtime directly. Previously startup replaced that selection with the CLI package pin and attempted an unrelated download, causing the lifecycle hangs after staging a release.
  • The portable archive is reduced from 184.22 MiB to 125.84 MiB, about 32% smaller. Bath Space thumbnails fit within 512 × 512 pixels at WebP quality 90 with preserved transparency. All 198 catalog thumbnails remain; the plugin image payload falls from 70.64 MiB to 3.65 MiB. All 767 previously recorded model/public assets are byte-for-byte unchanged. Static media still includes all 561 WebPs and 40 GLBs. The archive ceiling is now 140 MiB.
  • The expanded packed smoke test fetches and byte-compares all 601 WebP/GLB assets from the installed archive. Digest/tamper checks and MCP/CLI scene round-tripping also pass. Browser checks confirm the optimized thumbnails load in Guided and Catalog without broken images.

Quality check follow-up

  • Reproduced the reported shader errors locally using CI's actual merge commit bae442a04, which combines this branch with main's @types/three@0.186.0 upgrade. The branch alone still uses 0.184.1 and did not expose the failure.
  • Published explicit TextureNode<'vec4'> declarations in Pool (1da7fb0d29691f3e2e488e24b436261266c692ce on main) and Landscape (d60ee247334dad037e02a432a50bed9264193402 on packages/landscape). This preserves RGBA channels lost by ReturnType<typeof texture> under the new generic overload. Shader calculations are unchanged.
  • The editor follow-up changes only the two plugin pins and their lockfile entries.
  • A fresh install of those published revisions passes bun run ci on the CI merge: 13 typecheck tasks, 15 test tasks and 9 build tasks. Forced branch typechecks also pass. Pool's 19 shader tests and 13 targeted pond behavior tests pass.

Screenshots / screen recording

Not added yet.

Checklist

  • I've tested this locally with 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

Note

Medium Risk
Touches collaborative autosave/SSE, scene validation, and broad placement/topology logic (stairs, fences, clones); plugin pins and runtime size affect releases but not auth.

Overview
Integrates Bath Space, Landscape, Pool, Streetscape, and WebXR into the editor app via dynamic plugin discovery, Tailwind @source entries, updated GitHub pins, and Turbopack/transpile wiring; adds a lazy Pool section banner on the viewer and documents E-017 optional NodeDefinition capabilities (surface boundaries, connected move, primary inspector, independent child frames, metadata.roomBoundary opt-out).

Core/editor behavior expands plugin-friendly authoring: straight stairs gain destinationSurfaceId / autoSurfaceSnap and magnetic snapping against registered top-surface boundaries; fences validate explicit top-surface hosts on the same level; connected-move and preserve-level-and-elevation hooks extend port connectivity and the generic move tool; clones/deletes remap or strip supportSurfaceNodeId / destinationSurfaceId. Room topology ignores walls with roomBoundary: false. Shared distribution run tooling is exported from @pascal-app/editor/distribution.

Collaboration and API: live scene SSE skips in-flight autosave echoes (pending graph signatures) so tools/selection are not reset; the graph API accepts wall-point:<id> slot IDs while still rejecting dangerous URL schemes. CLI runtime staging reports static media sizes, raises the packed-archive budget to 140 MiB, and smoke-checks offline catalog WebP/GLB over HTTP; explicit runtime activation boots the chosen version despite CLI pins.

UX polish: global thin scrollbars, default sidebar 360px, contextual help “More shortcuts” collapse, and fence draft Alt angle lock.

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

@pascal

pascal Bot commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

What this PR does

This wires five Pascal cluster plugins (Bath Space, Landscape, Pool, Streetscape, WebXR) into the standalone editor and adds two building features on top of the core/editor packages: straight stairs that attach to registered top surfaces, and fences drawn as deck railings that snap inside a deck's perimeter and track the active floor. Supporting work in core covers support references (remapping on clone, clearing on host delete), port connectivity, and a new stair-surface snap service with tests. The author marks this a local development draft: the five plugin dependencies in apps/editor/package.json point at file:/Users/sudhir/Desktop/work/pascal-cluster/packages, and the PR body says portable dependency configuration and a committed companion plugin revision are needed before it can merge.

Changed files

File Change What changed
apps/editor/package.json modified Pool, Streetscape (renamed to -lab), WebXR switched from GitHub refs to local file: paths; Bath Space and Landscape added the same way
bun.lock modified Lockfile follows the file: dependency switch, pulls in maplibre, tanstack virtual and other new transitive deps
package.json modified Root manifest tweak (1 line)
apps/editor/next.config.ts modified Derives a Turbopack root from the file: dependency paths; transpile list updated for the new/renamed plugins
apps/editor/lib/bootstrap.ts modified Registers Landscape and Bath Space plugins and host panels; Streetscape import points at plugin-streetscape-lab
apps/editor/app/globals.css modified Tailwind @source entries for the local plugins, plus global thin-scrollbar styling
apps/editor/app/page.tsx modified Replaces the inline local-editor notice with a viewerBanner holding a "Saved scenes" link and the pool banner
apps/editor/components/pool-section-banner.tsx added Thin wrapper rendering PoolSectionBar from the pool plugin
apps/editor/components/scene-loader.tsx modified Passes the pool banner through viewerBanner
packages/core/src/services/stair-surface-snap.ts (+ .test.ts) added New snap service for connecting stairs to top surfaces, with unit tests
packages/core/src/lib/surface-support-references.ts added Helper for surface support references
packages/core/src/services/port-connectivity.ts (+ .test.ts) modified Connectivity handling for the new support references, with added tests
packages/core/src/registry/types.ts, scene-api.ts, subtree.ts modified Registry types and SceneApi surface for support hosts and connected moves
packages/core/src/schema/nodes/stair.ts (+ stair.test.ts), fence.ts modified / added Schema fields for stair and fence support references
packages/core/src/utils/clone-scene-graph.ts, store/actions/node-actions.ts, hooks/spatial-grid/support-host-patch.ts, contracts/reference-inventory.ts modified Remap support refs on clone, clear refs when a host is deleted, inventory entries
packages/core/src/lib/room-graph.ts, room-topology-index.ts, structure-kernel.ts, space-detection.test.ts modified Room-boundary opt-out plumbing and a test for it
packages/editor/src/components/tools/stair/stair-tool.tsx modified Largest editor change: surface-aware placement and movement, flight preview, snap-mode handling
packages/editor/src/store/use-stair-build-preview.ts modified Preview state follows the snapped surface
packages/editor/src/components/tools/fence/fence-drafting.ts modified Deck-top elevation, inward edge/corner snapping, floor-change chain reset
packages/nodes/src/fence/lift.ts, definition.ts, geometry.ts, packages/nodes/package.json modified Fence lift/geometry support for deck railings
packages/editor/src/components/tools/registry/move-registry-node-tool.tsx, item-surface-move.ts, item/use-placement-coordinator.tsx modified Connected-move hooks and wall-mounted grab offset / face placement handling
packages/editor/src/lib/wall-placement-pointer.ts added Pointer helper for wall placement
packages/editor/src/components/ui/panels/panel-wrapper.tsx, editor/floorplan-panel.tsx, src/index.tsx modified Inspector extensions supply card content instead of Landscape-specific dispatch
packages/editor/src/components/editor-2d/*, lib/direct-manipulation.ts, fresh-planar-placement.ts, glb-export.ts, selection-routing.ts, use-floorplan-background-placement.ts modified 2D overlay/layer updates, alpha-cutout selection outlines, export and routing follow-ups
20 further files — Remainder of the 70 changed files, not shown in the truncated diff listing

Where to start

Start with apps/editor/package.json and next.config.ts to see the dependency setup this draft depends on, then read packages/core/src/services/stair-surface-snap.ts with its test and packages/editor/src/components/tools/stair/stair-tool.tsx, which carry most of the behaviour change.

@sudhir9297
sudhir9297 force-pushed the t3code/link-local-plugins branch from 3761c31 to 94c1dad Compare October 6, 2026 09:36
@sudhir9297
sudhir9297 marked this pull request as ready for review October 6, 2026 09:49

@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.

Stale Bugbot comment from a previous run.

Comment thread packages/editor/src/lib/wall-placement-pointer.ts
Comment thread packages/editor/src/components/tools/fence/fence-drafting.ts Outdated
Comment thread packages/editor/src/components/tools/stair/stair-tool.tsx Outdated

@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.

Stale Bugbot comment from a previous run.

Comment thread packages/nodes/src/stair/tool.tsx
Comment thread packages/editor/src/lib/wall-placement-pointer.ts

@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.

Stale Bugbot comment from a previous run.

Comment thread packages/core/src/services/stair-surface-snap.ts
Comment thread packages/editor/src/components/tools/item/use-placement-coordinator.tsx Outdated

@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.

Stale Bugbot comment from a previous run.

Comment thread packages/editor/src/components/editor/floorplan-panel.tsx
Comment thread packages/nodes/src/fence/drafting.ts
@sudhir9297
sudhir9297 force-pushed the t3code/link-local-plugins branch from 25f199d to 1c453b0 Compare October 7, 2026 05:21

@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.

Stale Bugbot comment from a previous run.

Comment thread packages/nodes/src/stair/tool.tsx
Comment thread packages/editor/src/components/editor/floorplan-panel.tsx

@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.

Stale Bugbot comment from a previous run.

Comment thread packages/editor/src/lib/wall-placement-pointer.ts
@ovurrsl

ovurrsl commented Oct 7, 2026

Copy link
Copy Markdown

Architectural Review: PR #1001

Thank you for the ambitious contribution connecting deck railings, landscape snapping, and stair surface workflows!

While the surface attachment mechanics and landscape transition math are valuable additions, this pull request introduces critical architectural boundary regressions, violates our unified modifier and snapping invariants, and breaks CI compilation for the host editor.

Review Summary

Verdict: REQUEST_CHANGES
Findings: 4 Blockers, 1 Suggestion, 1 Nit
Primary Files to Address:

  1. apps/editor/package.json & apps/editor/lib/bootstrap.ts
  2. packages/editor/src/components/tools/stair/stair-tool.tsx
  3. packages/nodes/src/fence/tool.tsx
  4. packages/nodes/src/stair/floorplan-move.ts

Findings

Blocker 1: Broken Typecheck and CI from External Git Packages

  • Where: apps/editor/lib/bootstrap.ts:12,19,21, apps/editor/components/pool-section-banner.tsx:3, apps/editor/package.json:24-27
  • Offending Code:
    // apps/editor/lib/bootstrap.ts:12,19,21
    import { bathSpaceHostPanel, bathSpacePlugin } from '@pascal-app/plugin-bath-space'
    import { landscapeHostPanel, landscapePlugin } from '@pascal-app/plugin-landscape'
    import { streetscapeHostPanel, streetscapePlugin } from '@pascal-app/plugin-streetscape-lab'
    
    // apps/editor/components/pool-section-banner.tsx:3
    import { PoolSectionBar } from '@pascal-app/plugin-pool'
  • Rule Violated: AGENTS.md Working Agreements ("bun run ci is exactly what CI runs"), DECISIONS.md E-014 (Plugin contract v1), and wiki/architecture/plugin-authoring.md.
  • Why: Running bun run check-types currently fails with fatal compilation errors:
    editor:check-types: components/pool-section-banner.tsx(3,10): error TS2305: Module '"@pascal-app/plugin-pool"' has no exported member 'PoolSectionBar'.
    editor:check-types: lib/bootstrap.ts(12,53): error TS2307: Cannot find module '@pascal-app/plugin-bath-space' or its corresponding type declarations.
    editor:check-types: lib/bootstrap.ts(19,53): error TS2307: Cannot find module '@pascal-app/plugin-landscape' or its corresponding type declarations.
    editor:check-types: lib/bootstrap.ts(21,57): error TS2307: Cannot find module '@pascal-app/plugin-streetscape-lab' or its corresponding type declarations.
    
    apps/editor/package.json points to personal git monorepo branches (github:sudhir9297/pascal-cluster#...) that fail type resolution in standard environments. Furthermore, scripts/link-local-plugins.ts and apps/editor/local-plugins.ts expect local disk checkouts (PASCAL_LOCAL_PLUGINS_ROOT). The host editor application cannot depend on unexported types from personal external git repositories.
  • Proposed Fix: Plugin discovery and registration must follow discoverPlugins() / setPluginDiscovery(). External plugins must either be published packages with valid exported TypeScript definitions or loaded dynamically via the standard plugin lifecycle. Remove broken static imports from bootstrap.ts and pool-section-banner.tsx.

Blocker 2: Legacy File Location & Registry Dispatch Regression

  • Where: packages/editor/src/components/tools/stair/stair-tool.tsx:615-674
  • Offending Code:
    // packages/editor/src/components/tools/stair/stair-tool.tsx:660-673
    const snap =
      event.nativeEvent?.altKey || !isMagneticSnapActive()
        ? null
        : resolveStairSurfaceSnap(
            draft,
            nodes,
            candidate,
            planStairSizing(previewRiseRef.current).length,
            baseElevation,
            useScene.getState().installedPlugins,
          )
    landscapeSnapRef.current = snap
    if (snap) return snap.position
    return candidate
  • Rule Violated: DECISIONS.md E-002 (Registry-driven composition: "A node kind is one NodeDefinition in packages/nodes/src// ... no per-kind files in legacy locations") and .agents/skills/review-architecture/SKILL.md §3 / §4.A / §4.B ("Does the file mention a specific kind by name? ... Then it belongs in packages/nodes/src//, NOT under packages/editor/src/components/tools//").
  • Why: Phase 6 systematically eliminated kind-specific tools from packages/editor/src/components/tools/<kind>/. Built-in and third-party plugins must participate equally through NodeDefinition:
    1. Authoring tool logic belongs on stairDefinition.tool in packages/nodes/src/stair/tool.tsx.
    2. Continuing to maintain and expand packages/editor/src/components/tools/stair/stair-tool.tsx creates a "special-cased" host file that violates plugin isolation.
  • Proposed Fix: Move all stair placement, preview, and surface snap interaction logic into packages/nodes/src/stair/tool.tsx exposed via stairDefinition.tool. Retire packages/editor/src/components/tools/stair/stair-tool.tsx.

Blocker 3: Alt-Key Misused as Snap and Alignment Bypass in Fence Drafting

  • Where: packages/nodes/src/fence/tool.tsx:738, 791, 821, 854, 1204
  • Offending Code:
    // packages/nodes/src/fence/tool.tsx:730-740
    const snappedLocal = alignPoint(
      snapFenceDraftPoint({
        point: localPoint,
        walls,
        fences,
        start: angleLocked ? [startingPoint.current.x, startingPoint.current.z] : undefined,
        angleSnap: angleLocked,
        magnetic: isMagneticSnapActive(),
        bypassSnap: event.nativeEvent.altKey,
      }),
      { applySnap: !angleLocked },
    )
    and
    // packages/nodes/src/fence/tool.tsx:1200-1205
    const point = snapPoint(
      [
        pointed?.localPoint?.[0] ?? event.localPosition[0],
        pointed?.localPoint?.[2] ?? event.localPosition[2],
      ],
      event.nativeEvent.altKey,
    )
  • Rule Violated: DECISIONS.md E-004 ("Snapping is a visible per-context mode. Shift tap cycles the mode; Alt hold forces the raw cursor past snapping and collisions. No held-Shift bypass; never read event.shiftKey for snapping ... event.altKey is not an alignment bypass") and review-architecture SKILL §4.F ("Already migrated — do not regress: wall + fence drafting (both modifier patterns)").
  • Why: In Pascal, snapping is strictly mode-driven (isGridSnapActive(), isMagneticSnapActive(), isAngleSnapActive()). Held modifier keys are undiscoverable and do not translate to 2D touch or accessible viewports. Alt is reserved exclusively for forcing placement/movement past physical collisions. Reading event.nativeEvent.altKey as bypassSnap directly bypasses magnetic snap and grid quantize, regressing the fence tool which was already migrated to the unified snapping model.
  • Proposed Fix: Remove bypassSnap: event.nativeEvent.altKey from all call sites in StraightFenceTool and SplineFenceDraft. Alignment and snapping must be gated purely on isMagneticSnapActive() and isGridSnapActive().

Blocker 4: Alt-Key Misused as Snap/Alignment Bypass in Stair Floorplan Move & 3D Placement

  • Where: packages/nodes/src/stair/floorplan-move.ts:59, 71, 84-86 and packages/editor/src/components/tools/stair/stair-tool.tsx:627-635, 660-662
  • Offending Code:
    // packages/nodes/src/stair/floorplan-move.ts:59-71
    const step = !modifiers.altKey && isGridSnapActive() ? getSegmentGridStep() : 0
    ...
    applyFloorplanAlignment(
      movingAnchors,
      candidates,
      { applySnap: !modifiers.altKey && isMagneticSnapActive() },
    )
    and
    // packages/nodes/src/stair/floorplan-move.ts:84-86
    landscapeSnap =
      modifiers.altKey || !isMagneticSnapActive()
        ? null
        : resolveStairSurfaceSnap(...)
  • Rule Violated: DECISIONS.md E-004 & review-architecture SKILL §4.F ("event.altKey is not an alignment bypass. A drafting/preview path that reads event.altKey to suppress Figma-alignment is a blocker in any new or touched tool — alignment follows the magnetic snap mode (bypass: !isMagneticSnapActive())").
  • Why: Checking !modifiers.altKey && isGridSnapActive() and !modifiers.altKey && isMagneticSnapActive() couples modifier state to snap suppression. If a user holds Alt to force free placement, it should not arbitrarily disable magnetic alignment or surface snapping via custom flags.
  • Proposed Fix:
    In packages/nodes/src/stair/floorplan-move.ts:
    const step = isGridSnapActive() ? getSegmentGridStep() : 0
    ...
    applyFloorplanAlignment(
      movingAnchors,
      candidates,
      { applySnap: isMagneticSnapActive() },
    )
    ...
    landscapeSnap = !isMagneticSnapActive() ? null : resolveStairSurfaceSnap(...)
    Remove all checks for modifiers.altKey and event.nativeEvent.altKey.

Suggestion 1: Schema Redundancy — supportSurfaceId vs Existing supportSurfaceNodeId in FenceNode

  • Where: packages/core/src/schema/nodes/fence.ts:103, packages/core/src/contracts/reference-inventory.ts:234-239, packages/nodes/src/fence/geometry.ts:18
  • Offending Code:
    // packages/core/src/schema/nodes/fence.ts:98-103
    supportSurfaceNodeId: z.string().optional(),
    supportSurfaceId: z.string().optional(),
    // packages/nodes/src/fence/geometry.ts:18
    const surfaceId = (node.supportSurfaceNodeId ?? node.supportSurfaceId) as AnyNodeId | undefined
  • Rule Violated: DECISIONS.md E-003 (Old scenes always load; clear schema evolution) and wiki/architecture/node-schemas.md.
  • Why: FenceNode already had supportSurfaceNodeId: z.string().optional() which represents the exact same host reference relationship. Introducing supportSurfaceId alongside it creates schema duplication and requires fallbacks like node.supportSurfaceNodeId ?? node.supportSurfaceId. Furthermore, fenceDefinition.capabilities.hostRefFields in packages/nodes/src/fence/definition.ts:387 only lists ['supportSurfaceId'], causing older scenes saved with supportSurfaceNodeId to miss host updates.
  • Proposed Fix: Consolidate onto a single field. Reuse supportSurfaceNodeId directly. If renaming to supportSurfaceId, implement a migration in packages/core/src/store/use-scene.ts (migrateNodes) that rewrites legacy scenes and strips supportSurfaceNodeId.

Nit 1: Comment Formatting in FenceNode Schema

  • Where: packages/core/src/schema/nodes/fence.ts:101-106
  • Offending Code:
    // Manual vertical offset from the elected slab, shaped surface, or level base.
    // Registered top surface supporting a drawn railing on the same level.
    supportSurfaceId: z.string().optional(),
    // Manual vertical offset from the elected slab or level support. This moves
    // the complete fence body without changing its height.
    supportOffset: z.number().finite().optional(),
  • Why: The description comment for supportOffset was duplicated and pasted above supportSurfaceId.
  • Proposed Fix: Clean up the JSDoc comments so each field has a distinct, accurate description.

Summary

  • Blockers: 4
  • Suggestions: 1
  • Nits: 1
  • Verdict: REQUEST_CHANGES

Addressing the package isolation in apps/editor, migrating the stair tool to packages/nodes/src/stair/tool.tsx, and adhering strictly to the mode-driven snapping convention (isMagneticSnapActive / isGridSnapActive without Alt bypass) will bring this PR into full alignment with Pascal's architecture.

@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.

Stale Bugbot comment from a previous run.

Comment thread packages/nodes/src/stair/floorplan-move.ts

@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.

Stale Bugbot comment from a previous run.

Comment thread packages/nodes/src/stair/floorplan-move.ts
Comment thread packages/nodes/src/stair/tool.tsx
Comment thread apps/editor/app/globals.css Outdated

@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.

Stale Bugbot comment from a previous run.

Comment thread packages/nodes/src/stair/tool.tsx
Comment thread packages/nodes/src/fence/tool.tsx
@sudhir9297
sudhir9297 force-pushed the t3code/link-local-plugins branch from 61f3148 to a64250f Compare October 9, 2026 18:13

@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.

Stale Bugbot comment from a previous run.

Comment thread packages/nodes/src/fence/tool.tsx
Comment thread packages/nodes/src/fence/tool.tsx
@sudhir9297
sudhir9297 force-pushed the t3code/link-local-plugins branch from 6dc22d9 to a1a1f81 Compare October 13, 2026 07:32

@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.

Stale Bugbot comment from a previous run.

Comment thread packages/editor/src/components/editor/floorplan-panel.tsx
Comment thread packages/nodes/src/stair/tool.tsx

@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.

Stale Bugbot comment from a previous run.

Comment thread packages/core/src/lib/room-topology-index.ts

@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.

Stale Bugbot comment from a previous run.

Comment thread packages/nodes/src/stair/floorplan-move.ts
Comment thread packages/nodes/src/fence/drafting.ts

@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.

Stale Bugbot comment from a previous run.

Comment thread packages/nodes/src/stair/tool.tsx
Comment thread packages/editor/src/lib/wall-placement-pointer.ts
Comment thread packages/core/src/hooks/spatial-grid/support-host-patch.ts
@sudhir9297
sudhir9297 force-pushed the t3code/link-local-plugins branch from e5d9d94 to 4865e43 Compare October 14, 2026 07:12

@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.

Stale Bugbot comment from a previous run.

Comment thread packages/editor/src/components/editor/floorplan-panel.tsx
Comment thread apps/editor/components/scene-loader.tsx
@sudhir9297
sudhir9297 force-pushed the t3code/link-local-plugins branch from 14b99f1 to b8f7aaf Compare October 15, 2026 03:23

@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.

Stale Bugbot comment from a previous run.

Comment thread apps/editor/lib/graph-schema.ts
Comment thread packages/core/src/services/stair-surface-snap.ts
wass08 and others added 2 commits October 15, 2026 14:31
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Streetscape stays @pascal-app/plugin-streetscape (pascal:streetscape),
  now pinned to wass08/streetscape-pascal-plugin@c4c012e, which brings in
  the streetscape-lab changes under its own name. Scenes that installed
  pascal:streetscape keep loading its nodes; the -lab id disabled them.
- A stair on a level is lifted onto its slabs by the stair system again
  (pascalorg#216); only under another parent (a deck) does the renderer bind its Y.
- The 2D move overlay has no stair branches: the stair's own move target
  reads the stair as the scene holds it, and already clears its surface.
- A fence's surface host lasts one drawing session on its floor: leaving
  the tool or the floor drops it instead of closing the fence tool, so a
  later fence is plain and the tool works on every floor.

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

wass08 commented Oct 15, 2026

Copy link
Copy Markdown
Collaborator

Pushed two commits on top of this branch:

0b518360b Merge main. The only conflicts were in packages/nodes/package.json (kept both the ./distribution and agent exports) and bun.lock.

eb773a231 Blocker fixes.

  • Streetscape keeps its name, so saved scenes keep loading. Every saved scene records pascal:streetscape in installedPlugins. With the -lab id, all their streetscape:* nodes were disabled, and the panel hid. Your lab changes are ported into wass08/streetscape-pascal-plugin under the original name and id (Bring in Sudhir's streetscape-lab changes under the streetscape name wass08/streetscape-pascal-plugin#1). The editor pins that commit (c4c012e) and keeps your lazy import().
  • The stair height fix from fix: sync stair elevations with floor slabs #216 is restored. On a level, the stair system lifts the stair onto its slabs again. The renderer binds Y only when the stair's parent is something else (a deck), where the stored Y is its height.
  • No stair branches left in floorplan-registry-move-overlay.tsx (E-002). The stair's own floorplanMoveTarget now reads the stair as the scene currently holds it. Its commit already clears landscapeSurfaceId, so the overlay's branch was dead code.
  • The fence tool no longer gets stuck as a deck railing. The deck link (supportSurfaceNodeId) from the railing button now lasts one drawing session on its floor. Leaving the tool or the floor drops it, instead of calling setTool(null). Before, a later plain fence snapped to the deck, and the fence tool was unusable on other floors.

Biome, skills validation, the build, check-types, all package tests and the packed-CLI smoke test pass locally.

Still open for you. These touch the API your external plugins rely on, so I left them:

  • External plugins import @pascal-app/nodes (./distribution), against E-001.
  • The built-in stair is wired to the landscape plugin. The schema has landscapeSurfaceId / autoLandscapeSnap, and the stair reads the plugin's private shape fields instead of surfaces.top.boundary.
  • New plugin contracts have no docs or decision record (E-014): connectedMove, primaryWhen, independent, preserveLevelAndElevation, surfaces.top.boundary, metadata.roomBoundary.
  • move-roof-tool's sameStairMoveStillActive workaround.
  • The inspector subscribes to the whole selected node (panel-wrapper.tsx:141), so it re-renders on every slider tick.
  • The fence supportSurfaceId migration is a shim for a field that never existed on main.
  • The portable runtime grows from under 70 MB to about 184 MB.
  • The plugin pins point at PR-specific branches of pascal-cluster. Please repin them to the canonical branches so installs survive branch cleanup.
  • The public DEFAULT_STAIR_* exports were removed from @pascal-app/editor.
  • Missing tests for deck railings, support-reference remapping, the wall grab tracker, alpha-cutout outlines, GLB LOD cloning and SSE echo suppression.

🤖 Generated with Claude Code

@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.

Stale Bugbot comment from a previous run.

Comment thread apps/editor/app/globals.css Outdated
The plugin moves from a personal fork to the org, at the same code as
before (the streetscape-lab changes under pascal:streetscape) with its
links pointing at the org repo.

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

wass08 commented Oct 15, 2026

Copy link
Copy Markdown
Collaborator

@sudhir9297 Follow-up to my last comment: Streetscape now lives in the org, at https://github.com/pascalorg/plugin-streetscape.

  • What's in it: your repo's history, plus your lab changes from pascal-cluster@54095f2 under the original identity (@pascal-app/plugin-streetscape, pascal:streetscape). Its links point at the org repo, and your creator credit stays.
  • editor: integrate local plugins, surface stairs and deck railings #1001 is updated: 4fb48d996 pins pascalorg/plugin-streetscape@bb563f3. The earlier fork (wass08/streetscape-pascal-plugin) is no longer used.
  • Please make streetscape changes there from now on, through PRs, rather than in streetscape-pascal-plugin or the pascal-cluster subtree. Keep the plugin id pascal:streetscape: saved scenes record it, and renaming it disables their streetscape objects.
  • Your standalone repo's main (c53516a) has work that isn't in 54095f2, such as the baseline reports and domain/. If you still want it, open a PR on the org repo.

Before this merges, please also repin bath-space and landscape from the PR-specific pascal-cluster branches (packages/*-1001) to stable ones. Otherwise installs break once those branches are deleted. The other open items in my previous comment still stand.

🤖 Generated with Claude Code

@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.

Stale Bugbot comment from a previous run.

Comment thread packages/core/src/services/stair-surface-snap.ts Outdated
Comment thread packages/core/src/hooks/spatial-grid/support-host-patch.ts

@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.

Stale Bugbot comment from a previous run.

CI merges main with @types/three 0.186, where ReturnType<typeof texture> erases the RGBA type through a generic overload. Publish and pin explicit TextureNode<vec4> declarations in Pool and Landscape.

@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 046f962. Configure here.

nodeRegistry.get(surface.type)?.capabilities?.surfaces?.top
) {
return { ...fence, supportSlabId: undefined }
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Rejected fence hosts stay persisted

Medium Severity

resolveFenceConstructionSupport rejects a requested host on another level, then falls through to slab election while still spreading the original supportSurfaceNodeId. A fence that already carries that rejected id keeps it, so railing elevation can keep sampling a host on the wrong floor.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 046f962. Configure here.

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.

3 participants