# Conformité SRD Pathfinder 1re édition — journal d'audit Ce document consigne, de façon exhaustive et vérifiable, l'écart entre les règles implémentées par le moteur et le SRD Pathfinder 1re édition. Il complète le `README.md` (qui décrit le comportement attendu) en traçant **ce qui a été corrigé**, **ce qui est hors périmètre**, et **ce qui reste assumé comme résiduel**. ## Méthode 1. **Audit read-only par domaine** : chaque passe couvre un domaine étanche (sorts, mouvement, morts-vivants, dons, manœuvres, conditions, données de sorts, bestiaire). L'auditeur croise le code avec la base de connaissances SRD (`pathfinder-kb`, collection `pathfinder-1e-rules`) et cite la règle. 2. **Classement** : `High` (change matériellement l'issue d'un combat), `Med` (clairement faux, impact étroit), `Low` (donnée / cosmétique). 3. **Correction** : un commit par correctif, gate complète verte avant chaque commit (`ruff` `select=ALL`, `basedpyright` strict, `pytest`). 4. **Non-régression** : le transcript doré (`tests/test_pc_combat_golden.py`) n'est réécrit que lorsqu'un correctif SRD change légitimement la sortie, avec justification ligne à ligne. 5. **Traçabilité** : tout constat non corrigé est classé ici en *hors périmètre* (choix délibéré) ou *résiduel assumé* (écart connu, non corrigé). ## État de la gate | Contrôle | Résultat | |---|---| | `uv run pytest -q` | 1850 tests verts | | `uv run ruff check src tests` (`select=ALL`) | conforme | | `uv run basedpyright src` (strict) | 0 erreur | | Transcript doré depuis la passe 1 | inchangé | --- ## 1. Écarts corrigés ### Correctifs de la passe 2 (commits) | Commit | Objet | |---|---| | `b03a61d` | Données de sorts : niveaux (`abundant_ammunition`, `comprehend_languages`, `deja_vu` 0→1 ; `create_water` 1→0 ; `enhance_water` 2→1), sauvegardes (`blindness_deafness` Will→Fort ; `enhance_water` none→Fort), RM de `summon_monster_i/ii`, écoles (6 sorts), portées (4 sorts) + pins de registre | | `317f91a` | *Entangled* : jet de concentration DD 15 + niveau ; `dex_skills` −4 | | `bfe0b76` | *Exhausted* : −6 Dextérité → −3 CA / −3 Réflexes | | `6220edc` | *Fatigued* : −2 Dextérité → −1 CA / −1 Réflexes | | `def8533` | *Nauseated* : privé d'attaques d'opportunité | | `68a03a3` | *Confused* : privé d'attaques d'opportunité (simplification) | | `cf8a073` | *Grappled/Pinned* : −2 aux jets de manœuvre (hors grapple/escape) | | `f31cc88` | *Pinned* : ne peut plus attaquer | | `4d45409` | Weapon Focus : correspondance insensible à la casse (le don s'applique enfin) | | `2807f71` | Attaque sournoise : toute dissimulation l'annule | | `350844f` | *Up Close And Deadly* : réservé aux armes à feu | | `fdc9127` | *Toughness* : +3 pv sous 4 DV (`max(3, niveau)`) | | `2b5920c` | *Disarm* : l'arme tombe (`weapon_dropped`) au lieu d'une pénalité −4 | | `06da519` | *Dirty trick* : liste RAW étendue (`shaken`, `sickened`) | | `0cccea2` | Manœuvres : succès automatique contre cible incapable | | `3a5948c` | CMD : plus de double comptage de Dextérité (Tiny, CMB pré-calculé) | | `e89ea42` | README/capacités : grapple (pin hors périmètre), `pinned`/`nauseated` sans attaque, Weapon Focus par groupe | > Transcript doré : mis à jour **deux fois**, chaque fois par un correctif SRD > justifié ligne à ligne dans le docstring du test — `4d45409` (Weapon Focus : > le +1 transforme le jet 15 en 16 contre CA 16) puis `bee224a` (Shield of > Faith et Divine Favor portent enfin leurs vrais buffs : `_find_buff_spell` > retient désormais Divine Favor, index 20, ce qui remonte la CA de tammara et > réécrit son transcript). Le second correctif déplace la mort du gobelin au > **round 5** (le « round 4 » du premier correctif est superseded). ### Correctifs des passes 3 et 4 (commits) | Commit | Objet | |---|---| | `e0bf484` | Tir dans une mêlée : exemption mesurée **cible → allié le plus proche** (High) | | `cc9fba3` | CA d'une cible inerte : −5 exact, plus de double comptage d'une Dextérité négative | | `fa63829` | `trait` et `racial` non cumulables (APG « Traits », CRB) | | `1c2663d` | Type non cumulable : meilleur bonus **et** pire pénalité conservés séparément | | `ae037c9` | Dégâts minimum : 1 point sur une touche réduite sous 1 par la RD | | `b3a7c37` | Types de bonus `alchemical`/`inherent`/`resistance`/`size` (UM Table 2-7) | | `feaab5e` | `celestial_wolf` aligné sur le loup du SRD + template céleste (DR/RM) | | `1c94d48` | `harvie` : Sagesse 14, Talons primaires +2 (1d4 ×2), Morsure secondaire | | `b9477a2` | `ierlieth` : bonus de dégâts −1, Queue secondaire ajoutée | | `2b5b39a` | Chevaux : sabots 1d4 marqués naturels, Morsure secondaire de Jeanne | | `611952c` | `misty` : don « Plot Armor » ajouté en no-op tracé | | `83bbcae` | Ray of Enfeeblement : type `PenaltyEffect` (pénalité de Force lancée, Fort moitié) au lieu de *fatigued* | | `79d9ff0` | `drunkards_breath` : cône de 30 ft qui rend *nauseated* (niveau 2, conjuration, Fort annule) — l'ancien contenu était **inventé** (High) | | `48c816b` | `delay_disease` : niveau 2 conjuration (soins) | | `27f9629` | Données : `alarm` close, `air_bubble`/`endure_elements` touch, `delay_poison` conjuration, conventions 10 ft/0 ft documentées, `daze` 4 DV | | `47f563e` | Shield of Faith : +2 CA déflexion (+1 / 6 niveaux, max +5) | | `bee224a` | Divine Favor : +1 chance attaque/dégâts par 3 niveaux (max +3) — doré mis à jour | | `6d96779` | Spear of Purity / Shard of Chaos : 1d8 / 2 niveaux (max 5d8), Volonté moitié | | `a5bd3c5` | Défense totale : plus d'attaques d'opportunité | | `e253b03` | Charge restreinte à 1× pour un accablé/invalide (et au round de surprise) | | `980d53d` | Aide : expiration au début du tour de **l'aidant** | | `a144423` | Défense totale et combat défensif non cumulables | | `0c3f5fd` | Durées de condition scalées au niveau (hold person, doom, touch of fatigue, vanish) | ### Correctifs des passes 5 et 6 (commits) | Commit | Objet | |---|---| | `d0db208` | *Exalted of the Society* → +1 canalisation/jour (`resource_grants`) ; *Fortified Drinker* → no-op (état « alcool » non modélisé) | | `6d0ee1b` | *Born Damned* et *Axe to Grind* → no-ops documentés (descripteur « curse » absent ; « menacé par vous seul » inexprimable) | | `a5ebbec` | *Friendly Face* et *Extremely Fashionable* → no-ops (attitude animale et port de vêtements non modélisés) | | `b74baf1` | *Lonely* / *Bitter* → vraies penalties (fini les faux +1 Will) | | `81a09c8` | Métamagie : **ne gonfle plus le DD** — seul Heighten (désormais supporté) | | `418fdc8` | **Charge retenue** : un contact de mêlée manqué conserve le sort | | `cec3c5f` | Durée d'invocation **1 round/niveau** (`SummonEffect.duration_rounds_per_level`) | | `65a5e24` | Combat Casting : +4 retiré du jet *entangled* | | `22724f5` | Extend Spell double la durée d'invocation | | `b2739c5` / `1902877` / `17c06e1` | Documentation : échec d'armure, convention `spell_slots`, dissipation `(D)` | | `2dd3fef` | *Larger Than Life*, *Ambitious*, *Focused Study* → no-ops documentés | | `7262568` | Traits sylphes d'Esha + noms inventés (*Whispering Wind*, *Like the Wind*, *Fey-touched*, *Pingre*) → no-ops tracés | | `2df9dd7` | *Scaled Skin* (résistance électricité 5) ; *Maw or Claw* morsure 1d6 | | `13e4a27` | Couverture de test de tout le lot no-op | | `d9b590e` | Acid Arrow (cap total 7) ; Ice Slick (+1/niveau, max +10) | | `56310b1` | Mirror Image (images lancées + miss chance dynamique) ; Bleed (seuil ≤ −1 pv) ; Bane (−1 limité à la peur) | | `35ce41e` | Owl's Wisdom (+2 Volonté) ; docs affinées des utilitaires différés | | `b95533d` | Bear's Endurance (+2 pv/DV) ; Aid (moral limité aux sauvegardes de peur) ; Charm Person (portée close) | | `5250763` | **Ligne** s'arrête au premier obstacle de ligne d'effet | | `389e160` | **Cône** exige une ligne d'effet depuis son origine | | `948edc1` | **Burst** n'affecte pas une créature en couvert total par rapport au centre | | `8774e51` | **Couvert → Réflexes** (moitié du bonus de CA, couvert mou exclu) | | `a2ca78f` | `blocks_los` documenté comme sémantique **ligne d'effet** (vision seule non modélisée) | | `beb8421` | High ground +1 **mêlée uniquement** (vérifié conforme, Table 8-5) | | `fb6f58a` | Règle des coins en diagonale documentée comme plus stricte que le RAW (approximation conservatrice assumée) | | `9f8655d` | README synchronisé (truncature des lignes, LoE cône/burst, couvert Réflexes) | | `27ce33b` | Couvert au **corps-à-corps adjacent** : règle « n'importe quelle ligne » du SRD | | `5e478bf` | Charge et course appliquent la **règle des coins** | | `9086038` | Charge : terrain difficile testé sur **tout le footprint** (« on ne se déplace qu'à la vitesse du terrain le plus difficile occupé ») | ### Correctifs de la passe 6 (suite) et de la passe 7 | Commit | Objet | |---|---| | `792cec1` | Les créatures **mourantes mais vivantes** occupent leur case (couvert mou + gabarits de zone) | | `778d6a8` | Un **aveugle** ne peut ni charger, ni courir, ni retraiter | | `2e468ba` | Cône/ligne pointé : plus d'exigence de ligne d'effet vers le point visé (bursts seulement) | | `1e2de7f` | Cône/ligne : **tout le footprint** du lanceur est exclu de son propre gabarit | | `24e208e` | `square_size_ft ≠ 5` rejeté au chargement (géométrie figée à 5 ft) | | `2e2873f` | **Canal de soin** : le soin n'est plus compté comme `damage_dealt` | | `7fefce4` | `run_encounter` ne **plante plus** quand une invocation apparaît (accumulateurs à la demande) | | `0ad627c` | Saignement, dégâts récurrents et soin-sur-morts-vivants comptés dans `damage_taken` | | `9459ade` | `downgraded:immediate_swift` ajouté au vocabulaire `ACTION_RESULT_REASONS` | | `2ee19d3` | Formulation « snapshot figé » corrigée (les dicts internes sont des copies mutables) | | `ba5eb4c` | Déploiement : deux camps sur la **même lettre de zone** rejetés | | `9a087a4` | Exemples du README **rafraîchis** contre le moteur réel (Quick start 96,2 % ; exemple vérifié 33,0 %) | ### Correctifs de la passe 8 — vérification indépendante Une passe de vérification adversariale a confirmé que les 15 correctifs High/Med échantillonnés sont **réellement implémentés**, puis a trouvé des écarts **jamais documentés** (politique par défaut, dés, outillage), tous corrigés : | Commit | Objet | |---|---| | `31d47ae` | *Spell Combat* : garde `_has_slot` (sans emplacement, la policy ne provoque plus l'attaque à −2) | | `bdf15aa` | Soin de la policy : contrôle **portée + ligne d'effet** (fini le tour perdu sur un contact hors portée) | | `e8b7a73` | `parse_dice("d1"/"1d1")` lève bien `DiceParseError` (plus de `ValidationError` pydantique) | | `f93c55b` | *Up Close and Deadly* émis seulement si un tir d'arme à feu suit (fini le grit gaspillé) | | `c23fc36` | Seuil « < 50 % » exact (`hp*2 < hp_max`) | | `6f01a8e` | Mode soin du canal : seuls les **vivants** comptent (un allié mort-vivant ne le déclenche plus) | | `238e5f2` | Hex : portée **close scalée** au niveau (25 ft + 5 / 2 niveaux) au lieu d'un 25 ft figé | | `1b43f4e` | README : `data/pcs/*.json` sont **canoniques** ; `foundry.py` est un outil one-shot incomplet (ne pas régénérer sans réappliquer les correctifs) | ### Correctifs de la passe 9 — résiduels assumés (lots 1-3) | Commit | Objet | |---|---| | `ea83529` | **Course** bornée par le score de **CON** (jet de CON DD 10 par round au-delà, échec → arrêt + repos 10 rounds) ; **don Run** (+4 au jet, conserve la Dextérité à la CA) ; armure lourde ×3 reclassée hors périmètre (pas de champ d'armure) | | `4665a1c` | Sorts **« harmless »** : plus de jet de sauvegarde inutile sur cible consentante (drapeau `harmless` posé sur les 29 sorts SRD « (harmless) ») | | `9f0d862` | Bursts **Bless/Bane centrés sur le lanceur** (`centered_on_caster` piloté par les données) | | `5fe2b72` | **Selective Channeling** modélisé (exclusion par la policy, plafonnée au modificateur de Charisme, sans effet sans le don) | | `4f8a131` | Fiche du **liche alignée sur le KB** (pv 111, For 10, Int 22, init +2, aura de terreur 60 ft/DD 18) — doré re-pinné (2 lignes, toutes deux SRD-correctes) | | `5e7436b` | **Invocations** : identifiants désambiguïsés (chacune son emplacement de stats) | | `e6021a6` | **`healing_done`** exposé par combattant et dans le rapport (« soins prodigués ») | | `d347dde` | **Terrain difficile multi-cases en `move`** : le pas reflète le terrain le plus difficile sous tout le *footprint* | | `d5ad3c3` | Un **cône/trait** ne perd plus de longueur à cause des cases du lanceur effleurées | | `b775d46` | Origine des **bursts** (centre-à-centre vs intersection) : **différé** et documenté précisément (nécessite une coordonnée d'intersection dans le contrat) | ### Correctifs de la passe 10 — sorts utilitaires résiduels (lot 4) | Commit | Objet | |---|---| | `08f9af9` | **Guidance** : nouveau type `OneShotEffect` (+1 compétence one-shot sur un unique jet d'attaque, non appliqué au jet de confirmation) — implémente le variant attaque du SRD | | `1238c40` | **Resistance** : +1 résistance aux jets de sauvegarde (1 min) ; `_find_buff_spell` ignore désormais les cantrips sans emplacement (évite de préempter les buffs de niveau et de dégrader la policy) | | `a8a65b1` | **Virtue** : 1 pv temporaire (track `temp_hp` consommé avant les vrais pv) | | `f788613` | **Stabilize** : `StabilizeEffect` qui stabilise automatiquement une créature mourante | | — | `spiritual_weapon` (attaque flottante persistante) et `saving_finale` (reroll immédiat) restent **différés** (mécanique porteuse absente) | ### Correctifs de la passe 11 — alignement (sorti du hors-périmètre) | Commit | Objet | |---|---| | `f9e51e3` | Champ **`alignment`** sur `Combatant` (9 valeurs PF1e validées, défaut `N`) + dérivées `is_lawful/is_chaotic/is_good/is_evil` ; alignements renseignés pour tous les monstres et PJ (source KB/feuilles) ; exposé dans l'observation | | `6a18d45` | Type **`AlignmentGate`** sur les dégâts : cible immunisée / neutre (moitié, sans condition) / pleine (dégâts + condition si sauvegarde ratée) ; *Shard of Chaos* (chaotique/loyal, condition `staggered`) et *Spear of Purity* (bon/mauvais, condition `blinded`) | | `3be22b9` | Vocabulaire de conditions **`attacker_is_evil/lawful/good/chaotic`** câblé à l'attaquant réel ; **Protection from Evil/Law** (+2 CA déflexion et +2 sauvegardes contre l'alignement opposé) et variantes communales | ### Correctifs de la passe 12 — composantes & échec d'armure (sortis du hors-périmètre) | Commit | Objet | |---|---| | `1f8f068` | Moteur : `components` sur `SpellSpec` (V/S/M/F/DF validés), `armor_spell_failure` + `arcane_caster` sur `Combatant` ; jets d'échec **conditionnels** (sourd + composante verbale → 20 % ; arcanique + somatique + armure → ASF d100), exposés dans l'observation | | `91666d8` | Encodage des composantes SRD sur **107/108 sorts** (le 108e n'a pas de ligne Composants au KB) | | `f6292f8` | `arcane_caster` / `armor_spell_failure` posés depuis les feuilles (liche, Thrune, misty, nairda arcaniques) | | `9f72948` | README synchronisé | > **Registre des sorts clos** : les 35 derniers sorts ont été vérifiés champ par champ contre le KB — **0 divergence** (niveaux, sauvegardes, RM, portées, zones, formules conformes). Seuls 2 sorts sont absents du KB (`create_alcool`, `hidden_diplomacy`) et 1 nit de description subsiste (`detect_poison` mentionne « acid »). ### Passe 1 — sorts de buff, mouvement/grille, morts-vivants, armes naturelles | # | Constat | Sév. | Correctif (commit) | |---|---|---|---| | B1 | *Bless* affectait **toutes** les créatures d'un burst de 20 ft (y compris les ennemis) ; le SRD cible « you and each of your allies within a 50-ft. burst » | **High** | `e43066e` — filtre `AreaEffect.targets` (`all`/`allies`/`enemies`), burst 50 ft, alliés + lanceur | | B2 | *Bane* était un sort mono-cible ; le SRD cible les **ennemis** dans un burst de 50 ft | Med | `5e3505d` — conversion en `AreaEffect` 50 ft, `targets: "enemies"` | | B3 | *Bladed Dash* : niveau 1 (au lieu de 2), portée `close` (au lieu de `personal`) | Med | `312f9fd` | | B4 | *Aid* : niveau 1 (au lieu de 2), portée `long` (au lieu de `touch`) | Med | `312f9fd` | | B5 | *Doom* : portée `close` (au lieu de `medium`) | Med | `312f9fd` | | B6 | *Bull's Strength* : sauvegarde `fort` (le SRD n'accorde pas de jet ; valeur neutre corrigée en `will`) | Med | `312f9fd` | | B7 | *Bear's Endurance* : sauvegarde `fort` (idem) | Med | `312f9fd` | | B8 | *Mage Armor* absent du registre | Low | `3e19d29` — sort ajouté (niveau 1, conjuration, contact, +4 CA d'**armure**, RM non) + type de bonus `"armor"` non cumulable (registre porté à 108 sorts) | | C1 | Budget de déplacement : parité des diagonales figée à 0 dans les descentes gloutonnes → la règle 5-10-5 était **violée** (un marcheur vitesse 30 parcourait 6 cases en diagonale au lieu de 4) | Med | `2cc2ba1` — parité propagée (`_best_move_step`, `_descend_path`, `_run_line_path`, `_flee_path`) + `_path_cost_5105` pour la charge | | C2 | Pas de placement (5 ft) autorisé depuis/vers un terrain difficile | Med | `437507e` — rejet si le footprint courant **ou** la destination touche du terrain difficile | | C3 | Entrer dans la case d'une créature hostile ne provoquait pas d'AoO | Med | `9a16ca0` — `_check_enter_aoo` câblé dans `_walk_steps` | | C4 | Traversée d'une case hostile à ≥ 3 catégories d'écart de taille non modélisée | Med | `9a16ca0` — `_can_pass_through` (porte « traversée ») distincte de `_blocked` (porte « fin de mouvement ») | | C5 | Un combattant **fatigué/épuisé** pouvait courir (seule la charge était bloquée) ; le SRD : « can neither run nor charge » | Low | `7fc7a1d` — garde `cant_charge` ajoutée à `_execute_run` | | D1 | Les morts-vivants (et les créatures artificielles) mouraient à `hp ≤ -CON` au lieu d'être détruits à `hp ≤ 0` | Med | `59caf67` — seuil de mort à 0, pas de bande d'agonie | | D2 | Fiche du liche non conforme au bloc SRD : BAB 8 (au lieu de +5), contact +10 (au lieu de +5), `damage_bonus` 5 doublant la formule (dégâts réels 1d8+10 au lieu de 1d8+5), CA 25/14/23 (au lieu de 23/14/21), jets 10/10/14 (au lieu de 6/7/11), `con_score` 14 alors qu'un mort-vivant n'a pas de Constitution | Low | `881f2ef` | | D3 | Les sorts de soin (`cure`) soignaient les morts-vivants au lieu de les **blesser** | Low | `cad35e2` — dégâts (Volonté pour moitié), ni RD ni stabilisation | | A1 | Armes naturelles : itératifs de BAB accordés à tort et absence de la pénalité −5 des attaques secondaires | Med | `e5691bd` — champs `natural`/`secondary` (une seule attaque, secondaires −5, Multiattack −2) | ### Passe 2 — dons/capacités, manœuvres, conditions, données de sorts Constats d'audit (6 High, ~28 Med, ~45 Low). La colonne *Disposition* indique le sort réservé : **corrigé** (commit), **à corriger**, **hors périmètre** (non modélisable proprement) ou **résiduel assumé** (écart connu, conservé). #### 2a. Données de sorts (vérifiées une à une contre le KB) | Constat | Sév. | Disposition | |---|---|---| | `abundant_ammunition` niveau 0 → **1** (toutes classes) | High | corrigé (passe 2) | | `comprehend_languages` niveau 0 → **1** | High | corrigé (passe 2) | | `deja_vu` niveau 0 → **1** | High | corrigé (passe 2) | | `blindness_deafness` sauvegarde `will` → **`fort`** | High | corrigé (passe 2) | | `create_water` niveau 1 → **0** (clerc/druide) | Med | corrigé (passe 2) | | `enhance_water` niveau 2 → **1**, portée personal → **touch** | Med | corrigé (passe 2) | | `deja_vu` portée personal → **medium** | Med | corrigé (passe 2) | | `summon_monster_i` / `summon_monster_ii` RM true → **false** | Med | corrigé (passe 2) | | `divine_favor` — effet SRD (+1 chance attaque/dégâts par 3 niveaux) absent | Med | résiduel assumé | | `owls_wisdom` — effet SRD (+4 Sagesse) absent | Med | résiduel assumé | | `shield_of_faith` — effet SRD (+2 CA déflexion) absent | Med | résiduel assumé | | `weapon_of_awe` — effet SRD (+2 dégâts sacrés) absent | Med | résiduel assumé | | Écoles fausses : `arcane_mark` divination→**universal**, `color_spray` enchantment→**illusion**, `dancing_lights` conjuration→**evocation**, `deja_vu` divination→**enchantment**, `enhance_water` abjuration→**transmutation**, `abundant_ammunition` transmutation→**conjuration** | Low | corrigé (passe 2) | | Portées fausses : `dancing_lights` close→**medium**, `create_water` medium→**close** | Low | corrigé (passe 2) | | `enhance_water` sauvegarde none → **fort** (inoffensif) | Low | corrigé (passe 2) | | Effets absents (sorts utilitaires) : `guidance`, `resistance`, `protection_from_evil`, `sanctuary`, `virtue`, `shard_of_chaos`, `spear_of_purity`, `spiritual_weapon` | Low | hors périmètre | | *Faux positifs* (conformes) : `web` RM, `flurry_of_snowballs` RM, `detect_fiendish_presence` niveau, `scorching_ray` projectiles (max 3), `make_whole`/`restoration_lesser` temps d'incantation (`long`) | — | conformes | | *Non vérifiable* (le KB omet la ligne RM) : `shield`, `read_magic`, `comprehend_languages` (RM) | — | indéterminé | | Portées « pieds fixes » (15/30/50/60/120 ft) approchées par les catégories close/medium/long pour les cônes, lignes et bursts (`burning_hands`, `color_spray`, `fear`, `flurry_of_snowballs`, `lightning_bolt`, `bless`, `bane`, `obscuring_mist`, `detect_magic`) | Low | hors périmètre (modèle de portée par catégories) | #### 2b. Conditions | Constat | Sév. | Disposition | |---|---|---| | *Entangled* : aucun jet de concentration **DD 15 + niveau** à l'incantation | Med | corrigé (passe 2) | | *Exhausted* : pénalités **−3 CA / −3 Réflexes** manquantes (−6 Dex) | Med | corrigé (passe 2) | | *Nauseated* : peut porter des **attaques d'opportunité** | Med | corrigé (passe 2) | | *Confused* : peut porter des attaques d'opportunité (le SRD l'interdit) | Med | corrigé (passe 2) | | *Grappled* : **−2 aux jets de manœuvre** (sauf grapple/escape) non appliqué | Med | corrigé (passe 2) | | *Pinned* : peut **attaquer** ; de plus la condition n'est **jamais appliquée** (code mort) | Med | corrigé (f31cc88) / hors périmètre (entretien) | | *Fatigued* : **−1 CA / −1 Réflexes** manquants (−2 Dex) | Low | corrigé (passe 2) | | *Fatigued/Exhausted* : pénalité de dégâts appliquée aussi aux armes à distance | Low | résiduel assumé | | *Entangled* : `dex_skills` −4 manquant (incohérent avec grappled/pinned) | Low | corrigé (passe 2) | | *Shaken/Sickened/Frightened/Panicked* : pénalités de compétence/caractéristique non modélisées | Low | hors périmètre (pas de tests de compétence) | | *Frightened/Panicked* : fuite = retraite 2× au lieu de la course 4× ; acculé attend au lieu de se recroqueviller | Low | résiduel assumé | | *Dazzled* / *Blinded* : malus de Perception (dont opposition) non modélisés | Low | hors périmètre | | *Deafened* : échec d'incantation 20 % | Low | hors périmètre (déjà documenté) | | *Stunned/Panicked* : « lâche tout ce qu'elle tient » non modélisé | Low | hors périmètre (pas de modèle d'objet tenu) | | *Grappled* : « aucune action à deux mains » non modélisé | Low | hors périmètre | | *Pinned* : composantes somatiques/matérielles non modélisées | Low | hors périmètre | | *Bleeding* : règle de non-cumul (« le pire effet l'emporte ») non vérifiée | Low | à vérifier | #### 2c. Manœuvres de combat | Constat | Sév. | Disposition | |---|---|---| | *Grapple* : aucun entretien/pin/dégâts/déplacement ; `pinned` jamais appliqué — **le README « grapple → grappled/pinned » est faux** | High | hors périmètre (README corrigé, e89ea42) | | *Disarm* : pénalité **−4 synthétique** au lieu du **lâcher d'arme** (le SRD fait tomber l'objet) | High | à corriger | | *Grappled* : −2 non appliqué aux jets de manœuvre de combat | Med | corrigé (cf. 2b) | | *Grapple* : plafond arbitraire de 10 rounds ; pas de bonus de +5 d'entretien | Med | hors périmètre | | *Disarm* : pas d'échec-de-10 → l'attaquant lâche son arme | Med | résiduel assumé | | *Trip* : `prone` expire en 1 round au lieu de persister jusqu'à `stand_up` | Med | résiduel assumé (README documenté) | | *Sunder* : dégâts `str_mod + 2` fixes au lieu des dégâts d'arme ; **dureté non modélisée** | Med | résiduel assumé (README documenté) | | *Sunder* : arme cassée retirée des attaques au lieu de **−2** (SRD : reste utilisable) | Med | résiduel assumé | | Pas de **succès automatique** contre une cible incapable/inconsciente | Med | à corriger | | *Reposition* : contrainte d'allonge non appliquée au déplacement | Med | résiduel assumé | | *Dirty trick* : options **shaken/sickened** manquantes ; pas de retrait par action de mouvement | Med | à corriger | | *Trip* : créatures sans jambes/volantes non trippables ; +2 par paire de jambes | Low | hors périmètre (pas de traits de créature) | | *Overrun* : option « se laisser éviter » non modélisée | Low | hors périmètre | | *Bull rush* : vérifications secondaires contre les créatures sur le passage non modélisées | Low | hors périmètre | | *Drag* : budget de déplacement de l'attaquant non vérifié | Low | hors périmètre | | *Disarm* : à mains nues −4, +10 → lâcher des deux objets, attente d'un round | Low | résiduel assumé | | *Escape* : option « devenir le grappleur » non modélisée | Low | hors périmètre | | *Grapple* : −4 si pas deux mains libres ; restrictions arme légère/Stealth | Low | hors périmètre (pas de modèle de mains) | | *CMD* : double comptage de Dextérité latent pour une créature Tiny avec `cmb` pré-calculé | Low | à corriger | #### 2d. Dons et capacités de classe | Constat | Sév. | Disposition | |---|---|---| | **Weapon Focus (Pistolet) est un don mort** : le filtre de don compare exactement « Pistol » au nom d'arme « Braises d'Automne (pistolet ?) » → le +1 ne s'applique jamais | Med | à corriger | | Attaque sournoise autorisée contre une **dissimulation partielle** (le SRD bloque dès « concealment » ; le README revendique à tort « total concealment ») | Med | à corriger | | *Up Close And Deadly* s'applique à **toute** attaque à distance ; le SRD l'exige d'une **arme à feu** | Med | à corriger | | *Toughness* : +niveau au lieu de **+3 puis +1 par DV au-delà de 3** (faux aux niveaux 1-2 ; données actuelles ≥ 3) | Low | à corriger | | *Channel Energy* : 2d6 **figés** (pas de progression +1d6 par 2 niveaux) ; le canaliseur est toujours inclus | Low | résiduel assumé | | *Combat Reflexes* : planché à 1 AoO (le SRD autorise 0 avec un modificateur de Dextérité négatif) | Low | résiduel assumé | | *Cackle* : étend les `evil_eye` de **tous** les lanceurs, pas seulement les siens | Low | résiduel assumé | | *Improved Critical* appliqué à **toutes** les armes (SRD : un type d'arme) | Low | résiduel assumé (README documenté) | | *Inspire Courage* : +1 plat (progression +1 par 4 niveaux non modélisée) | Low | résiduel assumé (README documenté) | | *Spell Combat* : le coût de pool arcanique est un no-op (misty n'a pas de pool) | Low | sans objet | --- ## 2. Hors périmètre (choix délibéré, documenté) Ces règles sont **volontairement** non modélisées et signalées dans le `README.md` (sections « Limites hors périmètre » et « Limites de sorts ») pour ne pas être confondues avec des bogues. | Sujet | Raison | |---|---| | **Squeeze** (se serrer dans un passage étroit) | La largeur de couloir n'est pas comparée à la taille ; une créature bloquée par son footprint l'est sans option de squeeze payante | | **Acrobatics « Tumbling »** (traverser une case ennemie sans AoO) | Le moteur n'a pas de système de compétences | | **Objets / inventaire** (`Steal`, `Sunder`) | Le modèle n'a pas de piste d'objets (tenu vs porté, PV/dureté d'objet) — seule l'usure d'arme simplifiée existe | | **Système de compétences** (Perception opposée, Discrétion, Acrobaties) | Pas de sous-système de compétences (hors `dex_skills`/bonus statiques) | | **Créature inerte très grande = obstacle à 2 cases** | Les cases d'une créature inactive ne bloquent pas et ne coûtent pas double | | **Échec d'incantation du personnage sourd (20 %)** | Modélisé : composante verbale + condition `deafened` → jet de d20% ≤ 20 | | **Incantation multi-round (`long` : 3 rounds, 10 min, 1 h)** | Non planifiable dans un tour ; jetée du budget (`downgraded:cast_time`) plutôt qu'approximée | | **Co-occupation au-delà de Tiny vs plus grand** | Deux créatures Small+ ne partagent jamais une case ; plusieurs Tiny sur une case non gérés | | **Combat à deux armes / arme en main secondaire (×0,5 Force)** | Hors du modèle d'attaque actuel | | **Vol 3D / vol par-dessus les obstacles** | La vitesse de vol est un budget au sol ; pas de maniabilité ni de survol du terrain | | **`markers`** (points nommés de la carte) | Validés à la lecture, non appliqués à la résolution | --- ## 3. Résiduels assumés (écart connu, non corrigé) | Sujet | Nature de l'écart | Décision | |---|---|---| | **Origine des bursts** | Mesure **centre-à-centre** au lieu d'**intersection-à-intersection** avec la règle du bord lointain (SRD « Aiming a Spell ») ; l'exactitude exigerait une coordonnée d'intersection dans le contrat d'observation et un choix de coin du lanceur | Différé, documenté précisément (`areas.py`, `_creatures_in_range`) | | **Course en armure lourde (×3)** | Le modèle n'a pas de champ d'armure ; la course est désormais bornée par la CON et le don Run est modélisé | Hors périmètre (reclassé) | | **Dégâts non létaux** | Aucune source dans les données ; le minimum de dégâts est approximé en dégâts normaux | Hors périmètre (aucune source) | | **Armes à éclaboussures** | Aucun objet concerné dans les données | Hors périmètre | | **Sorts utilitaires différés** | `spiritual_weapon` (attaque flottante persistante — pas d'attaquant sans porteur dans le moteur) et `saving_finale` (reroll immédiat — pas de crochet de réaction sur un jet de sauvegarde) restent hors d'atteinte ; `guidance`, `resistance`, `virtue` et `stabilize` sont désormais **modélisés** | Différés (raison moteur consignée) | | **Non vérifiable (KB)** | `create_alcool`, `hidden_diplomacy` absents du KB ; nit de description de `detect_poison` (« acid ») | Indéterminé / nit | | **Couverture d'audit** | Rendu du transcript et formats de données avancés non encore audités | À reprendre si besoin | --- ## 4. Conformités vérifiées (garde-fous anti-régression) Constats explicitement contrôlés et **confirmés conformes** : - **Résistance aux sorts** : le drapeau `spell_resistance` est respecté et `_check_spell_resistance` court-circuite sans consommer de RNG quand la cible n'a pas de RM. - **Description de *Lightning Bolt*** (ligne 120 ft, 1d6/niveau plafonné 10d6, Réflexes demi) : conforme. - **Diagonale entrant en terrain difficile** : coût plat de 3 cases, convention de table explicite dans `grid.py`, cohérente entre Dijkstra et descentes. - **Terrain mixte** : les coûts de pas s'additionnent sans double comptage. - **Déplacement d'un personnage aveuglé** : le SRD n'interdit ni le déplacement, ni la course, ni la charge à un aveugle (seuls la touche, la CA et les compétences sont affectés) — le constat d'audit initial ne visait pas une vraie règle. --- ## 5. Journal des audits | Passe | Domaines | Sessions | Constats | Statut | |---|---|---|---|---| | 1 | Sorts (B), Mouvement/grille (C), Morts-vivants (D), Armes naturelles (A) | `bg_9e9e22e6`, `bg_cda707bf`, `bg_ba80396a`, `bg_6a621d4c` | 1 High, 12 Med, ~20 Low | Corrigés + documentés (ci-dessus) | | 2 | Dons/capacités (E), Manœuvres (F), Conditions (G), Données de sorts (H) | `bg_5314f54c` (re-run), `bg_9fdc610e`, `bg_f5829c68`, `bg_b289533d` + extraction/vérification `bg_e1ccd2da`, `bg_4292da47`, `bg_14d5344a` | 4 High, ~18 Med, ~45 Low | Constats consignés (§ 1 passe 2) ; correctifs data/conditions/dons en cours | | 3 | Résolution d'attaque & défense, bestiaire/PJ (blocs de stats), économie d'action & tour, sorts restants | `bg_38d99eac`, `bg_8cdcb3e2`, `bg_73e3f878` | 1 High, ~10 Med, ~40 Low | 11 correctifs (`e0bf484`..`611952c`) + Ray of Enfeeblement (`83bbcae`) ; le reste documenté | | 4 | Sorts restants (champ par champ), dons des 8 PJ vs feuilles Foundry | `bg_29c36b1a` | 1 High, 1 Med, ~30 Low (dont 20 dons) | 11 correctifs (`79d9ff0`..`0c3f5fd`) ; 20 écarts de dons + effets de sorts différés documentés | | 5 | Sous-système des sorts (invocation, emplacements, métamagie, concentration, livraison) ; cas limites moteur (LoS/LoE, couvert, élévation, terrain, gabarits de zone) | `bg_938bceca`, `bg_27334a51` | 0 High, ~6 Med, ~15 Low | 15 correctifs (`81a09c8`..`9086038`) + documents ; 8 Low moteur résiduels | | 6 | Résiduels de dons (24) et d'effets de sorts (~13) | `bg_303e14a0`, `bg_151d5a57`, `bg_918e49cf` | 0 High, ~4 Med, ~30 Low | 16 correctifs (`d0db208`..`b95533d`) ; effets non exprimables documentés | | 7 | Registre des sorts (35 restants, champ par champ) ; moteur : Low documentés ; sous-systèmes runner/métriques/observation/CLI | `bg_0a3e3844`, `bg_2c4d185a`, `bg_cc8f0788` | 2 High, 2 Med, ~8 Low | 12 correctifs (`792cec1`..`9a087a4`) ; **registre des sorts clos (108/108)** | | 8 | Vérification adversariale (correctifs réels + chasse aux écarts non documentés : `dice`, `rng`, `foundry`, `map`, `default_policy`, transcript) | `bg_d8cba9d1`, `bg_1bac8900` | 15 claims vérifiés réels ; 2 High/Med + ~6 Low nouveaux | 8 correctifs (`31d47ae`..`1b43f4e`) ; reste = résiduels assumés et hors périmètre | | 9 | Résiduels assumés (lots 1-3) : course/CON+Run, harmless, centrage Bless/Bane, Selective Channeling, liche, invocations, healing_done, terrain multi-cases, cône effleuré | `bg_0a5b0d6b`, `bg_b304c5a3`, `bg_b277ee2d` | ~10 correctifs, 1 différé | 10 correctifs (`ea83529`..`d5ad3c3`), doré re-pinné une fois (liche) | | 10 | Sorts utilitaires résiduels (lot 4) : guidance, resistance, virtue, stabilize, spiritual_weapon, saving_finale | `bg_9c989e12` | 4 implémentés, 2 différés | 4 correctifs (`08f9af9`..`f788613`) | | 11 | **Hors périmètre — alignement** : champ + dérivées, Shard of Chaos / Spear of Purity, Protection from Evil/Law (+communales) | `bg_1a3b0faa`, `bg_6980098f`, `bg_07b3d604` | 3 correctifs | Alignement **sorti du hors-périmètre** | | 12 | **Hors périmètre — composantes & ASF** : composantes sur 107 sorts, sourd 20 %, échec d'armure, `arcane_caster` | `bg_02d4b4e3`, `bg_84baec1d` | 4 correctifs | Composantes/ASF **sortis du hors-périmètre** | | 13+ | Hors périmètre restant : objets/inventaire (Steal/Sunder), compétences, pv non létaux, armes à éclaboussures, vol 3D, rendu du transcript | — | — | À reprendre | --- ## 6. Relancer une passe d'audit Chaque passe suit le même protocole : 1. Choisir un domaine **non encore audité** (voir le journal § 5). 2. Lancer un auditeur read-only (agent `oracle`) avec la base SRD `pathfinder-kb` et l'exigence de citer la règle et la ligne de code fautive. 3. Trier chaque constat : **corriger** (si l'impact est matériel et le correctif propre) ou **classer** en hors périmètre / résiduel assumé (ce document). 4. Un commit par correctif ; gate complète verte ; transcript doré préservé ou justifié ligne à ligne. 5. Reporter les constats dans les tableaux ci-dessus et la ligne de journal.