Files
EscapistsReintroduced/docs/ordinary-input-observer.md
T

38 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Optional ordinary-game input observation
`ERR_OrdinaryInputObserver.c` is an ordinary-game-only, read-only diagnostic. It does nothing unless the existing `errOrdinaryScenario=core` or `chat` option and `errOrdinaryInputObserve=<nonce>` are present. The nonce must contain 1–32 ASCII letters/digits; path punctuation, whitespace and other characters are refused. The observer does not generate input, open/close inventory, move a prisoner, adjust a camera, grant protection or change gameplay. Native compilation and one bounded sampler lifecycle are now evidenced by the [160522 ordinary Chat run](evidence/game-2026-09-19-160522-observer-display-unverified/runner.json.txt). No input was sent; neither that run nor the source-policy tests establishes actual input delivery.
The request starts only after genuine finalized local admission. It pins the exact current mode, native world, local controller, connection ID, controlled body, native character controller, canonical roster life and existing account UUID. Every sample rechecks those bindings, active prison phase and the original conscious living body. The account and identity references remain private and are never logged. Loss of ownership, life, world or phase cancels the request permanently. Native movement-control disablement alone does not invalidate it: inventory UI may legitimately disable ordinary movement while the same body remains conscious.
One owned callback is queued at a time, at 100 ms intervals. At each callback the process tick clock enforces a strict 45-second window from queueing, independently of world time; 450 samples is a second hard bound. Clock reversal cancels/finishes observation. As with any game call queue, a paused or stalled engine cannot execute the callback exactly at its deadline: on resumption it records no further input sample past that real-time bound. Mission stop and world cleanup remove the owned callback and subscription. The process-wide one-attempt latch survives cleanup and prevents another round or re-admission silently starting a new experiment.
`READY` requires two continuous real seconds with inventory absent, input and CharacterForward near zero, velocity at most 0.05 m/s and no more than 0.05 m positional drift. Gaps over 500 ms reset that baseline. These tolerances qualify a stationary baseline only; they never classify later movement as successful. Every recorded `SAMPLE` includes the validated nonce, sample index, process/world clocks, actual origin, native CharacterForward value, character movement-input vector, native velocity and inventory visibility. A later wrapper must correlate those observations with separately authorized input timing. Displacement alone is not evidence of walking, and a blocked movement attempt is not a success.
Inventory observation requires the actual `SCR_InventoryMenuUI`, its character controller matching the pinned body's component, a visible root and native top-menu agreement. Only an open after `READY` counts. The subsequent absence of that menu counts as `INVENTORY_CLOSED`, with the original admission still valid. A replacement menu, mismatched body, hidden/incomplete root or a second opening cancels rather than manufacturing a close/reopen sequence. The native top-menu API excludes dialogs; this diagnostic does not claim that no modal overlay exists.
Optional `errOrdinaryInputScreenshots=1` requests at most three captures, on `READY`, first observed open and first observed close. Paths are fixed-format `$logs:err-input-<nonce>-baseline`, `-open` and `-closed`. A capture request is logged separately and does not prove the file was written or readable; an external archive must verify the actual images. No camera changes accompany capture.
## Integrated hooks and runner
The existing ordinary-only `ERR_OrdinaryScenarioLaunch.c` queues this observer after its genuine validated `PlayerSpawned` admission and clears it in `OnBeforeWorldCleanup`, before the native superclass. Both calls remain inside the existing `#ifndef WORKBENCH` guard; no extra spawn override is installed.
Use `headless_game.py --observe-player-input --settle 50` with loose Core or Chat. The runner supplies its fresh run ID as the nonce and enables the bounded captures. Control/packed modes and shorter settling windows are refused before launch setup. After cleanup it validates the exact nonce, ordered finite samples and clocks, QUEUED/READY/FINISHED lifecycle and any inventory/capture transitions. Missing or cancelled observation fails the opt-in diagnostic, while prior native/display/source failures remain failures. This qualifies a sampler lifecycle only; it cannot by itself prove input delivery or inventory usability. Actual image files require separate inspection.
## Installed API evidence and tests
The implementation reads installed generated `CharacterControllerComponent.GetMovementInput`, `GetVelocity` and `IsUnconscious`; the vanilla character controller already reads local `InputManager.GetActionValue`. Installed `SCR_InventoryMenuUI.GetInventoryMenu` returns the actual inventory menu and `GetCharacterController` returns its bound native character controller. `SCR_StringHelper.Filter` demonstrates native string indexing and `Contains` for the nonce whitelist. The existing successor ordinary screenshot request establishes `System.MakeScreenshot` and native call-queue lifecycle usage. The separate 160522 ordinary run supplies native compilation and sampler-lifecycle evidence; these API references alone do not.
`tests/test_ordinary_input_observer.py` executes the actual nonce/time/baseline policies, admission checks, queue/sample/menu/capture/cleanup methods with explicit native read-boundary adapters. It covers changed controllers, bodies, roster lives and accounts, mode/world changes, unconsciousness, disabled/invalid flags, menu replacement and root ownership, closed/open/closed sequencing, repeated callbacks, both time bounds, clock reversal, screenshot limits, cancellation and the retained one-attempt latch. Static checks reject input/menu/actor/camera mutators and identity fields in logging. None of these tests claims native user input, human playtesting, multiplayer, FPS improvement or a completed escape route.
## Native sampler result and separate display failure
The [160522 console](evidence/game-2026-09-19-160522-observer-display-unverified/console.log.txt) contains the exact nonce's QUEUED, READY and FINISHED lifecycle without CANCELLED. READY followed the stationary baseline, and 391 samples were recorded before `FINISHED observation-bound` at 45.014 seconds after queueing. The runner parser reports `sampler_complete: true`, with one baseline capture request and no observed inventory open or close. No movement or inventory input was generated, so this proves the bounded read-only observer ran, not that player controls or inventory interactions succeeded. A logged screenshot request remains distinct from verified image content.
The overall run result remains **`display-probe-incomplete`** because private-display game-window ownership was not verified. Its ordinary startup report has a genuine local participant, the Chat header, normal game modules and zero script/runtime or engine errors; cleanup was confirmed and sources were unchanged. Successful sampler evidence does not erase the independent display-verification failure, authorize later input, or qualify a manual playtest.
The [subsequent ordinary run](evidence/game-2026-09-19-163745-observer-display/report.json) passes overall: 398 samples over 45.096 seconds, a canonical prisoner, verified private game-window ownership and mapped existing focus, zero captured engine errors, and verified idle cleanup. No external input is sent and neither inventory transition is observed. The native baseline screenshot shows the authored prison and readable starting objective. This supersedes the display-verification failure only for the new run; earlier evidence remains unchanged.
Later [real keyboard diagnostics](headless-input-proof.md) observe movement and exact inventory transitions, but the native runs fail on two stock-inventory slot errors. The helper sends inputs; this observer remains read-only. The third diagnostic's sampler ends early under failure grace, so its observed transitions are not promoted to complete sampler or clean runtime acceptance. Its open-labelled screenshot shows the prior world frame and cannot establish inventory visibility.