# LEGACY_VIEWPORT_V1_FAILURE_REPORT

**Status:** FROZEN — no further repairs. Source retained; route mounted pending
Babylon Viewport V2 integration approval. Must not be re-enabled.

## Replacing renderer: Legacy Viewport V1 (React Three Fiber / Three.js)

## Replaced by: SHiRE LimbForge Viewport V2 (Babylon.js)

## Documented failures

1. **`Cannot read properties of undefined (reading 'source')`**
   Thrown inside Three.js material/shader pipeline when a R3F reconciler pass
   referenced a disposed or unmounted object. The error originated inside the
   Canvas render tree and bubbled to the viewport error boundary, replacing the
   entire viewport with the fatal "3D viewport could not start" screen.

2. **`Cannot read properties of undefined (reading 'addEventListener')`**
   Three.js OrbitControls register browser events on a DOM element passed to
   them. React remount timing (route changes, Suspense, lazy mounts) exposed
   windows where the controls received `undefined` / a ref object /
   `renderer.domElement` that was no longer connected, so `addEventListener`
   threw and the controls crashed the viewport.

3. **Stale Vite Three.js dependencies**
   Pre-bundled Drei/Three chunks under `node_modules/.vite` were served after the
   source changed, causing version skew between Drei helpers and the pinned
   Three.js version, which surfaced as the `source` read failure above.

4. **Fragile controls lifecycle**
   A single OrbitControls instance was created and re-bound across camera
   swaps (perspective <-> orthographic). Disposal/re-bind races left dangling
   event listeners and, under rapid navigation, a second controls instance
   attaching to the same canvas.

5. **Optional scene elements crashing the whole viewport**
   Optional layers (Drei `Html` labels, conceptual cover, movement envelope,
   branding) ran inside the Canvas render tree. Any throw in an optional layer
   tore down the entire viewport via the error boundary.

## Why it was replaced

The failures are structural to the R3F + Drei + Three-controls approach used:
controls and HTML portals execute inside the React render loop, so React
remount timing can invalidate the DOM elements and objects they depend on.
Hardening the existing core (StableViewportCore) reduced the frequency but
could not eliminate the class of failure.

Babylon Viewport V2 owns the `Engine`, `Scene` and `ArcRotateCamera` in one
isolated component, attaches the camera directly to one confirmed canvas, and
keeps all labels and optional features in plain DOM / isolated modules that
cannot reach the render loop. This removes the failure class entirely.

## Why it must not be re-enabled

- R3F controls will re-introduce the `addEventListener` / `source` crashes.
- Hidden R3F canvases running behind V2 double the WebGL contexts and leak
  event listeners.
- The V2 diagnostics contract (exactly one Engine, one Scene, one canvas) is
  violated by any concurrent V1 canvas.

**Decision:** V1 source is retained under archive. Its route is kept active
only until V2 passes integration (Step 16). After approval, V1's route
mounting, canvas, controls listeners and automatic startup are removed
(Step 17) and V1 is marked unsupported.