# M02-RND-CAMERA-001 — Third-person camera rig boundary

<!-- OPENWC_CLAIM:M02-RND-CAMERA-001:sindo-main-codex:2026-07-16 -->

## Ownership

- Target: M02
- Program: RND/GMP
- Owner/Agent ID: sindo-main-codex
- Branch: `work/sindo-main-codex/m02-camera-rig`
- Lease expires UTC: 2026-07-16
- Integrator: M02 milestone integrator

## Outcome

Move mouse capture, orbit yaw/pitch, zoom state and Camera3D transforms from
`ThirdPersonWowController` into a reusable `ThirdPersonCameraRig`, with an
explicit replaceable camera-collision policy that preserves the current
no-collision sandbox baseline.

## Non-goals

- Enable a new collision/raycast behavior before build-12340 comparison.
- Change initial yaw/pitch, zoom limits, sensitivity, FOV, far plane or camera path.
- Implement first-person, follow lag, shoulder offsets or cinematic cameras.
- Change movement, terrain query, character presentation or renderer streaming focus.
- Mark M02 complete or edit its checklist/Evidence.

## Paths

- Exclusive: `src/scenes/player/third_person_camera_rig.gd`,
  `src/scenes/player/camera_collision_policy.gd`,
  `src/scenes/player/no_camera_collision_policy.gd`,
  `src/tools/verify_third_person_camera_rig.gd`,
  `docs/modules/third-person-camera.md`, this claim
- Shared/hotspots: `src/scenes/player/third_person_wow_controller.gd`,
  runtime streaming scenes, player regression scene,
  `src/tools/verify_player_input.gd`, `docs/modules/player-input.md`,
  `docs/modules/local-player-movement.md`, `docs/modules/README.md`
- Generated/ignored: local `.godot`, native DLL, generated resources and renderer corpus

## Contracts and data

- Public API: `ThirdPersonCameraRig.initialize_for_character`,
  `handle_camera_input`, `godot_world_flight_movement_basis`, state getters and
  `set_collision_policy`
- Policy: `CameraCollisionPolicy.resolve_camera_distance`; default
  `NoCameraCollisionPolicy` returns requested distance unchanged
- Scene paths and renderer camera path remain unchanged
- Schema/cache/coordinate contracts: unchanged
- Consumers: player composition, sandbox flight movement and renderer viewport

## Dependencies

- Requires: merged TerrainQuery package on master `f5bb64e`
- Blocks: character appearance/animation extraction from remaining player hotspot
- External state: none; tests use asset-free camera/player scene

## Verification

- Commands: dedicated orbit/zoom/clamp/policy verifier, input/movement/terrain
  regressions, asset-free scene, coordinate/StreamingFocus gates, renderer dry-run
  and repository gates
- Fixtures: initial state, remappable action events, mouse deltas and fixed-distance policy
- Fidelity evidence: preserve current `-18°` pitch, `8` distance, `1` zoom step,
  `2..18` clamp, `0.003` sensitivity and no-collision output
- Performance budget: constant-time state/transform update; no raycast in baseline policy

## Documentation deliverables

- Inline API/export documentation for rig and collision policies
- Camera module spec with inputs/outputs, data-flow, state and sequence diagrams
- Updated input/movement consumer diagrams/source maps and module registry

## Simplicity and naming

- Important names: `ThirdPersonCameraRig`, `CameraCollisionPolicy`,
  `NoCameraCollisionPolicy`
- Simplest approach: one Node3D rig on existing CameraPivot and one explicit identity policy
- Rejected complexity: generic camera framework, spring arm migration and hidden physics raycast
- Unavoidable complexity: rig mutates Camera3D/character Node transforms on main thread
- Measured optimization evidence: not applicable

## Status

- State: ready-for-review
- Done: extracted rig and collision policy, migrated all three scene compositions,
  added regressions and completed required module documentation
- Next: milestone integrator reviews and merges `8c1cf9b`
- Blocked by:

<!-- OPENWC_HANDOFF:READY:M02-RND-CAMERA-001:8c1cf9b -->
<!-- OPENWC_INTEGRATION:ACCEPTED:M02-RND-CAMERA-001:68e6f60 -->

## Handoff

- Outcome: `ThirdPersonCameraRig` now owns capture, orbit, zoom and camera
  transforms; `ThirdPersonWowController` only dispatches camera events and
  consumes the rig basis for sandbox flight.
- Public contracts: `initialize_for_character`, `handle_camera_input`,
  `godot_world_flight_movement_basis`, `set_collision_policy`, read-only state,
  and `CameraCollisionPolicy.resolve_camera_distance`.
- Verification: camera `state_cases=12 policy_cases=3 scenes=3`, input
  `actions=12 intent_cases=6`, movement `cases=12 state_transitions=2`, terrain
  `contract=4 interpolation=1 cache=1 failures=2`, coordinate boundary
  `files=98 consumers=5`; documentation, coordination and diff checks passed.
- Renderer dry-run: seven checkpoint plans and report completed; expected
  diagnostics only for unavailable proprietary corpus/character GLB.
- Fidelity: preserves the sandbox defaults (`-18 degrees`, distance `8`, zoom
  `2..18` step `1`, sensitivity `0.003`, pivot `1.7`, far `50000`) and the prior
  no-collision behavior. No build-12340 parity claim is made.
- Local ignored inputs: native extension DLL and generated ADT resource scripts
  were used for the renderer dry-run and are not part of the commit.
- Migration: none; `ThirdPersonPlayer/CameraPivot/Camera3D` remains stable.
- Risks: active collision and exact original-client camera semantics remain
  unverified; exported initial values are captured at ready; mouse mode is
  process-global.
- Documentation: added the camera API/module spec plus data-flow, state and
  sequence diagrams; updated player-input and local-movement consumer maps.
