docs(phase2): record the runner entry points (P0.4) and replay (P0.5)
run_encounter gains llm_policy and per-run policy_factory (mutually exclusive with policy/llm_policy); replay.py logs every (observation, action) keyed by call_seq to JSONL and replay() reproduces the recorded battle bit-identically (wins/draws/rounds/transcript) with mismatch, exhausted, duplicate and out-of-order guards. P0 frontier complete: the recorded run replays identically.
This commit is contained in:
@@ -357,10 +357,35 @@ hex/deed si ressource présente, défense totale, ready/delay) ; `swift`/`free`/
|
|||||||
`full_round` exclus ; liste bornée et triée. **Pas de second moteur de
|
`full_round` exclus ; liste bornée et triée. **Pas de second moteur de
|
||||||
légalité** : le moteur reste l'arbitre. Test : `tests/test_phase2_candidates.py`.
|
légalité** : le moteur reste l'arbitre. Test : `tests/test_phase2_candidates.py`.
|
||||||
|
|
||||||
|
### Runner et rejeu (P0.4 + P0.5 — commits 334f8f9, 6c6de16)
|
||||||
|
|
||||||
|
`run_encounter` accepte désormais `llm_policy=` (observation-only ou legacy,
|
||||||
|
transmise à chaque `CombatEngine`) et `policy_factory=` (constructeur de
|
||||||
|
`Policy` **par run**, appelé une fois par indice dans l'ordre ; `None` pour un
|
||||||
|
run = repli `default_policy`). Les trois entrées (`policy`, `llm_policy`,
|
||||||
|
`policy_factory`) sont mutuellement exclusives (erreur claire). Test :
|
||||||
|
`tests/test_phase2_runner.py` (factory 1 appel/run dans l'ordre, repli,
|
||||||
|
exclusivité, une bataille complète pilotée par `llm_policy`).
|
||||||
|
|
||||||
|
`replay.py` : `ReplayRecord(call_seq, observation, action)` + `ReplayLog`
|
||||||
|
(spec + seed + round_cap + appels) sérialisé en **JSONL** (clé `call_seq`),
|
||||||
|
`observation_key()` (digest déterministe, insensible à la collapse
|
||||||
|
tuple/liste de JSON), et `replay(log) -> LLMPolicy` qui renvoie les actions
|
||||||
|
enregistrées dans l'ordre des `call_seq`, avec gardes : observation
|
||||||
|
divergente (`ReplayMismatchError`), log épuisé (`ReplayExhaustedError`),
|
||||||
|
`call_seq` dupliqué ou hors ordre, JSONL invalide. **Un run enregistré se
|
||||||
|
rejoue à l'identique** (wins/draws/rounds/transcript — aussi depuis un log
|
||||||
|
dégelé du JSONL). Test : `tests/test_phase2_replay.py`. Le rejet de replay
|
||||||
|
par défaut est documenté (D3 : pas de mémoire inter-tours ; `delay`/ready
|
||||||
|
rejoués par les actions enregistrées elles-mêmes, sans ré-invocation).
|
||||||
|
|
||||||
### État du plan
|
### État du plan
|
||||||
|
|
||||||
- **P0.0 (D1)** ✅, **P0.1 (`schema_version`)** ✅, mesures ✅, `objectives.py` ✅,
|
- **P0.0 (D1)** ✅ · **P0.1 (`schema_version`)** ✅ · mesures ✅ ·
|
||||||
`collect_runs` ✅, **P0.2** (vue compacte) ✅, **P0.3** (`candidates`) ✅.
|
`objectives.py` ✅ · `collect_runs` ✅ · **P0.2** (vue compacte) ✅ ·
|
||||||
- Restent : **P0.4** (`llm_policy` sur le runner + `policy_factory`), **P0.5**
|
**P0.3** (`candidates`) ✅ · **P0.4** (`llm_policy` + `policy_factory`) ✅ ·
|
||||||
(replay `call_seq`) → puis P1 (client + politiques), P3 (optimiseur), P4
|
**P0.5** (ReplayLog `call_seq` + `replay()` identique) ✅.
|
||||||
(cartographie complète), P5 (fournisseur + rapport).
|
- **Frontière P0 atteinte** : gate verte (2022 tests) ; un run enregistré se
|
||||||
|
rejoue à l'identique.
|
||||||
|
- Suite : **P1** (client + politiques), P3 (optimiseur), P4 (cartographie
|
||||||
|
complète), P5 (fournisseur + rapport).
|
||||||
|
|||||||
Reference in New Issue
Block a user