Files
pf1e-simulator/_session_handoff/session-summary.md
T

152 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Résumé de session — PF1e Simulator (finalize-engine)
> Document de transfert de session entre ordinateurs. Généré le 29 août 2026.
## Contexte du projet
**Projet** : `pf1e-simulator` — simulateur de combat Monte Carlo déterministe pour Pathfinder 1re édition (Python ≥3.12, `uv`, Pydantic v2, pytest, ruff, basedpyright strict).
**Chemin** : `/home/armorial/Documents/pf1e-simulator` (git, branche `main`).
**Objectif global** : finaliser le moteur de combat pour couvrir ~90% des patterns mécaniques PF1e, prêt pour reprise de campagne **janvier 2027**. Pas de couche LLM, pas de base complète 9500 entrées.
## Décisions clés (validées par l'utilisateur)
- Compétences = **système complet** (37 skills)
- Manœuvres = **système complet** (incl. lutte/grapple)
- Summoning = **complet**
- Ordre des phases : Fondations (A) → Magie (B) → Systèmes (C) → Contenu 8 PJ (D) → Validation (E)
- **1 commit par étape**, gate verte à chaque commit
- Subagents réactivés (fallback_models réparés)
- Ne jamais push (l'utilisateur pousse manuellement)
## Contraintes / garde-fous
- Pas toucher à `fiches_personnages/`, `.codegraph/`, `.omo/` (sauf plans + evidence)
- Pas de suppression de type (`type: ignore`, `Any`) pour masquer les erreurs
- Pas de base complète PF1e, pas de tailles Large+, pas de 3D/élévation
- Réponses en français; commits en anglais, style conventionnel
- **Gate obligatoire** avant chaque commit :
```bash
export PATH="$HOME/.local/bin:$PATH" && uv run ruff check src tests && uv run basedpyright src && uv run pytest -q
```
## Bugs critiques identifiés du moteur (à corriger dans le plan)
1. Flags comportementaux (`cant_act`, `must_flee`, `denies_dex_to_ac`, `speed_mult`...) jamais appliqués
2. `state.effects.clear()` au début de chaque tour efface les buffs quel que soit `duration_rounds` ; les conditions n'expirent jamais
3. DC de sort incorrect (`base_dc + level` au lieu de `10 + niveau sort + mod stat casting`)
4. `default_policy` ne lance JAMAIS de sorts (101 sorts PJ inertes en MC)
5. Pas de ressources (slots, grit, channel, hexes, rounds bardique)
6. Pas d'AoO sur incantation, pas de concentration
7. Pas d'AoE / multi-cibles
8. Pas de manœuvres (CMB/CMD)
9. Pas de summoning
10. Pas de métamagie
11. Pas de compétences (StatTarget : 14 cibles combat uniquement)
12. Pas de capacités de classe (deed, hex, channel, performance)
13. Pas de capacités de monstres (ex. liche)
## Contenu des 8 PJ (source `fiches_personnages/*_sheet.json`)
- **Esha** (lv4) : Luring Cavalier / Phantom Thief — Mount, Order, Tactician. 11 feats, 1 sort.
- **Harvie** (lv2) : Animal Companion — Link, Natural Armor. 3 feats, 0 sort.
- **Ierlieth** (lv4) : Court Drake Companion. 3 feats, 0 sort.
- **Jeanne** (lv4) : Animal Companion (Bodyguard). 6 feats, 0 sort.
- **Misty** (lv4) : Magus (Eldritch Scion/Fiend Flayer) + Bard (Dervish Dancer) — Spell Combat, Arcane Pool, Bloodline, Battle Dance. 10 feats, 24 sorts.
- **Nairda** (lv4) : Sage WyrmWitch (Witch Sage/Sorcerer Arcane) — Hexes. 7 feats, 32 sorts.
- **Oni** (lv4) : Cleric (Blossoming Light)/Shifter (Feyform) — Channel Energy 2d6 6/jour, Domaines. 7 feats, 20 sorts.
- **Tammara** (lv4) : Gunslinger (Pistolero)/Warpriest — Grit, Deeds. 13 feats, 56 sorts.
Total : **55 feats uniques**, **101 sorts uniques** (dont 10 déjà implémentés dans `data/spells/`).
## Architecture (fichiers clés)
- `src/pf1e_simulator/combat.py` (~1150 ln) — moteur : CombatantState:169-193, Action:221-239, _take_turn:284-299, _stat_modifiers:380-399, resolve_save:481-496, _enemies_threatening:535-544, _check_provoked_aoo:560, _cast_spell:781-827, _apply_spell_effects:829-866, default_policy:1126-1152
- `models.py` — Combatant:93-115 (ajouter `casting_ability`, `resources`, `cmb`, `cmd`, `skills`)
- `spells.py` — types d'effets:32-57, _parse_effect:84-117, load_spell:120-132, load_spell_registry:135-140
- `effects.py` — StatTarget:40-44, StatModifier:49-65 (ajouter filtre `skill`)
- `conditions.py` — Condition:21-39, 18 conditions prédef, registry:212-220
- `abilities.py` — AbilitySpec:24-36, factories (weapon_focus:41, toughness:52)
- `loaders/combatant.py` — _KNOWN_FEATS:47, _resolve_feat:59-75, load_combatant:107-147
- `loaders/foundry.py` — _FEAT_MAP:52-61, load_sheet_detailed:280-355
- `data/pcs/*.json` (8), `data/monsters/{goblin,orc}.json`, `data/spells/` (10)
- Tests : `tests/test_combat.py`, `tests/test_spells.py` (:113-124 all-10-spells), `tests/test_combatant_loader.py` (24), `tests/test_pc_combat_golden.py` (à créer)
## État git (au moment du transfert)
- Branche `main`, dernière ligne : `37f07d9 chore(data): drop Plot Armor from misty features (non-combat feat)`
- Commit précédent : `82148ce test(loaders): add unit tests for combatant feat resolution...`
- **Gate verte** : 401 tests pass, ruff clean, basedpyright strict clean (0 erreur)
- Arbre de travail propre
## Fichiers plan/draft (.omo/)
- **Plan complet** : `.omo/plans/finalize-engine.md` (écrit, validé par l'utilisateur) — NOTE : `.omo/` est dans `.gitignore`, ce fichier n'est PAS versionné.
- **Draft** : `.omo/drafts/finalize-engine.md` (status: `plan-written`)
- Evidence par todo : `.omo/evidence/task-<N>-finalize-engine.md` (à créer par chaque agent)
## Exécution en cours — état
**Problème rencontré** : les délégations des subagents étaient interrompues (« le mauvais modèle était chargé »). L'utilisateur a réparé `fallback_models` et demandé de relancer la délégation. Tentatives sur Todo 1 (catégorie `deep` puis `unspecified-high`, skill `programming`) — certaines ont été abortées/modèle incorrect. Dernière tentative : `Task aborted`, session continuable `ses_fea75176fffeAxRSe6huDrsiWL`. L'utilisateur a ensuite demandé un **arrêt** et la sauvegarde de ce résumé.
**Note d'ajustement importante** : l'exécution se fait **séquentiellement** (pas en vagues parallèles) car tous les todos modifient les mêmes fichiers cœur (`combat.py`, `models.py`, `effects.py`) — des agents parallèles créeraient des conflits. La structure en vagues du plan est maintenue pour l'ordre/dépendances mais les agents s'exécutent un par un.
## À reprendre (prochaines étapes)
**Tout d'abord** : relancer la délégation du **Todo 1** (prompt standard référençant le plan ; exige TDD + evidence + commit `feat(combat): effect and condition durations`).
### Liste des tâches (Todo) — plan approuvé
#### Wave 1 (fondations)
- [ ] **T1** — Durées effets/conditions : `ActiveBuff`/`ActiveCondition` (rounds_left), retirer `effects.clear()`, charge = ActiveBuff 1r. Commit `feat(combat): effect and condition durations`
- [ ] **T3** — Formule DC = 10 + niveau sort + mod casting_ability ; enrichir 8 JSON. Commit `fix(combat): correct spell DC formula`
- [ ] **T4** — Ressources : `resources` dict + `resources_left` + `spend_resource` ; tammara grit:3, oni channel:6. Commit `feat(models): combat resources`
- [ ] **T9** — Métamagie Empower/Maximize/Extend à la volée + `metamagic_feats`. Commit `feat(combat): metamagic`
#### Wave 2 : T2, T6, T10
- [ ] **T2** — Enforcement flags (cant_act, cant_move, must_flee→withdraw, denies_dex→flat_footed, speed_mult, cant_aoo, cant_charge). Commit `feat(combat): enforce behavioral condition flags`
- [ ] **T6** — AoO sur incantation + concentration DC 15+2×niveau (Combat Casting +4). Commit `feat(combat): AoO and concentration on casting`
- [ ] **T10** — Compétences complètes (37) : `SkillSpec`, `resolve_skill`, Skill Focus (+3), loader Foundry (rank/total/classSkill/armorPenalty). Commit `feat(combat): skills system`
#### Wave 3 : T5, T7, T11, T8
- [ ] **T5** — Politique de sort dans `default_policy` (soin si <50%, offensif si en portée, buff sinon ; jamais si menacé sans concentration). Commit `feat(combat): spellcasting default policy`
- [ ] **T7** — AoE : `AreaEffect` burst + fireball 20-ft, demi-dégâts sur save. Commit `feat(combat): area-of-effect spells`
- [ ] **T11** — Manœuvres CMB/CMD (`Action kind="maneuver"` : trip, disarm, bull_rush, sunder). Commit `feat(combat): combat maneuvers CMB/CMD`
- [ ] **T8** — Summoning : `SummonEffect` + `data/monsters/celestial_wolf.json`, insertion après lanceur dans l'initiative. Commit `feat(combat): summoning`
#### Wave 4 : T12, T13, T14
- [ ] **T12** — Lutte complète : GRAPPLED, grappled_with, maintain/pin/escape/release, Escape Artist. Commit `feat(combat): grapple`
- [ ] **T13** — 55 feats des 8 PJ → AbilitySpec (Combat Reflexes + AoO, Skill Focus, autres passifs/no-op notés) ; sync _KNOWN_FEATS/_FEAT_MAP. Commit `feat(loaders): map 8-PC feats`
- [ ] **T14** — 91 sorts JSON générés (101 total), registre + test all-101. Commit `feat(data): 101 spell JSONs`
#### Wave 5 : T15, T16, T17, T18
- [ ] **T15** — JSON compagnons : harvie, ierlieth, jeanne, monture esha. Commit `feat(data): companions and mounts`
- [ ] **T16** — Channel energy Oni (30ft, 2d6, ressource 6/jour) + hexes Nairda (Evil Eye, Slumber, Cackle). Commit `feat(combat): channel energy and hexes`
- [ ] **T17** — Deeds Tammara (Up Close and Deadly +1d6≤30ft coûte 1 grit, Quick Clear) + Misty (Spell Combat = sort+full attack, Inspire Courage 30ft). Commit `feat(combat): class action patterns`
- [ ] **T18** — Liche : `data/monsters/lich.json` (Fear Aura shaken Will DC22, Paralyzing Touch → PARALYZED 1d4+1r, DR 15/bludgeoning+magic). Commit `feat(data): lich monster`
#### Wave 6 : T19, T20
- [ ] **T19** — `tests/test_pc_combat_golden.py` : 8 PJ vs gobelin + tammara vs liche, ScriptedRng épinglés. Commit `test(combat): PC golden transcripts`
- [ ] **T20** — README à jour + gate finale verte (~500 tests) + retirer références obsolètes ("377 tests", "Manœuvres non modélisées"). Commit `docs: finalize engine documentation`
#### Vérification finale
- [ ] **F1** — Audit conformité plan (20 todos + evidence présentes)
- [ ] **F2** — Qualité code (ruff + basedpyright propres, pas de suppression de type)
- [ ] **F3** — QA CLI manuelle : `pf1e-sim --side players data/pcs/tammara.json --side monsters data/monsters/lich.json --runs 100 --seed 1` et oni vs gobelins (vérifier sorts/summon/manœuvres/ressources)
- [ ] **F4** — Fidélité scope (8 PJ jouables, pas de modif fiches_personnages/.omo/.codegraph, pas de LLM)
## Matrice de dépendances (ordre d'exécution)
- T2 ← T1 ; T6 ← T2 ; T5 ← T2, T6
- T11 ← T10 ; T12 ← T11, T10
- T13 ← T2, T10 ; T14 ← T7, T8, T9
- T16 ← T4 ; T17 ← T4, T7, T14 ; T18 ← T14
- T19 ← 2,5,12,13,14,15,16,17,18 ; T20 ← 19
- T1, T3, T4, T9, T7, T8, T10, T15 : indépendants (mais exécution séquentielle pour éviter conflits sur `combat.py`)
## Matériel pour la reprise sur un autre ordinateur
- Besoin du repo cloné : `git clone <url> pf1e-simulator && cd pf1e-simulator && uv sync --dev`
- Fichiers de contexte à conserver : `.omo/plans/finalize-engine.md`, `.omo/drafts/finalize-engine.md`
- Lancer le plan depuis `.omo/plans/finalize-engine.md` (il contient tous les references par todo)
- Le processus d'exécution attendu : délégation séquentielle par todo via subagent, TDD, gate verte, un commit par todo, puis vérification finale F1-F4