docs: record the publication derivation, pagination and pure/impure seam

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Pierre Martin
2026-07-17 18:18:15 +02:00
co-authored by Claude Opus 4.8
parent 9c7099f224
commit 346ae78a9a
2 changed files with 42 additions and 2 deletions
+37
View File
@@ -181,3 +181,40 @@ sont le vrai risque, invisible sous `TZ=Europe/Paris`) ; `formulaire-mairie.js`
est fin, impur et **non testé unitairement** — aucun harnais DOM dans le repo, et est fin, impur et **non testé unitairement** — aucun harnais DOM dans le repo, et
happy-dom n'émulerait de toute façon pas Gravity Forms. C'est le test humain qui happy-dom n'émulerait de toute façon pas Gravity Forms. C'est le test humain qui
tranche. tranche.
## 2026-07-17 — [T2] Publication mairie : dérivée, paginée, seam pur/impur
Le statut *publié* est **dérivé** de l'agenda public de la mairie (pas de tag),
en retrouvant l'événement Nextcloud par **date locale de Cugnaux + titre
normalisé**. Il donne aussi le **lien direct** (lu dans la carte).
**Corrections factuelles vérifiées en phase plan :**
- **L'agenda est PAGINÉ** : `.../agenda/page/N/?f=1&…`. Un seul fetch « période »
ne suffit pas → on boucle jusqu'à une page vide (plafond de sécurité anti-boucle).
- **Le slug porte des suffixes WordPress** (« Atelier dessin » →
`/agenda/atelier-dessin-2/`) : on matche sur **date + titre**, jamais sur le
slug. Le lien est **lu** dans la carte, jamais reconstruit.
- `<time datetime="YYYY-MM-DD">` est une **date nue** (pas d'heure) → comparer à
la date locale de Cugnaux du `debut`, jamais à une conversion de fuseau.
Journée entière = date flottante → composantes locales (comme `presentation.js`).
**Seam extraction impure / matching pur** (même logique que
`formulaire-valeurs.js` vs `formulaire-mairie.js`) : `DOMParser` est **absent de
Bun**, donc `extraireCartes(html)` (`agenda-mairie.js`) est impur et **non testé
unitairement** (test humain sur l'agenda réel) ; le **matching** (`publication.js`)
et la boucle de pagination (via impls injectées) sont purs et **testés à fond** —
c'est le vrai risque produit.
**Biais PRÉCISION v1** : match STRICT (date identique + titre normalisé
identique). Titre proche mais non strictement identique le même jour → on
**n'affirme pas** « publié » (faux négatif bénin ; le formulaire modéré rattrape
un doublon éventuel). Dans le doute — agenda injoignable, HTTP ≠ 200, DOMParser
qui lève, structure HTML changée — la liste s'affiche **sans badge** (dégradation
gracieuse, jamais d'exception, aucun faux positif). Deux cartes de même clé
(même jour + même titre normalisé, rare) : la **dernière indexée** l'emporte.
**Périmètre v1 = badge « publié » + lien uniquement.** L'annotation est
**additive** : la liste est rendue immédiatement, l'agenda ne la bloque jamais.
Fetch de l'agenda **sans** `credentials` (public). Aucune modification de
`manifest.json` (`host_permissions` couvre déjà `ville-cugnaux.fr`).
+5 -2
View File
@@ -120,9 +120,12 @@ URL filtrée par mois :
### Structure HTML d'un résultat (confirmée) ### Structure HTML d'un résultat (confirmée)
Chaque événement publié = `<div class="card card-thumbnail card-event ...">` contenant : Chaque événement publié = `<article class="card card-thumbnail card-event ...">`
contenant (balise `<article>`, PAS `<div>` : vérifié sur l'agenda réel le
2026-07-17 — matcher sur la classe `.card-event`, agnostique de balise) :
- **Date** : `<time datetime="YYYY-MM-DD">` (ancre de match la plus fiable) - **Date** : `<time datetime="YYYY-MM-DD">` (ancre de match la plus fiable)
- **Lien direct** : `<a href="https://www.ville-cugnaux.fr/agenda/<slug>/">` — c'est le lien à afficher dans l'extension - **Lien direct** : `<a href="/agenda/<slug>/">` — parfois **relatif**, à
résoudre contre l'agenda avant affichage ; c'est le lien à afficher dans l'extension
- **Titre** : `.card-title > a` - **Titre** : `.card-title > a`
- **Thème** : classe `event_theme-<slug>` - **Thème** : classe `event_theme-<slug>`