Observation is not payload consumption

More than one recovery mechanism may read the same Gameface model. A mutation observer can peek at model availability to decide whether a native rerender removed owned controls, while a poll compares the model payload with the last payload that was actually rendered.

The observer must not advance the render signature. If it marks a newly published value as consumed between polling ticks, the poll can suppress the only reconciliation of that payload. Keep observer reads side-effect-free and update the consumed revision only inside the render that applies it. This matters especially for staged publication where a preliminary payload has values and a later payload adds deltas, catalogs, or tooltip details under the same stable row keys.

Cache observer peeks without consuming revisions

A non-consuming model read can still be expensive if it parses full JSON on every native DOM mutation. Cache the observer's parsed snapshot by the raw payload string separately from the renderer's consumed revision and mutable UI draft. Release this cache when the model disappears or the view unloads. Never let a cached snapshot become the mutable sandbox state.

Check for a missing owned control only while its native host exists and the renderer supports that exact context. The observer and renderer must share the same eligibility predicate. Otherwise the observer repeatedly requests a control that cannot be mounted, and the renderer's own DOM writes can retrigger the loop. Native hover and animation mutations on neighboring routes are not new data revisions.

Verify repeated reads of one payload, delivery of a later detail revision, host removal and recreation, an unsupported context, and teardown with a render queued. These checks establish revision and ownership behavior; browser checks alone do not establish in-client tooltip latency.

Request-scoped hover previews

Use a separate compact preview property for hover comparisons instead of publishing the entire main-page payload. Include a request ID and enough context to identify the vehicle, current draft, mode, shell, and proposed change. Resolve the proposal when delayed work is sent so an older captured draft cannot overwrite newer edits.

Debounce rapid pointer movement, validate proposed choices in Python, and calculate both sides from isolated configurations. Reject replies whose request or context is no longer current. Cancel pending work on leave, click, context changes, and teardown. Hover must not mutate the draft or issue an account command.

For an unselected choice, compare current to proposed configuration. For an applied choice, compare the configuration without that choice to current. Keep baseline attribution separate from the proposed-choice preview, and retain identical mode and shell selection on both sides.

Repeated and interrupted lifecycle validation

Test several backward seeks and normal close/reopen cycles. Each active checkpoint should contain one owned view/window; after teardown, check that owned surfaces and callbacks disappear. Include frontend listener and media cleanup where a normal-close handshake is available. A visually correct reopening alone can conceal duplicate work.

Another integration failed recovery because avatar reconstruction cleared its page-ready flag while the retained page never populated again. Track actual parent/page ownership separately from avatar generation; do not depend exclusively on a page-populate hook.

Test closing while the native window is LOADING, before native or frontend readiness, then create a fresh window. Invalidate the old generation before destruction and cancel retained callbacks. Inspect the actual loading status: a short delay alone does not establish which stage was interrupted.

A normal-close handshake can dispose frontend listeners and media before native destruction. Owner loss still requires immediate teardown; do not wait indefinitely for acknowledgment. Empty topology and whole-process memory measurements do not prove JavaScript heap or decoder leak freedom.

Seek attempts and completion meaning

A seek attempt is not proof of playback movement. Start is published before the native seek call, and a refused attempt can still publish finish during cleanup. Both forward and backward attempts invalidate transient state; backward seeks additionally enter the gameplay rewind path.

Finish listeners can still observe the time-warp flag before the event wrapper clears it. Defer recovery that requires post-dispatch state, then reread playback position, owner identity and readiness. Do not interpret a start/finish pair as proof of the requested position or a reconstructed avatar. Preserve traceback diagnostics inside mod-owned shared-dispatch handlers so their failures do not interrupt client lifecycle bookkeeping.

Communication owner boundaries

Readiness, model publication and DOM application have distinct owners. Recreating a model does not necessarily recreate its parent document, and an observation can inspect a payload without consuming its revision. The dedicated Communication and Updates reference maps initial delivery, late subviews, frame-coalesced updates and cleanup. Keep lifecycle recovery responsible for owner identity; keep reconciliation responsible for the current view's applied state.

Retained windows: hidden is a separate state

Observed scope: WG 2.4.1.0 #977 / Cohtml 2.2.8.1, retained owned window. While hidden, a recursive timer stopped advancing and a frame chain nearly stopped, but model observations continued. Showing the window resumed the loops. document.hidden, visibilityState and browser visibility events did not describe this native state.

For this host, engine.on('self.onShowingStatusChanged', handler) delivered old/new numeric states, and viewEnv.getShowingStatus() supplied the current state. The recorded values were showing=0, shown=1, hiding=2 and hidden=3. Subscribe, then seed from the getter; compare named states rather than truthiness. Intermediate callbacks are meaningful transition states, not duplicate initialization. The Python view event has a different signature.

Keep receiving current model state while hidden when needed, but gate nonessential DOM reconciliation on fully shown. Own one pending frame, cancel it on hide and queue the latest state on show. This deliberately coalesces display state; it must not discard an event history. Final disposal still removes subscriptions, cancels work and releases references independently of visibility.

Do not depend on a hidden JavaScript timer or frame for essential restoration or cleanup. These observations do not establish OS-minimization behavior, every Wulf layer, CPU/GPU savings or heap reclamation.