# ROUTINE — Traitement Veille du matin

> Orchestrateur exécuté chaque matin (lun-ven) par Claude Code, déclenché par launchd.
> Rôle : lire la file de posts scrapés par n8n, faire tourner les **VRAIS agents spécialisés** (42 et 50), écrire leurs livrables, notifier l'équipe, et renvoyer un résumé à n8n pour l'email + Kimi.
>
> **Principe non-négociable :** aucun tri généraliste. On ne classe pas les posts « à la place » des agents. On donne le lot complet à chaque agent, et **chacun filtre avec sa propre expertise** (ses UKP, ses critères). Un post peut être retenu par 42, par 50, par les deux, ou par aucun. C'est ce qui produit la qualité supérieure vs un Claude généraliste.

---

## CONFIGURATION

Les secrets sont lus depuis `~/.config/fidulia/veille.env` (chmod 600, hors repo) par le lanceur `veille-matin.sh`, qui les exporte comme variables d'environnement avant d'appeler Claude :

| Variable | Source | Valeur |
|---|---|---|
| `N8N_HOST` | env | `https://n8n.srv1258257.hstgr.cloud` ✅ rempli |
| `FIDULIA_TOKEN` | env | jeton header `X-Fidulia-Token` ✅ généré (à recopier dans le credential n8n) |
| `CLIENT` | constante | `Fidulia` |

Endpoints n8n consommés par cette routine :
- `GET  {N8N_HOST}/webhook/veille-queue` → renvoie les posts en statut `PENDING`
- `POST {N8N_HOST}/webhook/veille-queue/done` → marque les posts traités `DONE`
- `POST {N8N_HOST}/webhook/veille-digest-fidulia` → envoie le digest du matin (déclenche l'email). Schéma attendu : `{"subject": "...", "html": "..."}` — le script converti le markdown en HTML avant l'envoi. Voir ÉTAPE 5.

**Digest unifié** : cette routine est la **dernière des 3 routines du matin** (~7h40, après `prospection-fidulia-batch` à ~7h00 et `verification-acceptations-linkedin` à ~7h20 — toutes trois calées juste après le réveil machine quotidien confirmé de 6h58 depuis le correctif du 27/07/2026, cf. incident du même jour). Elle assemble et envoie l'**unique email du jour**, qui regroupe les sections des 3 routines. Fichier d'assemblage partagé : `Agents/70-Agent-Automatisation/routine/DIGEST-DUJOUR-[YYYY-MM-DD].md` — les deux routines précédentes y ont déjà ajouté leurs sections (`## 📊 Prospection` et `## ✅ Invitations acceptées`) si elles ont tourné.

---

## ÉTAPE 1 — Récupérer la file

```bash
python3 /Volumes/Samsung_T5/entreprise/Linked-Connexion/Agents/70-Agent-Automatisation/scripts/veille_queue_client.py fetch
```

(script fixe, remplace l'appel curl brut — permission Bash scopée à ce script exact ; le script charge lui-même `~/.config/fidulia/veille.env`, plus besoin de `source` en préfixe)

Le JSON est aussi écrit dans `Agents/70-Agent-Automatisation/routine/.cache/veille-queue-latest.json` (chemin fixe du repo). Si la réponse est trop volumineuse pour tenir dans la sortie de l'outil Bash, lire ce fichier directement avec l'outil Read plutôt que de manipuler le fichier `tool-results` éphémère du harness (protégé, ne pas y toucher).

**Manipulation du lot — script fixe obligatoire (ajout 20/07/2026).** Pour dédupliquer, compter, extraire les postId ou produire un dump lisible du lot, utiliser exclusivement :

```bash
python3 /Volumes/Samsung_T5/entreprise/Linked-Connexion/Agents/70-Agent-Automatisation/scripts/veille_lot_tools.py stats   # total / uniques / doublons / rôles
python3 /Volumes/Samsung_T5/entreprise/Linked-Connexion/Agents/70-Agent-Automatisation/scripts/veille_lot_tools.py dump    # dump markdown → routine/.cache/lot-dump-latest.md
python3 /Volumes/Samsung_T5/entreprise/Linked-Connexion/Agents/70-Agent-Automatisation/scripts/veille_lot_tools.py ids     # postId uniques en CSV (à réutiliser tel quel à l'ÉTAPE 4)
```

❌ **Jamais de `python3 -c "..."` inline, de boucle shell (`cd ...; for ...`), ni de `grep`/`find` via Bash** pendant la routine : toute commande Bash qui ne matche pas exactement un pattern de l'allowlist `settings.json` bloque la tâche planifiée sur un prompt d'autorisation, **même une commande "simple" comme un `grep` isolé** (doctrine 15/07/2026, récidive constatée le 20/07/2026 et le 29/07/2026 — trois arrêts). Il n'existe **pas d'outil Grep dans ce projet** — pour fouiller les fichiers du repo (ex. vérification cooldown dans `CANDIDATS-*.md`), utiliser exclusivement l'outil **Read** sur chaque fichier concerné (déjà pré-autorisé sur les chemins du repo, contrairement à Bash), jamais de composition Bash.

Réponse attendue : tableau JSON de posts. Schéma d'un post :
```json
{
  "postId": "urn:li:activity:...",
  "author": "Prénom Nom",
  "profileUrl": "https://linkedin.com/in/...",
  "url": "https://linkedin.com/feed/update/...",
  "text": "contenu du post (max 2000 car.)",
  "postedAt": "2026-06-29T08:12:00Z",
  "likes": 42,
  "comments": 7
}
```

**Si la file est vide** (`[]`) → écrire une ligne de log, sauter directement à l'ÉTAPE 5 (assembler et envoyer le digest quand même — la section "À commenter"/"Veille du jour" sera vide, mais les sections Prospection/Acceptations des routines précédentes doivent quand même partir), et **arrêter avant les étapes 2/3/4**. Ne pas réveiller les agents 42/50 pour rien.

---

## ÉTAPE 2 — Agent 42 (Engagement) sur le lot complet

Invoquer le skill **/42** en mode batch sur l'intégralité des posts récupérés.

**Pré-filtrage par rôle Sheet (obligatoire, avant application des critères) :**
Le lot brut contient des posts issus de tous les rôles du Sheet « Veille » (colonne `role`). Le flux commentaire ne traite **que les rôles FR-commentaire** :
- ✅ `REACH-FR` · `NICHE-CGP-FR` · `NICHE-FR`
- ❌ `CRÉATEURS-INTL` (flux partage avec note — **gelé**, cf. `Agent-Engagement.md` §Règles anti-dérive)
- ❌ `CURATION` · `CONCURRENTS` · `AUTORITÉS-INTL` (observation seule, jamais commenté)

Un post issu d'un rôle non-FR-commentaire est **écarté avant tout autre filtre** — il ne doit jamais atteindre `CANDIDATS-*.md`. Double filet de sécurité côté Agent 42 : le critère langue (§A.2) écarte tout ce qui ne serait pas français, même si le routage par rôle a laissé passer un post.

L'Agent 42 applique ensuite SES critères (cf. `Agent-Engagement.md` §A.2 + `UKP-PUBLICATION-ENGAGEMENT.md`) sur le sous-lot restant :
- post rédigé en français (non-négociable)
- sujet aligné LinkedIn · IA · professions de confiance
- hors politique/religion/polémique stérile, hors anti-cible
- engagement déjà visible (≥ 5 commentaires) = priorité
- compte hors cooldown (`JOURS_RETOUR_RELANCE` = 14 j) — **vérification via l'outil Read uniquement, un appel par fichier `CANDIDATS-*.md` récent** (cf. §Étape 1 : jamais de Bash, même un `grep` isolé — pas d'outil Grep disponible dans ce projet, et tout Bash non-allowlisté bloque la routine sur un prompt d'autorisation)

Pour chaque post retenu, il rédige un **brouillon de commentaire** (1 phrase par défaut, voix client, règles anti-dérive : pas de tiret cadratin, pas de « et vous ? », pas de pitch).

> **Coordination avec l'Agent 20 (Stratège)** : avant de figer la sélection, l'Agent 42 vérifie la cohérence avec `Clients/{{CLIENT}}/STRATEGIE.md` (sujets prioritaires du mois, angles différenciants). Les posts retenus doivent servir le positionnement Benedict Evans en cours, pas seulement « faire du volume ».

**Livrable :** `Clients/{{CLIENT}}/Engagement/CANDIDATS-[YYYY-MM-DD].md`
(format exact défini dans `Agent-Engagement.md` §A.3, statut `À VALIDER par Fabien`).

---

## ÉTAPE 3 — Agent 50 (Veille) sur le lot complet

Invoquer le skill **/50** en mode batch sur le même lot complet.

L'Agent 50 applique SES critères (cf. `Agent-Veille.md` + `UKP-VEILLE.md` + `UKP-ALGO-LINKEDIN-2026.md`) selon ses 5 périmètres :

**3a — Matière contenu pour Fabien** (priorité 1)
- signaux d'autorité, chiffres vérifiables, changements d'algo LinkedIn, tendances B2B de fond
- tags : `[POST]` / `[NEWSLETTER]` / `[SKIP]`
- **Livrable :** `Agents/50-Agent-Veille/Captures/[YYYY-MM-DD].md` (format §"Capture quotidienne")
- les items `[NEWSLETTER]` s'ajoutent à `Agents/50-Agent-Veille/Newsletter/VEILLE-NEWSLETTER-[YYYY-WW].md`

**3b — Nourrir l'équipe (notifications cross-agents)**
Dès qu'un post porte un signal pertinent pour un autre agent, l'Agent 50 écrit une entrée dans le fichier INBOX de l'agent concerné :

| Signal détecté | Agent à prévenir | Fichier INBOX |
|---|---|---|
| Nouveau design/format visuel performant sur LinkedIn | Graphiste (31) | `Agents/31-Agent-Graphiste/INBOX.md` |
| Tendance design system, palette, typo, codes visuels niche | Design System (21) | `Agents/21-Agent-Design-System/INBOX.md` |
| Sujet brûlant, angle éditorial, mouvement de fond stratégique | Stratège (20) | `Agents/20-Agent-Stratege/INBOX.md` |

Format d'une entrée INBOX (append, jamais écraser) :
```markdown
## [YYYY-MM-DD] — De l'Agent 50 (Veille)
- **Signal** : [ce qui a été repéré, 1-2 lignes]
- **Source** : [auteur] — [URL du post]
- **Pourquoi ça te concerne** : [angle pour l'agent destinataire]
- **Action suggérée** : [ce que l'agent pourrait en faire]
- **Statut** : 🆕 non traité
```

---

## ÉTAPE 4 — Clôturer la file

Une fois 42 et 50 passés, marquer tous les posts du lot comme traités :

```bash
python3 /Volumes/Samsung_T5/entreprise/Linked-Connexion/Agents/70-Agent-Automatisation/scripts/veille_queue_client.py done \
  --post-ids "id1,id2,..." --traite-par "42,50"
```

(script fixe, remplace l'appel curl brut — permission Bash scopée à ce script exact)

Envoyer **tous** les postId du lot (même ceux qu'aucun agent n'a retenus — ils sont traités, donc on ne les repropose pas demain).

---

## ÉTAPE 5 — Assembler et envoyer le digest unique du matin

Cette routine est la **dernière à tourner** (~7h40) — c'est elle qui envoie l'unique email du jour, pas les deux précédentes (elles se contentent d'ajouter leur section au fichier partagé).

### 5.1 — Ouvrir/créer le fichier d'assemblage du jour

`Agents/70-Agent-Automatisation/routine/DIGEST-DUJOUR-[YYYY-MM-DD].md`

- S'il existe déjà (créé par `prospection-fidulia-batch` et/ou `verification-acceptations-linkedin` plus tôt ce matin) → le lire, on va lui **ajouter** les 2 sections suivantes à la fin.
- S'il n'existe pas (routines précédentes non exécutées ou en échec) → le créer avec l'en-tête :
  ```markdown
  # 🗞️ Digest Fidulia — [date en toutes lettres, ex: mercredi 2 juillet 2026]
  ```

### 5.2 — Section "À commenter aujourd'hui"

Version condensée et lisible de `Clients/{{CLIENT}}/Engagement/CANDIDATS-[YYYY-MM-DD].md` — **pas un copier-coller brut** : ne garder que l'essentiel, pas les champs internes (Flux, Source, case Décision).

```markdown
## 💬 À commenter aujourd'hui

### [Auteur]
[Sujet en 1 ligne]

> [Commentaire proposé]

🔗 [Voir le post]([URL])

---
(répéter pour chaque candidat)
```

Si zéro candidat : `## 💬 À commenter aujourd'hui` suivi de `Rien à commenter aujourd'hui.`

### 5.3 — Section "Veille du jour"

Version condensée de `Agents/50-Agent-Veille/Captures/[YYYY-MM-DD].md` — reprendre uniquement les items tagués `[POST]`/`[NEWSLETTER]` et les signaux forts remontés en INBOX (pas la liste brute des posts écartés/monitoring).

```markdown
## 📰 Veille du jour

- [Résumé signal 1, 1-2 lignes] — 🔗 [URL source](url)
- [Résumé signal 2] — 🔗 [URL source](url)

(si des pistes de recherche ou signaux stratégiques ont été soulevés, les lister brièvement ici aussi)
```

**Règle** : le lien source est **obligatoire** pour chaque bullet — jamais optionnel. Fabien doit pouvoir cliquer directement depuis l'email pour lire la source sans chercher dans les fichiers de capture.

Si rien de notable : `## 📰 Veille du jour` suivi de `Rien de notable aujourd'hui.`

### 5.3 bis — Vérification anti-digest-tronqué (avant d'envoyer)

Avant d'envoyer, vérifier que la section `## 📊 Prospection` est bien présente dans le fichier assemblé. Si elle est absente :
1. Lire `Clients/Fidulia/Prospection/JOURNAL-BATCH.md` — chercher une entrée `## [DATE] — Batch CGP` datée d'aujourd'hui.
2. Si une entrée existe (la routine `prospection-fidulia-batch` a bien tourné mais a raté son ÉTAPE 4 d'écriture au digest) → reconstruire la section Prospection à partir de cette entrée et l'insérer en tête du fichier (juste après le H1), plutôt que d'envoyer un digest tronqué en silence.
3. Si aucune entrée n'existe pour aujourd'hui → la routine `prospection-fidulia-batch` n'a probablement pas tourné du tout : envoyer quand même (ne pas bloquer les 2 autres sections), mais ajouter une ligne d'alerte visible dans le fichier juste sous le H1 : `⚠️ Section Prospection absente — JOURNAL-BATCH.md ne contient aucune entrée pour aujourd'hui, à vérifier.`

Ce filet de sécurité existe parce que le 15/07/2026 la routine `prospection-fidulia-batch` a exécuté son batch d'invitations avec succès mais a sauté son étape d'écriture au digest sans lever d'erreur — `verification-acceptations-linkedin` a alors silencieusement recréé un digest partiel (sa propre logique de repli suppose que "fichier absent" = "routine précédente non exécutée", ce qui n'était pas le cas). Le digest envoyé ce jour-là ne contenait que la section acceptations.

### 5.4 — Envoyer l'email

Lire le fichier `DIGEST-DUJOUR-[YYYY-MM-DD].md` complet (avec les sections des 3 routines si elles ont toutes tourné), puis :

```bash
python3 /Volumes/Samsung_T5/entreprise/Linked-Connexion/Agents/70-Agent-Automatisation/scripts/render_digest.py \
  "/Volumes/Samsung_T5/entreprise/Linked-Connexion/Agents/70-Agent-Automatisation/routine/DIGEST-DUJOUR-[YYYY-MM-DD].md"
```

(script fixe — permission Bash scopée à ce script exact ; remplace `send_digest_webhook.py` depuis le 15/07/2026. Injecte les sections du markdown dans le template HTML validé le 14/07 — `Agents/70-Agent-Automatisation/templates/digest-email.template.html`, header navy/magenta + stat cards + comment cards + footer "FIDULIA" — au lieu du CSS basique de l'ancien script. Extrait le sujet du titre H1, poste `{"subject": "...", "html": "..."}` vers `$N8N_HOST/webhook/veille-digest-fidulia`. Option `--no-send` pour prévisualiser le HTML sur stdout sans envoyer.)

Le webhook `veille-digest-fidulia` attend exactement `{"subject": "...", "html": "..."}`. Le workflow n8n `VEILLE-DIGEST-EMAIL` (2 nœuds : Webhook → Gmail) lit `$json.body.subject` et `$json.body.html` en mode expression. Ne pas envoyer de clé `markdown` : le workflow n'a plus de nœud de conversion.

**Notification Kimi** : la routine ne pousse pas de notif à part. Les fichiers `CANDIDATS-`, `Captures/` et les `INBOX.md` mis à jour restent la source pour **Kimi** au prochain *programme du jour* (`/kimi` Mode 2). Le digest email est un canal séparé, immédiat, pour Fabien.

---

## ÉTAPE 6 — Journal

Append dans `Agents/70-Agent-Automatisation/routine/JOURNAL-ROUTINE.md` :
```markdown
| Date | Posts traités | Candidats 42 | Items 50 | Notifs équipe | Statut |
|---|---|---|---|---|---|
| 2026-06-29 | 34 | 6 | 4 | 2 (31, 20) | ✅ OK |
```

En cas d'erreur (file injoignable, agent en échec) : logguer `⚠️ ÉCHEC` + la cause, et **ne pas** marquer la file `DONE` (pour rejouer demain ou manuellement).

---

## RÈGLES NON-NÉGOCIABLES DE LA ROUTINE

- ❌ **Jamais de classification généraliste** en amont des agents — chaque agent filtre lui-même.
- ❌ **Jamais marquer la file `DONE`** si un agent a échoué (sinon perte de posts).
- ❌ **Jamais commenter/publier automatiquement** — la routine prépare des brouillons, Fabien valide (validation humaine, cf. règles agents 42/50).
- ✅ **Toujours écrire dans les vrais fichiers** des agents (source unique de vérité), jamais dans des copies.
- ✅ **Toujours envoyer tous les postId** à `veille-queue/done`, retenus ou non.
- ✅ **Un seul email par matin** : cette routine (~7h40) est la seule à poster vers `veille-digest-fidulia`. Les routines `prospection-fidulia-batch` et `verification-acceptations-linkedin` ajoutent leur section au fichier `DIGEST-DUJOUR-[date].md` mais n'envoient rien elles-mêmes.
- ✅ **Toujours Write/Edit pour éditer `DIGEST-DUJOUR-[date].md`** — jamais `Bash cat >>`/`echo >>` (cohérence avec les autres routines).

---

*Créé le 2026-06-29 · Agent 70 · Routine consommée par launchd `com.fidulia.veille-matin`*
