# Ordinary local camera observation `ERR_OrdinaryLookObserver.c` is an opt-in read-only companion to the ordinary input observer, excluded from Workbench builds. It adds no timer, input, camera, actor, menu or action mutation. The [183944 ordinary Chat run](evidence/game-2026-09-19-183944-relative-look/runner.json.txt) passes native compilation, actual camera response/return and subsequent keyboard delivery, with zero captured errors and verified cleanup. Response was 1.935°, return error 0.149°, over 2101 ms of native samples. The earlier [183353 review](evidence/look-review-2026-09-19-183353/review.json) corrected a checker timing assumption without changing that run's failed verdict. Policy tests alone do not establish native mouse response. Enable `-errOrdinaryLookObserve ` only alongside the identical `-errOrdinaryInputObserve ` and ordinary Core/Chat selection. It also requires a local server in `RplMode.None`, a non-console process, and a canonical active PRISON participant. The existing observer supplies the original clock start and sample index, so no new observation lifetime is created. ## Integration After the existing observer increments `m_Samples` and validates the ordinary SAMPLE (without changing its schedule), invoke: ```c ERR_OrdinaryLookObserver.Sample(m_Mode, m_World, m_Controller, m_Actor, m_Nonce, m_Start, m_Samples, now); ``` There is no additional cleanup callback. One process-wide attempt pins the original mode, world, controller, actor, roster life/account and player camera. It stops permanently on context loss, menu opening, changed explicit opt-in, clock/sample violation or invalid pose. When the main observer stops calling it, it performs no work. Restarting a mode cannot adopt another camera under the old attempt. ## Exact native API basis Installed vanilla sources used: * `scripts/Game/generated/Player/PlayerController.c`: `GetPlayerCamera()` returns the controller's `PlayerCamera`. * `scripts/Game/generated/Camera/CameraBase.c:22`: `GetWorldCameraTransform(out vector mat[4])` is documented as the current camera world transformation. Its forward basis `[2]` and position `[3]` supply the actual view; the body is not used as a view approximation. * `scripts/Game/generated/ChimeraGame.c:27` and `generated/Camera/CameraManager.c:19`: the active manager's `CurrentCamera()` must equal the exact pinned controller camera, before and after native reads. * Actor `GetTransform()[2]` provides the separately logged body facing. The `body` position comes from the exact pinned actor’s `GetOrigin()`, matching the ordinary INPUT and GATE observers. Camera position still comes from the native camera transform `[3]`. Neither camera transform application nor setters are called. All entity/world/controller/roster bindings are rechecked per sample. Any top menu blocks observation, including inventory. The camera's world must match the original world. Basis lengths must be finite and within 0.5–2 before normalization; all emitted vector components and native turn inputs must be finite and bounded. Indices must be contiguous from 1, at most 450, with a monotonic real clock still less than 45 seconds from the **original input-observer start**. Pose sampling may miss short-lived input deltas between ticks; measured view response remains necessary. ## Log contract The first valid sample emits one basis declaration followed by the sample: ```text ERR LOOK OBSERVE: run=N sample=1 real=T BASIS native-player-camera-world-transform ERR LOOK OBSERVE: run=N sample=1 real=T SAMPLE direction= camera= body= bodyForward= turn= ``` `direction` and `bodyForward` are normalized. `camera` and `body` are distinct world positions. `turn` contains native `CharacterTurnRight` and `CharacterTurnUp` values; it does not assert that a helper sent input. Nonce/index/real clock match the corresponding ordinary input SAMPLE. No account identifier is logged. On invalidation, exactly one terminal record is emitted: ```text ERR LOOK OBSERVE: run=N sample=I real=T CANCELLED menu-opened ``` Other reasons are `explicit-scope-lost`, `original-binding-changed`, `sample-or-clock-bound`, `native-camera-or-player-context-lost` and `invalid-native-pose`. No sample follows cancellation. The main input observer continues independently. Thus normal inventory opening **after** the completed look proof may legitimately cancel look telemetry; proof verification must examine only the agreed interval before the first W movement, not treat later menu cancellation as failure of an already-observed look response. The external helper must require fresh stable native baseline samples, actual direction change after its bounded positive relative input, and a fresh return near baseline after its negative input. It must independently retain the existing stationary-body, private-display/window/focus ownership and input-release checks. This utility issues no authorization to send input and claims no gameplay, escape, multiplayer or performance qualification. ## Logical body-position correction (native rerun pending) The ordinary approach run whose session started `2026-09-19 19:07:07` refused its live join at sample 180 after normal forward input: actor transform translation and actor `GetOrigin()` differed by approximately `(0.04, -0.001, -0.03)` metres, just beyond the existing 0.05m cross-API check. INPUT and GATE, which both use `GetOrigin()`, agreed. This establishes a telemetry API mismatch; it does not establish a teleport or a completed approach. Preserve that run’s failed result. The staged correction logs `body` from the same pinned actor’s `GetOrigin()` instead of `GetTransform()[3]`. Body-facing `[2]`, actual camera position/direction, identity checks, finite-value guards, original observation lifetime and all validation tolerances remain unchanged. A focused actual-method test deliberately gives the transform and logical origin different translations, verifies the emitted body equals only `GetOrigin()`, and verifies facing and view still use their original native sources. A nonfinite logical origin refuses the sample. This source/test correction requires a new ordinary native run before qualification; it changes no gameplay state or input.