Commit Graph
774 Commits
Author SHA1 Message Date
Wassim SAMADandClaude Opus 4.7 3de098fe4f Add Presentation + IconRef to NodeDefinition v1 surface
Adds optional `presentation` field for tool palette metadata: sentence-
case label, optional description, icon (iconify reference, inline SVG,
or lazy React component), palette section override, sort order, and a
`hidden` flag for container kinds that exist but should not appear in
the palette.

Consumer arrives in Phase 4 (auto-derived palette buttons) — defining
the type now means Phase 2's `column` and `shelf` definitions ship with
the field already populated, no later round-trip.

Iconify is the encouraged form for built-ins and AI-authored nodes:
matches the @iconify-react setup the editor app already uses, and AI
emits a name string from a curated list (no asset upload step needed).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 12:09:10 -04:00
Wassim SAMADandClaude Opus 4.7 c683c04c39 Add test script to @pascal-app/core so turbo picks up its unit tests
Without a "test" script the package was invisible to `turbo test` —
private-editor's CI runs `bun run test` (= `turbo test`), which only
walks workspace packages that declare a test runner. Mirrors mcp and
nodes which already do this.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 11:41:46 -04:00
Wassim SAMADandClaude Opus 4.7 2a8eb3e1de Registry-first dispatch in ToolManager (shim 4/4)
Before mounting any legacy build tool, ToolManager checks whether the
active tool's kind has a registered NodeDefinition with a tool
contribution. If yes, the registry tool wins; the legacy tool map and
special-cased spawn/column/elevator branches are skipped for that kind.

Lazy-loaded via React.lazy (cached by loader) and wrapped in Suspense.

Today the registry is empty, so useRegistryTool is always false and
every code path renders unchanged. The moment a kind registers (Phase
2+), its registry tool takes over without further edits here.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 11:39:31 -04:00
Wassim SAMADandClaude Opus 4.7 7dd3ffed3f Wrap legacy systems in LegacySystem + mount RegisteredSystems (shim 3/4)
Two additions plus a viewer JSX rewire:

- legacy-system.tsx: <LegacySystem kind="..."> wrapper that renders its
  children only when nodeRegistry.has(kind) is false. Lets one wrapper
  cover all legacy systems for a kind (door has DoorSystem and
  DoorAnimationSystem — both belong to 'door' so they yield together).
- registered-systems.tsx: <RegisteredSystems /> iterates the registry,
  filters entries that contribute a system, sorts by system.priority
  (default 5; e.g. wall mitering at 8 runs after door cuts at 3),
  mounts each via React.lazy. Today empty registry = renders nothing.
- viewer/index.tsx: every existing per-kind system is wrapped in
  LegacySystem. RegisteredSystems is mounted alongside.

With the registry empty (Phase 0), every LegacySystem passes through
unchanged and RegisteredSystems is a no-op — zero behavior change.
Once a kind registers in Phase 2+, its legacy systems yield and its
registry-contributed system runs in their place.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 11:36:02 -04:00
Wassim SAMADandClaude Opus 4.7 0fd7af216c Registry-first dispatch in NodeRenderer (shim 2/4)
NodeRenderer now checks the registry first. Registered kinds load
their renderer module via React.lazy (cached by RendererSource so the
Suspense boundary is stable across re-renders). Unregistered kinds
fall through to the legacy chain below.

Today the registry is empty (Phase 0 builtinPlugin.nodes is []), so
every node still hits the legacy chain — no behavior change. The
moment a kind registers in @pascal-app/nodes (Phase 2 onward), the
registry path takes over without further edits here.

GLB / instanced-GLB RendererSource kinds are typed but not yet
honored — they get their built-in renderers in Phase 5.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 11:32:05 -04:00
Wassim SAMADandClaude Opus 4.7 4c3feea052 Proxy-back sceneRegistry.byType for registry/plugin kinds (shim 1/4)
byType was a hardcoded object keyed by the built-in node kinds. With
the registry, kinds can come from @pascal-app/nodes (or future
plugins) — so byType now wraps a Map via a Proxy that auto-creates an
empty Set the first time any kind is touched.

Built-in kinds are still pre-seeded at module init so the fast path
(no Proxy trap) is preserved. clear() iterates the backing Map.

useRegistry's `type` parameter widens from `keyof typeof byType` to
`KnownNodeKind | (string & {})` — preserves autocomplete for
built-ins while accepting plugin-supplied kinds.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 11:30:55 -04:00
Wassim SAMADandClaude Opus 4.7 4d5226ce10 Wire loadPlugin(builtinPlugin) at editor app bootstrap
Adds apps/editor/lib/bootstrap.ts that calls loadPlugin(builtinPlugin)
as a module-side-effect on first import. Imported from scene-loader.tsx
so it runs on the client side where the editor mounts.

Idempotency guard handles HMR re-execution (would otherwise throw on
duplicate registerNode). For the empty plugin this commit, the entire
call is a no-op — included now so future commits that add real node
kinds only need to push them onto builtinPlugin.nodes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 11:28:01 -04:00
Wassim SAMADandClaude Opus 4.7 a41321e193 Lock bun.lock for @pascal-app/nodes workspace + sort registry barrel
Companion changes for the new nodes package: bun.lock entry from
`bun install`, and a Biome-auto-sort of the registry barrel.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 11:25:27 -04:00
Wassim SAMADandClaude Opus 4.7 fc36b5b600 Add @pascal-app/nodes package skeleton with empty builtinPlugin
New workspace package that owns built-in node bundles, one folder per
kind. Today the plugin is empty — no behavior change. Future commits
will add column/, shelf/, wall/, etc. and append each definition to
builtinPlugin.nodes.

The package depends on core (registry types) at v1; viewer, editor,
react, three are declared as peer deps so future node bundles can use
them without bumping their own version on every monorepo bump.

External plugins land as separate packages with the exact same shape
— this package is the dogfooded reference.

Tests: builtinPlugin shape + loadPlugin succeeds with zero kinds.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 11:24:59 -04:00
Wassim SAMADandClaude Opus 4.7 1d7ec0b5a7 Block @pascal-app/nodes imports from framework packages
Adds a Biome noRestrictedImports rule scoped to core/, viewer/, and
editor/ packages. Framework code must reach node-specific behavior via
nodeRegistry.get(kind), never via direct import. The @pascal-app/nodes
package doesn't exist yet (lands in the next commit) so the rule is a
no-op today; codifies the boundary ahead of node bundles.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 11:22:40 -04:00
Wassim SAMADandClaude Opus 4.7 fb91713374 Add node registry primitives (PR 0.1 of node-registry plan)
Introduces the @pascal-app/core/registry surface that future node-bundle
packages (and external plugins) will use to register node kinds with the
host. No runtime behavior changes — registry is empty until subsequent
PRs populate it.

- types.ts: NodeDefinition, Capabilities, Relations, DragAction, Plugin,
  ParametricDescriptor, Affordance, SceneApi, NodeRegistry. Capability
  configs accept an override escape hatch; additive-only after v1.
- registry.ts: nodeRegistry singleton, registerNode, async loadPlugin.
  Validates kind, schemaVersion, apiVersion; rejects duplicate kinds.
- scene-api.ts: createSceneApi factory wrapping the scene store with
  copy-on-write snapshot semantics for pauseHistory/restore/resumeHistory.
- index.ts: barrel re-exporting the public surface.
- core/index.ts + package.json: export * from registry and add the
  ./registry subpath so consumers can import either way.

Tests (27 cases, all bun:test): registry registration / validation /
plugin loading; SceneApi read/write/dirty/history; lazy snapshot capture
with update/upsert/delete reversal via restore and restoreAll.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 11:18:29 -04:00
Wassim SAMADandGitHub c50a4df8e1 Merge pull request #307 from pascalorg/fix/elevator-opening-use-client
Mark elevator-opening-system as client
2026-05-13 16:51:05 -04:00
Wassim SAMADandClaude Opus 4.7 c5ee1c64d0 Mark elevator-opening-system as client
The file imports useEffect/useRef from React, which Next.js RSC builds
flag as client-only. Other core systems (e.g. elevator-runtime-system)
use useFrame from @react-three/fiber and slip through, but this one
needs the directive explicitly.

Fixes Turbopack build failure in private-editor community app:
"You're importing a module that depends on useEffect into a React
Server Component module."

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 16:49:17 -04:00
Wassim SAMADandGitHub 29fd673860 Merge pull request #305 from sudhir9297/feat/elevator-system
Add procedural elevator system with floorplan, runtime, and first-person support
2026-05-13 16:42:25 -04:00
sudhir 77c55a2e7c Reduce viewer rendering cost with lighter materials 2026-05-13 22:47:10 +05:30
sudhir 1ffa3d2d73 Restore item controls and guard placement asset bounds 2026-05-13 22:45:58 +05:30
Sudhir YadavandGitHub aa6885e4c4 Merge branch 'main' into feat/elevator-system 2026-05-13 22:29:09 +05:30
sudhir ce69433a1a Refine elevator sync and viewer rebuild handling 2026-05-13 22:28:19 +05:30
Wassim SAMADandGitHub 90c948df59 Merge pull request #306 from pascalorg/perf/viewer-render-improvements
perf improvements
2026-05-13 09:24:23 -04:00
Wassim SAMAD 9de7a8ee77 perf improvements 2026-05-13 09:05:09 -04:00
sudhir 9838d2cd4f Refactor elevator runtime into core 2026-05-13 01:56:06 +05:30
sudhir b782ce9cf2 Merge branch 'main' into feat/elevator-system
# Conflicts:
#	packages/editor/src/components/tools/item/move-tool.tsx
#	packages/editor/src/components/tools/tool-manager.tsx
#	packages/editor/src/components/ui/panels/panel-manager.tsx
#	packages/editor/src/store/use-editor.tsx
#	packages/viewer/src/components/renderers/site/site-renderer.tsx
#	packages/viewer/src/components/viewer/ground-occluder.tsx
#	packages/viewer/src/components/viewer/index.tsx
#	packages/viewer/src/components/viewer/post-processing.tsx
2026-05-13 01:38:55 +05:30
Wassim SAMADandGitHub eeacae568c Merge pull request #304 from pascalorg/fix/panel-overflow
fix max panel height
2026-05-12 12:07:06 -04:00
Wassim SAMAD 9c248b7e0c fix max panel height 2026-05-12 12:06:27 -04:00
Wassim SAMADandGitHub 3a62b8f224 Merge pull request #302 from sudhir9297/fix/fri-8-may
fix: Add procedural column variants, editor copy/paste, and wall junction planning improvements
2026-05-12 11:11:07 -04:00
sudhir 70c85d7760 Refine wall move previews and expose auto-slab planning 2026-05-12 12:15:45 +05:30
sudhir 0fd6e3d144 Fix mirrored elevator indicators and arrows 2026-05-12 11:21:03 +05:30
sudhir f3444d4275 Add wall drag previews and fix move arrow handles 2026-05-12 11:00:27 +05:30
sudhir 0dcc72a57a Merge remote-tracking branch 'origin/main' into fix/fri-8-may 2026-05-12 09:52:32 +05:30
sudhir 2fc754108d Use community viewer toolbars in editor app 2026-05-12 09:49:10 +05:30
sudhir 564bfa229e Merge remote-tracking branch 'origin/main' into fix/fri-8-may
# Conflicts:
#	packages/editor/src/components/tools/fence/move-fence-endpoint-tool.tsx
#	packages/editor/src/components/tools/select/box-select-tool.tsx
#	packages/editor/src/components/tools/wall/move-wall-tool.tsx
#	packages/editor/src/components/ui/panels/column-panel.tsx
#	packages/editor/src/components/ui/panels/door-panel.tsx
#	packages/editor/src/components/ui/panels/window-panel.tsx
#	packages/viewer/src/components/renderers/column/column-renderer.tsx
#	packages/viewer/src/components/viewer/index.tsx
#	packages/viewer/src/systems/slab/slab-system.tsx
2026-05-12 00:27:06 +05:30
sudhir d78308b366 Hide inapplicable door and window panel settings 2026-05-12 00:05:41 +05:30
sudhir be41511474 Fix wall move junction ownership 2026-05-11 23:46:57 +05:30
Wassim SAMADandGitHub 3326517de7 Merge pull request #301 from pascalorg/chore/agents
Restructure agent config: unified .agents/skills + wiki/architecture
2026-05-11 09:59:41 -04:00
Wassim SAMADandClaude Opus 4.7 cf07fcaa97 Restructure agent config: unified .agents/skills + wiki/architecture
Replace per-tool rule trees (.cursor/rules, .claude/rules, .codex/rules)
with a single wiki/architecture/ source — 11 pages + README — readable
as plain markdown by any agent. Canonical skills live in .agents/skills/;
.claude/skills, .cursor/skills, .codex/skills are directory symlinks.

AGENTS.md is the entrypoint (rewritten as a lean overview, no per-tool
path lists). CLAUDE.md, GEMINI.md, and .github/copilot-instructions.md
all point to it.

Add open-pr skill (uses .github/pull_request_template.md as the source
of truth for the PR body) and remove the dangling .claude/CLAUDE.md
relative symlink.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 09:51:25 -04:00
sudhir afadfb2ea8 Guard viewer BVH against empty geometries 2026-05-11 11:24:44 +05:30
Wassim SAMADandGitHub ca333dd912 Merge pull request #299 from pascalorg/fix/release-peerdep-sync
Fix/release peerdep sync
2026-05-10 20:25:40 -04:00
Wawa 6488efe296 bun lock 2026-05-10 09:13:03 -04:00
Wawa 8921e341cc Bump inter-package peerDeps to ^0.8.0 + fix release.yml sync bug
Two bugs in one fix:

1. The 0.8.0 release commit only bumped .version, not the inter-package
   peerDependencies / devDependencies. So the published packages still
   declared peer constraints like "@pascal-app/viewer": "^0.7.0". Caret
   in semver 0.x doesn't allow 0.8.0 to satisfy ^0.7.0, so bun resolves
   workspace consumers (and apps/editor's deep import paths) to the
   stale npm-published 0.7.0 instead of the workspace 0.8.0 — meaning
   local edits never show up in apps/editor or any linked consumer.

2. The release.yml sync step was using $GITHUB_ENV to read back the new
   versions in the same step, which doesn't work — env-file writes only
   surface in subsequent steps. Switched to a bash associative array
   (NEW_VERSIONS) for in-step lookup, kept the $GITHUB_ENV write for the
   downstream publish/commit/tag steps. Also added a final "refs after
   sync" debug print so this is visible in the workflow log.

After this lands and you bun install, packages/editor/node_modules/@pascal-app/viewer
should symlink to the workspace packages/viewer/, not to .bun/@pascal-app+viewer@0.7.0.
Future releases will sync peerDeps correctly on their own.
2026-05-10 13:12:08 +00:00
sudhir 4956de4910 Refine column support selection and polygon handling 2026-05-10 12:51:57 +05:30
sudhir 92a9846193 Refactor elevator systems across core, viewer, and editor 2026-05-10 12:38:44 +05:30
sudhir 909f96ef09 Improve elevator floorplan resize and drag controls 2026-05-10 12:20:53 +05:30
sudhir fdf08c091f Add elevator floorplan overlay 2026-05-10 10:50:22 +05:30
github-actions[bot] 60dbfcd3fe release: @pascal-app/core@0.8.0 @pascal-app/viewer@0.8.0 @pascal-app/editor@0.8.0 @pascal-app/mcp@0.2.0 2026-05-10 00:41:38 +00:00
Wassim SAMADandGitHub 747d8c9ad4 Merge pull request #298 from pascalorg/chore/community-merge
Chore/community merge
2026-05-09 20:37:12 -04:00
Wawa 7f74e18456 Update bun.lock from macOS install
Lockfile dedup pass after running bun install on macOS — picks up the
darwin-arm64 native binaries hoisted to top-level node_modules and removes
a redundant cmdk@radix nested resolution edge that wasn't needed.
2026-05-10 00:33:36 +00:00
Wawa c89d392147 Add shared styles/elevation.css used by apps/editor globals
apps/editor/app/globals.css imports '../../../styles/elevation.css', a shared
elevation/shadow utility set used across both private-editor's apps and the
public editor-v2 apps/editor. Was missing from this repo because the swap
covered packages/{core,viewer,editor,mcp} and apps/editor but not the
top-level styles/ directory.

Copied verbatim from private-editor.
2026-05-10 00:21:02 +00:00
Wawa b27e53415f Hoist platform-specific native packages via root optionalDependencies
Real root cause:
Tailwind v4's lightningcss is invoked from a Turbopack-bundled postcss.js at
runtime. Turbopack resolves require() against the workspace's TOP-LEVEL
node_modules, not against bun's nested .bun/ store. So even when
lightningcss-darwin-arm64 is correctly installed inside .bun/ with proper
symlinks, Turbopack can't see it — and lightningcss falls back to a sibling
'.node' file which doesn't exist, hence the runtime error.

Private-editor accidentally works because it has TWO lightningcss versions
(1.27.0 from Expo + 1.32.0 from Tailwind), which forces bun's hoisting
algorithm to put one copy at the top level. Editor-v2 has only one version,
so bun keeps it nested in .bun/ and nothing is at top-level.

Fix: declare the platform binary packages as optionalDependencies at the
WORKSPACE ROOT (not apps/editor). Root deps are always hoisted to top-level
node_modules, so Turbopack's resolver finds them. Bun still applies the
os/cpu filter at install time, so each developer only ends up with their
host's binaries on disk.

Verified on Linux: node_modules/lightningcss-linux-arm64-gnu is a top-level
symlink after install. On macOS, the darwin variants will be hoisted instead.
2026-05-10 00:14:28 +00:00
sudhir 263228cbf0 Add cab door-open control and align elevator buttons 2026-05-10 02:28:00 +05:30
Wawa e618175bba Reset core/viewer/editor/mcp packages and apps/editor from private-editor
Wholesale swap of packages/{core,viewer,editor,mcp} and apps/editor with the
versions from the private editor repo, which is the production source of truth.

Setup changes:
- packages/{core,viewer,editor} versions held at 0.7.0 baseline (matching
  the most recent published release) so a bump=minor publishes 0.8.0
- packages/mcp held at 0.1.1 (never published; first publish will go through
  the new release.yml flow)
- peerDependencies and devDependencies for inter-package @pascal-app/*
  references pinned to ^0.7.0 instead of '*' / 'workspace:*' so they are
  valid for npm consumers
- Root package.json: TypeScript bumped to 6.0.2, added overrides for
  @types/react, @types/react-dom, @types/three to prevent JSX namespace
  fragmentation across the workspace
- release.yml extended to also publish editor and mcp; 'both' option renamed
  to 'all'; added a sync step that updates inter-package peerDeps/devDeps to
  match the new versions on every bump (so viewer/editor/mcp tarballs always
  reference the version of core they were built against)
- Root scripts gained release:editor and release:mcp shortcuts

Verification:
- bun install --frozen-lockfile is consistent
- packages/{core,viewer,mcp} build cleanly, dist/index.d.ts emitted
- packages/editor check-types reports 21 pre-existing errors, identical to
  what private-editor currently reports

Open PRs against editor-v2 will need rebasing/conflict resolution.
2026-05-09 20:52:26 +00:00