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

11 KiB
Raw Blame History

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)

  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

  • T19tests/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