fix(docs): correct the Observation 'frozen' claim - the dataclass is frozen at the top level but the inner per-combatant/pair dicts are mutable copies; wording softened in the docstring and README (deep-freeze rejected: it would change the LLM contract and require touching pinned observation tests; copies are never read back by the engine, so policy mutation is already inert)
This commit is contained in:
@@ -1578,8 +1578,11 @@ Règles modélisées :
|
|||||||
`spell_slots` sans clés dupliquées.
|
`spell_slots` sans clés dupliquées.
|
||||||
- Snapshot d'observation (contrat LLM, Phase 2) : avant chaque appel de
|
- Snapshot d'observation (contrat LLM, Phase 2) : avant chaque appel de
|
||||||
politique, le moteur construit une `Observation` sérialisable (`to_dict()` →
|
politique, le moteur construit une `Observation` sérialisable (`to_dict()` →
|
||||||
JSON) figée — le snapshot est la SEULE source d'info de la LLM (aucune
|
JSON) isolée du combat — le snapshot est la SEULE source d'info de la LLM
|
||||||
référence `engine.*` exposée, collections copiées/figées). Une politique LLM
|
(aucune référence `engine.*` exposée, collections copiées, jamais relues en
|
||||||
|
retour : la politique peut les muter sans affecter le combat ; l'objet est un
|
||||||
|
dataclass figé au premier niveau, les dictionnaires internes sont des copies
|
||||||
|
mutables, non deep-freezés). Une politique LLM
|
||||||
se branche via `CombatEngine(..., llm_policy=...)` (`LLMPolicy(observation,
|
se branche via `CombatEngine(..., llm_policy=...)` (`LLMPolicy(observation,
|
||||||
state) -> tuple[Action, ...]`). Schéma enrichi (E1-E5) :
|
state) -> tuple[Action, ...]`). Schéma enrichi (E1-E5) :
|
||||||
- Par combattant : id, side, pos, occupied_cells, hp/hp_max, active/dead,
|
- Par combattant : id, side, pos, occupied_cells, hp/hp_max, active/dead,
|
||||||
|
|||||||
@@ -929,8 +929,11 @@ class Observation:
|
|||||||
|
|
||||||
Built by the engine at the point of policy invocation; the snapshot is the
|
Built by the engine at the point of policy invocation; the snapshot is the
|
||||||
ONLY source of information for an ``LLMPolicy`` — it never exposes
|
ONLY source of information for an ``LLMPolicy`` — it never exposes
|
||||||
``engine.*`` callables nor mutable references to live state. All collections
|
``engine.*`` callables nor mutable references to live state. All
|
||||||
are copied (tuples/dicts) so the snapshot is frozen and JSON-serializable.
|
collections are copies (tuples/dicts), never read back by the engine, so a
|
||||||
|
policy may mutate them freely without touching combat; the snapshot is
|
||||||
|
JSON-serializable (the top level is a frozen dataclass; the inner dicts are
|
||||||
|
plain mutable copies, not deep-frozen).
|
||||||
|
|
||||||
``combatants`` holds one dict per combatant in ``self._states`` order;
|
``combatants`` holds one dict per combatant in ``self._states`` order;
|
||||||
``pairs`` holds one dict per (acting combatant x each other combatant) with
|
``pairs`` holds one dict per (acting combatant x each other combatant) with
|
||||||
|
|||||||
Reference in New Issue
Block a user