11 KiB
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 :
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)
- Flags comportementaux (
cant_act,must_flee,denies_dex_to_ac,speed_mult...) jamais appliqués state.effects.clear()au début de chaque tour efface les buffs quel que soitduration_rounds; les conditions n'expirent jamais- DC de sort incorrect (
base_dc + levelau lieu de10 + niveau sort + mod stat casting) default_policyne lance JAMAIS de sorts (101 sorts PJ inertes en MC)- Pas de ressources (slots, grit, channel, hexes, rounds bardique)
- Pas d'AoO sur incantation, pas de concentration
- Pas d'AoE / multi-cibles
- Pas de manœuvres (CMB/CMD)
- Pas de summoning
- Pas de métamagie
- Pas de compétences (StatTarget : 14 cibles combat uniquement)
- Pas de capacités de classe (deed, hex, channel, performance)
- 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-1152models.py— Combatant:93-115 (ajoutercasting_ability,resources,cmb,cmd,skills)spells.py— types d'effets:32-57, _parse_effect:84-117, load_spell:120-132, load_spell_registry:135-140effects.py— StatTarget:40-44, StatModifier:49-65 (ajouter filtreskill)conditions.py— Condition:21-39, 18 conditions prédef, registry:212-220abilities.py— AbilitySpec:24-36, factories (weapon_focus:41, toughness:52)loaders/combatant.py— _KNOWN_FEATS:47, _resolve_feat:59-75, load_combatant:107-147loaders/foundry.py— _FEAT_MAP:52-61, load_sheet_detailed:280-355data/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), retirereffects.clear(), charge = ActiveBuff 1r. Commitfeat(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 :
resourcesdict +resources_left+spend_resource; tammara grit:3, oni channel:6. Commitfeat(models): combat resources - T9 — Métamagie Empower/Maximize/Extend à la volée +
metamagic_feats. Commitfeat(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). Commitfeat(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). Commitfeat(combat): spellcasting default policy - T7 — AoE :
AreaEffectburst + fireball 20-ft, demi-dégâts sur save. Commitfeat(combat): area-of-effect spells - T11 — Manœuvres CMB/CMD (
Action kind="maneuver": trip, disarm, bull_rush, sunder). Commitfeat(combat): combat maneuvers CMB/CMD - T8 — Summoning :
SummonEffect+data/monsters/celestial_wolf.json, insertion après lanceur dans l'initiative. Commitfeat(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). Commitfeat(data): lich monster
Wave 6 : T19, T20
- T19 —
tests/test_pc_combat_golden.py: 8 PJ vs gobelin + tammara vs liche, ScriptedRng épinglés. Committest(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 1et 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