# CLAUDE.md

## 1. Think Before Coding

**Don't assume. Don't hide confusion. Surface tradeoffs.**

Before implementing:
- State your assumptions explicitly. If uncertain, ask.
- If multiple interpretations exist, present them - don't pick silently.
- If a simpler approach exists, say so. Push back when warranted.
- If something is unclear, stop. Name what's confusing. Ask.

## 2. Simplicity First

**Minimum code that solves the problem. Nothing speculative.**

- No features beyond what was asked.
- No abstractions for single-use code.
- No "flexibility" or "configurability" that wasn't requested.
- No error handling for impossible scenarios.
- If you write 200 lines and it could be 50, rewrite it.

Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify.

## 3. Surgical Changes

**Touch only what you must. Clean up only your own mess.**

When editing existing code:
- Don't "improve" adjacent code, comments, or formatting.
- Don't refactor things that aren't broken.
- Match existing style, even if you'd do it differently.
- If you notice unrelated dead code, mention it - don't delete it.

When your changes create orphans:
- Remove imports/variables/functions that YOUR changes made unused.
- Don't remove pre-existing dead code unless asked.

The test: Every changed line should trace directly to the user's request.

## 4. Goal-Driven Execution

**Define success criteria. Loop until verified.**

Transform tasks into verifiable goals:
- "Add validation" → "Write tests for invalid inputs, then make them pass"
- "Fix the bug" → "Write a test that reproduces it, then make it pass"
- "Refactor X" → "Ensure tests pass before and after"

For multi-step tasks, state a brief plan:
```
1. [Step] → verify: [check]
2. [Step] → verify: [check]
3. [Step] → verify: [check]
```

Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification.

## What this project is

`@archvisioninc/canvas` is a React component library built on BabylonJS 7. It exposes a `<Canvas />` component that drops into the FOVEA host application, providing a full 3D viewer/editor with bidirectional communication over props. Only the code under `src/package/` is published — everything else in `src/` is a local dev harness that mimics the FOVEA environment.

## Commands

```bash
npm install          # Install dependencies
npm start            # Run local dev app (react-scripts)
npm test             # Run tests (react-scripts test)
npm run test -- --testPathPattern=<file>  # Run a single test file
npm run lint         # ESLint check
npm run lint:fix     # ESLint auto-fix
npm run build        # Babel-compile src/package → dist/
npm run push         # Build + publish to npm (requires version bump first)
```

## Architecture

### Published code vs. dev harness

| Path | Purpose |
|---|---|
| `src/package/` | **Published.** All code here goes into `dist/` and is consumed by FOVEA. All imports must be relative. |
| `src/` (outside `package/`) | **Dev only.** Mocks FOVEA's components, constants, and App shell for local testing. Not bundled. |

### Entry point and lifecycle

`src/package/Canvas.js` is the single exported React component. On mount it calls `initHelpers.js` which:
1. Creates a BabylonJS `Engine` (WebGPU → WebGL → NullEngine fallback).
2. Creates a `Scene` with cameras, lights, highlight managers, shadow generator, grid, environment, and GUI overlay.
3. Registers the render loop.

After init, `Canvas.js` manages three effects that drive the rest of the lifecycle:
- **File effect** — loads a model file via `loadHelpers.js` when the `file` prop changes.
- **Update effect** — dispatches `updateData` payloads to `canvasCommunicationHelpers.js`.
- **Export effect** — triggers scene serialization / screenshot when `exportModel` or `toDownload` props change.

### Update data flow

Host app sends `updateData = { type, method, ...payload }` as a prop. `canvasCommunicationHelpers.js` routes by `type` (material, mesh, camera, environment, viewport, lighting, publish) and `method` (update, add, remove) to the appropriate helper. After every mutation the scene is serialized and sent back to the host via the `setSerializedData` callback prop.

```
Host prop: updateData → canvasCommunicationHelpers → domain helper → Babylon scene
                                                                          ↓
Host callback: setSerializedData ←──────────────── serializeScene()
```

### Helper files (`src/package/helpers/`)

Each file owns one domain. Key ones to know:

| File | Responsibility |
|---|---|
| `initHelpers.js` | Scene/engine creation, global Babylon object exports (`engine`, `scene`, `canvas`, `gizmoManager`, etc.) |
| `canvasCommunicationHelpers.js` | Central `updateData` dispatcher |
| `canvasUpdateHelpers.js` | Material, mesh, camera, environment update logic |
| `canvasAddHelpers.js` / `canvasRemoveHelpers.js` | Add/remove scene items |
| `loadHelpers.js` | GLTF/GLB model loading |
| `materialHelpers.js` | PBR material creation and texture assignment |
| `meshHelpers.js` | Mesh transforms, selection, simplification |
| `cameraHelpers.js` | Orthographic/perspective camera management, screenshots |
| `gizmoHelpers.js` | Transform gizmo setup |
| `guiHelpers.js` | Babylon GUI overlays (safe frames, drag selection, dimensions) |

### Canvas modes

Configured via props from the host:

- **Full mode** — default; bidirectional communication, gizmos, grid, inspector
- **Preview mode** — read-only; no grid, no gizmos, simplified UI
- **Material mode** — material editor with a shaderball scene and fixed camera

### Constants and enums

`src/package/constants/constants.js` — Named string/number constants for Babylon camera/light/gizmo types, GUI element names, update message types, and performance thresholds (max texture size 4096, max materials 50, max meshes 500).

`src/package/enums/` — Aspect ratios, ortho options, scale units, downscaling presets, format options, mesh exclusions, shortcut keys. These are kept in sync with FOVEA's enums.

## Publishing rules

- Bump the version in `package.json` before publishing — npm will reject a duplicate version.
- **All imports inside `src/package/` must be relative paths.** Absolute imports work locally (via `jsconfig.json` baseUrl) but will crash when the package is consumed externally.
- `npm run push` = build + publish. Requires npm login with 2FA and membership in the `archvisioninc` npm org.

## Linting rules (`.eslintrc.js`)

Single quotes, semicolons, max line length 120, arrow-parens always, prefer destructuring, no commented-out code. Parser is `@babel/eslint-parser`.
