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.
This commit is contained in:
Wawa
2026-05-09 20:52:26 +00:00
parent 146f0a846f
commit e618175bba
196 changed files with 5899 additions and 3966 deletions
@@ -119,7 +119,7 @@ export function registerGenerateVariants(server: McpServer, bridge: SceneOperati
// 2. Seed the RNG. Default seed is a time-ish number so runs vary, but
// tests always pass a fixed seed for determinism.
const initialSeed = seed ?? Math.floor(Math.random() * 0xffffffff)
const initialSeed = seed ?? Math.floor(Math.random() * 0xff_ff_ff_ff)
const mutations = vary as MutationKind[]
const variants: Array<{
+14 -16
View File
@@ -11,21 +11,19 @@ export type MutationKind =
| 'door-positions'
| 'fence-style'
/** Deterministic 32-bit RNG. */
/** Deterministic seeded RNG. */
export type Rng = () => number
/**
* Tiny PRNG. Returns a function that produces uniformly distributed floats in
* [0, 1). Source: https://stackoverflow.com/a/47593316/17118
* Tiny Park-Miller PRNG. Returns a function that produces uniformly
* distributed floats in [0, 1) without bitwise operators.
*/
export function mulberry32(seed: number): Rng {
let state = seed | 0
let state = Math.trunc(Math.abs(seed)) % 2_147_483_647
if (state === 0) state = 1
return () => {
state = (state + 0x6d2b79f5) | 0
let t = state
t = Math.imul(t ^ (t >>> 15), t | 1)
t ^= t + Math.imul(t ^ (t >>> 7), t | 61)
return ((t ^ (t >>> 14)) >>> 0) / 4294967296
state = (state * 16_807) % 2_147_483_647
return (state - 1) / 2_147_483_646
}
}
@@ -74,10 +72,10 @@ function siteBounds(
if (node.type !== 'site') continue
const pts = (node as { polygon?: { points?: Array<[number, number]> } }).polygon?.points
if (!pts || pts.length === 0) continue
let minX = Infinity
let maxX = -Infinity
let minZ = Infinity
let maxZ = -Infinity
let minX = Number.POSITIVE_INFINITY
let maxX = Number.NEGATIVE_INFINITY
let minZ = Number.POSITIVE_INFINITY
let maxZ = Number.NEGATIVE_INFINITY
for (const [x, z] of pts) {
if (x < minX) minX = x
if (x > maxX) maxX = x
@@ -101,7 +99,7 @@ function isPerimeterWall(
bounds: { minX: number; maxX: number; minZ: number; maxZ: number } | null,
epsilon = 0.01,
): boolean {
if (!bounds || !wall.start || !wall.end) return false
if (!(bounds && wall.start && wall.end)) return false
const onBound = (x: number, z: number): boolean =>
Math.abs(x - bounds.minX) <= epsilon ||
Math.abs(x - bounds.maxX) <= epsilon ||
@@ -154,7 +152,7 @@ function applyRoomProportions(graph: SceneGraph, rng: Rng): SceneGraph {
start?: [number, number]
end?: [number, number]
}
if (!wall.start || !wall.end) continue
if (!(wall.start && wall.end)) continue
if (isPerimeterWall(wall, bounds)) continue
// Nudge each endpoint by ±10% of its current value.
const nudge = (v: number): number => v * (1 + (rng() * 2 - 1) * 0.1)
@@ -193,7 +191,7 @@ function applyOpenPlan(graph: SceneGraph, rng: Rng): SceneGraph {
out.rootNodeIds = out.rootNodeIds.filter((id) => !removal.has(id))
// Drop references from any parent's `children` array.
for (const parent of Object.values(out.nodes)) {
if (!('children' in parent) || !Array.isArray((parent as { children?: unknown[] }).children)) {
if (!('children' in parent && Array.isArray((parent as { children?: unknown[] }).children))) {
continue
}
const children = (parent as { children: unknown[] }).children