# SGS Runtime Evidence Contract ## Battle Lifecycle Battle state is not derived from `console.log`. Entry evidence: ```text Laya.stage -> effectively visible TableGameScene or RogueLikeGameScene -> scene.manager.seats exists ``` Core emits `battle:start` once when this state appears. Core emits `battle:end` once when the active scene is no longer effectively visible, its seats disappear, or the scene leaves the stage. Plugins must remove battle-only UI and clear temporary state on `battle:end`. ## Window Lifecycle Window registries are not authoritative. Core scans effective visibility under `Laya.stage`, including scene and window layers, and emits: ```text window:open window:close ``` Payloads include stable runtime object identity for the current Core instance, class/scene/name information, and the raw node reference. ## Battle Logs Core may expose `battle:log` only from visible/public log containers or an observed public log cache. The event is a convenience stream, not permission to inspect hidden seat state. ## Laya Access `framework.laya.getLaya()`, `getStage()`, `walk()`, `find()`, and raw scene/node references remain available when a higher-level event is insufficient. Registered class strings in `Laya.ClassUtils._classMap` are preferred over compressed constructor names when a stable class lookup is needed. ## Tracker Boundary Known cards may come from the current player's own hand, visible logs/windows, public zones, and protocol records that explicitly reveal a card. Opponent `handCards` must never be read as known-card facts. ## Effect Blocking Boundary Do not globally disable Laya Tween, Timer, Animation, or rendering. A blocking rule must target a named, reversible method or an identified node class/pattern and must restore the original behavior when disabled or uninstalled.