"""Freeze action identity against its decision-time observation.""" import hashlib import json from pathlib import Path def observation_anchor(state, elements: list[dict] | None = None) -> dict: image = getattr(state, "latest_screenshot", None) image_name = Path(image).stem if isinstance(image, str) else None tree = elements if elements is not None else getattr(state, "indexed_elements", None) tree = tree if isinstance(tree, list) else [] signature = json.dumps([image_name, tree], sort_keys=True, ensure_ascii=False, default=str) return { "target_image_name": image_name, "target_snapshot_id": hashlib.sha256(signature.encode()).hexdigest()[:24], } def element_semantics(element: dict, index: int) -> dict: """Copy evidence; no live element/index lookup is allowed after dispatch.""" result = {"target_index": index} for key in ("editable", "input_value_state", "hint", "showing_hint", "focused", "is_hint"): if key in element: result[f"target_{key}"] = element[key] return result