Files
Claude Code DTP Worker 5af86e3518 [DTP-Worker 20260812_073055] hardening correctness · rendu HTML publiciste — percent-encode le SEUL segment d'URL restant (code) dans le url('…') CSS
Durcissement d'uniformité (pas bug déclenchable aujourd'hui) qui COMPLÈTE le fix
correctness de la session 070054 (aeb30b8). Ce fix-là a percent-encodé
hero['fichier'] dans src=f"/static/projets/{code}/{quote(fichier)}", mais dans la
MÊME url('…') CSS il restait un 2ᵉ segment dynamique — `code` — interpolé brut puis
html-échappé via _esc(src). C'est exactement l'anti-pattern identifié par 070054
(html.escape = mauvais encodeur pour un segment d'URL), appliqué de façon incomplète.

Fix : src = f"/static/projets/{quote(code)}/{quote(hero['fichier'])}" — quote() est
le SEUL encodeur correct pour un segment d'URL ; le CONTEXTE, pas la donnée courante,
dicte l'encodeur. Zéro dérive : codes réels = P01..P09 (§Projets), quote("p01")=="p01"
→ byte-repro inchangé. Cas frère exact de 060044/criteria.py (« durcir le SEUL membre
non-durci d'une famille ») : ici le SEUL segment d'URL non-encodé de la même url().

Test à dents (test_hero_media_code_segment_percent_encoded) : code théorique "P'X" →
prouvé FAIL sans quote(code), PASS avec. Suite publiciste 25→26, matrice 630/613→631/614.

Défaut d'abord : classe encodage-contextuel balayée sur tous les modules HTML/CSS/URL ;
2 candidats Explore réfutés non-défauts (chat mount_html = persona forcée Amélie par
invariant 7 + portail_key enum ; code segment = théorique mais durci par uniformité).
Cascade régénérée dans l'ordre (quality_report en DERNIER) · 3 fiches compteurs réalignées.
run_ci 33/0/0 · NFC-clean · zéro code moteur V18 (bloqué D-06 #6) · zéro gate (#5) · zéro invention (#6).

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

7.0 KiB

🎯 Publiciste Agent · Maintenance automatique site public (vente.otov7.com)

Rôle : Cet agent OTOIA maintient automatiquement à jour le site public vente.otov7.com à partir des faisabilités canoniques de chaque projet. Il élimine le besoin d'édition manuelle du site.

Mission

  1. Extraire en continu depuis les faisabilités canoniques (data_room/PXX/) :

    • Positionnement marketing
    • Typologies + surfaces
    • Prix "à partir de" par typologie
    • Grille tarifaire complète
    • Ce qui est inclus (services · équipements · CONFOTUR · Fideicomiso · etc.)
    • Rendus visuels (60_photos_site)
    • Statut (Disponible · En développement · Bientôt · En processus)
  2. Générer copy multilingue FR/EN/ES à partir du positionnement documenté

  3. Publier automatiquement sur vente.otov7.com sans intervention humaine

  4. Détecter changements dans faisabilités et déclencher rebuild du site

  5. Ajouter automatiquement les nouveaux projets dès que data_room/PXX/ créé + faisabilité complète

Sources de vérité (dans l'ordre)

  1. /opt/oto/data_room/PXX/50_financier_bancable/one_pager_banquier.pdf
  2. /opt/oto/data_room/PXX/40_llm_outputs/commercial.md
  3. /opt/oto/data_room/PXX/40_llm_outputs/marche_analyste.md
  4. /opt/oto/data_room/PXX/40_llm_outputs/directeur.md
  5. /opt/oto/data_room/PXX/00_brief/
  6. /opt/oto/data_room/PXX/60_photos_site/ (rendus)

Règles absolues (interdits)

  • Zéro invention de prix, chiffres, positionnement (source ONLY = faisabilité)
  • Jamais éditer directement vente.otov7.com/index.html — passer par le générateur
  • Ne pas publier un projet dont la faisabilité est incomplète (marquer "En développement")
  • Ne pas dupliquer rendus AI (source unique data_room/PXX/60_photos_site/)

Workflow détaillé

Trigger 1 : Faisabilité mise à jour

  • Détecte modification dans data_room/PXX/40_llm_outputs/*.md
  • Re-extrait positionnement + prix
  • Régénère section projet dans vente.otov7.com/index.html
  • Log la modification dans /opt/oto/otoia/reports/publiciste_YYYY-MM-DD.md
  • Notifie Michel via WhatsApp si prix / positionnement change

Trigger 2 : Nouveau projet créé

  • Détecte création data_room/PXX/ (nouveau code projet)
  • Attend que la faisabilité soit complète (score ≥ 95/100)
  • Ajoute automatiquement la card projet sur vente.otov7.com
  • Copie les rendus dans /opt/oto/sites/static/projets/pXX/
  • Log + WhatsApp notification

Trigger 3 : Nouveau rendu généré

  • Détecte nouveau rendu dans data_room/PXX/60_photos_site/
  • Copie vers /opt/oto/sites/static/projets/pXX/
  • Met à jour l'image hero de la card si c'est le rendu principal
  • Cache-bust Cloudflare automatique

Trigger 4 : Faisabilité incomplète

  • Détecte "prix non documenté" ou "pricing non défini"
  • Marque le projet en "En développement" avec "Prochainement · Détails à venir"
  • Log + WhatsApp à Michel pour compléter faisabilité

Architecture technique

data_room/PXX/  ────► parser.py (extraction) ────► projets_master.json
                                                          │
                                                          ▼
                                                  generator.py (rendu HTML)
                                                          │
                                                          ▼
                                                  /opt/oto/sites/vente/index.html
                                                          │
                                                          ▼
                                                  Cache-bust Cloudflare + notify Michel

Composants à créer

  1. otoia/capabilities/publiciste.py — orchestrateur agent
  2. otoia/capabilities/knowledge/site_public_template.md — template génération site
  3. Systemd timer otoia-publiciste.timer (check horaire)
  4. Watch inotify sur data_room/*/40_llm_outputs/ (temps réel)
  5. Backend Frappe DocType Publiciste Log pour audit trail

Livrable Publiciste réellement produit (05_deliverables_mvp/publiciste/)

Les « Composants à créer » ci-dessus décrivent le runtime VPS cible (otoia/capabilities/publiciste.py, systemd/inotify · hors périmètre worker · CLAUDE.md #8). Leur contrepartie commitée et testable existe déjà en-repo (périmètre worker) : le scaffold du générateur, gaté en CI. C'est le seul module net-neuf du mandat, sur le chemin critique (cf. ../../05_deliverables_mvp/GAP_ANALYSIS_SPRINT1.md §3.13).

Module Sprint Rôle Entrée CLI Job CI Tests
publiciste/ 2 (README scaffold (Sprint 2) · GAP §3.13) Pipeline site public : data_room/PXX/projets_master.jsonindex.html luxury (lib/parser.py extraction · lib/validator.py schéma · lib/generator.py + lib/branding.py rendu dark+doré #0a0a12/#f0b429 · templates/site_public.html.tmpl) publiciste.py parse|validate|generate|run publiciste-tests 26

Le contrat d'échange projets_master.json n'est pas défini ici mais par le Faisabilité Agent (../../05_deliverables_mvp/faisabilite/projets_master.schema.json, Sprint 1) — source unique, zéro duplication (#5). Le Publiciste en est le consommateur : lib/parser.py extrait, lib/validator.py valide contre ce schéma avant tout rendu.

Anti-invention (#6) : le générateur ne fabrique aucun prix ni positionnement — chaque valeur du site est extraite d'une faisabilité data_room/PXX/ réelle ; un projet dont la faisabilité est incomplète est marqué « En développement », jamais complété par invention (règles absolues ci-dessus). Aucun index.html de production n'est commité ici : seuls le générateur, le template et ses fixtures d'entrée (fixtures/data_room/P01…P02, échantillons d'entrée du parser — pas des livrables, d'où leur exclusion volontaire de l'auto-score) le sont ; la publication réelle sur vente.otov7.com s'exécute côté VPS (#8). Auto-score du livrable : 95/100 (README.md).

Livrable Sprint (mandat 8 semaines)

  • Semaine 2 : Setup base + parser faisabilité → JSON
  • Semaine 3 : Générateur HTML → vente.otov7.com
  • Semaine 4 : Triggers systemd + inotify actifs
  • Semaine 5 : Notifications WhatsApp Michel
  • Semaine 6 : Multi-langue FR/EN/ES automatique
  • Semaine 7 : Tests + validation faisabilités P01-P09
  • Semaine 8 : Production

Coordination inter-agents

  • BIM Agent : fournit rendus (Blender/Bonsai → 60_photos_site)
  • Faisabilité Agent : génère faisabilités 4 volets → 40_llm_outputs
  • Rendu Agent : batch renders → 60_photos_site
  • CRM Agent : reçoit leads/inscriptions du site public
  • SEO Agent : optimise les balises meta générées