SPB Git

Repository Public

History of tests Clear filter
Page 1
  1. Tue, Oct 27, 20261 commit

    1. [ka2] fix connecteur summum: migration du portail — Building Stack (location.summumpm.com) → Eversa (rental.summumpm.com). Au sync de 15:36 le connecteur rapportait found=0 « ok » (dérive détectée, retraits suspendus) : location.summumpm.com redirige désormais TOUT en 302 vers app.buildingstack.com (le portail jumeau edifialocation.com, lui, répond encore — c'est bien Summum qui a migré, lien « rental.summumpm.com/listings/list » sur summumpm.com). Le nouveau portail est une app Eversa (React Router « turbo-stream »), exactement le gabarit de gestion_cem : réécriture sur le patron gestion_cem.py (dont on importe _decode/_num/_unit_type) — /fr/listings/list.data (45 cartes immeuble) puis /fr/listings/<slug>/details.data par immeuble (units[] listed=true, via cache BD detail, clé = prix/dispo/compteur de la carte ; la fiche LÈVE si `listing` absent pour ne jamais empoisonner le cache). external_id = slug-uuid de l'UNITÉ (granularité inchangée, mais ids nécessairement neufs : les ApartmentId Building Stack n'existent plus → 75 ajouts, les 40 anciens partent en miss_count). Nouveautés : secteur (quartier, 56/75), pi² bornés 80-20000 (le portail publie des area=0/1 bidons), images Supabase préfixées BASE. Volume : le nouveau portail publie plus d'inventaire → 75 unités vs ~40 (Montréal 69, Blainville 2, Granby 2, Saint-Calixte 1, Longueuil 1 ; 695-2 589 $, 100 % prix/images, GPS 70/75). robots.txt : Crawl-delay 10 → request_delay = 10 s (patron halfred). Garde-fous : erreur franche si payload sans `listings` ou si cartes présentes mais 0 parsée. sources.json : URLs migrées vers rental.summumpm.com, secteurs mis à jour. Fixture ré-enregistrée (46 requêtes, 75 annonces), pytest summum 2 passed. Testé : fetch() venv → 75 unités, run.py sync summum → found=75 ok (added=75, removed=0, missed=40, 2,4 s) vs médiane 40, pm2 restart lou-ka-sync, site :8095 → 200.
      Simon-Pierre Boucher 88 files +929 −26,418
  2. Mon, Oct 26, 20262 commits

    1. [ka2] fix connecteur logispro_mauricie: refonte du site — thème Elementor « adncommunication », migration sur l'API REST WP. Au sync de 12:18 le connecteur rapportait found=0 « ok » (dérive détectée, retraits suspendus) : logispro.ca a été entièrement refait — /appartements-a-louer/ (cartes div.apartments-item que l'ancien parseur lisait) redirige 301 vers /locations/, nouveau gabarit Elementor sans aucun des anciens sélecteurs. Réécriture complète sur l'API REST WordPress : les logements sont des posts CPT « location » (/wp-json/wp/v2/location, ACF exposé) — prix numérique + prix promo (le plus bas affiché, ex. « 1495 $ / mois (promo, prix régulier 1725 $) »), adresse géocodée + GPS (100 %), chambres/salles de bain/superficie/étage, galerie d'IDs médias résolus via /wp-json/wp/v2/media (requête groupée, avec cache BD detail invalidé par la date `modified` du post — et qui LÈVE sur hoquet HTTP pour ne jamais empoisonner le cache avec une galerie vide), taxonomies disponibilité/ville-secteur/dimension/caractéristiques/stationnement/proximité. external_id = slug (inchangé comme schéma : 10 des 12 anciennes annonces ont matché → updated=10, zéro churn inutile). Volume : le nouveau site publie TOUT l'inventaire à louer (dispo immédiate ET à venir) → ~69 unités vs ~12 avant la refonte (5 villes : Trois-Rivières 38, Bécancour 14, Shawinigan 11, Grandes-Piles 4, Nicolet 2). Garde-fous : échec franc si la requête page 1 échoue (pas de faux zéro) et si des posts existent mais 0 parsé (structure ACF changée). sources.json : listing_url migrée vers /locations/, secteurs mis à jour. Fixture enregistrée (75 requêtes, 69 annonces), pytest logispro_mauricie 2 passed. Testé : fetch() venv → 69 unités (775-1 745 $, 100 % prix/images/GPS, 31 promos), run.py sync logispro_mauricie → found=69 ok (added=59, updated=10, removed=0, 8,3 s) vs médiane 12, pm2 restart lou-ka-sync, site :8095 → 200.
      ···
      Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
      Simon-Pierre Boucher 77 files +1,573
    2. [ka2] fix connecteur immogex: refonte du site — GoDaddy Website Builder → site statique Netlify (www.immogex.com). Au sync de 11:55 le connecteur rapportait found=0 « ok » (zéro silencieux) : immogex.com a été entièrement refait (assets versionnés v=20261026h, déployé le jour même) — l'ancienne page /%C3%A0-louer redirige vers www.immogex.com/a-louer.html, nouveau gabarit SSR sans aucun bloc ABOUT_* (data-aid) que l'ancien parseur lisait. Réécriture : la liste /a-louer expose les logements en cartes <li class=annonce> (titre, adresse, prix, dispo, photo) pointant vers de vraies pages détail /logements/<slug> (nouveauté : galerie complète, immeuble en surtitre, <dl> de faits Disponibilité/Grandeur/Étage/Adresse, description, inclusions) — parsing liste + détail via self.detail() (cache BD, clé = hash titre|adresse|prix|dispo de la carte). external_id = slug de la page détail, PAR UNITÉ — l'ancien schéma nom+civique fusionnait les unités d'un même immeuble (« 4955-4955 » couvrait les logements 14 et 17 du 4955 Fugère) → les 2 anciens ids sont de vrais retraits remplacés par 3 ids granulaires. Garde-fous : ul.annonces introuvable = erreur franche (gabarit changé) ; cartes affichées mais 0 parsée = erreur franche ; ul présent et vide = vrai zéro. Bonus : amenities, étage et immeuble (details), galeries 5-7 photos (vs 1 avant). sources.json : URLs migrées vers www.immogex.com. Fixture ré-enregistrée (4 requêtes, 3 annonces), pytest immogex 2 passed. Testé : fetch() venv → 3 unités (3½, 955-1 355 $, 100 % prix/adresse/dispo/images/inclusions), run.py sync immogex → found=3 ok (added=3, removed=2, 2,8 s) vs médiane 1.0 et dernier bon sync à 2, pm2 restart lou-ka-sync, site :8095 → 200.
      Simon-Pierre Boucher 7 files +529 −595
  3. Sat, Oct 24, 20261 commit

    1. [ka2] fix connecteur solaris: libellé « Plan » → « Photos et plan » + IP du nœud tarpitée par Cloudflare. Au sync de 13:07 le garde-fou anti zéro silencieux levait « aucune unité parsée alors que data-count=8 » : le site a remanié les lignes d'unités — le bouton « Plan » (terminateur de ROW_RE) est devenu « Photos et plan » et un lien « Visiter » s'est ajouté → 0/8 lignes matchées (parsing cassé, pas un hoquet — le retry ×3 du fix 8eff094 ne pouvait rien). Fix 1 : ROW_RE accepte les deux formes ((?:Photos\s+et\s+plan|Plan)\b). Constat additionnel : l'accès direct depuis le nœud pend sans réponse (tarpit Cloudflare, racine incluse, curl/requests 000 après 25-60 s) alors que Scrapfly/Oxylabs passent — base.get() escaladait HORS session via _resilient (sync OK mais fixtures inenregistrables : record → requests=0, MissingFixture au rejeu). Fix 2 : sonde courte (12 s) en début de fetch ; au timeout, bascule de TOUTE la session sur proxy résidentiel Oxylabs CA collant (patron boreal 763a8ca / citiluxx) — le trafic reste dans la session, l'enregistrement des fixtures capture la page, ~30 s de tarpit économisées par sync ; au rejeu la sonde tombe en MissingFixture → rester direct (adapter de rejeu). Images plans/photos inchangées (34 plans + 4 photos -md vérifiés). Fixture ré-enregistrée (1 requête, 8 annonces), pytest solaris 2 passed. Testé : fetch() venv → 8 unités (3½/4½, 1 630–2 730 $, pi² et dates de libération complets), run.py sync solaris → found=8 ok (updated=4, removed=0, 82 s) = médiane 8.0, pm2 restart lou-ka-sync, site :8095 → 200.
      Simon-Pierre Boucher 2 files +371 −100
  4. Thu, Oct 22, 202612 commits

    1. [ka2] fix connecteur voltige: refonte Livya 2026-10-22 — client « society-dev-immo » SANS module inventaire : rendu navigateur + vue TABLEAU du DOM + mapping immeuble via les frames du plan interactif. Au sync de 21:50 le connecteur rapportait found=0 « ok » (alerte dérive, retraits suspendus) : la refonte Livya du jour a retiré l'inventaire JSON du flux RSC de la page plans (app.livya.com/fr/society-dev-immo/projects/voltige/plans/2aad7013) que l'ancien connecteur lisait — unités chargées QUE côté client via api.realvuu.com (robots.txt interdit, non utilisé), et comme trudel/le_fjord/quartier_sila/somex pas de repli LivyaConnector (unitSelectorSummaries: [] sur /fr/society-dev-immo). Fix : rendu Scrapfly render_js (patron trudel d1f0465, scroll des conteneurs internes) de la page plans unique — la vue TABLEAU du DOM rendu (43 lignes = compteur « 43 résultats », colonnes Nom/Étage/Chambres/SdB/Superficie/Prix/Statut mappées par en-têtes) sert de source de vérité ; la grille de cartes fournit la photo de chaque unité (43/43 avec image cloudfront). Nouveauté vs trudel (projet MULTI-immeubles : Hélia/Belvédère/Aria/Panora, pas de colonne Immeuble dans le tableau ni dans les cartes) : mapping unité→immeuble via les « frames » du plan interactif, toujours SSR dans le RSC de la même page — frame « Vue du bâtiment X » (linkType BUILDING) → polygones FLOOR (linkedFrameId → frame d'étage) → polygones UNIT (linkId = unitId) ; 601 unités mappées, recoupé 23/23 avec l'historique, couvre 43/43 affichées ; adresse/GPS/ville repris de l'objet immeuble du RSC (Aria 1900 Yvette-Brillon, Belvédère 2000 Sauvé O, Panora 2200 Sauvé O), repli adresse projet si immeuble non mappé. ⚠️ PERTE STRUCTURELLE : les loyers ne sont plus affichés nulle part dans la nouvelle UI (colonne Prix = « — » sur 43/43, panneau détail cliqué sans prix, malgré showUnitPriceWeb:true — showUnitPrice:false semble gouverner) ; l'ancien connecteur les lisait dans le JSON brut du RSC, désormais retiré → price=None (cellule Prix parsée au cas où ils reviendraient), annonces en quarantaine qualité (alerte dérive prix attendue au sync), mais inventaire exact et retraits fiables. external_id = UUID unitId Livya (data-unit-id) PRÉSERVÉ — 21/23 actifs recoupés à 0 divergence (titre/adresse/unit_type/immeuble identiques), les 2 autres (Panora 906, Belvédère 204) sont de VRAIS retraits (plus affichés). unit_type dérivé des chambres (— → Studio, 1 → 3½, 2 → 4½, 3 → 5½) : recoupé avec l'historique. Found passe de 23 à 43 : la vue affiche aussi les unités « Disponible - <date future> » (22 au relevé, dates FR converties en ISO) — légitimes, incluses comme thrace b454e45. Garde-fous (patron quartier_sila) : compteur « N résultats » absent = erreur franche ; lignes uniques < annoncées = erreur franche après 3 tentatives ; en-têtes Nom/Statut introuvables = erreur franche ; « 0 résultats » = vrai zéro. Bonus : bedrooms/bathrooms/étage désormais renseignés depuis le tableau. Découverte client/project/entity inchangée (data-* sur voltigemtl.ca/plans/ + replis constants revérifiés). Fixture enregistrée (2 requêtes, 43 annonces), pytest voltige 2 passed. Testé : fetch() venv → 43 unités (Aria 13/Belvédère 16/Panora 14, 100 % GPS/adresse/superficie/images, 42/43 chambres), run.py sync voltige → found=43 ok (added=22, updated=21, removed=0, 25,0 s ; alerte dérive prix attendue), pm2 restart lou-ka-sync, site :8095 → 200.
      Simon-Pierre Boucher 4 files +2,340
    2. [ka2] fix connecteur trudel: refonte Livya 2026-10-22 — client « trudel » SANS module inventaire : rendu navigateur + parse de la vue TABLEAU du DOM. Au sync de 21:46 le connecteur rapportait found=0 « ok » (alerte dérive, retraits suspendus) : la refonte Livya du jour a retiré l'inventaire JSON du flux RSC de la page projet (app.livya.com/fr/trudel/projects/fdl) que l'ancien connecteur lisait — unités chargées QUE côté client via api.realvuu.com (robots.txt interdit, non utilisé), et comme le_fjord/louis14/quartier_sila/somex pas de repli LivyaConnector (unitSelectorSummaries: [] sur /fr/trudel, portefeuille annoncé 990 unités résidentielles). Fix : rendu Scrapfly render_js (patron somex_saintnicolas cd20073, scroll des conteneurs internes) de la page plans unique /fr/trudel/projects/fdl/plans — la vue TABLEAU du DOM rendu (43 lignes = compteur « 43 résultats », colonnes Nom/Étage/Chambres/SdB/Superficie/Prix/Statut mappées par en-têtes) sert de source de vérité ; la grille de cartes fournit la photo de chaque unité (43/43 avec image cloudfront). Malgré showUnitPriceWeb:false dans la config, les loyers SONT affichés (43/43 lignes avec prix — contrairement à damco). external_id = UUID unitId Livya (data-unit-id) PRÉSERVÉ — zéro churn : 30/30 actifs recoupés. unit_type dérivé des chambres (2 → 4½) : recoupé 30/30 avec l'historique ; adresse/GPS/code postal repris de l'immeuble « 21 mars » du RSC (toujours SSR, entrées « plan d'ensemble » écartées) — 550 Boulevard Wilfrid-Hamel, Québec G1M 2S6, GPS 46.8209/-71.2522. Titre/secteur (Vanier Fleur de Lys)/commodités inchangés. Statut « Réservé » exclu (13 au relevé) : 30 Disponible = exactement le dernier found ok. Garde-fous (patron quartier_sila) : compteur « N résultats » absent = erreur franche ; lignes uniques du tableau < annoncées = erreur franche après 3 tentatives ; en-têtes Nom/Statut introuvables = erreur franche ; « 0 résultats » = vrai zéro. Dates de libération françaises converties en ISO (aucune actuellement). Bonus : bedrooms/bathrooms désormais renseignés depuis le tableau. Fixture ré-enregistrée (1 requête, 30 annonces), pytest trudel 2 passed. Testé : fetch() venv → 30 unités (prix 2 080–2 590 $, 100 % prix/GPS/adresse/images/chambres), run.py sync trudel → found=30 ok (updated=30, added=0, removed=0, 22,7 s), pm2 restart lou-ka-sync, site :8095 → 200.
      Simon-Pierre Boucher 4 files +879 −70
    3. [ka2] fix connecteur thrace: refonte Livya 2026-10-22 — SSR inventory TRONQUÉ : rendu navigateur (ensemble affiché) + enrichissement JSON RSC. Au sync de 20:46 le connecteur levait une erreur franche (« aucun objet unitId dans le flux RSC du projet radisson » — garde-fou correct, rien dépublié) : la refonte Livya du jour a retiré l'inventaire JSON du flux RSC des pages plans des 3 projets (thrace/radisson/carree-radisson) que l'ancien connecteur lisait. Contrairement à damco/hulix/fjord, le client « thrace » A un module inventaire (unitSelectorSummaries : Résidentiel fb25970c + Commercial) — mais le patron LivyaConnector pur (atimco/floria 454f8c4) est INSUFFISANT ici : le flux RSC de /fr/thrace/inventory/<sel> est TRONQUÉ (464 unités rendues sur 564 annoncées par totalUnitsBySegments — p. ex. tout « Le Bellefeuille » absent), déterministe d'une requête à l'autre, aucun paramètre de pagination honoré, et les pages inventory scopées projet rendent 0 unité. Fix hybride : (1) rendu Scrapfly render_js de la page inventory (scroll des conteneurs internes ×16 — 8 itérations ne chargeaient que 100/109) → le compteur « N résultats » + les data-unit-id du DOM définissent l'ENSEMBLE des unités affichées (109 au relevé = résidentielles AVAILABLE ∪ NOT_AVAILABLE avec date de libération future — règle recoupée 109/109 exactement) ; (2) flux RSC direct de la même page → objet JSON complet par unité (statut, loyer, pièces, inclusions, adresse civique, GPS, photos) — couvre 109/109 affichées aujourd'hui ; (3) si une unité affichée sortait du SSR tronqué : repli DOM complet (carte : nom/prix/adresse/photos ; vue tableau mappée par en-têtes : étage/chambres/sdb/pi² ; GPS via l'objet immeuble du RSC apparié par adresse civique). Unités en vente (rental:false, 11 affichées sans loyer) et locaux commerciaux exclus comme avant. external_id = UUID unitId Livya PRÉSERVÉ — 76/137 actifs réutilisés tels quels, 0 divergence de unit_type vs l'historique (75/75 recoupés) ; les 61 retraits sont RÉELS (unités plus affichées par le site — le portefeuille affiché est passé de 137 à 109 avec la refonte, dont 11 en vente et hors périmètre). Volume 98 = 71 % de la médiane 137 (nouveau normal attendu). Garde-fous (patron quartier_sila) : compteur « N résultats » absent = erreur franche ; data-unit-id uniques < annoncés = erreur franche après 3 tentatives ; « 0 résultats » = vrai zéro. Découverte client/sélecteur inchangée (data-client + livya-module-container-inventory data-entity sur /fr/residential, vérifiée vivante) + replis constants ; sitemap des projets plus nécessaire. Bonus : bedrooms/bathrooms désormais renseignés (champs Listing), dates FR du DOM converties en ISO. Fixture ré-enregistrée (4 requêtes, 98 annonces), pytest thrace 2 passed. Testé : fetch() venv → 98 unités (94 prix 850–2 550 $, 98 GPS/adresse/images, 28 libérations futures ISO), run.py sync thrace → found=98 ok (added=22, updated=76, removed=0, 37,6 s), pm2 restart lou-ka-sync, site :8095 → 200.
      Simon-Pierre Boucher 9 files +1,550 −18,527
    4. [ka2] fix connecteur somex_saintnicolas: refonte Livya 2026-10-22 — client « hulix » SANS module inventaire : rendu navigateur + parse de la vue TABLEAU du DOM. Au sync de 20:43 le connecteur rapportait found=0 « ok » (alerte dérive, retraits suspendus) : la refonte Livya du jour a retiré l'inventaire JSON du flux RSC de la page plans (app.livya.com/fr/hulix/projects/somex/plans/…?noLayout=1) que l'ancien connecteur lisait — unités chargées QUE côté client via api.realvuu.com (robots.txt interdit, non utilisé), et comme le_fjord/louis14/quartier_sila pas de repli LivyaConnector (unitSelectorSummaries: [] sur /fr/hulix). Fix : rendu Scrapfly render_js (patron quartier_sila adf5c6a, scroll des conteneurs internes) de la page plans unique — la vue TABLEAU du DOM rendu (146 lignes = compteur « 146 résultats », colonnes Nom/Étage/Chambres/SdB/Superficie/Prix/Statut mappées par en-têtes) sert de source de vérité ; la grille de cartes (lazy-loadée, 100/146) ne fournit que les photos de plans, complétées par la galerie de la page WP /appartements/ (photos d'unités types). Contrairement à damco, hulix PUBLIE les loyers (showUnitPriceWeb: true, colonne Prix remplie) — prix recoupés 145/145 identiques à l'historique. external_id = UUID unitId Livya (data-unit-id) PRÉSERVÉ — zéro churn : 145/145 actifs recoupés. unit_type dérivé des chambres (1 → 3½, 2 → 4½) : recoupé 145/145 avec l'historique ; adresse/GPS/code postal repris de l'immeuble « Somex » du RSC (toujours SSR) — 710 Route des Rivières, Saint-Nicolas, G7A 2T6. Titre/secteur/ville (Lévis via infer_city) et commodités (liste de la page Appartements) inchangés ; téléphone toujours lu du lien tel: de la page WP /plans/ ; paramètres client/project/entity découverts dynamiquement sur /plans/ + replis constants. Garde-fous (patron quartier_sila) : compteur « N résultats » absent = erreur franche ; lignes uniques du tableau < annoncées = erreur franche après 3 tentatives ; en-têtes Nom/Statut introuvables = erreur franche ; « 0 résultats » = vrai zéro. Dates de libération françaises converties en ISO (aucune actuellement : 145 Disponible + 1 Réservé exclu). Bonus : bedrooms/bathrooms désormais renseignés depuis le tableau. Fixture ré-enregistrée (3 requêtes, 145 annonces), pytest somex_saintnicolas 2 passed. Testé : fetch() venv → 145 unités (1 775–2 850 $, 100 % prix/pi²/GPS/adresse/images/chambres), run.py sync somex_saintnicolas → found=145 ok (updated=145, added=0, removed=0, 26,9 s), pm2 restart lou-ka-sync, site :8095 → 200.
      Simon-Pierre Boucher 6 files +1,993 −227
    5. [ka2] fix connecteur quartier_sila: refonte Livya 2026-10-22 — client « damco » SANS module inventaire : rendu navigateur + parse de la vue TABLEAU du DOM. Au sync de 17:06 le connecteur rapportait found=0 « ok » (alerte dérive, retraits suspendus) : la refonte Livya du jour a retiré l'inventaire JSON du flux RSC de la page plans (app.livya.com/fr/damco/projects/sila/plans/…?noLayout=1) que l'ancien connecteur lisait — unités chargées QUE côté client via api.realvuu.com (robots.txt interdit, non utilisé), et comme louis14 (3eda9f8, même client damco) pas de repli LivyaConnector (unitSelectorSummaries: [] sur /fr/damco). Fix : rendu Scrapfly render_js (patron le_fjord/louis14, scroll des conteneurs internes) des pages plans des DEUX sélecteurs du projet — /condos-locatifs-sila/ (entity 629800af, phases 1-3, 50 unités) et /phase4/ (entity ec7c9199, toutes phases, 184 unités), découverts dynamiquement sur les pages WP + replis constants. Nouveauté vs le_fjord/louis14 : le DOM rendu contient une vue TABLEAU complète (Nom/Étage/Chambres/SdB/Superficie/Prix/Statut, mapping par en-têtes) qui sert de source de vérité — la grille de cartes (lazy-loadée, 112/184 après scroll) ne fournit que les photos de plans ; repli photos = galerie WP par immeuble comme avant. external_id = UUID unitId Livya (data-unit-id) PRÉSERVÉ — zéro churn : 183/183 actives recoupées + 1 nouvelle. unit_type dérivé des chambres (— → Studio, 1 → 3½, 2 → 4½, 3 → 5½) : recoupé 183/183 avec l'historique ; adresse/GPS repris des immeubles « Phase N » du RSC (toujours SSR), mappés par le préfixe « SILA N » des noms d'unités — adresses 183/183 identiques. Titres nettoyés (« unité 703 » au lieu de « unité SILA 2 -703 »). Commodités/galerie/téléphone/bannières de phases toujours lus de la page WP. ⚠️ PERTE STRUCTURELLE : les loyers ne sont plus collectables — damco masque les prix sur le web (showUnitPriceWeb: false, colonne Prix = « — », vérifié aussi sur les pages /unites/ WP : aucun $) ; l'ancien connecteur les lisait dans le JSON brut du RSC, désormais retiré → price=None (cellule Prix parsée au cas où ils reviendraient), annonces en quarantaine qualité (porte dure « sans prix », politique globale intouchée) mais inventaire exact et retraits fiables. Garde-fous : compteur « N résultats » absent = erreur franche ; lignes uniques du tableau < annoncées = erreur franche après 3 tentatives ; en-têtes Nom/Statut introuvables = erreur franche ; « 0 résultats » = vrai zéro. Dates de libération françaises (« 1 décembre 2026 ») converties en ISO. Fixture ré-enregistrée (4 requêtes, 184 annonces), pytest quartier_sila 2 passed. Testé : fetch() venv → 184 unités (P1:11/P2:5/P3:34/P4:134, 100 % GPS/adresse/superficie/images/commodités), run.py sync quartier_sila → found=184 ok (added=1, updated=183, removed=0, 55,5 s ; alerte dérive prix attendue), pm2 restart lou-ka-sync, site :8095 → 200.
      Simon-Pierre Boucher 7 files +3,130 −1,291
    6. Revert "[ka2] fix connecteur mellem: refonte Livya 2026-10-22 — migration sur la base commune _livya (pages inventory). Au sync de 16:53 le connecteur rapportait found=0 « ok » (alerte dérive, retraits suspendus) : la refonte Livya du jour a retiré l'inventaire JSON du flux RSC des pages plans (app.livya.com/fr/maitre-carre/projects/…/plans/…?noLayout=1) que l'ancien connecteur lisait depuis les pages /projets/<slug> de mellem.ca — les unités sont chargées côté client via api.realvuu.com (robots.txt interdit, non utilisé). Fix : mellem.py réécrit en sous-classe LivyaConnector (patron atimco/floria 454f8c4) — client « maitre-carre », 1 sélecteur d'inventaire résidentiel « Maitre-Carré » découvert via unitSelectorSummaries + repli default_inventory. ⚠️ Particularité : cet inventaire couvre TOUT le portefeuille Maître Carré (1460 unités, 9 immeubles) dont Evol (déjà couvert par le connecteur evol) et Noria 1-4 (pas une marque Mellem) → périmètre restreint aux immeubles des projets publiés sur mellem.ca, découverts via le sitemap comme avant (repli fallback_slugs) ; correspondance immeuble Livya → projet par préfixe de slug (grace-dart-b/c → grace-dart). external_id historique {slug}-{numéro} (ex. grace-dart-121) PRÉSERVÉ en surchargeant _listing — zéro churn : 63/65 actifs recoupés (les 2 autres ne sont plus disponibles, vrais retraits). Complétude 100 % (prix 1 557–3 658 $, GPS, adresse, superficie, 1 photo/unité). Fixture ré-enregistrée (3 requêtes, 63 annonces), pytest mellem 2 passed. Testé : fetch() venv → 63 unités (43 Montréal, 20 Gatineau), run.py sync mellem → found=63 ok (updated=63, added=0, removed=1, 6,5 s), pm2 restart lou-ka-sync, site :8095 → 200."
      ···
      This reverts commit d2a6cb06ce127e6289c50530c29081500a08ebfd.
      Simon-Pierre Boucher 11 files +1,286 −287
    7. [ka2] fix connecteur mellem: refonte Livya 2026-10-22 — migration sur la base commune _livya (pages inventory). Au sync de 16:53 le connecteur rapportait found=0 « ok » (alerte dérive, retraits suspendus) : la refonte Livya du jour a retiré l'inventaire JSON du flux RSC des pages plans (app.livya.com/fr/maitre-carre/projects/…/plans/…?noLayout=1) que l'ancien connecteur lisait depuis les pages /projets/<slug> de mellem.ca — les unités sont chargées côté client via api.realvuu.com (robots.txt interdit, non utilisé). Fix : mellem.py réécrit en sous-classe LivyaConnector (patron atimco/floria 454f8c4) — client « maitre-carre », 1 sélecteur d'inventaire résidentiel « Maitre-Carré » découvert via unitSelectorSummaries + repli default_inventory. ⚠️ Particularité : cet inventaire couvre TOUT le portefeuille Maître Carré (1460 unités, 9 immeubles) dont Evol (déjà couvert par le connecteur evol) et Noria 1-4 (pas une marque Mellem) → périmètre restreint aux immeubles des projets publiés sur mellem.ca, découverts via le sitemap comme avant (repli fallback_slugs) ; correspondance immeuble Livya → projet par préfixe de slug (grace-dart-b/c → grace-dart). external_id historique {slug}-{numéro} (ex. grace-dart-121) PRÉSERVÉ en surchargeant _listing — zéro churn : 63/65 actifs recoupés (les 2 autres ne sont plus disponibles, vrais retraits). Complétude 100 % (prix 1 557–3 658 $, GPS, adresse, superficie, 1 photo/unité). Fixture ré-enregistrée (3 requêtes, 63 annonces), pytest mellem 2 passed. Testé : fetch() venv → 63 unités (43 Montréal, 20 Gatineau), run.py sync mellem → found=63 ok (updated=63, added=0, removed=1, 6,5 s), pm2 restart lou-ka-sync, site :8095 → 200.
      Simon-Pierre Boucher 11 files +287 −1,286
    8. [ka2] fix connecteur louis14: refonte Livya 2026-10-22 — client « damco » SANS module inventaire : rendu navigateur multi-immeubles + parse des cartes DOM. Depuis 16:49 le connecteur levait une erreur franche (« aucune unité dans le flux RSC » — garde-fou correct, rien dépublié) : la refonte Livya du jour a retiré l'inventaire du RSC des pages plans, et comme le_fjord (7267ac1) le client damco n'offre PAS le repli LivyaConnector (unitSelectorSummaries: [] sur /fr/damco, aucune page détail d'unité SSR) — unités chargées QUE côté client via api.realvuu.com (robots.txt interdit, non utilisé). Particularité vs le_fjord : la grille plans n'affiche qu'UN immeuble à la fois (boutons data-nav-id « QUARTIER A-B » / « QUARTIER C-D », E-F à venir) → un rendu Scrapfly par immeuble, js_scenario qui clique le bouton voulu (vérif aria-current après clic = erreur franche si la bascule échoue) puis scrolle les conteneurs internes ; URL distincte par immeuble (&lkb=<navId>) pour la clé de rejeu des fixtures. external_id = numéro d'unité (« 816-C ») inchangé — zéro churn (updated=15). Adresse/GPS/code postal repris des métadonnées d'immeubles, toujours SSR dans le RSC. ⚠️ PERTE STRUCTURELLE : les loyers ne sont plus collectables — damco masque les prix sur le web (showUnitPriceWeb: false dans la config du sélecteur) ; l'ancien connecteur les lisait dans le JSON brut du RSC, désormais retiré ; vérifié jusque dans le panneau détail rendu (aucun « $ », « Loyer » ni « /mois » dans le DOM) → price=None, annonces en quarantaine qualité (porte dure « sans prix », politique globale intouchée) mais inventaire exact et retraits fiables. Garde-fous : compteur « N résultats » absent = erreur franche ; cartes uniques < annoncées = erreur franche après 3 tentatives ; « 0 résultats » = vrai zéro. Bonus : dates de libération françaises (« 1 mars 2027 ») converties en ISO. Fixture ré-enregistrée (3 requêtes, 18 annonces), pytest louis14 2 passed. Testé : fetch() venv → 17-18 unités (7 A-B + 10-11 C-D, 100 % superficie/type/img/GPS), run.py sync louis14 → found=18 ok (added=3, updated=15, removed=0, 48,8 s ; alerte dérive prix attendue), pm2 restart lou-ka-sync, site :8095 → 200.
      Simon-Pierre Boucher 6 files +1,998 −335
    9. [ka2] fix connecteur le_fjord: refonte Livya 2026-10-22 — client « fjord » SANS module inventaire : rendu navigateur + parse des cartes DOM. Depuis 16:33 le connecteur levait une erreur franche (flux RSC sans tableau "units" — garde-fou correct, rien dépublié) : la refonte Livya du jour a retiré l'inventaire du RSC des pages plans, et contrairement à atimco/floria le client fjord n'offre PAS le repli LivyaConnector (unitSelectorSummaries: [] sur /fr/fjord, /fr/fjord/inventory/<sel> → 404, pages /units et /inventory projet-scopées 200 mais sans unités) — les unités ne sont chargées QUE côté client via api.realvuu.com (robots.txt interdit, non utilisé). Fix : fetch() rend la page plans via Scrapfly render_js avec un js_scenario qui scrolle les conteneurs INTERNES (grille lazy-loadée : 50/63 cartes sans scroll, auto_scroll inopérant car le scroll est dans un div overflow), puis parse les cartes du DOM — data-unit-id = UUID unitId Livya, recoupement 63/63 avec les external_id actifs en base (zéro churn). Occurrences dupliquées des cartes fusionnées champ par champ (le prix manque dans ~1 occurrence sur 2 selon le rendu). Garde-fous : compteur « N résultats » absent = erreur franche ; cartes uniques < annoncées = erreur franche après 3 tentatives ; « 0 résultats » = vrai zéro accepté. get_rendered surchargé (même signature) pour rester compatible record/replay des fixtures. Bonus : images des unités désormais collectées (63/63). Fixture enregistrée (1 requête, 63 annonces), pytest le_fjord 2 passed. Testé : fetch() venv → 63 unités (1 027–3 045 $, 63 prix, 63 pi²), run.py sync le_fjord → found=63 ok (updated=63, added=0, removed=0, 26 s), pm2 restart lou-ka-sync, site :8095 → 200.
      Simon-Pierre Boucher 3 files +1,705
    10. [ka2] fix connecteur floria: refonte Livya 2026-10-22 — migration sur la base commune _livya (pages inventory). Depuis ~15h25 le connecteur rapportait found=0 « ok » (alerte dérive, retraits suspendus) : la refonte Livya du jour (pattern atimco, snapshot acdce7f) a retiré l'inventaire JSON du flux RSC des modules « plans » embarqués dans les pages gestionfloria.ca/immeuble/<slug>/ — la page 200 ne contient plus que frames/polygones + traductions i18n, les unités sont chargées côté client (api.realvuu.com, robots.txt interdit). Même casse en cours sur les frères Livya (le_fjord 16:33 et louis14 16:49 tombés à 0 après ma prise de mission — hors périmètre, signalés). Fix : floria.py réécrit en sous-classe LivyaConnector (patron atimco) — client « gestion-floria », découverte des 3 sélecteurs d'inventaire (Portefeuille Sherbrooke / MAGOG / résidentiel) via unitSelectorSummaries + repli default_inventory, pages /fr/gestion-floria/inventory/<sel> rendues serveur. external_id inchangé (UUID unitId Livya) : les 13 annonces actives réutilisées telles quelles (updated=13). Bonus de la migration : loyers désormais publiés (null_price_rate 1.0 → prix sur toutes les unités) et portefeuille complet (Le François-Hertel & cie absents de /secteurs/). Fixture ré-enregistrée (4 requêtes, 21 annonces), pytest floria 2 passed. Testé : fetch() venv → 21 unités (Magog/Sherbrooke, 1 925–2 150 $), run.py sync floria → found=21 ok (added=8, updated=13, 3,9 s), pm2 restart lou-ka-sync, site :8095 → 200.
      Simon-Pierre Boucher 27 files +148 −8,113
    11. Simon-Pierre Boucher 4 files +4,812
  5. Tue, Oct 20, 20261 commit

    1. [ka2] fix connecteur gestion_isr: la table listings passée derrière RLS — lecture dynamique de LISTINGS_URL (vue listings_public) + retry anti-timeout. Depuis le run du 2026-10-20 15:03 le connecteur rapportait found=0 « ok » (alerte dérive, retraits suspendus) : le portail location.gestion-isr.com a migré ses annonces publiques vers la VUE expurgée /rest/v1/listings_public (migration 145-listings-vue-publique.sql visible dans le JS inline) et l'ancienne table /rest/v1/listings renvoie désormais 200 [] à la clé anon (RLS) — zéro silencieux classique. Fix : le connecteur lit maintenant le chemin REST dans la const LISTINGS_URL du HTML du portail (même philosophie que l'URL/clé Supabase déjà lues dynamiquement — se répare seul au prochain renommage), erreur FRANCHE si la const disparaît. Piège rencontré en route : la vue est coûteuse côté Postgres — « canceling statement due to statement timeout » (57014 → 500) sur 2 runs sur 4 → retry ×3 (pause 4 s/8 s, pattern solaris 8eff094), même URL (timeout serveur, pas un cache). Schéma de la vue identique à l'ancienne table pour tous les champs consommés (pk, id_app, titre, id, loyer, adresse_geo, units, photos…) : _parse_row inchangé, external_id stables. Fixture ré-enregistrée (2 requêtes, 20 annonces), pytest gestion_isr 2 passed. Testé : fetch() venv → 20 annonces (médiane 20 ; 21 lignes dans la vue, 1 exclue par les filtres), run.py sync gestion_isr → found=20 ok (updated=1, 2,5 s), pm2 restart lou-ka-sync, site :8095 → 200.
      Simon-Pierre Boucher 5 files +1,730 −339
  6. Thu, Oct 15, 20263 commits

    1. [ka2] fix connecteur beaulieu_groupe: nouveau gabarit d'unités — en-tête « appartement N » + page /local/ avec loyer publié. Depuis 2026-10-15 ~13h33 le connecteur rapportait found=0 « ok » (missed=1) alors que l'archive affichait « Locaux disponibles : 1 » (304 rue Laval-Nord) : le h5 des cartes d'unités est passé de « 418 Alcide-C.-Horth, app #206 | 4 1/2 » à « 304 rue Laval-Nord, appartement 2 » — _UNIT_RE exigeait « app #N » et la carte était silencieusement ignorée. Fix : regex élargi (app #N / app. N / appartement N, rétrocompatible avec l'ancien format), et la carte pointe désormais vers une page d'unité /local/<slug>/ que le connecteur visite pour récupérer le LOYER maintenant publié (1 295 $/mois — avant le site ne publiait aucun prix, price=None historique), le type (4½ via <title>), la superficie si présente, la description de l'unité et les vraies photos (img /uploads/ hors logos, scope [data-elementor-type=single-page]). Piège regex corrigé en route : « appartement 2 1295$ par mois » faisait capturer « 2 1295 » → groupes de milliers stricts (\d{1,3}(?:[esp]\d{3})*|\d+). Garde-fous anti zéro silencieux (pattern sotramont bcdf125, qui aurait attrapé la casse du jour) : erreur FRANCHE si aucune div.card-batiment (gabarit remanié) ou si l'archive annonce N>0 unités disponibles mais 0 parsée ; tout COMPLET = vrai zéro accepté. external_id inchangé ({slug}--app-{n°}) ; url de l'annonce = page d'unité quand elle existe, sinon fiche immeuble. Fixture ré-enregistrée (3 requêtes, 1 annonce), pytest beaulieu_groupe 2 passed. Testé : fetch() venv → 1 unité (304-rue-laval-nord--app-2, 4½, 1 295 $, 4 photos), run.py sync beaulieu_groupe → found=1 ok (added=1, 1,9 s), pm2 restart lou-ka-sync, site :8095 → 200.
      Simon-Pierre Boucher 5 files +1,103 −316
    2. [ka2] fix connecteur nomade: refonte du site — le PDF mensuel remplacé par une mini-app liste.nomadegestion.com, granularité unité. Le run du 2026-10-15 14:48 levait « lien PDF Liste de prix introuvable » : le bouton de la home Squarespace pointe désormais vers /liste-location, page qui embarque en iframe https://liste.nomadegestion.com/ — mini-app rendue serveur (JSON-LD ItemList + sections HTML sémantiques), plus aucun /s/*.pdf nulle part. Réécriture du parseur : lecture des <section class="building-section"> (h2 nom, .owner-addr, .owner-link URL immeuble, data-photos UUIDs → /photo/<uuid>/image — plus besoin du cache détail ni de _fetch_images) et des <article class="unit"> (data-type, data-rent en cents, data-avail "now"/ISO, .unit-meta étage, badges aria-label = inclusions). Plus de pdfplumber dans nomade (la dep reste pour sept_elements/consolata — commentaire requirements ajusté). Schéma d'external_id inchangé ({slug}-{typo.5}-{étage|x} + compteur) : 3 ids réutilisés tels quels (astral-3.5-5, nordet1-5.5-4, nordet2-5.5-1) ; granularité PDF (étages agrégés « 1-4 ») → unité désormais. Téléphone concierge derrière POST /visit-phone avec jeton anti-bot + pot de miel : non collecté (politesse). Garde-fous anti zéro silencieux (pattern sotramont bcdf125) : erreur FRANCHE si aucune building-section ni section no-availability (gabarit remanié) ou si 0 unité parsée alors que les data-total annoncent des logements ; sections vides explicites = vrai zéro accepté. Fixture enregistrée pour la première fois (1 requête, 16 annonces), pytest nomade 2 passed. Testé : fetch() venv → 16 unités (7 immeubles : Nordet 1-2, Melozio, Astral, Bélanger, Griffon, Marie-Chapelier ; 1 275–2 025 $, dates ISO, 3-10 photos), run.py sync nomade → found=16 ok (added=13, updated=3, 0,1 s), pm2 restart lou-ka-sync, site :8095 → 200.
      Simon-Pierre Boucher 3 files +339
    3. [ka2] fix connecteur solaris: refonte du site — Wix /plans remplacé par un site custom, granularité unité. Le run du 2026-10-15 11:54 rapportait found=0 « ok » (missed=3) : l'ancien site Wix (www.solarisboisbriand.com/plans, cartes typologie « n ½ … à partir de NNNN$/mois ») redirige désormais vers solarisboisbriand.com/appartements/ — nouveau site rendu serveur (Tailwind, Cloudflare) qui liste les UNITÉS réellement libres (section data-live="units", <li data-unit>, « 6 unités libres sur 133 »). Réécriture du parseur : lecture des <li data-unit> (n°, typologie, chambres, pi², prix exact, date de libération — plus riche que l'ancien « à partir de »), external_id par unité (solaris-702…), images = plans/webp dont le nom contient le n° d'unité + photos -md du projet. Piège réel rencontré : le serveur n'annonce AUCUN charset → requests décodait en latin-1 (« 4½ ») et le regex ne matchait rien — décodage UTF-8 forcé sur resp.content. Garde-fous anti zéro silencieux (pattern sotramont bcdf125) : erreur FRANCHE si la section data-live="units" disparaît (gabarit remanié) ou si 0 unité parsée alors que data-count>0 ; data-count=0 explicite = vrai zéro accepté. Fixture enregistrée pour la première fois (1 requête, 6 annonces), pytest solaris 2 passed. Testé : fetch() venv → 6 unités (3½ 1 870–1 888 $, 4½ 2 110–2 730 $, pi² et dates ISO complets), run.py sync solaris → found=6 ok (added=6, removed=3 : les fiches typologie 3.5/4.5/5.5 désactivées, 0,1 s), pm2 restart lou-ka-sync, site :8095 → 200.
      Simon-Pierre Boucher 3 files +877
  7. Sun, Oct 11, 20261 commit

    1. Simon-Pierre Boucher 93 files +21,182
  8. Wed, Oct 7, 20261 commit

    1. [ka2] fix connecteur res_soleil: refonte du site — grille de prix HTML remplace l'image OCR « Notre offre ». Les syncs du 2026-10-06 17:18 au 2026-10-07 rapportaient found=0 (dérive signalée, puis les 54 annonces retirées le 07 07:36) et le dernier passage échouait en DNS transitoire (vague systémique connue du nœud). Vérifié live : l'API wp-json closest_residence_locator est intacte (15 manoirs, 200), mais les fiches manoir ne publient PLUS l'image uploads/…/Notre-offre_*.jpg que le connecteur lisait par OCR tesseract — elles embarquent désormais une grille de prix HTML sémantique (section .lrs-<manoir>-pricing : .pricing-row avec .unit-type / .meal-plan « Sans repas | N repas/mois » / .monthly-price « X $ à Y $ »), confirmée sur les 15 fiches. Fix : _parse_grille lit les .pricing-row de la soupe (plus d'OCR, plus de subprocess tesseract, plus de cache detail — la grille est inline), schéma d'external_id {slug}-{typo}-5 et logique de prix (plancher « sans repas » sinon forfait le moins cher) inchangés → aucune ré-ingestion. Erreur FRANCHE si AUCUNE fiche n'a de grille (pattern sotramont bcdf125 : gabarit remanié ≠ vrai zéro — c'est exactement le zéro silencieux qui a causé les retraits). Fixtures enregistrées pour la première fois (16 requêtes, 55 annonces). Testé : fetch() venv → 55 annonces (1½ Manoir Brossard 1 716 $ 60 repas/mois, 3½ 1 464 $ sans repas, 15 photos — 54 historiques + 1 typologie), pytest res_soleil 2 passed, run.py sync res_soleil → found=55 ok (added=1, updated=54 : les 54 retirées réactivées, 16,3 s), 55 actives en BD, pm2 restart lou-ka-sync, site :8095 → 200.
      ···
      Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
      Simon-Pierre Boucher 18 files +41,870
  9. Tue, Sep 22, 20261 commit

    1. Simon-Pierre Boucher 49 files +27,616 −887
  10. Mon, Sep 21, 20261 commit

    1. [ka2] fix connecteur sotramont: erreur franche + retry sur le GET du portfolio — fini le « 0 trouvé ok » silencieux sur hoquet réseau. Les syncs du 2026-09-21 11:42 et 19:07 rapportaient found=0 ok (médiane 8, dérive déclenchée, retraits suspendus → stale) alors que le site est parfaitement sain : les seuls autres zéros de l'historique (2×09-10, 1×09-18, seconds: 0.0) tombent PILE dans les vagues DNS systémiques du nœud — le `except Exception: return listings` de fetch() avalait l'échec transitoire du GET de liste et le transformait en zéro silencieux. Vérifié live : curl 3/3 → 200, 130 Ko ; requests venv 8/8 → 200, 76 cartes ; Apache/Ubuntu direct sur DigitalOcean, aucun WAF ; aucun autre connecteur en échec dans les fenêtres des zéros du 09-21 (pas systémique app). Fix minimal, pattern devimco (edd968e) : le GET du portfolio tente 3 fois (backoff 3/6 s) puis lève une erreur FRANCHE au lieu de retourner [] ; erreur franche aussi si la soupe ne contient AUCUNE carte article.c--article-project (gabarit remanié ≠ vrai zéro — le vrai zéro reste possible : cartes présentes mais toutes « Vendu »/« En construction »). Fixture enregistrée pour la première fois (run.py record sotramont, 8 requêtes). Testé : fetch() venv → 8 annonces (Liveo Pointe-Claire 3 1 620 $, Curtiss Charlie Saint-Laurent 1 460 $, 8-10 photos — médiane 6.0 couverte), pytest sotramont 2 passed, run.py sync sotramont → found=8 ok (8,3 s), pm2 restart lou-ka-sync, site :8095 → 200.
      Simon-Pierre Boucher 10 files +6,904
  11. Thu, Sep 17, 20261 commit

    1. [ka2] fix connecteur halfred: refonte Eversa « Editorial » du site — préfixe de locale /fr + nouveau gabarit de cartes. Le sync du 2026-09-17 (dernier succès 06:46, stale 5,2 h) rapportait found=0 : halfred.ca (plateforme Eversa, cf. gestion_cem 7f020de) a basculé sur des routes préfixées de locale (/listings/list → 301 /fr/listings/list) ET un nouveau gabarit : les cartes sont désormais des <a data-sentry-component="EditorialListingCard"> avec hrefs /fr/listings/…/details (le sélecteur a[href^='/listings/'] ne matchait plus rien), titre en h3 (plus h1), lieu « Secteur · Ville » (plus « Ville (Secteur) »), SpecItem textuels sans icônes lucide, prix « À partir de $1,559 » avec ancien prix .line-through dans un composant line, disponibilité en pill « Disponible le … » ; la fiche détail expose la description via RichTextDisplay (plus de h2 « Description de l'annonce ») et des Walk/Bike Score® en anglais. Fix minimal : LIST_URL → /fr/listings/list, _external_id retire le préfixe de locale (ids historiques préservés, aucune ré-ingestion), _city_sector gère « Secteur · Ville » (ancien format en repli, normalisation Gatineau intacte), _features lit SpecItem/pills/line, _fetch_detail lit RichTextDisplay et les scores bilingues. Testé : fetch() venv → 173 annonces en 133 s (30 Rue De Matapédia Gatineau/Pointe-Gatineau 4½ 1 300 $ promo, 12 fiches détail avec description+contact+scores — médiane 172 couverte), fixtures ré-enregistrées + pytest 2 passed, run.py sync halfred → found=174 ok (added=1, 131 s), pm2 restart lou-ka-sync, site :8095 → 200.
      Simon-Pierre Boucher 30 files +14,258 −13,180
  12. Wed, Sep 9, 20261 commit

    1. [ka2] fix connecteur groupe_theoret: réécriture pour la refonte du site (GoDaddy Website Builder → GoDaddy Airo, ~2026-09-09) — le widget « menu » n'existe plus. Le sync de 15:40 a rapporté found=0 ok=1 (médiane 23, retraits suspendus) : reproduit en live, l'URL accentuée /appartements-%C3%A0-louer redirige 301 vers /appartements-a-louer et la nouvelle page (React Router, 88 Ko) ne contient plus aucun marqueur data-aid MENU_SECTION_*. Le nouveau site embarque TOUT le catalogue dans le payload d'hydratation window.__staticRouterHydrationData (données créées le 2026-09-01, unités ajoutées encore aujourd'hui) : 40 immeubles avec adresse + ville + code postal + slug /proprietes/<slug> + services + photos (/airo-assets/images/<slotKey>, vérifiées 200 image/jpeg) + contact, et par unité DISPONIBLE un id stable, le type, le loyer et la date de dispo ISO. Nouveau fetch() : une seule requête (plus de pages immeuble ni de cache détail), extraction du littéral JS par regex tolérante aux guillemets échappés puis double json.loads, external_id=u<id> (clé BD du site), RuntimeError si le payload est absent ou sans immeuble (une page saine embarque toujours les ~40 immeubles même à 0 dispo — même pattern que c3r/brio). Gain net vs l'ancien site : photos 25/25 (avant 0 %), inclusions 25/25, contact 24/25, code postal systématique. Testé : run.py sync groupe_theoret → found=25 ok (médiane 23, added=25 — nouveaux ids, les 23 anciennes annonces seront dépubliées par les retraits), fixtures ré-enregistrées (record → 1 requête, 25 annonces ; pytest 2 passed), pm2 restart lou-ka-sync, site :8095 → 200. sources.json : listing_url → /appartements-a-louer.
      ···
      Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
      Simon-Pierre Boucher 16 files +272 −8,625
  13. Fri, Sep 4, 20262 commits

  14. Thu, Aug 27, 20261 commit

    1. feat(scraping): migration Firecrawl -> Scrapfly des 6 connecteurs a rendu JS
      ···
      - base.get_rendered : rendu via Scrapfly (render_js+ASP), wait_ms = ancien
        waitFor Firecrawl, retry x3 sur contenu vide puis echec honnete ;
        FIRECRAWL_API retire du socle
      - aalto/osgoode/brigil/realstar : _rendered delegue au socle (retry centralise)
      - realstar/osgoode/brigil : selecteur li[class*=property-box] — le rendu
        Scrapfly capture le DOM avant que le JS RentCafe ne revele les cartes
        (property-box-hidden), qui sont completes ; filtre QC en aval inchange
      - via_capitale : CARD_SPLIT accepte les hrefs relatifs (serialisation
        Scrapfly) en plus des absolus (fixtures Firecrawl historiques)
      - fixtures record/replay : get_rendered accepte wait_ms (cle de rejeu = URL)
      - fixtures re-enregistrees via Scrapfly : aalto 24, osgoode 4, brigil 12,
        realstar 9 ; rejeu test_connectors 10/10
      - gen_connector_docs : backend get_rendered documente Scrapfly (ex-Firecrawl)
      
      Valide en live : aalto 24, lynk_olymbec 4, via_capitale page 1 = 34 cartes.
      Lou-Ka ne depend plus de FIRECRAWL_API_KEY.
      Simon-Pierre Boucher 124 files +229,955 −483
  15. Fri, Aug 21, 20261 commit

    1. quality: porte de pertinence — quarantaine des stationnements, garages, locaux commerciaux et locations à la nuit
      ···
      Certaines sources mêlent aux logements des cases de stationnement (~200 $),
      garages/entreposage, locaux commerciaux/bureaux, objets divers et tarifs à la
      nuit. relevance_reason() les détecte (titre + description + seuils de prix,
      sans faux positif sur les logements « avec stationnement inclus ») et evaluate()
      les met en quarantaine (published=0). Backfill appliqué : 78 annonces retirées.
      
      Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
      Simon-Pierre Boucher 1 file +102
  16. Tue, Aug 18, 20263 commits

    1. KA Scores — suite géographique maison (Walk/Transit/Bike/Calme/Services)
      ···
      · environment.py : inventaire OSM par tuile (Overpass) — routes majeures,
        rails, aéroports, zones industrielles, bars, pistes cyclables (géométrie
        densifiée) et TOUS les POI par catégorie ; cache env_tiles ~3 mois.
      · kascores.py : 5 scores 0-100 par immeuble + global pondéré, barème
        versionné (2026.08-v1), détails honnêtes par score, « Données
        insuffisantes »/« Non desservi » plutôt que des 0 trompeurs ; Transit =
        proximité des arrêts × percentile PMD StatCan ; calcul incrémental
        (7 900 immeubles en ~8 s), distribution de calibration en sortie.
      · API : ks_* joints à /api/listings et /api/search (tri « ka », filtre
        kascore_min), détail complet sur la fiche, /api/kascores/stats.
      · Frontend : pastille KA sur les cartes d annonces, section KA Scores de
        la fiche (5 jauges + détail dépliable + date/version), page /ka-scores
        (méthodologie publique + pondérations personnelles en curseurs), tri
        « Meilleur KA Score » dans la vue carte, filtre « KA Score minimal ».
      · Boucle watch : env (4 tuiles max) + kascores incrémental à chaque sync.
      · Tests : test_kascores.py (barème, honnêteté, rendement décroissant,
        cohérence spatiale sur le parc réel).
      
      Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
      Simon-Pierre Boucher 2 files +231
    2. Recherche synchronisée liste ↔ carte (une seule vérité partagée)
      ···
      · /api/search : une réponse = page de liste + tous les points carte,
        même tri — compteur liste = marqueurs par construction ; bbox, polygone
        dessiné, tris (prix/récent/affaires), include=liste, annonces sans
        position comptées honnêtement.
      · MapSearch.tsx : état unique filtres+zone+tri+page, miroirs survol/clic
        < 100 ms dans les deux sens, page ajustée au clic marqueur + pulsation,
        « Rechercher quand je déplace la carte », « Rechercher dans cette zone »,
        recadrage animé respectant l intention (byUser), « Recadrer sur les
        résultats », zone dessinée en puce retirable + URL, carrousel mobile
        synchronisé aux marqueurs, états vides propres, URL complète partageable.
      · Géolocalisation d accueil : arrivée sur le site → demande de position →
        vue carte centrée sur l utilisateur (une fois par session, lien partagé
        respecté, refus silencieux).
      · Marqueurs « déjà vu » atténués (localStorage), fourchette de prix des
        clusters au survol, spiderfy discret des unités d un même immeuble.
      · Tests : scripts/test-sync.mjs (25 vérifications E2E Playwright, critères
        1-9), tests/test_search.py (9 tests API).
      
      Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
      Simon-Pierre Boucher 1 file +87
    3. Qualité des données + solidité mobile + framework de juste valeur (fair value)
      ···
      Mission 1 — enrichissement des connecteurs et qualité :
      - quality.py : score de complétude 0-100 + seuil de publication (quarantaine
        des annonces sans prix plausible / localisation / contenu exploitable)
      - imgcheck.py : audit des images (liens morts 404/410, minuscules, placeholders
        multi-adresses, doublons) -> galeries nettoyées images_ok, cache image_checks,
        politesse 3 requêtes/hôte, écriture hors transaction réseau
      - 26 connecteurs enrichis (galeries complètes, descriptions, prix, adresses) :
        kangalou, royal_lepage, medway, remax_quebec, groupe_maurice, mellem, sutton,
        lespac, heafey, kijiji, fb_marketplace, zumper, equinoxe_batimo, logis_experts,
        quartier_sila, msi, summum, quartier_plus, urban_services, cosoltec, garic,
        lakle, matinale, huma, jutras, groupe_theoret, ferrovia
      - normalize : clean_city/clean_sector (rues et entités HTML retirées des menus),
        kijiji : adresses françaises « 89, rue X » correctement découpées
      - geocode : virgule après le n° civique corrigée (lot AQ), base en WAL
      - dedup : une annonce en quarantaine ne masque jamais un doublon publié
      
      Mission 2 — mobile :
      - /api/img : miniatures WebP servies à la taille de l écran (cache disque)
      - SmartImg : miniature -> original -> visuel de secours Lou-Ka (jamais d icône cassée)
      - lightbox tactile : balayage scroll-snap + pincement + double-tape
      - bannière témoins : ne recouvre plus le bouton Filtres (--consent-h)
      - cibles tactiles >= 44 px (pointer: coarse) ; KA Agent plein écran à l ouverture
      - stats : complétude moyenne, quarantaine par source
      
      Mission 3 — juste valeur locative (fairvalue.py, fv-logement-1.0) :
      - 3 niveaux : segments médians (repli en échelle) + coefficients de
        caractéristiques appris et centrés + comparables kNN géographiques (médiane
        pondérée) ; couloir de sécurité, fourchette, indice de confiance
      - prudence : pas de verdict si confiance faible, prix « à partir de »,
        prix non mensuel, écart hors plausible ; chambres/coloc = segment dédié
      - pastilles sous/dans/au-dessus du marché (cartes + fiche), bloc Analyse de
        prix avec histogramme, filtre « Sous le marché » + tri, page /juste-valeur
      - API : champs fv_* + deal/sort, /api/fairvalue/{uid} ; stats + PDF ;
        historisation fv_segments ; tests synthétiques ; docs/FAIRVALUE*.md
      
      Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
      Simon-Pierre Boucher 20 files +1,522 −1,664
  17. Sun, Aug 9, 20267 commits

    1. Expansion P3 — Estrie (6 connecteurs +24 annonces, 17 non-connectables)
      ···
      terater (12) · alexcellence (4e Houzez, sous-classe Dynamic) · oxford ·
      immeubles_pm (plogg vivant) · majestic (Granby) · lequerre (OBNL).
      
      Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
      Simon-Pierre Boucher 49 files +53,323
    2. Expansion P3 — Est & Nord + Chaudière-Appalaches (7 connecteurs +98 annonces, 9 non-connectables)
      ···
      quartier_plus (Thetford, 59) · immeubles_bois (Rimouski, catalogue 23) ·
      louer_saguenay · luxuor · beaulieu_groupe · gestion_jdm · alias_appartements.
      LM Gestion et Alexandre Pelletier re-vérifiés (sites toujours morts).
      
      Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
      Simon-Pierre Boucher 32 files +28,807
    3. Expansion P3 — Mauricie/CdQ/Lanaudière (6 connecteurs +53 annonces, 8 non-connectables)
      ···
      moderno · acceslogis_gb · ferrovia (23, prix non publiés) · habitations_sf ·
      lambert · fournelle. Non-connectables documentés (parcs pleins, vitrines
      sans unités, renvois Facebook).
      
      Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
      Simon-Pierre Boucher 33 files +41,782
    4. Expansion P3 — Outaouais (5 connecteurs +41 annonces, 10 non-connectables)
      ···
      wandji (API /api/buildings découverte, 29) · gio (crawl-delay 3 respecté) ·
      immnasr · quanta · leviu (portail Magex). Registre fusionné.
      
      Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
      Simon-Pierre Boucher 20 files +9,687
    5. Expansion P2 — Estrie (15 connecteurs, +279 annonces)
      ···
      Famille Houzez factorisée (dynamic -> gestimmo_estrie, agence_sherbrooke) ·
      uptimo (51) · dynamic (49) · matinale (42, Crawl-Delay 20 respecté) ·
      gestimmo (41) · montagnais (6 campus étudiants) · floria (Livya) + 8 autres.
      6 non-connectables documentés (plateforme plogg morte, vitrines sans prix).
      
      Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
      Simon-Pierre Boucher 304 files +429,316
    6. Expansion P2 — Outaouais (10 connecteurs, +136 annonces)
      ···
      garic (admin-ajax JSON avec GPS, 47) · aalto (RentCafe/Zibi via Firecrawl,
      28) · desmarais (14) · souleymane (13) · elite (12) · lacite (crawl-delay 10
      respecté, prix non publiés) + 4 autres. Aucune exclusion nécessaire.
      
      Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
      Simon-Pierre Boucher 130 files +89,737
    7. Expansion P2 — Est & Nord (19 connecteurs, +633 annonces)
      ···
      medway (494 — Lévis 343, Québec 81, La Malbaie, Pont-Rouge, Rivière-du-Loup) ·
      immeubles_aeb (26, Saguenay) · location_saguenay (21, crawl-delay 10 respecté) ·
      appartements_rimouski (17, GPS permutés corrigés) · habitations_jeanne (14,
      Baie-Comeau) · stb_immobilier (11, correctif : Matane pas Lévis) ·
      immeubles_dcl (9, API FleetCart) + 12 autres. Non-connectables documentés :
      habitat_honguedo (Gaspé, vide depuis 2020), immofidelite (RPA hors périmètre).
      
      Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
      Simon-Pierre Boucher 201 files +251,215
Menu

Theme