SPB Git

spb/lou-ka

Public

Lou·Ka — tous les logements à louer du Québec, un seul endroit.

page 1
  1. Thu, Oct 29, 2026 1

  2. Wed, Oct 28, 2026 1

  3. Tue, Oct 27, 2026 2

    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 · 90 files +1,103 −26,675
  4. Mon, Oct 26, 2026 3

    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 · 79 files +1,796 −130
    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 · 9 files +629 −672
  5. Sun, Oct 25, 2026 1

    1. [ka2] fix connecteur solaris: variante ANGLAISE servie à l'URL française par le cache Cloudflare → parsing bilingue + rotation d'IP au retry. Au sync de 09:37 le garde-fou levait « aucune unité parsée alors que data-count=8 » sur les 3 tentatives (session proxy Oxylabs collante du fix 99c1a4b) : la page /appartements/ a été servie en ANGLAIS (gabarit identique, data-count=8, mais « 2 bedroom · 4½ 875 sq ft $2,140 a month Free now Photos and plan Visit ») → 0/8 pour ROW_RE. Constats live : le site a une version EN (/en/apartments/, hreflang) exactement à cette signature ; Cloudflare cache les deux variantes SANS Vary et sa clé de cache IGNORE la query string (cf-cache-status: HIT même sur ?lkb=<unique>) → le cache-buster du retry 8eff094 ne buste RIEN, et la session collante (même sortie/colo) revoyait la même variante empoisonnée aux 3 tentatives ; Accept-Language et géo de l'IP (testé Toronto vs Montréal) ne changent pas la réponse de façon déterministe. Fix 1 : parsing bilingue — ROW_EN_RE (ordre des champs inversé : chambres avant typologie, prix $2,140 avec virgule, sq ft, « a month ») en repli par ligne quand ROW_RE ne matche pas, avec renormalisation de la dispo en français canonique (_avail_fr : « Free now » → « Libre maintenant », « Free on Nov 1, 2026 » → « Libre le 1er novembre 2026 ») — parité vérifiée 8/8 FR↔EN sur les deux pages live (prix/typologie/chambres/pi²/dispo strictement identiques, zéro churn). Fix 2 : au retry, si la session est sur proxy, NOUVELLE session collante Oxylabs (_enable_residential_proxy re-appelé → autre IP/colo) — le vrai levier contre une variante en cache, le ?lkb= étant inopérant ; aide aussi contre les sorties résidentielles tarpitées (000 constatés ~1 essai sur 3 en test curl). Fixtures inchangées (page FR), pytest solaris 2 passed. Testé : fetch() venv → 8 unités (1 630–2 730 $, dispos FR), run.py sync solaris → found=8 ok (14,5 s), pm2 restart lou-ka-sync, site :8095 → 200.
      …
      Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
      Simon-Pierre Boucher · 1 file +46 −6
  6. Sat, Oct 24, 2026 1

    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 · 3 files +411 −102
  7. Thu, Oct 22, 2026 12

    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 · 5 files +2,657 −142
    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 · 5 files +1,143 −257
    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 · 10 files +1,904 −18,600
    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 · 7 files +2,324 −389
    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 · 8 files +3,491 −1,481
    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 · 12 files +1,570 −345
    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 · 12 files +345 −1,570
    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 · 7 files +2,219 −469
    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 · 4 files +1,856 −111
    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 · 28 files +166 −8,241
    11. Simon-Pierre Boucher · 6 files +4,892 −50
  8. Tue, Oct 20, 2026 1

    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 · 6 files +1,764 −347
  9. Mon, Oct 19, 2026 1

  10. Thu, Oct 15, 2026 3

    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 · 6 files +1,196 −322
    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 · 5 files +461 −156
    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 · 4 files +951 −53
  11. Sun, Oct 11, 2026 1

    1. Simon-Pierre Boucher · 95 files +21,321 −144
  12. Thu, Oct 8, 2026 1

    1. retrait: connecteur Ubee supprimé et 466 inscriptions effacées (plainte de Ubee, 2026-10-08)
      …
      - louka/connectors/ubee.py + docs/connecteurs/ubee.md supprimés, ligne INDEX retirée
      - data/sources.json : ubee → retiré (ne pas réactiver sans accord écrit)
      - louka/web.py : les statuts inactif/retiré sont aussi déclarés disabled_sources à api-ka
      - base : listings (466), price_log (505), fairvalue (375), listing_events (319),
        recycled_cache (77), managers (1), sync_log (372), image_checks (12 701 URL
        Cloudinary ubee-media) effacés ; dédup inter-sources recalculée
      - sauvegarde à froid hors dépôt : ~/ubee-retrait-20261008/
      
      Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
      Simon-Pierre Boucher · 5 files +2 −205
  13. Wed, Oct 7, 2026 2

    1. [ka2] fix connecteur simplex: pagination plafonnée par la RPC + erreur franche sur réponse non-liste — le zéro depuis le 2026-09-30 est un VRAI zéro. La RPC Supabase get_public_rental_listings_page plafonne désormais côté serveur à 24 lignes/appel quel que soit p_limit (le site utilise p_limit:12 et ne le voit pas) : le connecteur demandait 100, recevait 24, avançait l'offset de 100 (≥ total 28) et SAUTAIT les lignes 24-27 — où se trouvaient précisément les 3 anciennes annonces disponibles (dont le 2½ du Cégep 740 $). Chute found=3→0 le 2026-09-30 08:33, puis 49 runs « found=0 ok » ; le dernier run (10-07 21:08) était un échec DNS transitoire (vague systémique connue du nœud). Vérifié live : RPC 200, 28 fiches (25 rented + 3 unavailable) ; le code du site (publicRentalCatalog.js) ne considère « disponible » que available/coming_soon et affiche tout le reste « Indisponible » → le filtre _KEEP du connecteur est aligné, found=0 est le vrai état du marché. Fix minimal : offset += len(batch) au lieu de PAGE (toutes les lignes vues : 28/28 au lieu de 24/28), et _rpc lève une erreur FRANCHE si la réponse n'est pas une liste (clé révoquée/dict d'erreur → plus jamais de zéro silencieux, indétectable avec médiane 0.0 — pattern sotramont bcdf125). Pas de fixture enregistrée : test_listings_are_valid exige des annonces non vides, impossible pendant un vrai zéro. Testé : fetch() venv → 28/28 lignes brutes, 0 annonce (vrai zéro), run.py sync simplex → found=0 ok (1,1 s), pm2 restart lou-ka-sync, site :8095 → 200.
      Simon-Pierre Boucher · 1 file +9 −2
    2. [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 · 19 files +41,914 −80
  14. Fri, Oct 2, 2026 1

  15. Tue, Sep 22, 2026 1

    1. Simon-Pierre Boucher · 50 files +27,628 −888
  16. Mon, Sep 21, 2026 1

    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 · 11 files +6,931 −5
  17. Thu, Sep 17, 2026 2

    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 · 31 files +14,340 −13,246
  18. Mon, Sep 14, 2026 3

    1. Simon-Pierre Boucher · 1 file +43 −13
    2. [ka2] fix connecteur devimco: escalade Scrapfly contre le pare-feu Sucuri CloudProxy apparu sur devimco.com — même cause et même fix que brio (195f19a). Les syncs du 2026-09-13 (05:03, 15:16, 20:16... puis 23:23) rapportaient found=0 ok par INTERMITTENCE (médiane 695, dérive déclenchée, retraits suspendus) : devimco.com est passé derrière Sucuri/Cloudproxy, qui répond 307 + challenge JavaScript (cookie sucuri_cloudproxy, en-tête x-sucuri-id, ~1,4 Ko sans Location) aux clients sans navigateur selon l'humeur du filtre IP — un statut < 400 invisible de raise_for_status(), le hub sans lien projet devenait « 0 trouvé ok » silencieux via le `except Exception: return listings` de fetch(). Le diagnostic « échec transitoire » du passage ka2 de 08:08 était donc incomplet : le hoquet se répétait un sync sur deux. Vérifié live : 3 GET directs consécutifs → 307 challenge ; Scrapfly ASP + rendu JS → 200, 297 Ko, 10 pages projets. Fix minimal, pattern brio : _get_html() tente le direct (gratuit quand Sucuri laisse passer), détecte le challenge (statut 307 ou marqueur sucuri_cloudproxy) et escalade vers get_rendered() (Scrapfly ASP + rendu JS, standard du repo) ; hub ET pages projets passent par _get_html() ; le hub lève désormais une erreur franche au lieu de retourner [] (fini le zéro silencieux, idem si aucun lien projet dans la soupe) ; les pages projets gardent le continue (résultats partiels acceptables) ; l'API Planpoint (app.planpoint.io, domaine distinct) reste en direct. Testé : pytest fixtures devimco 2 passed, fetch() venv → 695 annonces (13 phases : Cosma 237, Ostral 160, Maestria A/B 121, Alexander 66... — unité 309 Alexander 2 130 $/mois, 2255 René-Lévesque O, 13 photos — médiane 695 restaurée), run.py sync devimco → found=695 ok (161 s), pm2 restart lou-ka-sync, site :8095 → 200.
      Simon-Pierre Boucher · 1 file +26 −5
  19. Sun, Sep 13, 2026 2

    1. [ka2] fix connecteur mondev: contournement du challenge sgcaptcha SiteGround via proxy résidentiel Oxylabs — même cause et même fix que boreal_abitibi (8923045), citiluxx (d17f5fe), cromwell (8351131), deschenes_pepin (f8aca03), gestion_habitation (8b0660b), gimcote (12df764), appartements_rimouski (af2be7c), lbm (5decd97), gestion_mj (15d2bbb) et mercini (5125859), hébergeur SiteGround identique (11e connecteur touché). Le sync du 2026-09-12 22:42 a rapporté found=0 ok (médiane 20.0, stale) : SiteGround sert son anti-bot sgcaptcha (HTTP 202, 199 octets, en-tête sg-captcha: challenge, meta refresh vers /.well-known/sgcaptcha/) à l'IP datacenter du nœud — un 2xx sans HTTPError, avalé par le `except Exception: return listings` de fetch() en « 0 trouvé ok », invisible du disjoncteur. Vérifié live : IP directe → 202 challenge ; IP résidentielle Oxylabs CA → 200, 557 Ko, 30 immeubles présents. Fix minimal, pattern lbm (liste unique + fiches immeubles re-fetchées à chaque sync, pas de detail_cache) : _get_html() détecte le challenge (en-tête sg-captcha ou marqueur /.well-known/sgcaptcha/) et bascule la session sur pr.oxylabs.io:7777 en session collante -cc-CA (liste + fiches immeubles partagent l'IP), erreur franche si le challenge persiste — la page de liste (unique, pas de pagination) lève désormais au lieu de retourner [] (fini le zéro silencieux, ingest journalise ok=0) ; _parse_building() passe aussi par _get_html() et garde le continue autour (résultats partiels acceptables). Le chemin direct reste tenté d'abord (gratuit si SiteGround déflague l'IP). Testé : fetch() venv → 40 annonces (Florence 3½ 1 500 $ → 5½ 2 600 $ rue Florian, Jacques Studio 1 630 $ rue Fullum — adresses complètes, 16-40 photos, médiane 20.0 largement couverte, dernier sync sain à 43), pytest fixtures 2 passed, run.py sync mondev → found=40 ok (94 s), pm2 restart lou-ka-sync, site :8095 → 200.
      Simon-Pierre Boucher · 1 file +45 −5
    2. [ka2] fix connecteur mercini: contournement du challenge sgcaptcha SiteGround via proxy résidentiel Oxylabs — même cause et même fix que boreal_abitibi (8923045), citiluxx (d17f5fe), cromwell (8351131), deschenes_pepin (f8aca03), gestion_habitation (8b0660b), gimcote (12df764), appartements_rimouski (af2be7c), lbm (5decd97) et gestion_mj (15d2bbb), hébergeur SiteGround identique (10e connecteur touché). Le sync du 2026-09-12 22:40 a rapporté found=0 ok (médiane 20.0, stale) : SiteGround sert son anti-bot sgcaptcha (HTTP 202, 181 octets, en-tête sg-captcha: challenge, meta refresh vers /.well-known/sgcaptcha/) à l'IP datacenter du nœud (76.70.60.50 flaguée « ipr ») — un 2xx sans HTTPError, avalé par le `except Exception: break` de fetch() en « 0 trouvé ok », invisible du disjoncteur. Vérifié live : IP directe → 202 challenge ; IP résidentielle Oxylabs CA → 200, 244 Ko, 24 blocs property_listing page 1. Fix minimal, pattern gimcote (liste paginée + detail_cache identiques) : _get_html() détecte le challenge (en-tête sg-captcha ou marqueur /.well-known/sgcaptcha/) et bascule la session sur pr.oxylabs.io:7777 en session collante -cc-CA (liste paginée + fiches détail partagent l'IP), erreur franche si le challenge persiste — la 1re page de liste lève désormais au lieu de break (fini le zéro silencieux, ingest journalise ok=0), les pages suivantes gardent le break (résultats partiels acceptables) ; _fetch_detail() passe aussi par _get_html() pour ne pas empoisonner detail_cache avec un payload vide (clé figée jamais invalidée) ; les cartes gardent le continue (résultats partiels acceptables). Le chemin direct reste tenté d'abord (gratuit si SiteGround déflague l'IP). Testé : fetch() venv → 40 annonces (4½ Duberger 1 895 $, projet neuf Limoilou 1 595 $, 5½ Nicolet 1 550 $ — adresses complètes, 7-21 photos, médiane 20.0 largement couverte), pytest fixtures 2 passed, run.py sync mercini → found=40 ok (53 s), pm2 restart lou-ka-sync, site :8095 → 200.
      Simon-Pierre Boucher · 1 file +52 −5
Menu

Theme