# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

---

## Build

**Prerequisites:** MSVC 2022, CMake ≥ 3.20, Python 3.12 at `%LOCALAPPDATA%\Programs\Python\Python312`.  
OpenUSD 25.05 is expected at `third_party/OpenUSD-v25.05` (set via `CMAKE_PREFIX_PATH` in the preset).

```powershell
# Configure (one-time; downloads ACES 1.2 OCIO config ~124 MB on first run)
cmake --preset default

# Build Release (copies all USD/DLL dependencies to build/Release/)
cmake --build build --config Release

# Install to install/bin/
cmake --build build --config Release --target install
```

The `default` preset (in `CMakePresets.json`) enables `WITH_CYCLES=ON`, `HDARNOLD_ROOT`, and `HDEMBREE_USD_ROOT` for the maintainer's machine. For a minimal build without optional render delegates, configure manually:

```powershell
cmake -B build -G "Visual Studio 17 2022" `
  -DCMAKE_PREFIX_PATH="third_party/OpenUSD-v25.05" `
  -DIMGUI_DIR="third_party/imgui-1.92.7" `
  -DWITH_CYCLES=OFF
```

**No test runner** — `BUILD_TESTS=OFF` by default. Tests (`ViewportDisplayTest`, `RendererDiagnosticTest`) have stale USD include paths; do not enable without fixing them first.

---

## Architecture

**Entry point:** `src/main.cpp` — sets `PXR_PLUGINPATH_NAME`, pre-flight loads each plugin DLL via `LoadLibraryA` (skips missing deps gracefully), then hands off to `Application`.

**Application** (`src/ui/Application.h/.cpp`) — owns all top-level managers and ImGui panels. Drives the main loop: `Update()` → `RenderUI()`. Persists viewport settings to `%APPDATA%\UsdLayerManager\viewport_settings.ini`.

**Core managers** (all in `src/core/`):
- `UsdStageManager` — opens/closes/saves USD stages; single source of truth for the active `UsdStageRefPtr`.
- `LayerManager` — enumerates and manipulates SdfLayer stack (mute, set edit target, add/remove sublayers).
- `PropertyManager` — reads/writes prim attributes; drives `PropertyPanel`.
- `CommandHistory` — undo/redo stack; all mutating operations go through commands in `src/core/commands/`.

**Viewport rendering pipeline** (the most complex subsystem):
- `ViewportPanel` (`src/ui/`) — container for 1–4 `ViewportTile` instances, handles split layout and shared selection.
- `ViewportTile` — owns one `ViewportCamera` + one `UsdSceneRenderer`. Renders into an ImGui child window by passing the scene texture as an ImGui image.
- `UsdSceneRenderer` (`src/core/`) — wraps `UsdImagingGLEngine` (Hydra/Storm). Renders into a `GlfDrawTarget` (offscreen RGBA16F FBO). All GL overlay drawing (grid, axis, bbox, camera/light wireframes) happens here while the draw-target FBO is bound.
- `ViewportColorCorrector` — **file-local class inside `UsdSceneRenderer.cpp`** (pimpl). Applies sRGB or OCIO color correction as a fullscreen GL pass *after* Hydra renders linear. Hydra's own `HdxColorCorrectionTask` is bypassed (`colorCorrectionMode = "disabled"` always passed to Hydra). See `docs/adr/0001-viewport-color-correction.md`.

**OCIO config:** `$OCIO` is set at startup (in `Application.cpp`) to `resources/OpenColorIO-Configs/aces_1.2/config.ocio` (downloaded at CMake configure time). The `OcioConfigParser` utility (`src/utils/`) wraps the OCIO C++ API to enumerate displays/views/colorspaces for the UI.

**UI panels** (all `src/ui/`):
- `StageEditorPanel` — edit target, dirty state, drag-drop sublayer ordering.
- `SceneHierarchyPanel` — prim tree with type icons.
- `PropertyPanel` — attribute inspector/editor.
- `TimelinePanel` — transport controls, loop/bounce, frame scrub.
- `CurveEditorPanel` — Maya-style F-curve editor with Bezier round-trip to USD time samples.

**GL loader:** `glad` (generated loader in `src/utils/GLExt.h`). Do not call GL functions before `gladLoadGL`.

**Logging:** `LOG_INFO / LOG_WARNING / LOG_ERROR` macros (`src/utils/Logger.h`). USD diagnostics (`TF_WARN`, `TF_ERROR`) are routed to the same logger via a `TfDiagnosticMgr::Delegate` installed in `UsdSceneRenderer::InitRenderer()`.

**DLL layout (Windows):**
- Exe + all USD/OCIO/FFmpeg DLLs live in `build/Release/`.
- Hydra plugin DLLs live in `build/Release/usd/` (so `plugInfo.json`'s `LibraryPath "../<name>.dll"` resolves correctly).

---

# 12-rule template

These rules apply to every task in this project unless explicitly overridden.
Bias: caution over speed on non-trivial work. Use judgment on trivial tasks.

## Rule 1 — Think Before Coding
State assumptions explicitly. If uncertain, ask rather than guess.
Present multiple interpretations when ambiguity exists.
Push back when a simpler approach exists.
Stop when confused. Name what's unclear.

## Rule 2 — Simplicity First
Minimum code that solves the problem. Nothing speculative.
No features beyond what was asked. No abstractions for single-use code.
Test: would a senior engineer say this is overcomplicated? If yes, simplify.

## Rule 3 — Surgical Changes
Touch only what you must. Clean up only your own mess.
Don't "improve" adjacent code, comments, or formatting.
Don't refactor what isn't broken. Match existing style.

## Rule 4 — Goal-Driven Execution
Define success criteria. Loop until verified.
Don't follow steps. Define success and iterate.
Strong success criteria let you loop independently.

## Rule 5 — Use the model only for judgment calls
Use me for: classification, drafting, summarization, extraction.
Do NOT use me for: routing, retries, deterministic transforms.
If code can answer, code answers.

## Rule 6 — Token budgets are not advisory
Per-task: 4,000 tokens. Per-session: 30,000 tokens.
If approaching budget, summarize and start fresh.
Surface the breach. Do not silently overrun.

## Rule 7 — Surface conflicts, don't average them
If two patterns contradict, pick one (more recent / more tested).
Explain why. Flag the other for cleanup.
Don't blend conflicting patterns.

## Rule 8 — Read before you write
Before adding code, read exports, immediate callers, shared utilities.
"Looks orthogonal" is dangerous. If unsure why code is structured a way, ask.

## Rule 9 — Tests verify intent, not just behavior
Tests must encode WHY behavior matters, not just WHAT it does.
A test that can't fail when business logic changes is wrong.

## Rule 10 — Checkpoint after every significant step
Summarize what was done, what's verified, what's left.
Don't continue from a state you can't describe back.
If you lose track, stop and restate.

## Rule 11 — Match the codebase's conventions, even if you disagree
Conformance > taste inside the codebase.
If you genuinely think a convention is harmful, surface it. Don't fork silently.

## Rule 12 — Fail loud
"Completed" is wrong if anything was skipped silently.
"Tests pass" is wrong if any were skipped.
Default to surfacing uncertainty, not hiding it.