9da9537995
Build a decision-sufficient ObservationView from the raw snapshot and render it as a deterministic line-based prompt string. The raw to_dict() is ~64 KB (~16k tokens) for a 7-combatant encounter; the compact view renders at ~15.7 KB (~3.9k tokens, 24% of raw), under the 4k-token ceiling of the phase-2 architecture doc. Compaction: sparse terrain/elevation/threatened grids, per-combatant key selection (occupied_cells, abilities, skills, initiative_mod/total, temp_hp_rounds_left, features, carried_items, weapon_damage, aware, alignment, armor_spell_failure, arcane_caster, run_rounds dropped), attacks compacted to formula+type damage strings, spells to 7 decision-relevant fields, pair target_index replaced by the stable combatant id, condition_definitions dropped. Attacks and spells render as positional tuples declared by attack_fields/spell_fields legend lines, with '-' for missing values. Tests pin the size bounds (compact < 0.25 x raw and < 16000 bytes), the sparse-grid contract, the dropped-key contract and the deterministic id/render contract on a caster-heavy 3v4 representative battle.