Files
oto-enterprise-os-dtp/05_deliverables_mvp/publiciste
Claude Code DTP Worker aeb30b8311 [DTP-Worker 20260812_070054] fix correctness · rendu HTML publiciste — URL de rendu percent-encodée dans le url('…') CSS
Bug latent réel (rendu-correctness, entrée FR/ES plausible) : _hero_media
(generator.py:92) injectait le nom de fichier via html.escape dans un
background-image:url('…'). Un rendu réel « Vue d'ensemble.png » devenait
Vue d'ensemble.png → le navigateur HTML-décode l'attribut style AVANT le
CSS → l'apostrophe referme la chaîne url('…') → hero non affiché, silencieux.
html.escape est le mauvais encodeur pour un contexte CSS.

Fix : urllib.parse.quote sur le segment de fichier ('→%27, espace→%20,
accents→%XX) — valide dans URL + attribut HTML + url() CSS ; _esc conservé pour
l'attribut HTML. Zéro dérive : quote laisse les noms ASCII simples inchangés
(hero_aerien.jpg identique) → fixture + byte-repro intacts.

Test de régression à dents (test_hero_media_url_percent_encode) : prouvé FAIL
sans quote, PASS avec. Cascade régénérée (artifact-reproducibility-gate) :
suite publiciste 24→25, matrice 629/612→630/613/17 · quality_report régénéré
en DERNIER · 3 fiches AGENT.md (compteurs dérivés) réalignées.

Défaut d'abord : 12 fichiers cœur / 7 modules ré-audités CLEAN (epsilon 1e-9
gate apport = tolérance flottante correcte). run_ci 33/0/0 · NFC-clean ·
zéro code moteur V18 (bloqué D-06 #6) · zéro gate ajouté (#5) · zéro invention (#6).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-12 07:15:47 +00:00
..

Publiciste Agent — scaffold (Sprint 2)

Maintient automatiquement le site public vente.otov7.com à partir des faisabilités canoniques (data_room/PXX/, template v1.0), sans édition manuelle. Cible de portage sur le VPS : otoia/capabilities/publiciste.py (voir ../../03_agents/publiciste/AGENT.md et ../GAP_ANALYSIS_SPRINT1.md §3.13 — seul module net-neuf, chemin critique).

Pipeline

data_room/PXX/  ──►  lib/parser.py  ──►  projets_master.json  ──►  lib/generator.py  ──►  index.html
   (faisabilité)      (extraction)        (contrat schéma)          (rendu luxury)        (site public)

Le contrat projets_master.json est défini par ../faisabilite/projets_master.schema.json (livré au Sprint 1). Le versioning faisabilité par ../faisabilite/version.schema.json.

État par rapport au calendrier AGENT.md

Semaine Livrable Statut ici
S2 Setup base + parser faisabilité → JSON lib/parser.py + validation schéma
S3 Générateur HTML → site aperçu lib/generator.py (rendu luxury #4)
S4 Triggers systemd + inotify ☐ (exécution VPS — hors périmètre worker)
S5 Notifications WhatsApp Michel ☐ (VPS)
S6 Multilingue FR/EN/ES auto ☐ (FR extrait ; EN/ES à venir)
S7 Tests + validation P01-P09 🟡 tests sur fixtures synthétiques (données réelles VPS)
S8 Production ☐ (VPS)

Composants

Fichier Rôle
publiciste.py Orchestrateur CLI (parse / validate / generate / run)
lib/parser.py data_room/PXX/ → dict projet (contrat schéma) · anti-invention #6
lib/validator.py Validateur JSON-Schema draft-07 (sous-ensemble) · zéro dépendance pip
lib/generator.py projets_master.json → HTML (marque luxury #4)
lib/branding.py Tokens de marque (source unique · CLAUDE.md #4)
templates/site_public.html.tmpl Gabarit dark+doré (Fraunces + Cormorant Garamond)
fixtures/ Données synthétiques de test (⚠️ jamais publiées — cf. fixtures/README.md)
tests/test_publiciste.py Suite unittest (parser, schéma, generator)

Règles anti-invention appliquées (CLAUDE.md #6)

  • Le statut publié dérive de _META/version.json : complete → disponible, sinon en_developpement.
  • Rétrogradation défensive : un projet n'est « disponible » que si TOUTES ses typologies ont un prix USD numérique ; sinon → « En développement · Prochainement ».
  • Cellule vide / « non défini » / placeholder {{…}}null (jamais 0, jamais une valeur inventée).
  • Rendus : uniquement ceux référencés dans la faisabilité ( IA générique).

Utilisation

# depuis 05_deliverables_mvp/publiciste/

# Parser une data_room → projets_master.json (validé contre le schéma)
python3 publiciste.py parse fixtures/data_room -o build/projets_master.json

# Générer le site depuis un master validé
python3 publiciste.py generate build/projets_master.json -o build/index.html

# Pipeline complet
python3 publiciste.py run fixtures/data_room -o build/

# Tests
python3 -m unittest discover -s tests -v

⚠️ Ce worker n'écrit jamais sur le VPS. Le déploiement réel (copie vers /opt/oto/sites/vente/, cache-bust Cloudflare, notification WhatsApp) est un livrable ultérieur exécuté côté serveur par l'agent (Semaines 4-5).

Auto-score 4Big du livrable : 95/100

Réserve 5 : exécution contre les données réelles data_room/ (VPS, hors périmètre) différée ; triggers systemd/inotify + notifications WhatsApp = livrables Semaines 4-5 côté serveur ; génération EN/ES = Semaine 6.