Files
nav-carte/JOURNAL-V2.md
2026-05-14 06:05:48 +02:00

1111 lines
75 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
type: journal
note_J8: Phase 8.G LIVREE 2026-05-14 - voir PILOTE-RAG-PE.md pour details
project: NAV V2
created: 2026-04-14
status: actif
---
# NAV V2 — Journal de développement
Journal technique de la V2. Décisions, anomalies, points bloquants, TODOs.
---
## 2026-05-08 — Fix mobile + chatbot prod (cause racine résolue)
**Commits :** session loggée sur main (pushé sur gitea)
**Pattern :** pilote direct, 2 batches successifs, ~3h, 11 fichiers
### Cause racine bug "chatbot Carte 1 == Carte 2"
`/api/chatbot-reseaux` était **404 en prod** (jamais déployé) — explique pourquoi 5 cycles de fix précédents (ChatbotReseaux.vue prop endpoint, useRoute fallback, useMarkdown direct, etc.) n'ont rien donné : le code source était correct depuis le début. Le rebuild + redeploy de cette session résout le bug.
**Verif :** `curl -s -X POST https://aep.trans-former.fr/api/chatbot-reseaux` → 200 + réponse distincte de `/api/chatbot`.
### Batch 1 — fixes mobile principaux
- Hamburger app.vue : ajout Jobs + Manifeste + Soutenir, ré-ordonnancement (Manifeste dans 2e groupe avec À propos/Soutenir/Signaler)
- BandeauBas.vue : FAB cœur jaune mobile retiré (Soutenir migré dans hamburger via lien Liberapay direct)
- agences.vue mobile : 3e onglet "Graphe" ajouté + masquage MobileSheet en mode graphe (canvas fullscreen)
- a-propos.vue : section 1 "Mission" retirée (devient pop-up Carte 1) + `overflow-x: hidden` sur `.apropos-page` + retrait `white-space: nowrap` problématique sur `.badge-detail`
- pages/manifeste.vue : nouvelle page (texte version `manifeste-page-carto-V1.md`, sans le diagramme ASCII pour V1 web)
- components/MissionPopup.vue : nouveau composant générique (props `title`, `ctaLabel`, `storageKey`, slot pour contenu, `:slotted()` pour styles)
- index.vue : intégration MissionPopup + bouton (i) `position:fixed` bottom-left + auto-show 1ère visite via `localStorage.aep_mission_seen`
- trouver-du-taf.vue : toggle "Filtres [N] [chevron]" mobile-only (`@media max-width: 767px`) avec `taff-filters-collapsible` max-height transition
- FicheModal.vue + FicheModalV2.vue : sur mobile `top: 76px` + `max-height: calc(100dvh - 92px)` au lieu de `top: 50% translate(-50%, -50%)` + `max-height: 90vh` qui mordait sur le header
### Batch 2 — pop-up Carte 2, logo, intro Jobs, labels graphe
- agences.vue : pop-up Réseaux AEP avec MissionPopup (storageKey `aep_reseaux_seen`, ctaLabel "Explorer les 120 réseaux") + bouton (i) flottant
- app.vue logo header : badge AEP + 2 spans `logo-line-1` ("Architecture") / `logo-line-2` ("d'Écologie Politique") avec font-size responsive (0.7rem mobile → 0.85rem ≥1024)
- trouver-du-taf.vue : `<details class="taff-pedago" open>` avec 3 blocs (deux onglets, trois étiquettes, cinq axes) + onglet "Plateformes B2C" → "Pour archi indépendants"
- GraphView.vue : `d3NodeSelection.filter(type==='structure').append('text')` avec class `graph-struct-label`, `dy: -(d.r + 5)`, font-size 9.5px, halo via `paint-order: stroke; stroke: var(--nav-bg)` (style global non-scoped pour piercer D3)
### Bug d'opération à retenir
Lors du 1er déploiement batch 2, `bash deploy.sh` semblait OK (HTTP 200) mais le HTML en prod ne contenait pas les modifs. **Cause** : Dropbox sync a effacé `.output/` entre `npm run build` et le tar SCP — le tar a uploadé un `.output` quasi-vide. Solution : 2e cycle clean (`Remove-Item .nuxt/dist + .output`) + rebuild + redeploy avec `yes y |` (skip confirm interactif `.env diff`).
**Réflexe à intégrer** : après build, vérifier `grep -o "<un-fragment-de-modif>" .output/public/_nuxt/*.js | head` AVANT le deploy. Si 0 match → ne pas deploy, rebuild.
### Bug de communication à retenir
Jules a signalé "le logo n'a pas marché", "B2C pas renommé", "hamburger pas modifié" alors que le HTML en prod contenait bien les modifs (vérifié curl avec `?nc=$(date +%s)`). **Cause** : cache navigateur / service worker Nuxt. Réflexe à mettre en place pour /done de toute session web : si Jules dit "ça n'apparaît pas", vérifier curl en bypass cache AVANT de chercher un bug. Si match curl → demander hard refresh (Ctrl+Shift+R).
### Reste à faire (batch 3)
Voir `0 INBOX/PROMPTS/cascade-megaboum/REPRISE-aep-carto-fix-batch3.md` :
- Bouton "+" → sélecteur 3 cartes (Entraide/Réseaux/Jobs)
- Pop-up explication 5 axes Jobs (paragraphe par axe)
- Pop-up Carte 1 visibilité (option à clarifier avec Jules)
- GraphView Carte 1 (centres = hashtags, couche échelle activable) — gros chantier session dédiée
---
## 2026-04-27 — Session V3 : Finition mobile + Blog Liberapay + 3 deploys
**Commit :** `a02a555` — feat(mobile): accordéon outremer, hamburger nav, logo AEP, fiches cliquables, chatbot fullscreen
**Pattern :** agents parallèles (3 × Sonnet) pour les 3 SSH indépendants — ~90s total vs ~20min séquentiel
### Changements implémentés
**B — OutremerMap.vue : accordéon vertical DOM-TOM**
- Template : row horizontale → accordéon `<button>` + `v-show` par territoire
- Lazy-init Leaflet : `initSingleMap(domName)` appelé au 1er clic (plus de `initMaps()` en `onMounted`)
- `invalidateSize()` sur ré-ouverture d'une carte déjà initialisée
**E — app.vue : hamburger mobile**
- Bouton `lg:hidden` tout à droite de `<!-- Actions droite -->`
- Dropdown `v-if` : 5 liens (/, /agences, /rag, /a-propos, /signaler)
- `z-index: 9999` en inline style sur le dropdown
- `watch(() => route.path)` → ferme le menu à chaque navigation
- **Fix stacking context :** header → `relative z-[9999]` (sans `position`, le z-index Tailwind n'avait pas d'effet → dropdown passait sous Leaflet)
**F — app.vue : badge "A" → "AEP"**
- `w-7 h-7``h-7 px-2`, `text-sm``text-xs tracking-tight`
**G — pages/index.vue : fiches ouvrables mobile**
- `onSelectOrgMobile` : ajout `storeFiltersForBack()` + `router.push('/fiche/${id}')`
- NB : `router.push` était déjà là (modif pilote antérieure) — seul `storeFiltersForBack` ajouté
**H — ChatbotSheet.vue : fullscreen + scroll lock iOS**
- `92dvh → 100dvh`, `border-radius: 16px 16px 0 0 → 0`
- `defineProps``const props = defineProps` (fix "can't find variable: props" en prod)
- `watch(props.modelValue)` → lock `document.body.style.overflow` + `document.documentElement.style.overflow`
- `onUnmounted` → cleanup overflow
**A — Blog trans-former.fr : Liberapay retiré**
- VPS `/opt/astro-site/src/layouts/PostLayout.astro` : import + `<DonateButton />` supprimés
- Docker rebuild → 31 pages, HTTP 200
**C — Website pro deploy**
- `index.astro` SCP → `/opt/astro-pro/`, Docker rebuild → 13 pages, HTTP 200
### TODOs ouverts AEP
- [ ] Valider visuellement les 8 fixes sur tel (Jules)
- [ ] Pousser nav-carte sur Gitea (`git.trans-former.fr/jules/nav-carte`)
---
## 2026-04-15 — Session 5 : Corrections post Phase 2 (11 retours Jules)
**Exécutant :** Sonnet (agent autonome full auto)
**Durée :** ~45min
**Commits :** 7 commits atomiques (8ae4be3 → d30ee2c)
### Retours implémentés
**#1 — Barre de recherche** ✅
- Desktop : supprimée du header (doublon avec sidebar `NavSidebar.vue`)
- Mobile : ajoutée dans le header (`app.vue`, visible `<lg`)
**#2 — Sheet swipable mobile** ✅
- Nouveau composant `MobileSheet.vue` — 3 états : collapsed (56px) / half (50dvh) / full (92dvh)
- Touch events natifs (pas de `@vueuse/core` — implémentation vanilla pour 0 dépendance)
- Drag handle + cycle d'états au clic header + snap-back si delta < 60px
- Vue mobile index.vue : carte pleine hauteur en fond + sheet en overlay
- Décision d'exécution : vanilla touch events choisis vs useSwipe (pas installé)
**#3 — Onglets header desktop** ✅
- 3 onglets centrés remplacent la barre de recherche desktop : Écosystème / Agences Inspirantes / RAG
- Active state via `route.path` + underline `--nav-primary-solid`
- Badge "en construction" sous les 2 onglets inactifs
**#4 — Supprimer "+ Ajouter carte"** ✅
- Bouton retiré du header `app.vue`
- Route `pages/ajouter-carte.vue` supprimée
**#5 — Report/modif participatif via Resend** ✅
- `server/api/report.post.ts` : rate limit 5/IP/jour, validation email + message, envoi Resend API
- `FicheDetail.vue` : bouton "Signaler une erreur" → form inline dépliable (message + email, compteur 500 chars)
- Email envoyé à `jules@trans-former.fr` (fallback Resend, pas NocoDB)
**#6 — Texte intro commentaires** ✅
- `CommentSection.vue` : intro italique avant la liste
**#7 — DOM-TOM row horizontale pleine largeur** ✅ (Option A)
- `OutremerMap.vue` : layout row flex 5 colonnes égales, hauteur 140px
- Desktop `index.vue` : layout vertical (Métropole flex-1 + DOM-TOM row 140px fixe en bas)
- Suppression de l'encart 1/3 droit
**#8 — Supprimer layer control carte** ✅
- `NavMap.vue` : `L.control.layers(...)` supprimé, seul CartoDB Positron reste
**#9 — Dark mode switch tuile** ✅
- `NavMap.vue` + `OutremerMap.vue` : `MutationObserver` sur `html.classList``setUrl()` light_all/dark_all
- Initialisation correcte dès le premier rendu (lire `document.documentElement.classList`)
**#10 — Bandeau bas : logique inversée** ✅
- `BandeauBas.vue` : `isCollapsed = ref(true)` par défaut
- `onMouseLeave` : repli immédiat (suppression du timer 3s)
- Opacité bandeau déployé : 70%
**#11 — Bouton Soutenir recentré** ✅
- `bandeau-col--center` : `padding-top: 8px` pour décaler vers le bas dans la hauteur du bandeau
### Cleanup
- Supprimés : `TerritoireTabs.vue`, `TerritoireToggle.vue` (composants morts)
- Supprimée : `pages/ajouter-carte.vue`
- Créées : `pages/agences.vue`, `pages/rag.vue` (placeholders)
- Créé : `components/MobileSheet.vue`
### Décisions d'exécution S5
- **#2 useSwipe** : `@vueuse/core` absent du `package.json` — vanilla touch events choisis pour éviter d'ajouter une dépendance. Même résultat, 0 dép supplémentaire.
- **#5 NocoDB vs Resend** : fallback Resend appliqué conformément aux décisions Jules pré-tranchées. Pas de table NocoDB créée.
- **DOM-TOM desktop** : layout du `index.vue` passé de `flex row (2/3 + 1/3)` à `flex col (Métropole flex-1 + DOM-TOM row 140px)` pour intégrer l'Option A cohéremment.
### Build & deploy
- Build : `npx nuxt build` ✅ (223 modules client, 134 modules serveur)
- Deploy : tar → SSH → `systemctl restart nav-carte`
- Vérif : `curl https://aep.trans-former.fr/ → 200`, service `active`
---
## 2026-04-15 — Session 4 : Phase 2 UX (10 features)
**Exécutant :** Sonnet (agent délégué Opus)
**Durée :** ~1h30
### Réalisé
**Feature 1 — Modal fiche sidebar desktop**
- Composant `FicheModal.vue` : overlay centré max-w-3xl (768px), 90vh scroll interne
- Backdrop semi-transparent, fermeture Esc / clic backdrop / bouton croix
- Lien "Ouvrir" → `/fiche/[id]` (URL partageable préservée)
- Fetch `$fetch('/api/fiche/X')` avec watch sur orgId
- `onSelectOrg` desktop (≥1024px) → ouvre modal
- Mobile : comportement inchangé (navigation vers `/fiche/[id]`)
**Feature 2 — Fusion Outre-mer (suppression TerritoireTabs)**
- Desktop : layout flex `flex:2` Métropole + `flex:1` bandeau DOM-TOM (max 340px, OutremerMap réutilisé)
- Mobile : section DOM-TOM scroll horizontal avec compteurs par territoire
- `TerritoireTabs` retiré du template (composant conservé, non utilisé)
**Feature 3 — CartoDB Positron + layer control + maxBounds**
- `NavMap.vue` : fond par défaut CartoDB Positron (`light_all`), layer control 3 fonds (Clair / Schématique Stamen / Standard OSM)
- `maxBounds` France métr. `[41-51.5°N, -5.5-10°E]`, `minZoom: 5`, `maxZoom: 18`
- `OutremerMap.vue` : fond CartoDB Positron par défaut (sans layer control)
**Feature 4 — Bandeau bas rétractable desktop**
- `bg-opacity-80` (rgba 0.8)
- Auto-collapse après 3s, déploie au hover ou mouvement souris < 80px du bas
- Barre fine `32px` en état rétracté avec label "AEP · Transparence IA"
**Features 5+6 — Textes bandeau corrigés + lien Liberapay**
- "Coût IA ce mois : X.XX €" + "Tokens : X" (sans ratio budget)
- Tooltip "1 € = 30 fiches mises en ligne" au hover bouton Soutenir
- Lien Liberapay → `https://liberapay.com/trans-former.fr/donate`
- Mobile : BandeauBas absent, remplacé par FAB coeur (gauche) → bottom sheet
**Feature 7 — Logo AEP tooltip**
- Sous-titre "Architecture d'Écologie Politique" visible en `lg:`
- Tooltip au hover pour `sm:` (sans le sous-titre)
- Attribut `title` sur le lien pour accessibilité
**Feature 8 — Header desktop refonte + barre de recherche**
- Barre de recherche ~500px centrée dans le header desktop (≥1024px)
- Sync URL `?q=` via watch, fonctionne depuis toutes les pages
- Boutons "+ Proposer" et "+ Ajouter carte" en haut à droite
- Route `/ajouter-carte` créée (placeholder)
**Feature 9 — Dark mode**
- Toggle soleil/lune en top nav, persistance `localStorage` clé `aep_theme`
- Variables CSS `.dark` dans `main.css` : fonds sombres, texte clair
- Overrides Leaflet (popup, control layers)
- Note : tuile CartoDB dark (`dark_all`) non switchée automatiquement — à améliorer en S5
**Feature 10 — /a-propos CTA Contribuer + lien Liberapay**
- Section "Contribuer" existante améliorée (lien `/donate`)
- Liens Liberapay unifiés sur `/donate`
### Commits
| Hash | Message |
|------|---------|
| `46b6051` | feat(aep-s4): CartoDB Positron + layer control + maxBounds France |
| `3c036db` | feat(aep-s4): logo AEP + tooltip nom complet + dark mode toggle |
| `775ec64` | feat(aep-s4): dark mode CSS variables + Leaflet overrides |
| `9736ba7` | feat(aep-s4): bandeau bas — rétractable desktop + FAB mobile + textes corrigés |
| `d092fd0` | feat(aep-s4): /a-propos — liens Liberapay corrigés (/donate) |
| `955a561` | feat(aep-s4): page /ajouter-carte (placeholder bientôt disponible) |
| `b406cc9` | feat(aep-s4): fusion outremer — suppression TerritoireTabs + vue 2/3+1/3 |
| `2b43e90` | feat(aep-s4): modal fiche sidebar desktop |
### Build & Deploy
- `npm run build` : ✓ 2.84 MB bundle
- Deploy VPS : ✓ `systemctl is-active = active`
- `curl -sI https://aep.trans-former.fr/` : HTTP/2 200
### Points d'attention pour S5
- Dark mode tuile Leaflet : switcher automatiquement vers `dark_all` CartoDB quand `.dark` est actif
- BandeauBas détection mobile avec `isMobile` ref côté client : SSR safe (montage) mais risque blink. Envisager `useWindowSize` ou classe CSS média
- `TerritoireTabs` et `TerritoireToggle` non utilisés → à archiver ou supprimer en S5
- Barre de recherche header : sur les pages `/fiche/[id]` et `/a-propos`, la recherche navigue vers `/?q=X` — comportement acceptable mais pas élégant
- Modal fiche : pas de CommentForm affiché côté SSR (correctement client-only via watch)
---
## 2026-04-14 — Session 3a : Chatbot API (Étape 5bis)
**Exécutant :** Sonnet (agent chatbot)
**Durée :** ~30 min
### Réalisé
**ChatbotSheet.vue** — Déjà complet (S2) : onboarding exact E-spec §Détails chatbot, bulles user/assistant, fiches recommandées avec lien, erreurs 429/503, animation slide-up mobile.
**API POST /api/chatbot** (nouveau) :
- Rate limit : 10 req/IP/jour via `rateLimitJson.ts` (JSON + SHA-256 RGPD, spec F §8)
- Circuit breaker : vérification budget 20€/mois via `circuitBreaker.ts` → HTTP 503 si dépassé
- Keyword scoring : extraction mots-clés question → score sur nom+description+tags → top 20 fiches
- Filtrage optionnel par `fonction` et `echelle` si fournis dans le body
- Appel Mistral Small (mistral-small-latest, temp 0.3, max 600 tokens, json_object)
- Parse JSON → `{ reponse_texte, fiches_recommandees: [{ id, nom, explication }] }`
- Log asynchrone `stats_usage` (non bloquant)
**Helpers nouveaux** :
- `server/utils/rateLimitJson.ts` — fichier JSON par IP hashée SHA-256 dans `/tmp/nav-ratelimit/`
- `server/utils/circuitBreaker.ts` — budget check NocoDB stats_usage + calcul coût Mistral Small/Nemo
- `nuxt.config.ts` — ajout `statsTableId` (défaut `mbbq7n47ixy19mc`)
### Décisions
| Décision | Détail |
|----------|--------|
| rateLimitJson vs Redis existant | JSON fichier créé séparément (spec F §8 + RGPD SHA-256). Redis existant conservé pour submit/comment. Les deux coexistent. |
| Prompt Mistral Small | Construit depuis E-spec-frontend.md §Détails chatbot — pas de prompt verbatim dans F-spec §3 (qui est Nemo enrichissement). **Checkpoint Jules requis avant deploy prod.** |
| circuitBreaker.ts | Worker absent → créé dans server/utils/ (source unique, réutilisable par le futur worker) |
| statsTableId | Défaut hardcodé `mbbq7n47ixy19mc` + env var `STATS_TABLE_ID` en override |
### Commits
- `718e9f6` — feat(chatbot): API /api/chatbot + rate limit JSON SHA-256 + circuit breaker
### Build
- `npm run build` : ✓ sans erreur, 2.78 MB bundle
### TODO avant deploy (S3b)
- [ ] `STATS_TABLE_ID=mbbq7n47ixy19mc``/opt/nav-carte/.env` (confirmer ou corriger l'ID)
- [ ] Vérifier que `/tmp/nav-ratelimit/` est accessible en écriture sur VPS (droits node)
- [ ] Cron journalier reset `/tmp/nav-ratelimit/` (0h UTC) → à ajouter en S3b
- [ ] Tester chatbot 2-3 requêtes réelles sur VPS après deploy
- [ ] **Checkpoint Jules** : valider prompt Mistral Small (construit, pas copié-collé de F-spec)
---
## 2026-04-14 — Session 2 Ajustements UX v3
**Pilote :** Sonnet
**Durée :** ~30 min
### Réalisé
**A) Search desktop déplacé top nav → sidebar (haut)**
- `TopSearchBar` retiré du header `app.vue` — top nav épuré (logo + Contribuer + Aléatoire)
- Barre recherche inline ajoutée en haut de `NavSidebar.vue` : toujours visible, pleine largeur sidebar, styles scoped `sidebar-search-*`
- Focus ring `var(--nav-primary)`, bouton clear intégré
- Mobile inchangé (search sticky bandeau entre filtres et liste)
- URL sync `?q=` conservé via `pages/index.vue`
- Commit : `3f88e86`
**B) Chatbot desktop cliquable + expand/collapse**
- `ChatbotPlaceholder.vue` refactorisé : état replié (56px) → étendu (45vh) au clic
- Header entier cliquable + chevron dédié avec rotation SVG 180° animée
- `transition: max-height 0.3s ease` — animation fluide
- Zone étendue : placeholder conversation S3, overflow-y auto
- Mobile `ChatbotSheet.vue` inchangé
- Commit : `88d0319`
### Build
- `npm run build` clean (0 erreurs, 0 warnings TS)
---
## 2026-04-14 — Session 1 : Setup + Fondations
**Pilote :** Opus
**Exécutants :** Sonnet-1 (VPS/NocoDB), Sonnet-2 (seed parsing)
**Durée estimée session :** 4-5h
### Décisions validées
| Décision | Détail | Source |
|----------|--------|--------|
| Palette | A (sobre institutionnel) + bleu nuit #1a2238 à 60% opacité **partout** (bandeau, pins, chips, surlignages) | Jules 2026-04-14 |
| Texte | Bleu plein pour titres/courant (lisibilité > esthétique) | Déduction palette |
| Liberapay | `liberapay.com/trans-former.fr` (pas `nav-archi`) | Jules |
| Seed | Bypass modération pour 94 fiches, 2-3 réservées pour test pipe IA (doc de la pipe → skill Mistral Nemo futur) | Jules |
| Liberapay transparence | Section dédiée dans `/a-propos` (étape 8), pas dans le bandeau | Jules |
| Circuit breaker dépassé | Bandeau "manque de fonds" + CTA Liberapay + pédagogie "1€ = N requêtes" + transparence origine Liberapay | Jules |
| From email modération | `contact@trans-former.fr` (existant Resend) | Jules |
| Session stratégie | 3 sessions dédiées (S1 fondations, S2 front, S3 IA+deploy) — préserve jauge Opus, use Sonnet pour exécution | Jules |
| Tokens | Mistral key stockée dans `/opt/nav-carte/.env`, jamais committée | Standard |
### Réalisé
**Sonnet-1 — Setup VPS + schéma NocoDB :**
- Token NocoDB `nav-v2-worker` créé : `R-Yhd_0KgfW0ZjFxIl5iNyLS1ca7VpP8dNbo4OOa`
- `/opt/nav-carte/.env` créé (chmod 600) avec `MISTRAL_API_KEY`, `NOCODB_TOKEN`, `NOCODB_BASE`, `NOCODB_TABLE_*`, `RESEND_FROM`, `NOCODB_URL`
- crawl4ai 0.8.6 installé via pip (`--ignore-installed` pour conflit lib `rich`)
- Table `organisations` (`m08t7g5v4wch6wb`) étendue : 19 champs ajoutés
- Contenus : url, description_user, description_enrichie, points_cles, localisation_ville, submitted_by_email, moderator_note, ai_raw_output, scrape_content
- Taxonomie : echelle (SingleSelect), territoire (SingleSelect), tags_fonction (MultiSelect)
- État : scrape_status, moderation_status, ai_processed (Checkbox)
- Géo : latitude, longitude
- Meta : submitted_at, moderated_at
- Table `stats_usage` créée : `mbbq7n47ixy19mc` (model, endpoint, tokens_in/out, cout_eur, timestamp, orga_id)
- Table `scrape_queue` skippée : F§2 n'en définit pas, la pipe utilise `scrape_status` sur `organisations`
- Tests insert/update OK sur les deux tables avec nouveau token
**Sonnet-2 — Parsing biblio + géocodage seed :**
- 93 entités parsées (A-biblio annonçait 94, erreur de comptage source)
- 72 géocodées via Nominatim, 21 sans ville (lat/lon null, pas de fallback centre France pour éviter bruit carte)
- Correction manuelle Saint-Ouen (93) vs Saint-Ouen-l'Aumône (Picardie)
- 3 fiches réservées test pipe IA : CNOA, Archireport, Collectif Fil
**Sonnet-3 — Re-tag + CROA + import NocoDB :**
- Re-tag : 32 Prospection → Développement, 17 RH → Gestion d'agence
- Formation détecté et ajouté à 9 fiches (Réseau des MA, Cité de l'Archi, MAJ, CFAA, REFC'A, DU Dauphine, UNAID, FFP, Cité Archi Formation continue)
- 13 CROA régionaux : 6 créés + 7 existants enrichis (tous avec "Gestion d'agence")
- CNOA National isolé et réservé aux 3 fiches test pipe IA
- **96 fiches importées** dans NocoDB (99 v2 3 test pipe)
- Apostrophe typographique U+2019 appliquée pour compat NocoDB
- Anomalie : 8 anciens records V1 présents (IDs 1-8, `moderation_status null`) → **à purger avant mise en prod**
### Anomalies & points à surveiller
1. **Taxonomie `moderation_status` — divergence F/G**
- F§2 définit : `approved` / `rejected`
- G mentionne : `published` / `approved`
- Front V1 existant utilise : `approved`
- **Décision Session 2 :** rester sur `approved`/`rejected` partout, retirer `published` du prompt G si la doc est mise à jour. Le statut `pending` (avant modération) existe de fait comme absence de validation.
2. **Endpoint NocoDB 0.301.5**
- L'endpoint correct pour ajouter des colonnes est `/api/v1/db/meta/tables/{id}/columns`
- L'endpoint `/api/v2/meta/tables/{id}/fields` n'existe PAS dans cette version
- Le MCP `nocodb` n'était pas configuré avec la bonne URL de base → contournement direct par SSH + curl
- **TODO :** reconfigurer le MCP nocodb pour qu'il pointe correctement (utile pour sessions futures)
3. **Disque VPS : 72,4%** (était 69,8% avant install crawl4ai)
- crawl4ai a pris ~2,6 GB
- Hypothèse : Playwright + Chromium embarqué (crawl4ai utilise Playwright pour les pages JS)
- **Marge :** OK pour Sessions 2-3. À surveiller quand on commencera à scraper et stocker du contenu dans `scrape_content`
- **Alternative si problème disque :** remplacer crawl4ai par `httpx + BeautifulSoup` pour le scraping statique (bien plus léger, mais perd le rendu JS)
- **TODO :** vérifier via `du -sh` le poids exact de crawl4ai et ses deps Playwright, décider si on garde ou on allège
4. **Conflit lib Python `rich`**
- Résolu avec `pip install --ignore-installed`
- Risque : peut casser un autre outil Python VPS qui utilise `rich` (lightrag, formations, etc.)
- **TODO :** vérifier que lightrag et autres services Python tournent toujours
### Fichiers produits
- `/opt/nav-carte/.env` (VPS, chmod 600)
- Tables NocoDB : `organisations` étendue + `stats_usage` nouvelle
- `0 INBOX/NAV-V2-recherches/palette-nav-v2.md` — palette finale CSS
- `0 INBOX/NAV-V2-recherches/palettes-preview.html` — mockup validé
- `0 INBOX/NAV-V2-recherches/seed-94-fiches.json` *(à produire par Sonnet-2)*
- `0 INBOX/NAV-V2-recherches/seed-94-rapport.md` *(à produire par Sonnet-2)*
### Prochaines étapes
- Sonnet-2 finit le parsing + géocoding
- Import seed NocoDB (bypass modération, 2-3 fiches réservées test pipe IA)
- Rédaction des prompts Sessions 2 et 3 (livrable fin Session 1)
---
## Taxonomie finale NAV V2 (validée 2026-04-14)
**Échelle** (3 niveaux) : `National` / `Régional` (inclut Départemental) / `Local`
**Territoire** : `Métropole` + 5 DOM-TOM (Guadeloupe, Martinique, Guyane, La Réunion, Mayotte)
**Fonctions** (10 tags, multi 1-5, ordre = priorité) :
1. Juridique
2. Technique
3. Économique *(strictement finance : aides, fiscalité, rentabilité, tarification)*
4. Administratif *(démarches externes : permis, OA, déclarations)*
5. Chantier
6. Comptabilité
7. **Développement** *(ex-Prospection — AO, concours, réseaux pro, acquisition clients)*
8. **Formation** *(NOUVEAU — école, MOOC, organisme, formation continue)*
9. **Gestion d'agence** *(ex-RH — élargi : RH + management + pilotage + orga interne)*
10. Santé mentale
**Renommages appliqués :**
- Prospection → Développement
- RH → Gestion d'agence (élargi)
- Ajout : Formation
**Cas particuliers :**
- CNOA → éclaté en 1 fiche National (siège Paris) + 13 fiches CROA Régional (préfectures de région)
- Option 3 (antennes pins secondaires via champ multi-coords) → backlog V3
## Points ouverts (à trancher en amont des prochaines sessions)
- [ ] Session 2 : choix rate limit chatbot (fichier JSON vs Redis)
- [ ] Session 3 : seuil email modération (N fiches en attente → envoi)
- [ ] Facteur CO2eq : confirmer `0.052 kg CO2/kWh` (RTE FR) ou utiliser valeur plus récente (ADEME 2024 ≈ 0.055)
- [ ] Nominatim policy : user-agent `NAV-V2/1.0 (contact@trans-former.fr)` → OK ?
- [ ] UX Session 2 : options échelle vides (Local) + onglet Outre-mer vide → afficher avec compteur "0" pour inviter à contribuer (cohérent esprit collaboratif)
## Enrichissement DOM-TOM (post V2)
Session d'enrichissement à lancer après déploiement V2 :
- Recherche ciblée par territoire (Guadeloupe, Martinique, Guyane, La Réunion, Mayotte)
- Sources : CROA locaux, maisons de l'archi outre-mer, réseaux pro insulaires
- Agent Sonnet-research 1-2h → complément seed
## Piste externe : team.archi
Contacter le fondateur de team.archi (forum entraide archi) pour :
- Lui présenter NAV V2 (esprit, périmètre)
- Demander si team.archi documente d'autres réseaux d'entraide qu'on pourrait intégrer
- Proposer un échange / listing mutuel
Brouillon email à préparer (requiert nom + email fondateur de Jules).
---
---
## 2026-04-14 — Session 2 : Front — Carte + Sidebar Filtres
**Exécutant :** Sonnet (agent)
**Durée :** ~1h
### Décisions prises
| Décision | Détail |
|----------|--------|
| Leaflet sans plugin Nuxt | `@nuxtjs/leaflet` a une compat instable avec Nuxt 3.15 — import dynamique direct dans `onMounted()` + `<ClientOnly>` wrapper. Plus fiable, zéro config SSR à gérer. |
| Cluster seuil 15 (spec dit 15+) | `disableClusteringAtZoom: 14` — au-delà de zoom 14 les pins se défiltrent, cohérent avec la granularité ville/rue |
| `@headlessui/vue` installé mais non utilisé pour le drawer | Le drawer implémenté en Vue natif (Teleport + transition) est plus léger et sans dépendance. `@headlessui/vue` reste disponible pour l'étape 3 (modales commentaires). |
| Seed JSON : Id fictif 1000+ | Pour éviter collision avec les IDs NocoDB réels (1-96+). Les URLs `/fiche/1000+` ne seront pas résolues en prod — comportement attendu en dev. |
| `moderation_status=approved` | Confirmé — retirer `published` du filtre comme résolu en Session 1 |
| Compteurs calculés sur orgs non filtrées | Les (0) montrent les options sans aucune fiche dans la base totale, pas dans la sélection courante. Plus honnête vis-à-vis de l'invitation à contribuer. |
### Composants créés
- `NavMap.vue` — Leaflet + OSM + clusters + pins personnalisés
- `EchelleFilter.vue` — chips exclusifs National/Régional/Local
- `FonctionFilter.vue` — multi-sélect 10 fonctions (max 5)
- `TerritoireToggle.vue` — Métropole + 5 DOM-TOM sous-onglets
- `NavSidebar.vue` — wrapper desktop
- `FilterDrawer.vue` — drawer mobile (Teleport + transition Vue native)
### Fichiers modifiés
- `assets/css/main.css` — tokens CSS palette NAV V2 + surcharges Leaflet/clusters
- `tailwind.config.js` — couleurs `nav.*` ajoutées
- `nuxt.config.ts` — optimizeDeps Leaflet pour Vite
- `server/routes/api/organisations.get.ts` — V2 champs + fallback seed JSON
- `pages/index.vue` — refonte complète layout + filtres + URL sync
### Commits Session 2
- `64f5b0a` — feat(deps): installer leaflet, markercluster, headless UI
- `dc849ef` — feat(style): palette NAV V2 — tokens CSS + tailwind
- `799d8fc` — feat(api): GET /api/organisations V2 avec fallback seed JSON
- `450a45c` — feat(components): carte Leaflet + sidebar filtres (étape 2)
- `3f486df` — feat(page): index.vue V2 — carte + sidebar + URL sync
### Validation build
- `npm run build` : ✓ sans erreur, 2.09 MB bundle
### Notes pour Sonnet 2 (étape 3 — fiche détail)
- `@headlessui/vue` installé et disponible si besoin pour la modale commentaires
- Interface `Org` définie dans `pages/index.vue` — à extraire dans `types/org.ts` si partagée (étape 3 en aura besoin)
- Route API existante : `GET /api/organisations/[id]` dans `server/routes/api/organisations/[id].get.ts` — fonctionne, utiliser tel quel
- Champ `description_enrichie` prévu mais absent du seed — prévoir fallback sur `description`
- Champ `points_cles` : chaîne ou JSON array ? Vérifier dans NocoDB avant d'afficher
### Notes pour Sonnet 3 (étape 6 — formulaire contribuer)
- Route `POST /api/organisations` existe déjà en V1 (`server/routes/api/organisations.post.ts`) — à adapter pour V2 (nouveaux champs + moderation_status: pending)
- Zod non encore installé — à ajouter dans package.json
- Rate limit : trancher JSON simple (recommandé pour MVP) vs Redis
### Points ouverts
- [ ] 8 anciens records V1 (IDs 1-8, moderation_status null) à purger en prod
- [ ] Vérifier type de `points_cles` dans NocoDB avant rendu fiche (string ou JSON)
- [ ] Tester carte sur VPS avec données NocoDB réelles (96 fiches)
---
---
## 2026-04-14 — Session 2 (suite) : Spec définitive — Top nav + chatbot + filtres
**Exécutant :** Sonnet 2/3
**Durée :** ~1h
### Décisions prises
| Décision | Détail |
|----------|--------|
| `app.vue` = layout global | Refondu avec top nav (logo + TopSearchBar + Contribuer + Aléatoire). Supprime le header V1 (vert sage). NuxtPage prend le flex-1 restant. |
| Recherche top nav → URL `?q=` | TopSearchBar émet vers app.vue → router.replace ?q=. pages/index.vue watch route.query.q. Pas de prop passée via NuxtPage (non supporté simplement). |
| Sidebar sans recherche | Input recherche retiré de NavSidebar — redondant avec top nav. |
| Sidebar sans chatbot | Zone chatbot déplacée dans la zone carte (bas). |
| ChatbotPlaceholder sous carte | Input désactivé 52px, fond `--nav-bg`. Présent sous Métropole ET Outre-mer. |
| Échelle multi-select (string[]) | EchelleFilter + NavSidebar + FilterDrawer + pages/index.vue tous adaptés en `string[]`. Plus de `string \| null`. |
| Fiche aléatoire | ?random=1 dans l'URL → pages/index.vue redirige vers /fiche/[id] aléatoire. |
| shadcn | Écarté — Vue+Tailwind+CSS scoped suffit, zéro complexité d'intégration. |
| Bonus "ouvrir chatbot" | Skippé — pas de valeur avant S3. |
### Composants créés
- `TopSearchBar.vue` — barre recherche animée (compact 44px → 280px au focus), CSS scoped
- `ChatbotPlaceholder.vue` — zone bas carte, input désactivé, réserve espace S3
### Composants modifiés
- `app.vue` — refonte complète layout global (V1 sage vert → V2 bleu nuit)
- `pages/index.vue` — supprime header dupliqué, intègre ChatbotPlaceholder, échelle string[]
- `EchelleFilter.vue` — single-select → multi-select (string[])
- `NavSidebar.vue` — supprime input recherche + zone chatbot, prop echelle string[]
- `FilterDrawer.vue` — prop echelle string[], activeCount adapté
### Commits Session 2 (suite)
- `33fbd3b` — feat(nav): top nav global avec barre de recherche animée
- `1d5d9ab` — feat(ux): chatbot placeholder sous la carte + sidebar sans chatbot
- `905f338` — feat(filtres): échelle multi-select + sidebar sans recherche ni chatbot
### Validation build
- `npm run build` : ✓ sans erreur, 2.12 MB bundle
### Points en attente / non implémentés
- [ ] TerritoireTabs dans le drawer mobile — non dupliqué (à faire si besoin)
- [ ] Fiche aléatoire nécessite que les orgs soient chargées — si orgs vides au moment du ?random=1, pas de redirect. Acceptable pour MVP.
---
---
## 2026-04-14 — Session 2 (Sonnet 2) : Fiche détail + Commentaires
**Exécutant :** Sonnet 2 (agent NAV V2)
**Durée :** ~1h
### Décisions prises
| Décision | Détail |
|----------|--------|
| types/org.ts | Interface Org canonique extraite — suppression des 2 déclarations dupliquées dans index.vue et fiche/[id].vue |
| Route API dédiée | GET /api/fiche/[id] dans server/api/fiche/ (distinct de server/routes/api/organisations/[id]) — meilleure séparation des responsabilités |
| Table commentaires | commentTableId = COMMENT_TABLE_ID ?? AVIS_TABLE_ID (fallback table V1 si pas de table dédiée configurée) |
| Mistral Nemo timeout | 2s via AbortController — fallback safe_check: 'pending' si timeout ou clé absente |
| Retour filtres | sessionStorage nav_back_filters (pas de query param _back) — plus simple, pas de fuite dans URL partagée |
| mini-carte | Leaflet non-interactif dans FicheDetail — zoom:10, dragging:false, toutes interactions désactivées |
| points_cles | Tente JSON.parse d'abord, fallback découpage par lignes si format texte |
| Rate limit Redis | Posé par Sonnet 3 — server/utils/rateLimit.ts avec fallback mémoire si Redis KO |
### Composants créés
- `components/FicheDetail.vue` — affichage complet avec mini-carte Leaflet
- `components/CommentSection.vue` — liste commentaires publiés + refresh prop
- `components/CommentForm.vue` — formulaire soumission + gestion 429
### Routes API créées
- `server/api/fiche/[id].get.ts` — proxy NocoDB champs V2 complets
- `server/api/comment/index.post.ts` — filtre éthique Mistral Nemo (timeout 2s, fallback pending)
- `server/api/comment/[orgId].get.ts` — commentaires publiés triés chronologiquement
### Fichiers modifiés
- `pages/fiche/[id].vue` — refonte complète SSR (FicheDetail + CommentSection + CommentForm + SEO)
- `pages/index.vue` — ajout storeFiltersForBack() pour sessionStorage + import type Org
- `types/org.ts` — CRÉÉ : interface canonique V2
- `nuxt.config.ts` — ajout mistralApiKey + commentTableId
### Commits Session 2 (Sonnet 2)
- `a653336` — refactor(types): extraire interface Org canonique dans types/org.ts
- `89bd22a` — feat(api): GET /api/fiche/[id] + POST/GET /api/comment avec filtre Mistral Nemo
- `06c44cd` — feat(components): FicheDetail + CommentSection + CommentForm
- `420f534` — feat(page): /fiche/[id] SSR complète — FicheDetail + comments + SEO + retour filtres
### Validation build
- `npm run build` : ✓ sans erreur, 2.74 MB bundle
### Coordination Sonnet 3 (rate limit Redis)
**Posé par Sonnet 3 :** `server/utils/rateLimit.ts` (ioredis + fallback mémoire) importé dans POST /api/comment.
Sonnet 3 a modifié `server/api/comment/index.post.ts` pour brancher `checkRateLimit(ip, 'comment', 5)`.
Configuration : `REDIS_URL` dans `.env`, fallback mémoire si Redis KO (dev sans Docker).
### Points ouverts pour Session 3
- [ ] `public/og-default.png` à créer (logo par défaut pour og:image) — actuellement référencé, pas encore créé
- [ ] `COMMENT_TABLE_ID` à ajouter dans `.env` VPS si table dédiée à part de `AVIS_TABLE_ID`
- [ ] `MISTRAL_API_KEY` à vérifier dans `/opt/nav-carte/.env` — la clé est dans le .env VPS (Session 1), juste s'assurer du nom de variable exact
- [ ] Vérifier type de `points_cles` dans NocoDB (JSON array stringifié ou texte brut ?)
- [ ] Tester sur VPS avec données NocoDB réelles (96 fiches seed)
---
## 2026-04-14 — Session 2 (parallèle) : Étape 6 — Formulaire `/contribuer` + Redis rate limit
**Exécutant :** Sonnet 3 (agent)
### Redis VPS
- `redis-server` absent au départ (pas mentionné dans VPS-check.md)
- Installé : `apt-get install redis-server``systemctl enable + start`
- Bind : `127.0.0.1 -::1` uniquement (localhost, sécurisé)
- Test : `redis-cli ping` → PONG ✓
- **En prod :** ajouter `REDIS_URL=redis://127.0.0.1:6379` dans `/opt/nav-carte/.env`
- **En dev local :** fallback compteur en mémoire (ioredis lazyConnect — pas de crash si Redis absent)
### Fichiers produits
| Fichier | Description |
|---------|-------------|
| `server/utils/rateLimit.ts` | Helper Redis générique — `checkRateLimit(ip, action, maxPerDay)` avec fallback mémoire |
| `server/api/submit/index.post.ts` | POST /api/submit — Zod + Nominatim + NocoDB pending + rate limit 3/IP/j |
| `server/api/comment/index.post.ts` | Rate limit Redis 5/IP/j ajouté en tête (base Sonnet 2) |
| `pages/contribuer.vue` | Page dédiée — 8 champs, validation Zod client+serveur, 422/429, succès + trackingUrl |
### Décisions
| Décision | Détail |
|----------|--------|
| Page vs modal | Page dédiée `/contribuer` — plus simple pour MVP. Route duale desktop (redirect ?contribute=1 + modale) en backlog V2.1 |
| description_user | K-prompt (50-500) > E-spec (20-200) — tranché : 50-500 chars |
| Champ ville | Optionnel (K-prompt) — moins de friction, fallback fiche sans coords prévu |
| NOCODB_BASE_ID | Valeur fallback `p_nav_v2` dans le code. À confirmer : `ssh vps-hetzner "grep -i base /opt/nav-carte/.env"` |
### Rate limits posés (Redis)
- `/api/submit` : **3 soumissions / IP / jour**
- `/api/comment` : **5 commentaires / IP / jour**
### Commits
- `d9b6a31` — feat(deps): ajouter zod + ioredis + REDIS_URL runtime config
- `e81625f` — feat(server): helper rate limit Redis avec fallback mémoire
- `5c24c06` — feat(api): POST /api/submit — validation Zod + geocoding + NocoDB pending
- `fc0c52c` — feat(page): /contribuer — formulaire V2 Zod client + UX mobile-first
- (rate limit /api/comment dans commit Sonnet 2 `420f534`)
### Build
- `npm run build` : ✓ sans erreur, 2.74 MB bundle
### TODO avant prod
- [ ] `REDIS_URL=redis://127.0.0.1:6379``/opt/nav-carte/.env` (VPS)
- [ ] Confirmer `NOCODB_BASE_ID` : `ssh vps-hetzner "grep -i base /opt/nav-carte/.env"`
- [ ] Tester submit valide → fiche `pending` dans NocoDB
- [ ] Tester 4ème submit → vérifier HTTP 429
---
## 2026-04-14 — Session 2 (Étape 2) : Mobile UX
**Exécutant :** Sonnet 1.8 (agent NAV V2 Mobile)
**Durée :** ~1h
### Décisions prises
| Décision | Détail |
|----------|--------|
| FilterDrawer supprimé | L'ancien drawer filtres (bouton flottant gauche, slide depuis gauche) est supprimé. Les filtres sont désormais inline dans le flow mobile. |
| ChatbotSheet nouveau composant | `ChatbotSheet.vue` — bottom sheet plein écran, Teleport + transition slide-up, `92dvh`, input désactivé (S3), fermeture backdrop + bouton Retour. |
| Carte mobile 45dvh | `height: 45dvh` sur mobile, `min-height: 180px`. `dvh` pour éviter le bug clavier mobile. |
| Tagging compact inline | Bandeau entre carte et liste : échelle 3 checkboxes `16px` avec labels courts (Nat/Rég/Loc) + fonctions scroll horizontal `overflow-x: auto`. |
| Tap card → centre carte | `onSelectOrgMobile``selectedId` change → `NavMap.vue` réagit via `watch selectedId → mapInstance.panTo`. |
| Bouton chatbot flottant | `56×56px`, `bottom: 1.5rem; right: 1rem`, `opacity: 0.88`, `z-[1000]`, `lg:hidden`. |
| Multi-Leaflet Outre-mer | Grille 5 mini-cartes existante conservée — build clean, à tester en conditions réelles. |
| Poignée draggable | Skippé — estimé > 30 min, noté pour Session 3. |
| Interface Org | Sonnet 2 a extrait `types/org.ts`, linter auto-appliqué l'import dans `pages/index.vue`. |
### Composants créés
- `ChatbotSheet.vue` — bottom sheet chatbot plein écran (92dvh, slide-up, backdrop, poignée visuelle, input désactivé)
### Composants supprimés
- `FilterDrawer.vue` — drawer filtres mobile (remplacé par tagging inline + ChatbotSheet)
### Fichiers modifiés
- `pages/index.vue` — refonte complète zone mobile + bouton chatbot flottant + ChatbotSheet
### Commits Session 2 (Mobile)
- `d39e7be` — feat(mobile): ChatbotSheet — bottom sheet plein écran avec animation slide-up
- `0843301` — feat(mobile): supprimer FilterDrawer — remplacé par tagging inline + ChatbotSheet
- `pages/index.vue` — inclus dans refacto Sonnet 2 (`a653336` → import `types/org.ts`)
### Validation build
- `npm run build` : ✓ sans erreur, 2.12 MB bundle
### Backlog mobile S3
- [ ] Poignée draggable entre carte et liste (drag resize)
- [ ] Multi-Leaflet Outre-mer mobile à tester en conditions réelles → fallback dropdown si trop lourd
- [ ] Animation léger zoom pin au tap card (spec F)
- [ ] Chatbot IA branché (Session 3)
---
---
## 2026-04-14 — Session S2 Ajustements finaux v2 (correctif branding + polish)
**Exécutant :** Sonnet 1.9b (agent AEP V2)
### Contexte
L'agent précédent avait commis une erreur de spec sur le renommage : "NAV" avait été remplacé par "Écosystème Architecture" dans les textes visibles. La bonne règle est : "NAV" (texte visible) → "AEP" (Architecture d'Écologie Politique).
### Corrections branding (commit fix)
| Fichier | Avant | Après |
|---------|-------|-------|
| `app.vue` logo icône | `N` | `A` |
| `app.vue` logo texte | `Écosystème Archi.` | `AEP` |
| `components/ChatbotSheet.vue` | `aria-label="Assistant Écosystème Architecture"` | `aria-label="Assistant AEP"` |
| `pages/index.vue` SEO title | `Écosystème Architecture — Cartographie AEP` | `AEP — Cartographie de l'écologie politique architecturale` |
| `pages/contribuer.vue` SEO title | `Proposer une ressource — Écosystème Architecture` | `Proposer une ressource — AEP` |
| `pages/ajouter.vue` SEO title | `Proposer une fiche — Écosystème Architecture` | `Proposer une fiche — AEP` |
| `pages/fiche/[id].vue` og:description fallback | `Fiche organisation — NAV Architectes` | `Fiche organisation — AEP` |
| `pages/fiche/[id].vue` SEO title | `{nom} — NAV` | `{nom} — AEP` |
| `pages/fiche/[id].vue` og:title | `{nom} — NAV Architectes` | `{nom} — AEP` |
### Ajustements complémentaires
- Bouton flottant mobile : icône seule → pill avec texte "Chatbot" visible (48px h, gap-2, font-weight 600)
### État des 4 ajustements spec
| # | Ajustement | État |
|---|-----------|------|
| 1 | Échelle inline 1 ligne | ✓ Fait par agent précédent (`EchelleFilter.vue` `flex-wrap gap-x-4`) |
| 2 | NAV → AEP (textes visibles) | ✓ Corrigé dans ce commit |
| 3 | Mobile search au-dessus liste | ✓ Fait par agent précédent (lignes 167-203 `pages/index.vue`) |
| 4 | Bouton mobile "Chatbot" | ✓ Fait dans ce commit (pill avec label visible) |
### Build
- `npm run build` : ✓ sans erreur, 2.74 MB bundle
---
## 2026-04-14 — Session 3 : Chatbot IA (Étape 5bis)
**Pilote :** Opus
**Exécutant :** agent Sonnet S3
**Durée :** ~1h
### Réalisé
**ChatbotSheet.vue (mobile) — refactorisé :**
- Conversation IA complète : messages user/assistant, scroll auto, loading dots
- Message onboarding exact (texte E §6) affiché avant la première question
- Bulles fiches recommandées : card compacte avec lien `/fiche/[id]` + explication
- Erreurs typées : 429 (rate limit), 503 (budget épuisé), fallback générique
- Emit `highlightOrgs` pour highlight carte
- Animations slide-up + `prefers-reduced-motion` respecté
**ChatbotPlaceholder.vue (desktop) — refactorisé :**
- Même conversation IA que le mobile, format panneau latéral expand/collapse
- Même onboarding, mêmes bulles fiches, même gestion d'erreurs
- Input en bas du panneau étendu, Enter pour envoyer
**server/api/chatbot/index.post.ts — créé :**
- Rate limit : `checkRateLimit(ip, 'chatbot', 10)` via helper Redis S2 existant
- Circuit breaker : lecture cumul `stats_usage` mois courant, 503 si ≥ 20€
- Fetch top-20 fiches NocoDB (`moderation_status=approved`) avec scoring keyword
- Contexte JSON compact injecté dans le prompt système Mistral Small
- Appel `mistral-small-latest` (temperature: 0.3, max_tokens: 600, json_object)
- Parse JSON → `{ reponse_texte, fiches_recommandees }`
- Log `stats_usage` (fire and forget)
### Décisions
| Décision | Détail |
|----------|--------|
| Rate limit helper | Réutilisation du helper Redis S2 (`checkRateLimit`) — plus robuste que JSON fichier /tmp. Comportement identique (10 req/j). |
| `STATS_TABLE_ID` env | Valeur par défaut `mbbq7n47ixy19mc` (créé en S1) — override via env si besoin |
| Scoring fiches | Keyword match sur nom + description + tags — suffisant pour MVP, pas de vector search |
| `prefers-reduced-motion` | Animations supprimées si l'utilisateur a activé ce préfé navigateur |
### Build
- `npm run build` : ✓ sans erreur, 2.78 MB bundle
### Commits Session 3 (étape 5bis)
- feat(chatbot): ChatbotSheet mobile + ChatbotPlaceholder desktop — conversation IA branchée
- feat(api): POST /api/chatbot — Mistral Small + rate limit + circuit breaker
### TODO avant prod
- [ ] Vérifier `STATS_TABLE_ID` dans `/opt/nav-carte/.env` (valeur par défaut : `mbbq7n47ixy19mc`)
- [ ] Tester 2-3 requêtes réelles sur VPS avec fiches NocoDB
- [ ] Vérifier index.vue passe bien `highlightOrgs` au NavMap depuis ChatbotSheet et ChatbotPlaceholder
- [ ] Tester mobile iOS Safari + Android Chrome
---
---
## 2026-04-14 — Session 3 (Étapes 4-5) : Worker IA + Test pipeline
**Exécutant :** Sonnet (agent)
**Durée :** ~2h
### Réalisé
**Étape 4 — Worker enrichissement IA :**
- `worker/enrich.js` créé (Node.js ESM, systemd timer 5 min)
- Pipeline complet : fetch pending → scrape crawl4ai → Mistral Nemo → update NocoDB → log stats_usage
- Circuit breaker budget 20€ (filtre JS, car NocoDB v0.301.5 rejette les filtres datetime)
- Email Jules via Resend si seuil 5 fiches pending en modération
- Lock anti-overlap via `/tmp/nav-worker.lock`
- Retry 2x sur erreur Mistral + flag `ai_error` si 3 échecs
**Infrastructure :**
- `worker/package.json` + `node_modules/dotenv` installés
- Variables RESEND_API_KEY, EMAIL_JULES, BUDGET_MAX_EUR, WORKER_LIMIT ajoutées au `.env`
- `nav-worker.service` + `nav-worker.timer` systemd créés et activés
**Étape 5 — Test pipeline sur 3 fiches :**
- 3 fiches injectées en NocoDB (CNOA Id=106, Archireport Id=107, Collectif Fil Id=108)
- Checkpoint 1 fiche (CNOA) : €0.000029, extrapolé 96 fiches = €0.0028 → GO
- 3 fiches enrichies avec succès
### Métriques pipeline
| Fiche | tokens_in | tokens_out | cout_eur | Temps | Confiance |
|-------|-----------|------------|----------|-------|-----------|
| CNOA | 1 248 | 167 | €0.000029 | 3.0s | haute |
| Archireport | 4 376 | 261 | €0.000091 | 3.9s | haute |
| Collectif Fil | 2 628 | 221 | €0.000057 | 4.3s | haute |
| **Total** | **8 252** | **649** | **€0.000177** | **11.2s** | — |
Extrapolation 96 fiches : **€0.0057** (budget 20€ = 3 500× la consommation réelle)
### Problèmes résolus
| Problème | Solution |
|---------|---------|
| Playwright absent → crawl4ai crash | `AsyncHTTPCrawlerStrategy` (mode statique) |
| NocoDB rejette filtres datetime | Filtre JS sur tous les records stats_usage |
| Apostrophe U+0027 dans tags refusée | U+2019 (typographique) partout dans VALID_FONCTIONS |
| import dynamique ESM incompatible | spawnSync importé statiquement |
### Décisions prises en autonomie
| Décision | Raison |
|---------|--------|
| `AsyncHTTPCrawlerStrategy` au lieu d'`AsyncWebCrawler` standard | Playwright non installé sur VPS, mode statique suffisant pour sites archi |
| Filtre budget JS (pas NocoDB) | API NocoDB 0.301.5 ne supporte pas les filtres de date en mode gte |
| `spawnSync` pour appel Python | Évite les complications d'import dynamique en ESM |
### Fichiers produits
- `/opt/nav-carte/worker/enrich.js` — Worker IA principal
- `/opt/nav-carte/worker/package.json` — Dépendances (dotenv)
- `/etc/systemd/system/nav-worker.service` — Service oneshot
- `/etc/systemd/system/nav-worker.timer` — Timer 5 min
- `nav-carte/PIPE-IA-DOC.md` — Documentation complète pipeline + résultats
### TODO avant deploy prod (Étape 9)
- [ ] Chatbot (Étape 5bis) — non implémenté dans cette session
- [ ] Bandeau bas + Liberapay (Étape 7) — non implémenté
- [ ] Page /a-propos (Étape 8) — non implémenté
- [ ] Deploy git sur VPS + build Nuxt production
- [ ] Purger 8 anciens records V1 (IDs 1-8, moderation_status null) avant prod
- [ ] Tester worker sur soumission réelle via /contribuer
- [ ] Vérifier que les 3 fiches test (Ids 106-108) sont modérées ou purgées avant prod (sont en mode test)
---
---
## Session 3b — Deploy final AEP (2026-04-14 soir)
**Durée :** ~3h · **Résultat :** AEP V2 live sur `aep.trans-former.fr` + `nav.trans-former.fr` (alias)
### Dispatch
| # | Action | Modèle | Status |
|---|--------|--------|--------|
| A | Prompt système chatbot Mistral Small | Opus + Jules | ✓ |
| B | Composant `BandeauBas.vue` + endpoint `/api/stats` | Sonnet | ✓ |
| C | Page `/a-propos` (brouillon — texte à réécrire par Jules) | Sonnet | ✓ |
| D | Cron purge `/tmp/nav-ratelimit/` (systemd timer quotidien 03:00 UTC) | Sonnet | ✓ |
| E | Enrichissement rétro 96 fiches (worker IA Mistral Nemo) | Sonnet | ✓ |
| F | DNS OVH + Caddy alias + build + deploy + tests HTTPS | Opus + Jules | ✓ |
### Décisions tranchées
| Décision | Choix | Raison |
|----------|-------|--------|
| Domaine V2 | `aep.trans-former.fr` nouveau + alias `nav.*` | Pas de V1 figée réelle à préserver : le VPS servait déjà la V2 |
| Structure Caddy | Alias simple (2 domaines → même service `:3333`) | Éviter 2 instances Node pour un code identique |
| Prompt chatbot | "AEP — Écosystème Entraide", posture engagée, règle hors-scope | Cohérent avec positionnement AEP vs terminologie NAV résiduelle |
| Rate limit chatbot | JSON SHA-256 (RGPD) — Redis retiré | Volume borné par circuit breaker, pas besoin de Redis |
| Enrichissement rétro | Bulk patch `pending` → worker → bulk approve API | Spot-check qualité accepté, tags à corriger en modération manuelle |
### Commits
```
74c9722 feat(aep-s3b): bandeau transparence + /a-propos + cron purge rate-limit
68e1e53 fix(chatbot): purge version Redis + prompt système AEP
```
### Enrichissement IA — bilan qualité
- **Coût réel** : €0.006 pour 96 fiches (×3 300 sous le seuil €20/mois)
- **Descriptions** : factuellement correctes (spot-check 10 fiches OK)
- **Tags** : 6/10 vides sur Maisons de l'Architecture (mapping ne matche pas "expositions/conférences"), 1 sur-tagging MAOP Id 11 (10/10 tags — site généraliste scraped), MAF Id 15 manque "Juridique"
- **Action Jules** : correction manuelle tags dans NocoDB UI (non bloquant pour deploy)
### Découverte imprévue — bug `deploy.sh`
Incohérence entre `deploy.sh` (rsync vers `/opt/nav-carte/`) et `nav-carte.service` (exec `/opt/nav-carte/.output/server/index.mjs`). Le `deploy.sh` écrit au mauvais endroit — le service tourne sur `.output/` qui n'est jamais mis à jour par le script. Contournement cette session : tar + ssh extract manuel dans `.output/`. **À patcher en V3** : aligner `deploy.sh` sur la structure `.output/`.
### État à la clôture
```
✓ aep.trans-former.fr — HTTPS 200 (/, /a-propos, /api/stats)
✓ nav.trans-former.fr — alias OK
✓ 99 fiches approved (96 enrichies + 3 S3a)
✓ Bandeau bas + chatbot + lien À propos intégrés
✓ Cron purge rate-limit actif (prochaine exécution 2026-04-15 03:00 UTC)
✓ V1 Redis chatbot purgée
```
### TODO post-session (Jules, async)
- [ ] Réécrire le texte de `pages/a-propos.vue` (placeholders `<!-- TODO Jules -->` en tête de chaque section)
- [ ] Corriger tags Maisons de l'Architecture + MAOP + MAF dans NocoDB UI
- [ ] Tests manuels : submit `/contribuer`, chatbot mobile (iOS + Android), feedback UX
- [ ] Patcher `deploy.sh` pour cibler `/opt/nav-carte/.output/` (voir découverte ci-dessus)
- [ ] Vérifier widget Liberapay à `liberapay.com/trans-former.fr` — compte existe ?
---
## Backlog V3 (hors scope V2)
### Infra / deploy
- **Fix `deploy.sh`** — cible `/opt/nav-carte/.output/` pas `/opt/nav-carte/` (incohérence découverte en S3b)
- **Migration `/opt/nav-carte/``/opt/aep/`** — alignement nom projet (dette terminologique NAV)
- **Rebrand service systemd** `nav-carte.service``aep.service` (low-priority)
- **Monitoring** — sonde Uptime Kuma (`status.trans-former.fr`) : ajouter `aep.*/api/stats`
- **Backup NocoDB** — dump quotidien base `pipilvsi7dibo80` vers stockage externe
### Produit / UX
- **Tags auto** — améliorer le mapping worker pour matcher "expositions/conférences/culture" → Développement + Formation (évite tags vides sur MA)
- **Modération UI custom** — interface dédiée pour batch approve/reject (au lieu de cliquer 96 rows)
- **Sidebar "Fiches récemment ajoutées"** — boost engagement
- **Recherche sémantique chatbot** — passer de keyword match à embeddings (Mistral Embed, volume à estimer)
- **Page `/transparence` publique** — détail coûts, CO2, donateurs Liberapay
### Éditorial
- **Contenu `/a-propos`** — texte politique écrit par Jules seul (hors scope IA)
- **Badge IA souveraine** — vérifier formulation (Hetzner = Falkenstein DE, pas FR — dire "Hébergé en Europe" ?)
- **Page Contribuer — modération visible** — expliquer pipeline "formulaire → worker IA → modération humaine"
### Monétisation / association
- **Bascule Liberapay → HelloAsso** quand ASO créée (scénario 2 du doc `C-systeme-dons.md`)
- **Widget Liberapay "total collecté"** — actuellement juste CTA, ajouter feedback
### Technique
- **Caching API organisations** — actuellement re-fetch NocoDB à chaque render
- **Full-text search côté client** — Fuse.js sur descriptions enrichies
- **Mode offline / PWA** — manifest + service worker pour usage terrain
---
## Décisions structurantes (mémoire profonde)
> Archive des décisions structurantes du projet nav-carte (AEP V1/V2/Codev/Carte 3), déchargée hebdo depuis coordo-agent-dev. Tri chronologique inverse (plus récent en haut). Copies verbatim, pas de reformulation.
### 2026-W19 (décharge 2026-05-13)
- [W19 — 2026-05-08 19:21] **AEP nav-carte fix mobile batch1+2 LIVE + cause racine chatbot Carte1=Carte2 résolue** (~3h pilote direct, 2 batches successifs, 11 fichiers). **Cause racine identifiée** après 5 cycles de fix précédents infructueux : `/api/chatbot-reseaux` était **404 en prod** (jamais déployé). Le code source nav-carte était correct depuis le début. Rebuild + redeploy = bug résolu (vérifié curl POST sur les 2 endpoints, réponses distinctes). **Batch 1** : hamburger refondu (Jobs/Manifeste/Soutenir), FAB cœur jaune retiré, 3e onglet Graphe mobile sur agences, /a-propos refondue + scroll latéral fixé, page /manifeste créée (texte version page-carto-V1), MissionPopup générique avec slot/props (storageKey, title, ctaLabel) auto-show 1ère visite, filtres Jobs mobile repliables (toggle "Filtres [N]"), FicheModal/V2 décalage `top:76px` mobile pour ne plus mordre header. **Batch 2** : pop-up Carte 2 Réseaux AEP, logo header `Architecture d'Écologie Politique` en clair sur 2 lignes (logo-line-1/2 responsive), onglet "Plateformes B2C" → "Pour archi indépendants", intro pédagogique repliable Jobs (2 onglets / 3 tags / 5 axes éthiques), labels noms structures sur GraphView (D3 append text + halo via `paint-order: stroke`). **Pattern d'opération critique découvert** : Dropbox sync efface .output entre `npm run build` et `tar | ssh` du deploy.sh — 1er deploy batch 2 a uploadé un .output quasi-vide sans erreur visible (HTTP 200 trompeur). Réflexe : `grep "fragment-modif" .output/public/_nuxt/*.js | head` AVANT deploy. **Pattern de communication** : Jules a signalé "modifs pas faites" alors que HTML prod contenait bien les modifs (vérifié curl) — cache navigateur / service worker. Réflexe : si "ça apparaît pas", curl bypass cache AVANT chercher bug, puis demander hard refresh. Git : commit propre + push gitea/main (`yes y | bash deploy.sh` pour skip confirm interactif `.env diff`). Prompt batch 3 dans `0 INBOX/PROMPTS/cascade-megaboum/REPRISE-aep-carto-fix-batch3.md`.
- [W19 — 2026-05-07 17:18] **AEP Carte 3 "Trouver du taf" — T2 scoring 5 axes + T3/T4 LIVE** : 24 plateformes scorées (7✅/14⚠/3❌), plateformes-taff.json prod, page /trouver-du-taf complète (filtres, grille 1 col, modal fiche, chatbot FAB Guide IA). Endpoints /api/chatbot-taff (import JSON statique + Mistral Small) + /api/chatbot-reseaux (keyword search 120 structures). ChatbotReseaux.vue créé (standalone Carte 2). useMarkdown.ts inline styles CSS-free. Onglet Jobs nav desktop. Bug dev : cache .nuxt corrompu par agent concurrent → bat rmdir+délai 12s. Chatbot séparation + markdown à vérifier en PROD (pas dev). Menu hamburger mobile Jobs manquant. Branche main.
- [W19 — 2026-05-07 01:11] **Codev MVP LIVRÉ en prod** — cascade M1→M5 complète (5 agents Sonnet), merge feat/codev-mvp→main, push Gitea. App entraide /codev live avec lock screen, formulaire, graphe D3 force-directed, annuaire table sticky, 2 modes matching (Solution tokenize direct + Alliance Jaccard), mode admin (DELETE fiche), QR code public, panel mobile bottom sheet. Décision build : TOUJOURS depuis C:\tmp\nav-build (Dropbox corrompt cache Vite = 500 prod). Algo fix critique : Solution compare textes besoin↔offre directement (ignore hashtags), évite que les 3 modes donnent le même graphe.
- [W19 — 2026-05-06 17:11] **MP-TAFF T1b scraping compléments DONE** — BrowserMCP utilisé pour débloquer Trustpilot (7 pages) + instao.fr + francemarches.com. `T1-output-plateformes.json` finalisé : 25 plateformes, 7 avec feedback Trustpilot. Signaux forts T2 : Archionline 2.4/5 (spam + permis PLU non conformes), hemea = courtier déguisé en MOE, TMA = meilleur ratio pros. Prochaine étape : **MP-TAFF T2 scoring 5 axes éthiques**.
- [W19 — 2026-05-06 13:30] **Cascade dispatchable Codev MVP livrée — 9 fichiers prêts à dispatcher en session Opus dédiée** : Cadrage `/orchestrateur` app entraide / co-développement Jules pour facilitation IRL jeudi 8/05 ~10 amis. 5 intersections tranchées : URL `/codev` (sous-route aep.trans-former.fr pas nouveau domaine), naming "Co-développement"/"Entraide entre pairs", mot de passe partagé `merci`, persistance NocoDB nouvelle table `codev_fiches` (carto vit hebdo, pas effacée), démo route publique `/codev/demo` (10 prénoms factices pour pitch univ). **Démêlage trinôme** (problème mathématique flaggé par Jules) : matching pair-only en MVP, trinômes émergent visuellement du D3 force-directed (triangles dans le graphe), pas de logique trinôme explicite codée — économie combinatoire majeure. 3 modes : Solution (besoin→offre asymétrique avec flèche), Alliance (besoin↔besoin symétrique), Surprise (offre↔offre symétrique). **Algo matching MVP simple** sans IA : Jaccard sur hashtags si présents, sinon Jaccard sur tokens FR (stop-words filtrés) seuil 0.15 — V2 embeddings si scaling. **Réutilisation pattern GraphView.vue** (~700 lignes existant) en simplifié (~200-300 lignes pour CodevGraph) — pas de greenfield. Cascade dans `codev-build/` (même pattern que `aep-communaute-build/`) : INDEX (table+décisions+statut) + META-PROMPT-OPUS (preflight+dispatch séquentiel+1 checkpoint deploy+format récap) + M1 (NocoDB table API + 3 endpoints + runtimeConfig) + M2 (lock+fiche+middleware auth skip /codev+/codev/demo) + M3 (CodevGraph D3 + page carto affichage seul) + M4 (matching 3 modes + boutons + animation force.alpha(0.5).restart()) + M5 split phase 1 (démo+build local+stop) + phase 2 (deploy prod après checkpoint Jules) + FEEDBACK-PASSES (10 risques pré-dispatch corrigés) + PHRASE-LANCEMENT (one-shot pour session Opus). **Patches en cours de session** : M1 fait création table NocoDB en autonomie via API (token NocoDB `e9rU...` déjà dans nav-carte/.env, endpoint `POST /api/v2/meta/bases/{baseId}/tables`), M5 phase 2 sync .env VPS automatiquement (ssh append + restart aep), règle d'or "couper M4/M5 si timing serré" retirée du META car Jules a confirmé scope OK. **1 seul checkpoint Jules** : entre M5 phase 1 (build local 200) et M5 phase 2 (deploy prod). Pattern méga-dispatch consécutif #5 (avant : Simulateur V2 30/04, Méga-cascade AEP V2 30/04, MP-TAFF cascade-megaboum 06/05, AEP V2 graphe PV2-5 micro-itérations 06/05). À dispatcher en session Opus dédiée (jauge propre, ~1h30 cascade attendue + ~5 min action manuelle Jules NocoDB).
- [W19 — 2026-05-06 21:30→01:45] **AEP V2 graphe interactif PV2-5b/e/f/g + chatbot v2 vivant + decouverte 2 repos imbriqués** : 4 commits vault `feat/aep-v2-cartobifurcation` (062337a sidebar+chatbot intégré, 2adffdf toggle Familles/Pratiques+popover famille, 5d7556a carte unifiée layers superposables+popover hashtag+lisibilité, e1ae1b9 popovers enrichis+FicheFamilleModal). 4 micro-itérations dispatch agent Sonnet en séquentiel, pilote commit lui-même chaque fois (pattern anti-hallucination établi après agent 1 a inventé hash 755d1ef). **Décisions design** : skip PV2-5c bicolores (8/120 structures = effet marginal), toggle PV2-5e exclusif fusionné en layers superposables PV2-5f (intuition Jules : séparation artificielle), Pratiques default OFF perf-friendly (174 noeuds + 640 liens si tout coché), FicheFamilleModal composant dédié réutilisable, skip définitions hashtags (pas de contenu source) → ligne générique "portée par N structures de M familles". **Découverte 2 repos git imbriqués** (vault parent ATIS-IPCJRA branche v2 + sous-repo nav-carte/ branche v1.1 distincte) → expliquait les "hallucinations" branche des agents. Notée dans `ATIS-Dev.md` section "Pièges connus" + réflexe pilote `git rev-parse --show-toplevel` au démarrage. **Chatbot v2** : endpoint v1→v2 dans ChatbotPlaceholder.vue (commit sous-repo 5878c56), vectorize-v2.js renommé en .cjs (incompat ESM type=module), payload Mistral fixed `inputs``input`, 120 embeddings générés (3.5MB embeddings-v2.json gitignored), patch vectorSearch.ts process.cwd() au lieu d'import.meta.url (bug Nitro bundle). **Rotation clé Mistral** : nouvelle clé `PXsPUhk...` notée _System/API-credentials.md, appliquée local .env + VPS /opt/aep/.env (backup .env.bak.before-rotation-20260506) + restart aep + smoke test prod chatbot v1 OK. **Doc features graphe** créée : `aep-communaute-build/PV2-5-FEATURES-GRAPHE.md` (briefing agent qui découvre en 30 sec). **Backlog différé** : PV2-5d sous-noeuds projets emblématiques (perf-critique 480 noeuds), définitions hashtags (session écriture éditoriale Jules), décision repo imbriqués (intersection stratégique demain). **Test live chatbot v2 bloqué** par lock Dropbox sur .nuxt/dev → prompt cloture demain `PV2-5h-test-chatbot-v2-local.md`.
- [W19 — 2026-05-06 02:30] **MP-TAFF V2 cadré + prompt scraping autonome séparé + rename atis-humain** : Brainstorm divergent Jules pour Carte 3 AEP "Trouver du taf en archi". 5 axes scoring éthique AEP validés (Rémunération / Transparence / Pratiques pro / Écologie / Matching) avec définitions + critères + échelles ✅⚠️❌ — c'est le différenciant central vs annuaires neutres. Décisions verrouillées : freelance only V1 (70% archis indé = cible la plus en galère), IA applique scoring (critères validés une fois = pas de validation fiche par fiche), onglet `aep.trans-former.fr` (pas sous-domaine), branche parallèle `feat/aep-taff-v1` (pas attendre merge V2), SEO reporté V2 (skill `/seo-page-aep` à créer). MP-TAFF V2 ~430 lignes avec 2 tours auto-feedback (table décision tag global, format desc IA 5 sections, §risque juridique nominatif, calibrage chatbot 3 questions, préflight conflit branche V2 + i18n). **MP-TAFF-T1-scraping-autonome.md créé** (~270 lignes) — sortable sur PC séparé pour parallélisation pendant qu'ATIS Dev bosse T0/T2/T3+. Pattern routing scraping documenté : Jina d'abord → crawl4ai SPA → BrowserMCP RGPD/auth → manuel flag. Forums commu intégrés : Team.Archi, Reddit r/Architecture FR, presse pro (Le Moniteur, AMC, D'A). Output JSON structuré consommable par T2. 🔒1 simplifié = récap scope synthétique (10 min Jules). Backlog cascade : MP-MENTOR (carte 4 entraide), MP-CROSS (n8n + GitHub OS) restent prêts. **Rename `tara` → `atis-humain`** : skill renommée, routing patché dans `atis-archi.md` ligne 390 et `ATIS-agents-specialises.md` ligne 29. Anciennes refs à Tara la personne (Mediathèque, done.md, ton-jules.md) inchangées.
- [W19 — 2026-05-05] **AEP V2 PV2-4+5+8 DONE + vue graphique D3** : PV2-4 (887 edges, 480 projets, reseaux-bifurcation.json 847KB). PV2-5 UI (NavMapV2, HashtagFilter, IntentionBanner, FicheModalV2, palette 5 familles, geocodage 118/120, GraphView.vue D3 force-directed). PV2-8 RAG (chatbot-v2.post.ts + vectorize-v2.js). Fixes UI : onglets outremer desktop, sidebar scroll, chips colorees, hashtags repliables, F6 filtre, intention overlay localStorage. EDITO-V2.md cree. 13 commits feat/aep-v2-cartobifurcation. 🔒 PV2-5 checkpoint visuel Jules en attente.
### 2026-W18 (décharge 2026-05-13)
- [W18 — 2026-05-03] **AEP V2 PV2-2ter DONE** : 10 emails récupérés. Volet A F2 (amaco/LTE), F4 (toitsdechoix/HPO/HabiterAuvergne/EmmanuelleDucos). Confirmed not public : F3 (LALCA/Sentiers/AOA/METALAB), F4 (unitoit/atelier15/a-tipic/HPF/atcoop). Blocages : rfcp.fr GravityView JS, a-tipic HTTP 400. Volet B F6 : 7 flags + 4 emails (Forensic/Centrala/NBL/Assemble) + 1 new fiche Collectif Etc (contact@collectifetc.com). Seed 122 fiches. Commit `7ce8e12`.
- [W18 — 2026-05-03] **AEP V2 PV2-2 F1 DONE** : 26 fiches réemploi & filières (14 V1 + 12 nouvelles). Nouvelles : Cycle Up (contact@cycle-up.fr), Backacia (form), Mobius (contact@mobius-corp.com), AD VITAM MATERIAL (reemploi@embuild.be), Cirkla (c/o insitu), CANCAN (contact@collectifcancan.fr), HArquitectes (harquitectes@harquitectes.com), isla (press@isla-architects.com), jdviv BE (EUmies 2026 co-winner), SalvoWEB, B+L Architectes, REFAIR/BDR. 6/12 emails high. Hashtag nouveau proposé : #amo-reemploi (AMO/diagnostic PEMD spécialisés). BrowserMCP off toute la session → Jina only (Reuse Foundation non scrapée, jdviv URL à confirmer). Commit `656cc2d`. **PV2-2 5/5 familles DONE.** → Reste PV2-3+PV2-4.
- [W18 — 2026-05-03] **AEP V2 PV2-2 F2 DONE** : 36 fiches frugalité & low-tech (22 V1 + 14 nouvelles). Nouvelles : Lacaton&Vassal (Pritzker 2021), Kéré Architecture (mail@kerearchitecture.com), Anna Heringer, CRATerre (secretariat@craterre.org), Les Grands Ateliers, AsTerre (secretariat@asterre.org), RFCP, EnvirobatBDM, NUNC, LAPS, Dorodango, BEES, amàco (contact@amaco.org), Lehm Ton Erde. 4/14 emails high conf. Sources productrices : AsTerre annuaire (19 agences archi identifiées), Pritzker (2 nouvelles), frugalite.org réseau. Blocages : RFCP annuaire JS, lehmtonerde.at 422, OFF laureats non scraped, BrowserMCP instable (3 décos). Commits `8808a35`+`301c3be`. → Reste F1 Réemploi.
- [W18 — 2026-05-03] **AEP V2 PV2-2 F3 DONE** : 22 fiches architecture sociale & précarités (11 V1 + 11 nouvelles). Nouvelles : PEROU, Plateau Urbain (SCIC), Bellastock, ASF France, Rural Studio, Forensic Architecture, Collectif Parenthèse, WoMa, Fab City Grand Paris, CivicWise. 6/11 emails high conf (PEROU·Bellastock·Rural Studio·Parenthèse·WoMa·CivicWise). Sources : Quatorze /partenaires-new (meilleur hub), YWC lieux (Grands Voisins + Coco Velten), A&P filtres. 4 multi-famille (Bellastock F3+F5, Parenthèse F3+F4, WoMa F3+F4, YWC F3+F4+F5). Commit `d2028f5`. → Reste F1 + F2.
- [W18 — 2026-05-02 23:23] **AEP V2 PV2-2 F4 DONE** : 20 nouvelles fiches collectifs/écolieux/AMO via Jina (BrowserMCP déco → pivot Jina). 11/20 emails high conf. Structures-clés : RAHP, HPF, Habicoop, Hab-Fab SCIC, Regain SCIC, Coopérative Oasis, Mietshäuser Syndikat. 9 contacts partiels (tel/form) à compléter BrowserMCP. Commit `f54afe3`.
- [W18 — 2026-05-02 19:51] **AEP V2 PV2-2 F5 DONE** : 15 fiches urbanisme transition via BrowserMCP. 7 emails high (CLER/TEPOS/Coloco/Bas Smets/EP/FNAU/Atelier Georges). Commit `56c93eb`.
- [W18 — 2026-05-02 18:17] **C3 smoke test + PV2-1 scrape DONE** : C3 = 2 bugs (P0 algo-config.json 404, P1 redirect 301 manquant) + rapport `C3-RAPPORT.md`. PV2-1 = 5/5 emails trouvés via BrowserMCP (Opalis/Frugalité/Quatorze/Tepop/Transition France), commit 6df5b84. Stack BrowserMCP validé pour batch PV2-2. Patcher P0+P1 avant merge master simulateur.
- [W18 — 2026-04-30 12:00] **AEP Cascade V2 Phase A2+A3 figées + PILOTE-V2 doc pilote vivant** : Session "AEP COMMU V3 suite" /atis-archi puis /atis-dev. SPEC-V2-FEEDBACK-DEV.md livré (faisabilité pipeline 3 passes, email cascade 5 niveaux estim 65-80%, reclaim JWT HS256 30j single-use, grain JSON suffisant si desc_longue 600+ + 3 sources, branches 2 dédiées, pre-flights standardisés, fix BOM). PILOTE-V2.md créé comme **source de vérité vivante** à la racine `aep-communaute-build/` (Jules pilote depuis ce fichier ; tout Opus suivant le lit en premier). 13 prompts PV2-X dans `0 INBOX/PROMPTS/aep-v2-cartobifurcation/` (README + PV2-0 preflight + PV2-1 scrape test 5 fiches + PV2-2 5 agents recherche par famille en parallèle (idée Jules : recoupement multi-famille = signal politique transversalité) + PV2-2bis recoupement + PV2-3 passe2 analyse + PV2-4 passe3 croisements + PV2-5 refonte UI + PV2-6 reclaim + PV2-7 badges statut + PV2-8 RAG coexistence v1+v2 + PV2-9 bandeau regards d'ailleurs + PV2-10 E2E build + PV2-11 batch emails + tri DOM-TOM). NEXT-SESSION-PROMPT-V3.md créé pour relais. **Amendements Jules sur SPEC-V2** : famille 1 "Réemploi & matière" → "Réemploi & filières", AMO ajouté famille 4 (Tepop/Hab-Fab/Habicoop), famille 5 Urbanisme transition gardée fermement (cibler scrape agressif), centres ressources DOM-TOM → carte ressources existante (sauf Caribois praticien direct), pas de cap fiches sur agents recherche, stratégie snowball depuis nodes établis (Frugalité, Opalis, A&P) + crawl collaborateurs/influences/prix/distinctions. Sessions batch nocturnes dimensionnées Claude Max 5h Opus. PV2-0 partiel exécuté : branche `feat/aep-v2-cartobifurcation` créée depuis origin/main (tracking unset = anti-push main accidentel) + BOM UTF-8 retiré de `nav-carte/deploy.sh`. PV2-0 effectif (checkout + structure `nav-carte/V2-cascade/` + hook pre-commit no-BOM + sources-par-famille.md) à faire prochaine session après commit/stash des 830 fichiers pending sur `feat/aep-website-v1.1`.
- [W18 — 2026-04-30] **Cascade MEGABOUM opérationnelle — 4 MP rédigés + cockpit lisible** : `0 INBOX/PROMPTS/cascade-megaboum/` créé avec `00-COCKPIT-CASCADE.md` (index lisible en 3 min par tout Opus dispatché, format différent de la mégaspec — celle-ci reste lecture profonde optionnelle). 4 méga-prompts prêts à dispatcher : **MP-TAFF** (app trouver du taf B2C/B2B/appels publics, ~5h, étend `aep-communaute-build/`), **MP-MENTOR** (app mentorat-entraide M7-M, ~5h, post-TAFF), **MP-CROSS** (pipeline cross-posting n8n LinkedIn+Substack+Listmonk+@aep.politique + GitHub OS publish skills/lightrag/vps-kit, ~5h, parallèle), **MP-DESIGN** (création agent atis-design, prompt court ~1h via /create-agent + scrape Prisme.one). Brief archive `MP10-manifeste-aep-INFO-BRIEF.md` (chantier déjà lancé par Jules). Chaque MP démarre par CHECKPOINT 0 réflexion faisabilité (l'Opus lit, propose, attend OK Jules avant dispatch). Backlog explicite : page-cerveau Astro from scratch, méga-RAG FRACAS vague 1, atis-philosophe, frontend-slides, rename atis-humain (P1 30 min), Insta @julesneny n8n (Q3). LightRAG VPS DOWN **déclassé** : pas bloqueur P0 semaine si on ne fait pas méga-RAG, devient bloqueur quand on attaquera RAG. Cadence : Jules pilote au fil des jours, 1-2 MP/jour, 2 clusters max simultanés.
- [W18 — 2026-04-30 02:46] **Méga-cascade V2 AEP Phase A1 figée + 3 agents background livrés** : Session Opus orchestrateur "AEP commu V2". 9 intersections tranchées par Jules en un message (5 familles fusion F4+F5, UX vignette + template carte 1, scope FR+Europe francophone + capture incidente régénératifs hors scope, articulation pensées<->structures reportée V2, passe profonde GO, email champ soft, charte reportée, filtre échelle drop, A3 absorbé A1). SPEC-V2.md figée. 3 agents Sonnet dispatchés en parallèle background : VOIE 2 V1.1 nav-carte (4 commits `feat/aep-v1.1-nav-carte` basée sur feat/aep-pratiques-regeneratives car main pré-V1 ; PA1 DOM-TOM pattern desktop 2 onglets, PA3 bouton Proposer contextuel, PA5 chatbot pratiques régé Mistral, 6/6 bugs E2E M1-M3+L1-L3 corrigés, build Nuxt OK), VOIE 3 website (1 commit `feat/aep-website-v1.1` e95f693 ; PB1 hamburger 4 entrées + stubs /manifeste /ressources /signaler ; **/!\ livré sur renovation-energetique.trans-former.fr - website pro, pas aep.trans-former.fr - à clarifier prochaine session**), PASSE PROFONDE (52 pratiques régé + 99 ressources institutionnelles analysés ; 5 familles confirmées avec garde-fous F5 ; 46 hashtags ; 7 cas limites + 4 hors-grille type "mouvement-manifeste" potentiel ; **226 acteurs candidats enrichissement carte ressources : P1=56 fiches urgentes dont 30 CAUE manquants top dpts + 4 CAUE DOM-TOM + 9 MA régionales + 2 CROA DOM ; constat critique : 0 DOM-TOM + 6/92 CAUE dans carte ressources actuelle**). 5 questions stratégiques remontées pour Phase A2 (Q-PP1 5 vs 6 familles, Q-PP2 type mouvement-manifeste, Q-PP3 F5 différée passe 2, Q-PP4 double-référencement KEBATI/AQUAA/RBD/Envirobat, Q-V3 site cible hamburger). NEXT-SESSION-PROMPT.md pré-écrit pour reprise propre Phase A2 /atis-dev. Pattern méga-dispatch consécutif #4. Tokens : 130k orchestrateur + ~451k délégués sous-agents.
- [W18 — 2026-04-30 01:42] **Méga-cascade V2 AEP cadrée** : `MEGA-V2.md` master orchestration 3 voies créé. VOIE 1 = V2 conceptuelle (refonte carte écosystème AEP en carte des réseaux de bifurcation, 5-6 familles éditoriales, reclaim email magique, pipeline IA cascade 3 passes, ~75-100 fiches). VOIE 2 = V1.1 nav-carte (items 1+2+4+5+8 ; item 3 absorbé par VOIE 1). VOIE 3 = website astro-site (hamburger + manifeste + ressources). Décisions Jules : `/atis-archi` pilote la spec V2 conceptuelle Phase A1, `/atis-dev` en relai Phase A2. Apports critiques : champ email obligatoire dans le scrape (sans email = pas de reclaim), passe profonde sur fiches existantes (~52+80) pour faire remonter hashtags sous-familles, item 4 (filtre échelle) à questionner, A3 absorbable dans A1, page Manifeste à ajouter au hamburger website. Phrase d'amorce + effort `high` recommandé pour la session Opus dédiée demain. PHRASE-LANCEMENT-OPUS-V2.md marqué SUPERSEDED. 2 briefs INBOX (V2-BRIEF-AGENT-OPUS + V2-RECAP-PROJET) déplacés dans aep-communaute-build/.
- [W18 — 2026-04-29 11:48] **AEP scrape P1-P7 FAIT** : BrowserMCP (P1 architecture-precarites.fr : 200+ projets, 5 catégories) + Jina (P4 vegetal-e ✅, P6 colorado-architecture ✅, P7 karibati ✅, P3 caribois ✅). P2 archidev bot-protégé + P5 envirobat 422 → consultation manuelle. `scrape-browsermcp.json` créé (7 entrées). Email auteurs architecture-precarites.fr envoyé par Jules. INCLURE : vegetal-e (5/8), envirobat-RE (7/8), karibati (5/8). EXCLURE : caribois (2/8), colorado (3/8).
- [W18 — 2026-04-29] **AEP V1 E2E PASS** : 5/5 scénarios OK (3 mobile, 3 laptop). Branche `feat/aep-pratiques-regeneratives` prête à merger main. `E2E-RESULTS.md` créé. Bugs mineurs capturés : M1 chips a11y + M2 reset searchbox + M3 floating button + L1 redirection.
- [W18 — 2026-04-29 08:11] **AEP V1 LIVRÉE** : 52 fiches prod (`aep.trans-former.fr/pratiques-regeneratives`), 12 commits feat/. V1.1 mode divergent cadrée (8 items brain-dump Jules).