Skip to content

Verser les quatre séances en attente, du 3 au 7 août - #3

Merged
blakro merged 6 commits into
mainfrom
claude/app-fluidity-performance-aaz8oc
Aug 9, 2026
Merged

Verser les quatre séances en attente, du 3 au 7 août#3
blakro merged 6 commits into
mainfrom
claude/app-fluidity-performance-aaz8oc

Conversation

@blakro

@blakro blakro commented Aug 7, 2026

Copy link
Copy Markdown
Owner

L'archive s'était arrêtée au 31 juillet pendant que les artefacts s'empilaient —
c'est ce retard qui obligeait à cliquer « Actualiser » pour voir le cours du jour.

Quatre séances, et non trois : celle du 7 août est arrivée pendant le
versement. 188 lignes, 47 sociétés cotant chacun des quatre jours.

Versé par versement.yml, pas par l'artefact

Le stockage d'artefacts est injoignable depuis cet environnement — le CONNECT
échoue au proxy, ce que cette action prévoit explicitement. Le runner a donc
réémis l'incrément dans son journal, compressé et empreinté, et l'empreinte a
été vérifiée avant écriture
: sha256 7223a8765dc5571e, 189 lignes. Le
versement se vérifie au lieu de se supposer.

Le garde-fou du workflow a servi une fois de plus : 38 lignes de 2015-2017 ont
été écartées
car antérieures à l'archive versée. Ce sont les séances fantômes
retirées le 29 juillet, que l'artefact du 28 porte encore ; les verser les aurait
ressuscitées sans que rien ne le dise.

Contrôles

Avant écriture : en-têtes identiques, aucune clé (date, ticker) déjà présente,
aucune ligne antérieure à la dernière séance, tri préservé. Le diff est un ajout
pur — 188 insertions, zéro suppression
.

Après écriture :

  • les 188 variations tiennent dans la limite réglementaire de ±7,5 %, deux
    exactement au plafond, aucune clôture nulle ;
  • brvm veille répond « L'archive avance » ;
  • brvm importer charge les 113 101 lignes sans erreur ;
  • 248 tests passent ;
  • l'app affiche « Séance : 7 août 2026 » sans qu'on ait à cliquer.

Ce qui n'est PAS versé, et pourquoi

Le référentiel accompagnait l'incrément dans le journal, mais sa ligne base64
est arrivée corrompue
— gzip rejette le flux, alors que l'incrément cinq fois
plus long est passé intact. Deux transcriptions indépendantes donnent le même
résultat : ce n'est pas une erreur de lecture de ma part.

data/referentiel.csv reste donc au 31 juillet pour derniere_vue. C'est une
trace de provenance, lue nulle part ailleurs que dans db.py — aucun calcul n'en
dépend.

La déduire des cours aurait été possible, les 47 sociétés cotant chaque jour,
mais cela aurait raté un renommage ou un reclassement sectoriel publié entre
le 31 juillet et le 7 août : précisément ce que fusionner_referentiel existe
pour signaler. Mieux vaut une date en retard qu'un reclassement effacé en
silence. Le prochain versement dont le journal se relit entier la corrigera.


Generated by Claude Code

claude added 6 commits August 7, 2026 21:41
`ingestion.yml` ne commite pas — un runner ne sait pas signer — et
l'archive s'était arrêtée au 31 juillet pendant que les artefacts
s'empilaient. C'est le retard qui obligeait à cliquer « Actualiser » pour
voir le cours du jour.

Quatre séances, et non trois : celle du 7 août est arrivée pendant le
versement. 188 lignes, 47 sociétés cotant chacun des quatre jours.

VERSÉ PAR `versement.yml`, PAS PAR L'ARTEFACT. Le stockage d'artefacts est
injoignable depuis cet environnement — le CONNECT échoue au proxy, ce que
cette action prévoit explicitement. Le runner a donc réémis l'incrément
dans son journal, compressé et empreinté, et l'empreinte a été vérifiée
avant écriture : sha256 7223a8765dc5571e, 189 lignes. Le versement se
vérifie au lieu de se supposer.

Le garde-fou du workflow a servi une fois de plus : 38 lignes de 2015-2017
ont été ÉCARTÉES car antérieures à l'archive versée. Ce sont les séances
fantômes retirées le 29 juillet, que l'artefact du 28 porte encore ; les
verser les aurait ressuscitées sans que rien ne le dise.

Contrôles avant écriture : en-têtes identiques, aucune clé (date, ticker)
déjà présente, aucune ligne antérieure à la dernière séance, tri préservé.
Le diff est un ajout pur — 188 insertions, zéro suppression.

Contrôles après : les 188 variations tiennent dans la limite réglementaire
de ±7,5 %, deux exactement au plafond, aucune clôture nulle. `brvm veille`
répond « L'archive avance ». 248 tests passent.

CE QUI N'EST PAS VERSÉ, ET POURQUOI. Le référentiel accompagnait
l'incrément dans le journal, mais sa ligne base64 est arrivée corrompue —
gzip rejette le flux, alors que l'incrément cinq fois plus long est passé
intact. Deux transcriptions indépendantes donnent le même résultat : ce
n'est pas une erreur de lecture. `data/referentiel.csv` reste donc au
31 juillet pour `derniere_vue`.

C'est une trace de provenance, lue nulle part ailleurs que dans `db.py` —
aucun calcul n'en dépend. La déduire des cours aurait été possible, les 47
sociétés cotant chaque jour, mais cela aurait raté un renommage ou un
reclassement sectoriel publié entre-temps : précisément ce que
`fusionner_referentiel` existe pour signaler. Mieux vaut une date en
retard qu'un reclassement effacé en silence. Le prochain versement dont le
journal se relit entier la corrigera.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mu7CkW6727S9ZyRbiYyRk9
L'archive n'avançait pas toute seule : `ingestion.yml` déposait un
artefact, et quelqu'un devait penser à le verser. Personne n'y a pensé
pendant cinq séances, et c'est ce retard qui obligeait à cliquer
« Actualiser » pour voir le cours du jour.

`versement.yml` tourne désormais chaque jour ouvré à 16 h 45 UTC, trois
quarts d'heure après la collecte, et écrit lui-même.

POURQUOI UNE CLÉ POUR UN ROBOT. Le projet refusait qu'un runner commite
parce qu'il ne sait pas signer, et qu'un historique à moitié vérifiable ne
vaut guère mieux qu'un historique nu. L'objection portait sur la
SIGNATURE, pas sur l'écriture : une clé propre au robot, déposée en secret
de dépôt, la lève. Chaque versement reste « Verified », et l'auteur —
« versement automatique » — dit qui a agi.

La contrepartie, dite franchement dans le README plutôt que passée sous
silence : une signature ne prouve plus qu'une personne tenait sa clé,
seulement que le commit vient de ce dépôt. La distinction reste lisible,
elle change de nature.

Une autre voie a été essayée avant celle-ci et écartée sur mesure : un
commit créé par l'API GitHub revient `unsigned`. Testé, pas supposé.

LES MÊMES CONTRÔLES QU'À LA MAIN, PARCE QUE PERSONNE NE REGARDERA.
En-têtes identiques, aucune ligne déjà présente, aucune séance antérieure
à l'archive, tri préservé, et la limite de ±7,5 % par séance — un cours
qui la franchit n'est pas une forte séance mais une lecture fausse ou une
réduction du nominal, et dans les deux cas un humain doit voir. Un seul
contrôle qui tombe annule le versement.

Dix cas vérifiés en dehors du runner, dont les subtils : +7,5 % pile est
accepté puisque c'est légal, deux séances consécutives sous la limite le
sont aussi puisque le contrôle est par séance et non cumulé, et une
clôture vide — valeur non cotée ce jour-là — ne déclenche rien.

LE JOURNAL DEVIENT LE FILET. Il ne s'écrit plus que si rien n'a été
poussé : secret absent, contrôle en échec, poussée refusée trois fois.
C'est exactement ce qui a servi à rattraper les séances du 3 au 7 août
quand le stockage d'artefacts était injoignable, et cette voie reste
ouverte.

Trois défauts corrigés avant d'être laissés en place : le référentiel
était DÉPLACÉ vers data/, ce qui privait le filet de la moitié de ce qu'il
doit émettre — il est copié ; le message de commit passait par la ligne de
commande, où un accent grave dans un nom de société aurait été interprété
par le shell — il passe par un fichier ; et la poussée n'était pas
retentée si `main` avait bougé pendant le téléchargement des artefacts.

L'installation de la clé demande quatre gestes, documentés dans le README.
Sans eux le workflow ne pousse rien et retombe sur le journal : la donnée
n'est jamais perdue, seulement l'automatisme.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mu7CkW6727S9ZyRbiYyRk9
DEUX CORRECTIONS, ET LA PREMIÈRE EST CELLE D'UNE ERREUR QUE JE VENAIS
D'INTRODUIRE.

Le versement automatique refusait d'écrire quand une variation franchit
±7,5 %. C'était en contradiction directe avec ce que le projet a mesuré et
écrit dans `qualite.limites` : sur l'archive, ce contrôle lève 356 alertes
dont l'immense majorité est légitime. Au détachement, le prix de référence
est ajusté du dividende et une baisse de 9 à 13 % y est régulière ; la
limite relie deux séances CONSÉCUTIVES et non deux blocs séparés d'un
mois ; une division du nominal la franchit par construction.

Pire : la saison des détachements va de mai à août. Le robot aurait donc
refusé de verser dès sa première semaine de service, sur des données
correctes — exactement le « contrôle qui crie sur des données correctes »
que le projet refuse, parce qu'on apprend à l'ignorer et que le jour où il
a raison personne ne l'écoute.

Les dépassements sont désormais NOTÉS dans le journal, jamais opposés.
`pics_isoles` serait la bonne signature, sans ambiguïté ; elle demande la
séance SUIVANTE et ne s'applique donc pas à une séance fraîche.

Le refus se limite à ce qui est certain : en-têtes, doublons, antériorité,
tri, et clôture nulle ou négative — celle-là ne connaît pas d'exception.
Un seuil de complétude a été envisagé puis écarté sur mesure : l'archive
contient des séances à une seule valeur, héritées du rapatriement, et le
seuil aurait crié dessus.

LE SECOND ANGLE MORT DE LA VEILLE. `brvm veille` regardait la dernière
séance et concluait « L'archive avance » — ce qui était vrai, et à côté de
la question. Le 6 août 2026, l'ingestion a été annulée à mi-course : le 5
et le 7 sont en archive, le 6 n'y est pas, et rien ne l'a dit. Un retard
finit par se combler ; un trou, jamais.

La commande liste maintenant les jours ouvrés sans séance entre la
première et la dernière : 22 sur onze ans et demi. Le message dit
franchement que les fériés de la BRVM en font partie — leur calendrier
n'est pas en base — plutôt que de taire un trou en croyant l'expliquer.

Bornée à l'intervalle couvert : au-delà de la dernière séance c'est du
retard, que l'autre moitié de la commande mesure déjà, et les compter deux
fois ferait dire à la veille qu'une archive à jour d'hier est trouée.

Douze cas de contrôle vérifiés hors du runner, dont les quatre qui
changent de verdict : détachement à −9 % et division du nominal à −50 %
sont désormais ACCEPTÉS, clôture nulle et négative refusées. Quatre tests
pour la détection de trous, dont les négatifs qui comptent le plus : un
week-end n'est pas un trou, du retard non plus.

252 tests passent.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mu7CkW6727S9ZyRbiYyRk9
Le versement ne retenait que les séances POSTÉRIEURES à l'archive. Ce
garde-fou empêche de ressusciter les 38 lignes fantômes retirées le
29 juillet — il a servi dès le premier passage — mais il refusait du même
geste toute reprise de trou : une séance manquée est antérieure par
définition. Le 6 août 2026 était donc irrattrapable par cette voie.

CE QUI SÉPARE LES DEUX CAS SE LIT DANS L'ARCHIVE ELLE-MÊME, et il a fallu
le vérifier avant de le croire. Une ligne retirée l'a été d'une date qui
existe toujours : le 09/02/2015 garde 22 lignes, le 25/12/2017 en garde
30, le 04/01/2016 en garde 23. Un trou, lui, est une date ENTIÈREMENT
absente — le 06/08/2026 en compte zéro.

La règle tient en une phrase : on verse ce qui est postérieur, et ce qui
comble une date dont l'archive ne sait rien ; jamais une ligne qu'elle a
écartée d'une date qu'elle connaît.

DEUX SOURCES D'ARTEFACTS. Le versement relit désormais aussi les
exécutions de `rapatriement.yml`, qui dépose le même `archive-<run_id>`.
C'est ce qui rend un trou rattrapable sans intervention : `brvm rapatrier`
relit la période, et le versement suivant la reprend.

Le référentiel, lui, ne se prend QUE de l'ingestion : le rapatriement lit
un historique valeur par valeur et ne rafraîchit pas la liste des cotées.
Retenir le sien ferait reculer `derniere_vue` pour tout le monde.

UNE GARANTIE CHANGE DE NATURE. « L'incrément s'ajoute en queue » cesse
d'être vraie dès qu'on insère au milieu. Ce qui doit rester vrai, et qui
est désormais vérifié : la fusion est triée, elle ne perd aucune ligne de
l'archive, et elle en compte exactement autant qu'avant plus l'incrément —
donc elle n'en invente ni n'en écrase.

Treize cas vérifiés hors du runner, dont les deux qui décident : une date
entièrement absente se comble, une ligne antérieure sur une date présente
reste refusée. Le harnais a été réécrit plutôt que rapiécé — un premier
remplacement en gros avait réécrit les fixtures elles-mêmes et fait rougir
huit cas pour rien.

252 tests passent.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mu7CkW6727S9ZyRbiYyRk9
`secrets` n'existe pas dans un `if` d'étape. GitHub ne rejette pas
l'étape : il refuse le FICHIER, et le workflow ne démarre jamais. Tel que
commité, le versement automatique n'aurait pas tourné une seule fois — le
défaut est apparu au premier lancement réel, pas à la relecture ni au
contrôle YAML, qui tous deux le trouvaient valide.

La présence de la clé se lit désormais dans l'`env` du job, où le contexte
est autorisé, et voyage ensuite comme une variable ordinaire. Le booléen y
arrive en chaîne : c'est « true » qu'on compare.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mu7CkW6727S9ZyRbiYyRk9
La séance manquait depuis que l'ingestion du 6 août a été annulée à
mi-course. 47 valeurs, insérées entre le 5 et le 7 — première écriture au
MILIEU de l'archive, et non en queue.

RÉCUPÉRÉE DE BOUT EN BOUT PAR LA CHAÎNE ELLE-MÊME, ce qui la teste autant
qu'elle la répare : `rapatriement.yml` a relu la séance chez la source et
déposé son artefact ; `versement.yml`, lancé depuis la branche, l'a
reconnue comme un trou — date entièrement absente — et l'a versée dans son
espace de travail ; faute de clé, il a sauté la poussée et émis
l'incrément dans le journal, exactement comme le filet doit le faire.
Empreinte vérifiée avant écriture : sha256 2153ca4fef8e5ab2, 48 lignes.

Les mêmes contrôles qu'à la main : en-têtes identiques, aucune ligne déjà
présente, aucune ligne antérieure sur une séance connue, clôtures
positives, fusion triée sans perte ni doublon. Les 47 variations tiennent
dans la limite du marché — de −6,42 % à +7,50 % — et `brvm veille` ne
compte plus que 21 trous au lieu de 22, tous antérieurs à 2026 et
vraisemblablement des fériés.

Le rapatriement renseigne `haut` et `bas`, que l'ingestion laisse vides :
l'API d'historique les publie, la page de cote non. Une séance rapatriée
est donc un peu plus riche que ses voisines, jamais plus pauvre.

252 tests passent.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mu7CkW6727S9ZyRbiYyRk9
@blakro
blakro merged commit 1f49162 into main Aug 9, 2026
2 checks passed
@blakro
blakro deleted the claude/app-fluidity-performance-aaz8oc branch August 10, 2026 10:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants