docs(rules): conformance journal round 14 - transcript/format audit (14 bugs fixed)

A read-only audit of the transcript rendering, map and loader formats found
14 confirmed bugs (4 Med, 10 Low: duplicate --side, id-disambiguation
collision, range_increment_ft division by zero, silent spell_slots/features
drops, negative round-cap, multi-char legend keys, blank rows, id parsing,
duplicate YAML keys, move_cost default) - all fixed. The transcript/format
area is audited; only the structural out-of-scope items remain. Gate 1900.
This commit is contained in:
2026-09-20 18:08:29 +02:00
parent dd0b42b73b
commit 3d0fd0c101
2 changed files with 28 additions and 4 deletions
+27 -3
View File
@@ -26,7 +26,7 @@ résiduel**.
| Contrôle | Résultat |
|---|---|
| `uv run pytest -q` | 1861 tests verts |
| `uv run pytest -q` | 1900 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é |
@@ -210,6 +210,29 @@ Une passe de vérification adversariale a confirmé que les 15 correctifs High/M
| `74f5d64` | **Sunder réel** : statistiques d'objet par arme (dureté/PV SRD, +2/+2 par point d'amélioration) ; dégâts réels de l'attaque moins la dureté ; arme *broken* à ≤ moitié des PV, détruite à 0 ; **arme cassée utilisable à −2** avec critique sur 20 naturel ×2 (réconcilié avec le *misfire*/*quick_clear*) |
| `d0f7f3a` | **`carried_items`** (objets portés, non tenus) sur le modèle + données depuis les feuilles ; **Steal** transfère réellement un objet porté ; **récupération** d'une arme lâchée (pickup au désarmement à mains nues) |
### Correctifs de la passe 14 — audit du rendu du transcript & des formats
Audit read-only de la dernière zone non vérifiée (`cli.py` rendu du transcript, `map.py`, `loaders/combatant.py`) : **14 bogues confirmés** (4 Med, 10 Low), tous corrigés.
| Commit | Objet |
|---|---|
| `9656ae8` | Clé `spell_slots` non numérique → `CombatantLoadError` (au lieu d'un `ValueError` brut qui plantait la CLI) |
| `b8e9629` | `features` non-liste (ou entrée vide/non-chaîne) → erreur propre (au lieu d'une perte silencieuse) |
| `9adc87c` | `level` normalisé de façon cohérente (fini le *Toughness* calculé au niveau 1 pour un niveau 4) |
| `a8c7e37` | Ressources validées de façon cohérente avant fusion des dons |
| `130087a` | Carte : rejet d'une couche `zones` sans `deployment` |
| `de9309c` | CLI : rejet d'un `--side` dupliqué |
| `e9c2a63` | Désambiguïsation d'ids : le suffixe saute les ids déjà pris |
| `10f811e` | `range_increment_ft` strictement positif (0 provoquait une division par zéro) |
| `c46e636` | `--round-cap` ≥ 1 |
| `205ddec` | Clés de légende à un seul caractère |
| `bce0a59` | Lignes vides dans une couche → erreur ; cellules d'espace final conservées |
| `53c6dc0` | Ids de combattant rejetant `": "` (qui cassaient le parsing du transcript) |
| `ee22f75` | Clés YAML dupliquées rejetées (SafeLoader dédié) |
| `dd0b42b` | `move_cost` omis documenté explicitement comme infranchissable |
> Vérifiés conformes par l'audit : largeur d'affichage (accents NFC/NFD, CJK), repli en ligne brute sans perte, parsing des lignes conformes, capture du premier combat (`seed+0`), sémantique des nuls, normalisation du couvert (`cover_bonus`, `cover: true` → +4, `blocks_los` → +4), validations de déploiement/markers, ordre `(ligne, colonne)`, bande 3σ bornée.
> **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
@@ -358,7 +381,7 @@ ne pas être confondues avec des bogues.
| **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 |
| **Couverture d'audit** | Rendu du transcript et formats de données désormais **audités** (passe 14, 14 bogues corrigés) ; toutes les zones sont couvertes | Couverture complète |
---
@@ -398,7 +421,8 @@ Constats explicitement contrôlés et **confirmés conformes** :
| 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 — objets/inventaire** : Sunder réel (dureté/PV), Steal, récupération d'arme | `bg_f9c69e32`, `bg_44d81a98` | 2 correctifs | Objets/inventaire **sortis du hors-périmètre** |
| 14+ | Hors périmètre restant : compétences, pv non létaux, armes à éclaboussures, vol 3D, rendu du transcript | — | — | À reprendre |
| 14 | Audit du rendu du transcript + formats (cli/map/loader) | `bg_dc36ad2f` | 14 bogues (4 Med, 10 Low), 0 High | 14 correctifs (`9656ae8`..`dd0b42b`) |
| 15+ | Hors périmètre restant : compétences, pv non létaux, armes à éclaboussures, vol 3D | — | — | En cours (sans demande d'arrêt) |
---