<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Analyse De Pdf on Boris Dupoux</title><link>https://borisdupoux.com/fr/tags/analyse-de-pdf/</link><description>Recent content in Analyse De Pdf on Boris Dupoux</description><generator>Hugo -- gohugo.io</generator><language>fr</language><lastBuildDate>Mon, 01 Jun 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://borisdupoux.com/fr/tags/analyse-de-pdf/index.xml" rel="self" type="application/rss+xml"/><item><title>Automatisation déterministe des processus sous fortes contraintes de sécurité</title><link>https://borisdupoux.com/fr/research/deterministic-rpa/</link><pubDate>Mon, 01 Jun 2026 00:00:00 +0000</pubDate><guid>https://borisdupoux.com/fr/research/deterministic-rpa/</guid><description>&lt;h2 id="contexte"&gt;&lt;a href="#contexte" class="header-anchor"&gt;&lt;/a&gt;Contexte
&lt;/h2&gt;&lt;p&gt;Un client soumis à de fortes contraintes de sécurité gère plusieurs centaines de sites
et exécute chaque jour quatre processus administratifs récurrents : la maintenance des
équipements sur le terrain, le traitement des événements parasites récurrents émis par
ces équipements, la rédaction de rapports d&amp;rsquo;intervention pour ses propres clients et la
vérification de la bonne réception du contrôle de santé périodique de chaque site. Les
données d&amp;rsquo;entrée sont dispersées entre trois systèmes aux modes d&amp;rsquo;accès très différents :
des rapports PDF reçus par courriel, un portail web métier sans API publique et des
classeurs Excel tenus à la main depuis de nombreuses années.&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;objectif : automatiser ces processus sur un poste de travail de bureau tout en laissant
à un opérateur humain le dernier mot sur chaque message adressé aux clients.&lt;/p&gt;
&lt;h2 id="contraintes-de-conception"&gt;&lt;a href="#contraintes-de-conception" class="header-anchor"&gt;&lt;/a&gt;Contraintes de conception
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Aucun modèle de langage à l&amp;rsquo;exécution.&lt;/strong&gt; Chaque décision découle de règles explicites
et chaque phrase d&amp;rsquo;un modèle de texte. La sortie du robot est ainsi reproductible : les
mêmes entrées produisent toujours les mêmes brouillons, ce qui est conçu pour permettre
de comparer mot pour mot une nouvelle version à la production, et toute modification peut être
rattachée à une règle ou à une source de données. Aucune donnée client n&amp;rsquo;est transmise à
un service de modèle externe. Un modèle vision-langage a été utilisé une seule fois, hors
ligne, lors de la conception, pour cartographier des sessions d&amp;rsquo;écran enregistrées
d&amp;rsquo;opérateurs ; il ne fait pas partie du système déployé.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Des brouillons, pas des envois.&lt;/strong&gt; Le robot se contente de créer des brouillons
Outlook ; l&amp;rsquo;opérateur les relit et les envoie. Un interrupteur d&amp;rsquo;arrêt global impose le
mode brouillon quels que soient les réglages propres à chaque processus.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Exécution locale, sans nouvelle infrastructure.&lt;/strong&gt; Python sur un poste Windows, tâches
planifiées, dossier partagé sur NAS pour l&amp;rsquo;état et la configuration.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Aucun secret en clair.&lt;/strong&gt; Identifiants et jetons sont stockés dans le Gestionnaire
d&amp;rsquo;identifiants Windows (DPAPI) ; la configuration est en YAML, modifiable par
l&amp;rsquo;opérateur sans recompilation.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="architecture"&gt;&lt;a href="#architecture" class="header-anchor"&gt;&lt;/a&gt;Architecture
&lt;/h2&gt;&lt;pre class="mermaid" style="visibility:hidden"&gt;flowchart TB
 SCHED["Passages planifiés (matin / après-midi)"] --&gt; ING
 MAIL["Boîte aux lettres (Microsoft Graph, lecture)"] --&gt; ING["Ingestion rapports PDF regroupés par jour"]
 ING --&gt; PARSE["Analyseur PDF (pypdf + expressions régulières)"]
 PORTAL["Portail web métier connexion Playwright → jeton de session → rejeu des points d'accès JSON"] --&gt; RULES
 XLS["Classeurs de référence &amp; d'historique (Excel)"] --&gt; RULES
 PARSE --&gt; RULES["Moteur de règles 4 processus, règles ordonnées &amp; exclusions"]
 RULES --&gt; TPL["Composeur de modèles accords, noms, dates en français"]
 TPL --&gt; DRAFTS["Brouillons Outlook (Graph, jamais envoyés)"]
 RULES --&gt; TRACK["Classeurs de suivi (ajout atomique)"]
 DRAFTS --&gt; OP(["L'opérateur relit &amp; envoie"])
 OP -. "éléments envoyés : destinataires corrigés" .-&gt; RULES
 NAS[("NAS : verrous, battements de cœur, journal, registre d'idempotence")] --- RULES
 RULES --&gt; HEALTH["Alertes de santé webhook + contrôle de l'homme mort"]&lt;/pre&gt;&lt;h2 id="les-quatre-processus"&gt;&lt;a href="#les-quatre-processus" class="header-anchor"&gt;&lt;/a&gt;Les quatre processus
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Maintenance des équipements.&lt;/strong&gt; Les lignes de panne extraites des rapports PDF
quotidiens sont confrontées à l&amp;rsquo;historique des piles et des réparations de chaque
appareil. Un arbre de décision ordonné (la première correspondance l&amp;rsquo;emporte) choisit
entre ignorer, attendre, remplacer la pile, remplacer l&amp;rsquo;appareil ou tester la portée
radio, et rédige un ordre d&amp;rsquo;intervention pour le technicien ; chaque appareil d&amp;rsquo;un ordre
portant sur plusieurs appareils conserve sa propre décision.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Événements parasites récurrents.&lt;/strong&gt; Le nombre d&amp;rsquo;événements par site et par appareil sur
24 heures est comparé à des seuils pour détecter les événements parasites récurrents. Les
données du portail (un incident confirmé comme réel, un système mis à l&amp;rsquo;arrêt quelques
minutes après une salve) priment sur ces comptages ; il en résulte un courriel de
sensibilisation au client, un ordre d&amp;rsquo;intervention, ou rien.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rapports d&amp;rsquo;intervention.&lt;/strong&gt; Pour chaque intervention sur site, le robot reconstitue une
chronologie unique à partir du journal d&amp;rsquo;événements du portail, du journal d&amp;rsquo;appels et
des relevés des équipes de terrain, gère les événements à cheval sur minuit et rédige un
rapport client accompagné des fichiers médias.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Contrôles de santé périodiques.&lt;/strong&gt; Les sites dont le contrôle de santé périodique est
absent sont identifiés, l&amp;rsquo;état de chaque canal de connectivité est vérifié sur le
portail, puis un courriel au client, un ordre d&amp;rsquo;intervention ou une note interne est
rédigé.&lt;/p&gt;
&lt;h2 id="rédiger-un-courriel--des-paramètres-au-brouillon"&gt;&lt;a href="#r%c3%a9diger-un-courriel--des-param%c3%a8tres-au-brouillon" class="header-anchor"&gt;&lt;/a&gt;Rédiger un courriel : des paramètres au brouillon
&lt;/h2&gt;&lt;p&gt;Chaque brouillon est l&amp;rsquo;aboutissement d&amp;rsquo;une longue chaîne de décisions explicites.
Comptés dans le code source (octobre 2026), les quatre moteurs de règles comportent
&lt;strong&gt;53 issues terminales&lt;/strong&gt; (chaque endroit où une règle rend une décision), réparties sur
&lt;strong&gt;37 types de décision&lt;/strong&gt; et &lt;strong&gt;13 générateurs de brouillons&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Le courriel de sensibilisation du processus « événements parasites » en donne la mesure.
Un site n&amp;rsquo;y aboutit qu&amp;rsquo;après &lt;strong&gt;14 tests ordonnés&lt;/strong&gt; au plus dans le moteur de règles
(16 issues terminales pour ce seul processus). Le composeur lit ensuite &lt;strong&gt;une vingtaine d&amp;rsquo;entrées&lt;/strong&gt; :
17 champs de la fiche de décision du site et de la fiche client, la liste des
destinataires, les pièces jointes et deux ressources apprises (les noms de zones du
portail et un dictionnaire d&amp;rsquo;orthographe appris dans le classeur d&amp;rsquo;historique de
l&amp;rsquo;opérateur lui-même). Entre la décision et le texte final, on compte &lt;strong&gt;une centaine de points
de branchement conditionnel&lt;/strong&gt; (instructions &lt;code&gt;if&lt;/code&gt;, expressions conditionnelles et opérandes
booléens, comptés sur l&amp;rsquo;arbre syntaxique du composeur et des dix fonctions auxiliaires
qu&amp;rsquo;il appelle, avant la mise en forme HTML).&lt;/p&gt;
&lt;pre class="mermaid" style="visibility:hidden"&gt;flowchart TB
 IN(["1 · Moteur de règles — 14 tests ordonnés, la première correspondance l'emporte. Entrées : rapports d'événements quotidiens · journal du portail · fiche client · profil appris du site"]) --&gt; T0

 T0["Drapeau bloquant sur la fiche du site ?"] -- oui --&gt; X0["Pas de courriel"]
 T0 -- non --&gt; T1["R6 · incident confirmé comme réel aujourd'hui ?"]
 T1 -- oui --&gt; X1["Pas de courriel"]
 T1 -- non --&gt; T2["R17 · événements médias à moins de 30 s entre zones ?"]
 T2 -- oui --&gt; X2["Arbitrage manuel"]
 T2 -- non --&gt; T3["R12 · cause externe confirmée par les médias ?"]
 T3 -- non --&gt; T4["R8 · ≥ 8 événements d'intégrité ?"]
 T4 -- oui --&gt; T4b["persistants depuis ≥ 3 jours ?"]
 T4b -- oui --&gt; X3["Ordre d'intervention technicien"]
 T4b -- non --&gt; X4["En attente"]
 T4 -- non --&gt; T5["≥ 2 événements d'intégrité, ≥ la moitié de la salve ?"]
 T5 -- oui --&gt; X5["Pas de courriel"]
 T5 -- non --&gt; T6["R16 · ≥ 140 événements, sensibilisation ignorée depuis ≥ 4 semaines ? (désactivée par défaut)"]
 T6 -- oui --&gt; X6["Avis de facturation"]
 T6 -- non --&gt; T7["R15 · drapeau bâtiment partagé ?"]
 T7 -- oui --&gt; X7["Courriel de coordination"]
 T7 -- non --&gt; T8["R5 · week-end + drapeau appareil chroniquement défaillant ?"]
 T8 -- oui --&gt; X8["Demande de masquage temporaire"]
 T8 -- non --&gt; T9["R1 · même appareil ≥ 7 événements ?"]
 T9 -- non --&gt; T10["R2 · ≥ 5 appareils et ≥ 8 événements ?"]
 T10 -- non --&gt; T11["R4 · ≥ 8 événements, ≥ 50 % entre 5 h et 7 h ?"]
 T11 -- non --&gt; T12["R3 · ≥ 8 événements, ≥ 60 % entre 12 h et 18 h, ≥ 70 % en 4 h ?"]
 T12 -- non --&gt; T13["R1bis · total du site ≥ 7 événements ?"]
 T13 -- non --&gt; X9["Pas de courriel"]

 T3 &amp; T9 &amp; T10 &amp; T11 &amp; T12 &amp; T13 -- oui --&gt; ADV

 ADV(["2 · Composeur — courriel de sensibilisation, identifiant de règle transmis. Nom du client : forme juridique retirée, casse rétablie, sigles conservés"])
 ADV --&gt; SUBJ["≥ 30 événements ?"]
 SUBJ -- oui --&gt; S1["Objet avec préfixe d'urgence"]
 SUBJ -- non --&gt; S2["Objet simple"]
 S1 &amp; S2 --&gt; GR["Cellule contact"]
 GR -- "plusieurs personnes, ou mot de fonction / d'organisation" --&gt; G1["Salutation générique"]
 GR -- "civilité + nom" --&gt; G2["Salutation + civilité normalisée (7 abréviations) + NOM"]
 GR -- "nom seul" --&gt; G3["Salutation + NOM"]
 G1 &amp; G2 &amp; G3 --&gt; DEV["Appareils concernés"]
 DEV -- un --&gt; D1["Nom de zone du portail s'il est connu, sinon libellé nettoyé + table de jargon + accents appris"]
 DEV -- plusieurs --&gt; D2["Formule générique + liste de 6 au plus par nombre d'événements, chacun avec son code s'il est connu"]
 D1 &amp; D2 --&gt; HND["Système mis en marche ou à l'arrêt à quelques minutes de la salve ? (R1 à R4 seulement)"]
 HND -- "arrêt juste après" --&gt; C1["Erreur de manipulation, formulation A"]
 HND -- "marche juste avant" --&gt; C2["Erreur de manipulation, formulation B"]
 HND -- non --&gt; ACT["Site en activité ? — toutes les conditions : R1 à R4 ou R1bis · ≥ 2 appareils · ≥ 10 événements · aucune intervention dans la fenêtre · site professionnel · ≥ 90 % dans les heures apprises · capteurs médias seuls : ≥ 90 % système en marche"]
 ACT -- oui --&gt; C3["Formulation « site en activité »"]
 ACT -- non --&gt; RUL["Règle déclenchée"]
 RUL -- "R1, R2" --&gt; C4["Cause environnementale générique"]
 RUL -- "R3, R4" --&gt; C5["Cause : passages du personnel"]
 RUL -- R12 --&gt; C6["Cause externe confirmée par les médias"]
 RUL -- R1bis --&gt; C7["Cause à rechercher sur place"]
 C4 &amp; C5 --&gt; ATT["Médias réellement joints ?"]
 ATT -- oui --&gt; A1["+ renvoi aux pièces jointes"]
 ATT -- non --&gt; FLG
 A1 &amp; C1 &amp; C2 &amp; C3 &amp; C6 &amp; C7 --&gt; FLG["Drapeau du site : travaux fréquents ?"]
 FLG -- oui --&gt; F1["Demande : arrêt avant travaux"]
 FLG -- non --&gt; F2["Demande : traiter la cause"]
 F1 &amp; F2 --&gt; REC["Adresses dans la fiche client ?"]
 REC -- oui --&gt; RC1["Toutes les adresses trouvées"]
 REC -- non --&gt; RC2["Boîte interne de repli"]
 RC1 &amp; RC2 --&gt; DRAFT(["Texte brut → HTML Outlook (dé-repliage, listes, typographie fixe, signature) → dossier des brouillons, jamais envoyé"])
 classDef q stroke-dasharray:4 3,stroke-width:2px;
 class T0,T1,T2,T3,T4,T4b,T5,T6,T7,T8,T9,T10,T11,T12,T13,SUBJ,GR,DEV,HND,ACT,RUL,ATT,FLG,REC q;&lt;/pre&gt;&lt;p&gt;L&amp;rsquo;espace de formulation de ce seul courriel : 2 formes d&amp;rsquo;objet, 3 formes de salutation,
2 formes de phrase d&amp;rsquo;ouverture, 7 formulations de cause atteignables (dont deux avec ou
sans renvoi aux médias joints), 2 demandes d&amp;rsquo;action et une liste facultative de 2 à
6 appareils. La plupart des seuils ci-dessus sont dans la configuration YAML ; quelques-uns
(urgence, site en activité, concentration sur 4 h) restent dans le code.&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Paramètre&lt;/th&gt;
					&lt;th&gt;Source&lt;/th&gt;
					&lt;th&gt;Effet sur le courriel&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Nombre d&amp;rsquo;événements sur 24 h&lt;/td&gt;
					&lt;td&gt;rapports quotidiens&lt;/td&gt;
					&lt;td&gt;chiffre de la phrase d&amp;rsquo;ouverture ; à partir de 30, préfixe d&amp;rsquo;urgence dans l&amp;rsquo;objet&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Règle déclenchée&lt;/td&gt;
					&lt;td&gt;moteur de règles&lt;/td&gt;
					&lt;td&gt;choisit la formulation de la cause ; conditionne les vérifications « erreur de manipulation » et « site en activité »&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Appareils concernés (nettoyés, dédoublonnés)&lt;/td&gt;
					&lt;td&gt;rapports quotidiens&lt;/td&gt;
					&lt;td&gt;un appareil nommé, ou une formule générique suivie d&amp;rsquo;une liste de 6 lignes au plus, par nombre d&amp;rsquo;événements&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Code de l&amp;rsquo;appareil sur chaque ligne de rapport&lt;/td&gt;
					&lt;td&gt;rapports quotidiens&lt;/td&gt;
					&lt;td&gt;ajouté entre parenthèses à chaque appareil listé, seulement s&amp;rsquo;il est connu&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Nom de zone de l&amp;rsquo;appareil principal&lt;/td&gt;
					&lt;td&gt;portail&lt;/td&gt;
					&lt;td&gt;remplace le libellé brut du rapport lorsqu&amp;rsquo;il est disponible&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Graphies apprises&lt;/td&gt;
					&lt;td&gt;classeur d&amp;rsquo;historique de l&amp;rsquo;opérateur&lt;/td&gt;
					&lt;td&gt;rétablit accents et casse des noms d&amp;rsquo;appareils&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Cellules civilité et nom du contact&lt;/td&gt;
					&lt;td&gt;fiche client&lt;/td&gt;
					&lt;td&gt;l&amp;rsquo;une des 3 formes de salutation ; plusieurs personnes, une fonction ou un nom d&amp;rsquo;organisation ramènent à la forme générique&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Raison sociale&lt;/td&gt;
					&lt;td&gt;fiche client&lt;/td&gt;
					&lt;td&gt;forme juridique retirée, casse rétablie en conservant les sigles, utilisée dans l&amp;rsquo;objet et le corps&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Type de site, heures d&amp;rsquo;ouverture apprises, interventions dans la fenêtre&lt;/td&gt;
					&lt;td&gt;classeur de suivi, journal du portail&lt;/td&gt;
					&lt;td&gt;active ou neutralise la formulation « site en activité »&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Mise en marche ou à l&amp;rsquo;arrêt autour de la salve&lt;/td&gt;
					&lt;td&gt;journal du portail&lt;/td&gt;
					&lt;td&gt;formulation « erreur de manipulation » (2 variantes), prioritaire sur toute autre cause&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Drapeaux du site&lt;/td&gt;
					&lt;td&gt;fiche client&lt;/td&gt;
					&lt;td&gt;choix entre les 2 demandes d&amp;rsquo;action&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Présence de pièces jointes&lt;/td&gt;
					&lt;td&gt;médias du portail&lt;/td&gt;
					&lt;td&gt;renvoi aux pièces jointes, ou rien&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Adresses des destinataires&lt;/td&gt;
					&lt;td&gt;fiche client&lt;/td&gt;
					&lt;td&gt;toutes les adresses trouvées ; à défaut, une boîte interne de repli&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Les autres brouillons s&amp;rsquo;appuient sur les mêmes fonctions partagées de rédaction en
français : la préposition devant un nom de site s&amp;rsquo;accorde avec son premier nom (6 formes,
de « chez » à « à l&amp;rsquo; » et « aux ») ; les titres des rapports s&amp;rsquo;accordent en genre et en
nombre ; les dates sont écrites en toutes lettres ; l&amp;rsquo;intitulé « Contact » passe au
pluriel dès que plusieurs contacts sont listés ; et une table de 8 entrées traduit le
jargon technique des équipements en vocabulaire client.&lt;/p&gt;
&lt;h2 id="ingénierie-de-la-fiabilité"&gt;&lt;a href="#ing%c3%a9nierie-de-la-fiabilit%c3%a9" class="header-anchor"&gt;&lt;/a&gt;Ingénierie de la fiabilité
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Idempotence.&lt;/strong&gt; Un registre quotidien indexé par site, type de message et empreinte de
l&amp;rsquo;objet empêche les brouillons en double ; un registre inter-jours empêche de réémettre
un ordre d&amp;rsquo;intervention avant que l&amp;rsquo;intervention précédente n&amp;rsquo;ait eu lieu. Les jours
manqués sont rattrapés automatiquement.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Concurrence sur un NAS partagé.&lt;/strong&gt; Fichiers de verrou exclusifs (&lt;code&gt;O_CREAT|O_EXCL&lt;/code&gt;)
avec une durée de vie pour les verrous orphelins ; deux postes publient des battements de
cœur, et le poste secondaire ne prend le relais que lorsque le principal est silencieux
depuis deux minutes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Écritures sûres dans les classeurs.&lt;/strong&gt; Les écritures passent par un fichier temporaire
et un remplacement atomique, avec nouvelles tentatives lorsque le classeur est ouvert par
un utilisateur ; les lignes insérées décalent les formules de pied de tableau pour que
les totaux restent justes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Robustesse réseau.&lt;/strong&gt; Les appels Graph gèrent le renouvellement des jetons, l&amp;rsquo;en-tête
&lt;code&gt;Retry-After&lt;/code&gt; des réponses HTTP 429 et le repli progressif sur les erreurs 5xx.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Échec explicite.&lt;/strong&gt; Une enveloppe de plantage, sans dépendance au paquet principal,
envoie une alerte expurgée et un signal d&amp;rsquo;homme mort même lorsque les imports échouent ;
une sentinelle déclenche une alerte lorsque le portail ne renvoie aucune donnée au lieu
de signaler un succès.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Évaluation en parallèle (shadow).&lt;/strong&gt; Une version bac à sable rejoue une journée en
lecture seule et compare ses brouillons à ceux de la production. Le critère
d&amp;rsquo;acceptation sera la part des brouillons que l&amp;rsquo;opérateur envoie sans en modifier un
seul mot ; il n&amp;rsquo;a pas encore été mesuré.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="résultats"&gt;&lt;a href="#r%c3%a9sultats" class="header-anchor"&gt;&lt;/a&gt;Résultats
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;1 766&lt;/strong&gt; tests automatisés collectés dans le dépôt (octobre 2026 ; statut de réussite
non consigné), reposant sur des adaptateurs simulés de messagerie et de portail ; les
tests qui exigent de vraies données de référence sont ignorés lorsque celles-ci sont absentes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;9,5 %&lt;/strong&gt; (132/1 383) des lignes d&amp;rsquo;événements de 12 jours de rapports réels étaient
écartées silencieusement, ce qui a été découvert après qu&amp;rsquo;un site a manqué dans une
exécution : les codes et libellés d&amp;rsquo;événements sont concaténés dans le texte extrait des
PDF. L&amp;rsquo;analyseur a été réécrit pour reconnaître les formes de codes effectivement
émises ; depuis, aucune ligne n&amp;rsquo;est perdue sur 11 rapports réels.&lt;/li&gt;
&lt;li&gt;La mise en cache du classeur d&amp;rsquo;historique des pannes (1,49 Mo, 15 533 lignes) a réduit
la durée du processus de maintenance des équipements de &lt;strong&gt;161,1 s à 23,3 s&lt;/strong&gt;, sur un
rejeu des rapports réels d&amp;rsquo;une journée (une seule exécution) ; le nombre d&amp;rsquo;ouvertures du
classeur est passé de 26 à 3.&lt;/li&gt;
&lt;li&gt;Première journée en parallèle sans écart avec la production : &lt;strong&gt;14 brouillons de chaque
côté, mêmes décisions et mêmes objets, 0 manquant, 0 en trop&lt;/strong&gt;. Les corps n&amp;rsquo;ont pas
encore été comparés, et une journée ordinaire compte environ 90 brouillons.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="stack-technique"&gt;&lt;a href="#stack-technique" class="header-anchor"&gt;&lt;/a&gt;Stack technique
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Python 3.11&lt;/code&gt; · &lt;code&gt;Microsoft Graph&lt;/code&gt; · &lt;code&gt;MSAL&lt;/code&gt; · &lt;code&gt;httpx&lt;/code&gt; · &lt;code&gt;Playwright&lt;/code&gt; · &lt;code&gt;pypdf&lt;/code&gt; ·
&lt;code&gt;openpyxl&lt;/code&gt; · &lt;code&gt;pydantic&lt;/code&gt; · &lt;code&gt;keyring&lt;/code&gt; · &lt;code&gt;pytest&lt;/code&gt; · &lt;code&gt;PyInstaller&lt;/code&gt;&lt;/p&gt;</description></item></channel></rss>