Gmail Phase E/F + HANDOFF global + cleanup cron/root

- Réécriture HANDOFF.md dashboard multi-domaines

- Mise à jour MEMORY.md / TOOLS.md / AGENTS.md

- Cleanup fichiers cron obsolètes + fichiers root

- Gmail Phase E : audit, 18 filtres natifs, labels Promos/Dev-Tools/Social

- Gmail Phase F : archive Philippot + Ulys terminée
This commit is contained in:
Tallagrand Thierry
2026-06-26 00:28:07 +02:00
parent ea5dd014b6
commit 5363f99b76
10 changed files with 2387 additions and 0 deletions

View File

@@ -0,0 +1,328 @@
# Handoff — OpenClaw / Gmail Housekeeping
> _Document de reprise pour une nouvelle session (humain ou agent IA)._
> _Dernière mise à jour : 9 juin 2026._
> _Mainteneur : Thierry Tallagrand._
---
## 🎯 TL;DR (à lire en premier)
Le projet **OpenClaw** est un orchestrateur multi-agents tournant sur Synology NAS
(ARCHIVE3) qui pilote des comptes Google de Thierry via gateway gog.
**État actuel** : **Phase D Gmail housekeeping ✅ TERMINÉE** le 6 juin 2026.
12 401 mails trashés en 6 vagues. Boîte 12 703 → ~4 600.
**Prochaines phases prévues** :
- Phase E : filtres Gmail natifs (auto-trash à l'arrivée)
- Phase F : Vague 2 (archive Philippot + Ulys + labels)
- Phase G : 2ème passe Q8 (longue traîne newsletters tech)
- Phase H : digest VE (parsing Jeep uconnect)
---
## ⏰ Dates critiques
Date Événement Action
6 juillet 2026 Auto-purge Gmail Trash (30j) des mails Phase D Restaurer AVANT cette date si erreur
12 juin 2026 Token OAuth gmail.modify expire (Testing GCP, 7j) gog auth add --gmail-scope=full --manual --force-consent
9 juin 2026 Aujourd'hui — reprise après pause Vérifier gmail-doubts.md si existant
Export as CSV
---
## 🏗️ Architecture
### Hôte
- Synology ARCHIVE3 (DSM, hostname `ARCHIVE3`)
- Filesystem : `/volume1/docker/openclaw-data/workspace/`
- User : 1000:1000 (Thierry)
- TZ : Europe/Paris
### Containers Docker
- openclaw-gateway (daemon principal, expose gog CLI)
- openclaw-cli, openclaw-plugins, openclaw-dockerproxy
- gitea (versioning local), openvpn2 (VPN)
### Compte Google authentifié
- Email : tallagrand.thierry@gmail.com
- Project GCP : 666305633659 (test users mode = refresh tokens 7j)
- Scopes : gmail.modify + gmail.settings.basic + gmail.settings.sharing + userinfo.email + openid
- Token expire : **12 juin 2026**
### Infrastructure mail historique (3 NAS Synology)
- ARCHIVE → `[10.10.10.50]` (originel, IP locale)
- ARCHIVE2 → `[www.airtria.net]`
- ARCHIVE3 → `[www.airtria.pro]` (NAS actuel)
---
## 📂 Fichiers clés
Fichier Rôle
workspace/AGENTS.md Rules globales (NEVER/ALWAYS Gmail+WhatsApp, Heartbeats)
workspace/MEMORY.md Mémoire persistante session par session
workspace/gmail-audit.md Audit initial 3000 threads (Phase B)
workspace/gmail-rules.md Règles trash/archive/whitelist (Phase C, source de vérité)
workspace/gmail-housekeeping.md Log append-only actions Gmail (Phase D)
workspace/handoff.md Ce fichier
workspace/scripts/gmail_trash_v1.sh Vague 1 (>1y)
workspace/scripts/gmail_trash_v1_6m.sh Vague 1bis (6m→1y)
workspace/scripts/gmail_trash_v1ter.sh Vague 1ter (30j→6m)
workspace/scripts/gmail_trash_v1quinquies.sh Vague 1quinquies (7j→30j) + 4 nouvelles règles
workspace/scripts/gmail_trash_synology.sh Synology .net
workspace/scripts/gmail_trash_synology_all.sh Synology .pro + IP10 + .net
Export as CSV
---
## 📊 Bilan Phase D (5-6 juin 2026)
Vague Filtre temporel Trashed
Vague 1 older_than:1y 5 335
Vague 1bis 6m → 1y 1 647
Vague 1ter 30j → 6m 1 871
Synology .net toutes périodes 1 160
Synology .pro+IP10 toutes périodes 2 099
Vague 1quinquies 7j → 30j 289
TOTAL 12 401
Export as CSV
Boîte 12 703 → ~4 600 (-64%). Hits rate-limit : 0.
### Top performers
- LinkedIn (3 règles) : 3 502+
- Synology auto-notifs (3 variants) : 4 419
- Quora : 1 436+
- AliExpress : 469
- TAAFT : 418
- Rustica : 351
- Facebook : 365
- Cdiscount : 276
- Carrefour : 257
---
## 🔴 Whitelist absolue (NE JAMAIS toucher)
Source de vérité : gmail-rules.md.
### Banques
@cic.fr, @e-cic.fr, @bpgo.fr, @cmb.fr
### Admin & légal
@impots.gouv.fr, @dgfip.finances.gouv.fr, @digiposte.fr, @ameli.fr
### Telco perso
@orange.com, @orange.fr, @neuf.fr
### Véhicules
@vwfs.com, @volkswagen.fr, @jeep.com (cf. règle V01 digest VE),
@ze-watt.fr/.com, @zeromotorcycles.com, r.clientele@vwfs.com
### Plongée
@gissacg.fr, @lists.gissacg.fr, president@gissacg.fr, @arimair.fr
### AIRTRIA
@airtria.net, @airtria.fr, @laboutique-solaire-pro.com
### Identités personnelles
tallagrand.thierry@gmail.com, thierry.tallagrand@me.com,
Frederic Tallagrand (famille)
### Synology infrastructure (CRITIQUE — alertes opérationnelles)
- sns@synologynotification.com (Active Insight - alertes disque/storage)
- noreply@c2.synology.com (C2 backup subscription)
### Finance
- noreply@amundi-esr.com (épargne salariale PEE/PERCO)
### Labels système Gmail protégés
IMPORTANT, STARRED, SENT, DRAFT, Personal, Travail, Achats, Receipts, Notes
---
## 🛡️ Hard constraints opérationnels
### NEVER
1. messages.delete permanent (toujours messages.trash)
2. Toucher la whitelist (abort silencieux si match)
3. >200 actions par batch Gmail (en pratique 300 OK)
4. >2000 actions par jour sans confirmation humaine
5. Modifier labels système (INBOX retirable mais pas SENT/DRAFT/IMPORTANT)
6. Lancer une vague sans dry-run préalable validé
### ALWAYS
1. Dry-run obligatoire avant toute action en masse
2. Logger chaque batch dans gmail-housekeeping.md
3. Respecter gmail-rules.md comme source de vérité unique
4. Vérifier la whitelist au runtime (pas seulement au design)
5. Pause 5s entre 2 batchs gog gmail trash/archive
6. En cas de doute : laisser dans inbox + log dans gmail-doubts.md
### Limites runtime utilisées (Phase D)
- maxBatchSize: 300
- pauseBetweenBatchesMs: 5000
- Détection auto rate-limit 403 + retry 60s
- Hits rate-limit observés : 0 sur 12 401 actions
---
## 🔧 Patterns gog éprouvés
Recherche read-only :
sudo docker exec openclaw-gateway gog gmail search "QUERY" -a tallagrand.thierry@gmail.com --max 500 -j
Trash avec query + cap :
sudo docker exec openclaw-gateway gog gmail trash -a tallagrand.thierry@gmail.com --query "QUERY" --max 300 --force
Re-auth OAuth :
sudo docker exec openclaw-gateway gog auth remove tallagrand.thierry@gmail.com
sudo docker exec -it openclaw-gateway gog auth add tallagrand.thierry@gmail.com --services=gmail --gmail-scope=full --manual --force-consent
Vérification auth :
sudo docker exec openclaw-gateway gog auth list
sudo docker exec openclaw-gateway gog gmail labels list -a tallagrand.thierry@gmail.com
---
## 🟣 Cas spécial — Jeep uconnect (digest VE)
from:uconnectservices@jeep.com (~400 mails) :
- Phase D : aucune action (laissés en inbox)
- Phase H : agent quotidien parse les mails, génère charge-vehicule.md + notif WhatsApp synthèse, archive auto avec label Charge-VE
---
## 🟡 Phase F (Vague 2 — à faire)
Archive + label, pas de destruction :
ID Source Action Volume estimé
V2.01 florian.philippot@les-patriotes.fr Archive + label Newsletters ~30
V2.02 info@clients.ulys.com Archive + label Receipts ~50
Export as CSV
---
## 🔵 Phase E (filtres Gmail natifs — à faire)
Objectif : plus jamais d'accumulation. Filtres Gmail qui trashent automatiquement les mails matchant nos 23 règles V1 dès l'arrivée.
Approches possibles :
1. gog filters create (à explorer via gog gmail filters --help)
2. Gmail API directe : users.settings.filters.create (Python)
3. Gmail UI web : 23 clics manuels (lent mais sûr)
Pré-requis : Phase D doit avoir tourné 30 jours sans regret.
---
## 🟠 Phase G (2ème passe Q8 — longue traîne)
Identifier expéditeurs hors top 30 actuels (Medium, Substack, Frandroid, dev.to, mailchimp génériques).
Audit longue traîne :
sudo docker exec openclaw-gateway gog gmail search "category:promotions OR category:updates older_than:6m" -a tallagrand.thierry@gmail.com --max 5000 -j > /tmp/longue-traine.json
---
## 🐛 Quirks / pièges connus
### Horloge système
Le serveur expose un current_time parfois bloqué ou avec coquille UTCUTC.
Source de vérité = horloge système host (date sur ARCHIVE3) ou contexte conversationnel.
### Bug KeyError 'subject' dans gog gmail search
Certains threads n'ont pas de subject. Toujours utiliser t.get('subject', '').
### from:me ne fonctionne pas dans gog
Utiliser l'email complet à la place.
### Compteurs Gmail web vs API
- Compteur "Boîte de réception" gauche = fiable
- Compteur "1-50 sur N" en haut = inclut SENT en vue Principale
- Compteurs catégories (Promotions/Notifications/etc.) = INCLUENT TRASH, jamais représentatifs.
### Dry-run gog gmail trash
Le --dry-run ne pré-fetch PAS les message_ids. Pour validation, faire un gog gmail search séparé avec la même query.
---
## 📋 Checklist de reprise (pour nouvelle session)
[ ] Vérifier date système : date sur ARCHIVE3
[ ] Vérifier état token : gog auth list (si expire <24h, relancer flow OAuth)
[ ] Lire gmail-housekeeping.md (dernières actions)
[ ] Lire MEMORY.md (état général)
[ ] Vérifier gmail-doubts.md (mails à relire)
[ ] Vérifier inbox count : gog gmail search "in:inbox" --max=1 -j
[ ] Décider phase suivante : E, F, G ou H
[ ] Si action destructive → dry-run d'abord, valider, puis exécuter
---
## 🔗 Liens / refs
- gog CLI : gog gmail {search|trash|archive|labels} --help
- Gmail search syntax : https://support.google.com/mail/answer/7190
- Gmail API quotas : https://developers.google.com/gmail/api/reference/quota
- GCP project : 666305633659 (mode Testing, refresh 7j)
---
## 10 juin 2026 ~01:00-01:35 UTC+2 — Auth Gmail re-faite + persistance
### Contexte
Token OAuth expirant 12/6/2026. Découverte que le keyring vivait dans
/home/node/.local/share/gogcli/ (couche writable container) = perdu à chaque
compose down/up.
### Actions
- Re-auth gog complète via `gog auth add tallagrand.thierry@gmail.com
--services=gmail --manual --gmail-scope=full --force-consent`
- Ajout de GOG_HOME=/home/node/.openclaw/gogcli dans compose.yaml (env)
- Migration credentials.json + keyring/ vers gogcli/data/
- Permissions 1000:1000, files 600, dirs 700
- Test ULTIME compose down+up : auth survit ✅
### Garanties acquises
- Refresh token persisté dans /volume1/docker/openclaw-data/gogcli/data/keyring/
- Survit aux compose restart, stop+start, down+up, --force-recreate
- GOG_KEYRING_PASSWORD doit rester identique (sinon keyring illisible)
### TODO
- Investiguer config.path warning (non critique, gog créera /gogcli/config/
à la prochaine écriture config)
- Mettre à jour scripts/generate_gmail_token.sh (référence à `gog auth
generate-token` qui n'existe pas — la vraie commande est `gog auth add ... --manual`)
- Référencer la nouvelle syntaxe gog dans MEMORY.md (procédure compacte
~1100 chars proposée plus haut, à appliquer une fois reposé)
## ✅ Validation finale 10 juin 2026 ~02:13-02:18 UTC+2
Test fonctionnel complet via WhatsApp DM (session fraîche post-/new) :
### Questions/réponses
| Question | Comportement | Latence |
|---|---|---|
| "Combien de mails aujourd'hui ?" | 1 appel gog gmail search → "2 messages" | ~1min |
| "et hier ?" | Réutilise contexte + 1 appel | ~5s |
| "donne la liste" | Format structuré avec dates + étiquettes | ~30s |
| "et liste des mails de lundi" | Recherche multi-jours, format détaillé | ~1min |
### Test dashboard
"fait un classement par catégorie des mails depuis le 1juin 2026 et le 10 juin 2026"
→ Réponse multi-section (Newsletters/Actualités/Réseaux/Personnel/Systèmes/Autres)
→ Classification sémantique propre, ~30 mails listés
→ Aucune boucle, aucune saturation
### Conclusion
- Phase D bilan classement Gmail : **PHASE LECTURE COMPLÈTEMENT OPÉRATIONNELLE**
- Phase E (mutations en masse) : prête à être lancée, syntaxe validée par l'agent
- Aucune intervention manuelle nécessaire pour les questions Gmail standard

View File

@@ -0,0 +1,552 @@
# HANDOFF — OpenClaw + Qwen3-VL Production
**Dernière mise à jour : 2026-06-09 ~17:45 UTC+2** (post-debug session WhatsApp DM stalled)
> Document de transition entre sessions de production. À lire en premier dans toute
> nouvelle session de travail. Stocké hors workspace pour ne pas polluer le bootstrap.
---
## 1. Stack actuelle (état stable)
### Infrastructure
- **DGX Spark (10.10.10.8)** : vLLM Qwen3-VL-30B-A3B-Instruct-FP8 sur port 8000, Watchtower DÉSACTIVÉ
- **NAS ARCHIVE3 (192.168.144.2)** : OpenClaw 2026.6.1 sur port 18789, image `openclaw-custom:latest` (build local)
- **NAS ARCHIVE2** : sandbox stoppée, en attente
### OpenClaw (ARCHIVE3)
- Compose : `/volume1/docker/openclaw/compose.yaml`
- Volume bind : `/volume1/docker/openclaw-data` → `/home/node/.openclaw` (container)
- Container WORKDIR : `/app` (le `dist/index.js` est à `/app/dist/index.js`)
- Dashboard : http://192.168.144.2:18789/ (paired, 2 devices)
- Container uid : `1000:1000` (`node`) — **tout fichier écrit en root sera invisible côté agent**
### Modèles configurés
- `vllm/qwen3-vl` (primary) — 200k ctx déclaré, mais sessions plafonnées à 66k pour la plupart
- `vllm/qwen3.6` (fallback / legacy)
### Multimodal WhatsApp
- Activé via `tools.media.image.enabled = true` (config set + restart gateway)
- AUCUNE modification de models.json nécessaire pour l'activer
- Pipeline : WhatsApp inbound → resize auto → tool-images → Qwen3-VL → réponse
- Latences mesurées : cron text-only 14-21s, multimodal photo 5-13s, DM text simple ~30s
- Tests OK historiques : Bernard-l'ermite, Hippocampe ×2 photos
- Limite identifiée : Qwen3-VL imprécis en taxonomie spécialisée (crabe → Euphausiidae au lieu de Majidae)
---
## 2. Cron jobs Orange (production)
| ID | Nom | Horaire | Action | Notification |
|---|---|---|---|---|
| `d1f3041c` | orange-ouverture | 09:10 | Mesure d'ouverture | WhatsApp +33607148216 |
| `8cd988b1` | orange-intraday | 10:00→17:00 (8x) | Mesure horaire silencieuse | Aucune |
| `1a0d98b7` | orange-cloture | 17:40 | Mesure de clôture | WhatsApp +33607148216 |
| `7d4bbd3d` | orange-chart-update | 17:45 | Génère le SVG du jour | Aucune |
Tous : modèle `vllm/qwen3-vl`, runtime `OpenClaw Default` (light-context), jours mardi→vendredi.
Source données : Yahoo Finance via `curl + jq` (cf. AGENTS.md). Premier cycle complet : 4 juin 2026.
---
## 3. Outils créés par l'utilisateur (NE PAS recréer ni modifier)
### `generate_chart.py` (alias `gen_chart.py`)
- Localisation : `/home/node/.openclaw/workspace/scripts/generate_chart.py`
- Rôle : génère `orange_chart.svg` à partir de `orange-bourse.md`
- Stack : Python stdlib uniquement (PAS matplotlib, PAS yfinance)
- Validé en production le 4/6/2026
- Règles d'usage dans **TOOLS.md** + **AGENTS.md** (HARD CONSTRAINTS)
### Pattern global
> "Agent pour la sémantique, script pour la mécanique"
- L'agent : récup données via `curl`, lecture HEARTBEAT, formatage, décision WhatsApp
- Les scripts : génération SVG, parsing Gmail, calculs déterministes
---
## 4. Décisions techniques notables
- **Heartbeat désactivé** (`agents.defaults.heartbeat.every = "0"`) — évite la dérive de fréquence (voulait 1h, recevait 30 min). **Conséquence acceptée** : pas de recovery auto en cas de stall (cf. §6 TODO).
- **NODE_OPTIONS** = `--max-old-space-size=1536` (à passer à 4096 après upgrade RAM 20GB)
- **mem_limit** = 2g, **mem_reservation** = 512m (à passer à 6g/1g après upgrade)
- **Provider timeout** : 300s, **Job timeout** : 600s
- **Hard constraints renforcés** dans AGENTS.md suite à incident où l'agent a tenté matplotlib + yfinance + scraping Yahoo en parallèle au lieu de `generate_chart.py` (47% du contexte consommé en cascade d'outils).
---
## 5. Backups
- `/volume1/backups/openclaw/YYYYMMDD-HHMM/` (à créer **manuellement**, aucun cron orchestre actuellement)
- `/volume1/docker/openclaw-data/openclaw.json.last-good` (auto par OpenClaw)
- `/volume1/docker/openclaw-data/openclaw.json.bak` (auto par OpenClaw)
- `/volume1/docker/openclaw-data/workspace/MEMORY.md.bak-2026-06-09` (snapshot avant split du 9/6, 21117 chars)
- `/volume1/docker/openclaw-data/workspace/*.bak-20260604-*` (snapshots du round précédent du 4/6)
---
## 6. Bug du 2026-06-09 — Session WhatsApp DM stalled (RÉSOLU)
### Symptôme
Session `agent:main:whatsapp:direct:+33607148216` (id `cfb27376-d71a-4406-80aa-4a3e9ed5ced5`)
en state=processing, `lastProgressAge` ~6h43, aucune réponse aux messages WhatsApp.
### Cause racine identifiée
`MEMORY.md` = 21117 chars > `bootstrapMaxChars` = 20000 (défaut)
→ troncature côté bootstrap (`per-file-limit`)
→ silent fail de l'`embedded_run` sans réponse modèle ni delivery
→ état `processing` non libéré, payload contenant un champ string `undefined`
(qui faisait crasher `sessions tail` sur `.trim()` of undefined)
### Méthodologie de diagnostic appliquée
1. `sessions list` + `sessions tail` + `health` → 3 sources concordantes
2. **Aucune commande mutative sans avoir lu son `--help`** (règle d'or — à conserver)
3. `doctor --lint --json` → finding `core/doctor/bootstrap-size` confirmant la cause
4. Inspection du payload JSONL → `truncated: true` sur MEMORY.md confirmé
### Fix appliqué (sans restart gateway)
1. Backup : `cp MEMORY.md MEMORY.md.bak-2026-06-09`
2. Split MEMORY.md en :
- `MEMORY.md` réduit à **7453 chars** (essentiel always-in-prompt : outils, workflows, config, prefs user, runbook bref)
- `memory/2026-06-09.md` (**871 chars** : note du jour avec multimodal + bug stalled)
3. Suppression d'une duplication CONFIG-PRODUCTION qui s'était infiltrée
4. Vérification ownership `1000:1000` sur les 2 fichiers (sinon agent ne peut pas lire)
5. `doctor --lint --only core/doctor/bootstrap-size` → `{"ok":true,"findings":[]}`
6. **Test WhatsApp réel** : "Test post-fix" envoyé à 17:39:29 → "OK" reçu à 17:40:01 (32s, normal)
### Tailles bootstrap finales
| Fichier | Chars | Limite |
|---|---|---|
| MEMORY.md | 7453 | 20000 |
| AGENTS.md | 12259 | 20000 |
| TOOLS.md | 7522 | 20000 |
| SOUL.md | 1806 | 20000 |
| USER.md | 1489 | 20000 |
| IDENTITY.md | 1341 | 20000 |
| HEARTBEAT.md | 344 | 20000 |
| **Total bootstrap** | **40995** (+ workspace `.md` minuscules) | **60000** |
---
## 7. TODO / Différé
### Priorité haute
- [ ] **Décision OAuth Gmail** avant 12/6/2026 (token `gmail.modify` expire) :
Publish OAuth app GCP **vs** re-auth weekly via cron
- [ ] Phase E Gmail reportée : filtres natifs, vague 2 (Archive Philippot+Ulys), 2ème passe Q8 newsletters tech
### Priorité moyenne
- [ ] **Investiguer fichiers `gmail-audit.md` / `gmail-housekeeping.md`** créés en `root:root` mode 600
→ l'agent (uid 1000) ne peut pas les lire
→ probablement un cron-host qui `docker exec` en root au lieu d'un cron OpenClaw natif
- [ ] **`orange-chart-update` du 4/6 17h45** = `error` dans `cron list` → vérifier la cause
- [ ] **Activer `memorySearch`** (différé faute de provider d'embeddings local) :
- Pas d'Ollama installé sur ARCHIVE3 (curl localhost:11434 → no answer)
- Pas de `.gguf` dans `workspace/tools/models/`
- vLLM actuel sert le chat Qwen3-VL, pas les embeddings
- 3 options à arbitrer : (a) installer Ollama+nomic-embed-text, (b) ajouter endpoint
embedding sur DGX, (c) télécharger un .gguf local. Aucune urgente.
### Priorité basse
- [ ] **Pollution workspace** : fichiers parasites `-a`, `--max`, `--force`, `--query` à supprimer
(créés par flags shell mal échappés en sessions précédentes)
- [ ] **Backups OpenClaw** : aucune orchestration en place malgré la mention dans MEMORY.md
→ créer un cron host hebdo qui copie `/volume1/docker/openclaw-data/*` vers
`/volume1/backups/openclaw/$(date +%Y%m%d-%H%M)/`
- [ ] **Fragilité structurelle** : `Heartbeat disabled` empêche toute recovery auto.
Toute future panne d'un `embedded_run` (coupure WhatsApp, crash modèle, etc.) reproduira
le pattern stalled. Pas un bug en soi, mais à documenter pour la prochaine fois.
---
## 8. Préférences utilisateur (à respecter par l'agent et les sessions IA)
- L'utilisateur travaille **en vacances** → temps disponible pour expérimenter
(sinon sessions nocturnes courtes)
- Préfère la **transparence** : "tu as raison" plutôt que justifier une erreur
- N'aime PAS les solutions cloud payantes (Claude API, OpenAI, Groq) → **tout doit rester local**
- A tendance à **attaquer avant de lire** → être bref et structuré, ordre clair des actions
- Aime **challenger** les propositions : on lit toujours `--help` ou `config schema` avant
de proposer une commande mutative
- Convention de communication établie : ne pas inventer de référence externe sans recherche
vérifiable, préférer raisonner sur les sorties locales réelles
---
## 9. Convention pour la prochaine session
### Reprise de production
1. Lire ce HANDOFF en entier
2. `sudo docker exec openclaw-gateway node /app/dist/index.js health` (état général)
3. `sudo docker exec openclaw-gateway node /app/dist/index.js sessions list | head -10` (sessions actives)
4. `sudo docker exec openclaw-gateway node /app/dist/index.js doctor --lint --json` (findings)
### Si nouveau debug
- **Aucune commande mutative sans `--help` lu au préalable**
- **Lire toujours d'abord** : `health`, `sessions list`, `doctor --lint --json`
- Pour mutation config : `config patch --stdin --dry-run` puis sans `--dry-run`
- Pour cleanup sessions : `cleanup --dry-run` puis `cleanup --enforce`
- Penser à `chown 1000:1000` après tout `sudo tee`/`sudo cp` dans workspace
### Append-only sur ce HANDOFF
À chaque session significative, ajouter une entrée dans **§6** (sous forme de nouvelle
sous-section "Bug du YYYY-MM-DD" ou "Évolution du YYYY-MM-DD") plutôt que d'écraser.
---
_Fin du HANDOFF — 2026-06-09 17:45 UTC+2_
## 10 juin 2026 ~01:00-01:45 UTC+2 — Persistance OAuth gog (pattern réutilisable)
### Contexte général
Découverte que les tools CLI (gog, et probablement d'autres) stockent leurs
credentials/tokens dans la couche writable du container par défaut, donc PERDUS à
chaque `compose down/up` ou `--force-recreate`. Pattern à corriger pour tout outil
qui aura besoin d'auth persistée (gog, future MCP avec OAuth, etc.).
### Modification compose.yaml (mutation #1 infra)
Ajout dans la section `environment:` du service openclaw-gateway :
GOG_HOME: /home/node/.openclaw/gogcli
→ Redirige toute l'arborescence gog (credentials + keyring + config + cache) sous
le volume Synology persisté `/volume1/docker/openclaw-data:/home/node/.openclaw`.
→ Pattern applicable à d'autres outils via leur env var équivalente (XDG_DATA_HOME,
HOME custom, ou env-var-spécifique).
### Migration manuelle des fichiers gog (one-shot)
Structure attendue par gog avec GOG_HOME :
$GOG_HOME/data/credentials.json
$GOG_HOME/data/keyring/_gogcli_key_v1_<base64>...
$GOG_HOME/config/config.json (créé à la demande)
Migration chronologique :
1. mkdir /volume1/docker/openclaw-data/gogcli (uid 1000, mode 700)
2. compose up -d → gog crée data/keyring/.lock
3. mv credentials.json + keyring/ vers data/ (préservation des 4 _gogcli_key_v1_*)
4. chown -R 1000:1000, find -type f -exec chmod 600, dirs chmod 700
### Test de persistance validé
- `compose down` puis `compose up -d` (recreate complet container) — 60s
- Container Up healthy après ~60s (start_period: 120s dans healthcheck)
- `gog auth list` : compte tallagrand.thierry@gmail.com survit ✅
- `gog gmail labels list` : retourne INBOX/SENT/IMPORTANT/CHAT comme avant ✅
- OpenClaw `health` : WhatsApp linked (auth age 1m), 33 sessions store
### Sessions store état après nuit
- 33 entries (vs 32 avant purge cfb27376 + 1 nouvelle session WhatsApp + 1 dashboard)
- Plus de session ruinée à 87% saturation
- Compaction `mode=safeguard, reserveTokens=8192` actif (cf. config patch précédent)
### Backups préservés (à purger après ~2 semaines de stabilité)
- /volume1/docker/openclaw/compose.yaml.bak-pre-goghome-20260610-*
- /volume1/docker/openclaw-data/gogcli.bak-pre-mv-20260610-0132/
- /volume1/docker/openclaw-data/agents/main/sessions/sessions.json.bak-pre-purge-*
- /volume1/docker/openclaw-data/openclaw.json.bak-pre-restart-20260609
### TODO infra (reportés, non critiques)
- Pattern XDG_*_HOME pour autres outils CLI futurs (réflexe à appliquer
systématiquement pour tout outil qui stocke des credentials)
- Investiguer warning gog `config.path missing` (gogcli/config/config.json)
- Mettre à jour scripts/generate_gmail_token.sh (la commande `gog auth generate-token`
utilisée n'existe pas — la vraie procédure est `gog auth credentials set` puis
`gog auth add ... --manual --gmail-scope=full --force-consent`)
- Surveiller latence cron Orange après tuning compaction (potentiel impact +overhead
via `mode=safeguard`)
- Bug Qwen3-VL boucle de répétition sur prompts longs : reproduit en prod, pas en
API directe ≤300 tokens. Cause suspectée : tool catalog volumineux + tool error
qui dégrade attention. Mitigations à explorer : réduire AGENTS.md de 12259 chars,
désactiver dir_list sur runtime dashboard, ou repetition_penalty (non exposé en
config OpenClaw 2026.6.1)
### Changement comportemental notable
Avant cette session, l'agent ne pouvait pas répondre aux questions Gmail via
WhatsApp ou dashboard (auth absente → tool errors → boucle Qwen3). Maintenant :
- Gmail accessible via gog gmail search/trash/archive/labels
- Doc syntaxe + hard constraints dans MEMORY.md (section "Gmail (gog CLI v0.21.0)")
- Référence au HANDOFF Gmail pour la doc opérationnelle complète
## Validation 10 juin 2026 ~02:13 UTC+2 — Découvertes
### Commande /new dans WhatsApp DM
Le plugin OpenClaw WhatsApp supporte la commande slash /new qui crée une nouvelle
session sans toucher à l'ancienne. **C'est la méthode privilégiée** pour
redémarrer une conversation WhatsApp DM saturée — préférable à la purge manuelle
de sessions.json pour les cas non corrompus.
Quand utiliser :
- Session WhatsApp DM avec context overflow (> 60k tokens)
- Bouclage suspect après plusieurs heures de discussion
- Reset volontaire pour démarrer un nouveau sujet
Quand NE PAS utiliser (préférer purge manuelle) :
- JSONL corrompu (assistant content: [] empty array)
- Session avec compactionCheckpoints=7+ (irrécupérable)
- abortedLastRun=true persistant
### Hot-reload config compaction validé
agents.defaults.compaction.* est correctement hot-reloaded après compose restart.
Pas besoin de docker compose down/up pour ces changements.
### Bug observable mais sans gravité
effectiveReserveTokens plafonne à 16384 même avec reserveTokensFloor configuré
à 20000. Le système gère via fallback compaction multiple. À reporter upstream
OpenClaw si récurrent.
## 10/6/2026 mercredi ~15:00-15:03 UTC+2 — Fix bug "OK au lieu du cours" cron orange-intraday
### Cause racine
Le cron `orange-intraday` (id `8cd988b1-d91e-4ecb-8719-c1c72efb0d87`) :
- prompt terminait par "Réponds par 'OK' une fois fini. PAS de WhatsApp pour l'intraday."
- delivery configuré en mode=announce, channel=whatsapp, to=+33607148216
- → l'agent répondait "OK" en signal de fin, et le mode `announce` envoyait
systématiquement la dernière réponse à WhatsApp = donc "OK" partait à chaque heure.
- L'instruction "PAS de WhatsApp pour l'intraday" dans le prompt était ignorée
(delivery est piloté par config, pas par prompt).
### Fix appliqué
Édition du prompt via :
`cron edit 8cd988b1-... --message "<nouveau prompt>"`
Remplacement final :
AVANT : "Réponds par 'OK' une fois fini. PAS de WhatsApp pour l'intraday."
APRÈS : "Une fois fini, réponds avec UNIQUEMENT cette ligne au format strict :
'ORA.PA : <prix>€ (<variation>%)' OU 'ORA.PA : indisponible'
PAS de 'OK', PAS d'autre texte, PAS de tableau, PAS de commentaire."
### Validation
- 15:00 : cron horaire avec ancien prompt → envoi "OK" (état pré-fix)
- 15:03 : `cron run` manuel avec nouveau prompt → envoi "ORA.PA : 17,83€ (+0,99%)" ✅
- ✅ format conforme, valeur cohérente (vendredi 6/6 clôture 17,66 → +0,99% = 17,83 OK)
- À surveiller : prochains crons auto 16:00 et 17:00 mercredi
### Backup
/volume1/docker/openclaw-data/handoffs/cron-orange-intraday-before-20260610-0303.json
### Apprentissages
- `cron edit <id> --message "<text>"` est la méthode propre pour modifier un prompt
- `cron run <id>` permet un test immédiat (debug, ne respecte pas le schedule)
- Le delivery mode `announce` envoie automatiquement la dernière réponse de l'agent
→ écrire le prompt pour que la dernière réponse soit le format souhaité
- Les autres cron Orange (orange-cloture, orange-ouverture) utilisent un pattern
similaire, à monitorer mais pas à modifier (semblent OK structurellement)
## 10/6/2026 nuit (~22:00-23:48 Paris) — Session marathon résolution amnésie agent
### Phases réussies
- A. Audit complet (versions, dette technique, ressources)
- B. Backup pré-MAJ (156 MB préservés, image pre-maj-20260610-2237)
- C. MAJ OpenClaw 2026.6.1 → 2026.6.5 (sans régression)
- D. Tests baseline 6/6 pass
- F. TOOLS.md + MEMORY.md complets avec convention exec
### Découverte majeure — Bug structurel résolu
Le bug "amnésie Gmail" n'était PAS une vraie amnésie LLM.
L'agent essayait d'invoquer `gog` comme tool natif (10 fois !).
La cause : TOOLS.md documentait `gog gmail send --to ...` sans préciser
que `gog` doit passer par le tool natif `exec` (ou `bash`).
Fix : ajout section 1.0 dans TOOLS.md + section 7 hard constraint :
"Toute commande CLI (gog, python3, curl, jq, git, node) DOIT être
invoquée via `exec` ou `bash`."
### Test validation 23:46 ✅
Question : "Envoie un mail à tallagrand.thierry@gmail.com..."
Agent : appelle `tool=exec` avec `gog gmail send -a ... --to ... --subject ... --body ...`
Résultat : Mail reçu (ID 19eb38051276d01e), agent confirme avec détails.
### Pattern réutilisable (à appliquer aux futures capacités)
1. Identifier la commande exacte (--help)
2. Documenter EXPLICITEMENT que ça passe par exec
3. Donner un exemple concret avec arguments
4. Mapping question→action
5. Hard constraint anti-amnésie
6. Test immédiat après modification
### Reste pour Phase E (en cours dans la nuit)
- E.1 Refactor generate_chart.py (PNG + tri chronologique)
- E.2 Reconstruction orange-bourse.md propre
- E.3-E.5 Test pipeline + cron + WhatsApp PNG
### Backups préservés
- /volume1/docker/openclaw-backups-pre-maj-20260610-2237/ (compose + data)
- Image Docker openclaw-gateway:pre-maj-20260610-2237 (rollback ULTIME)
- TOOLS.md.bak-pre-skills-fix-* (avant tee)
- TOOLS.md.bak-pre-exec-fix-* (avant section 1.0)
- MEMORY.md.bak-pre-skills-fix-*
## 11/6/2026 nuit (~00:30-01:45 Paris) — Phase E pipeline PNG complet
### Phase E.1 (infra cairosvg) ✅
- Dockerfile patché : ajout libcairo2/libpango/libgdk-pixbuf/libffi-dev/shared-mime-info + cairosvg==2.7.1
- Build OK (~33s) → openclaw-custom:latest sha256:8164c3ae04793...
- Container UP healthy 5 min après recreate
- Test cairosvg : PNG 15933 bytes généré
- Test gog auth list : tallagrand.thierry@gmail.com préservé (3e validation persistance)
- Patch generate_chart.py : conversion SVG→PNG + horodatage charts/ora-YYYY-MM-DD-HHMM.png + symlink ora-latest.png
### Phase E.2 (reconstruction orange-bourse.md) ✅
- Script clean_bourse_md.py créé (parse + dédup + tri + retire pollution YAML)
- Avant : 44 lignes, 5 sections désordonnées avec double 06-05, 10 polluants YAML
- Après : 34 lignes propres, 4 sections triées (06-05, 06-07, 06-09, 06-10), 0 pollution
- Régénération graphe 06-10 : 10 mesures, courbe LISSE chronologique (vs zigzag avant)
- Visualisation PNG validée : 46519 bytes, charte graphique Orange parfaite
### Reste pour Phase E (demain en condition réelle)
- E.4 : Update prompt cron orange-intraday (ajouter étape send WhatsApp + image PNG)
- E.5 : Test cron run + validation WhatsApp avec image attachée
### Fichiers ajoutés cette nuit
- /workspace/scripts/clean_bourse_md.py (nouveau, ~140 lignes)
- /workspace/charts/ (nouveau dossier)
- /workspace/charts/ora-2026-06-11-0143.png + symlink ora-latest.png
### Backups préservés
- Dockerfile.bak-pre-cairosvg-20260611-0014
- generate_chart.py.bak-pre-png-patch-20260611-XXXX
- orange-bourse.md.bak-pre-clean-20260611-0140
- orange-bourse.md.bak-pre-apply-20260611-XXXX
## 11/6/2026 (~01:55-02:10 Paris) — Phase E.4 prompt cron mis à jour
### Cron run manuel à 01:55 — preuve que ancien prompt fonctionne
- Run "ok" 31.5s, WhatsApp delivered "ORA.PA : 18,02€ (+2,07%)" (capture validée)
- Note : Yahoo retourne le last close + variation hors séance, normal
### Phase E.4 — Update prompt cron orange-intraday
- Backup pré-E4 : cron-orange-intraday-pre-E4-XXXX.json
- Nouveau prompt : 4 étapes (ajout étape 4 message+attachment PNG)
- Précisions : heure Paris explicite, valeurs cohérentes 10:00-17:30, ora-latest.png comme attachment
- Cleanup data fictives 11/06 : restauration depuis backup pré-fake
- Phase E.5 différée à 11/6 matin avant 10h (avant cron auto)
### Phase E.5 faite
- cron run manuel test → vérifier WhatsApp reçoit texte + image PNG
- a vérifier et faire si besoin cron auto utilise nouveau prompt → 2e validation
- Si KO : revert via backup .bak-pre-E4-XXXX
- Si OK : Phase E entièrement validée, fin Phase E
## 23 juin 2026 ~01:15-01:30 UTC+2 — Migration cron email horaire vers rapport quotidien 8h30
### Contexte
L’utilisateur souhaitait abandonner le rapport Gmail horaire (`hourly-email-check`) au
profit d’un unique résumé quotidien à 8h30 Europe/Paris, tous les jours (week-end inclus),
sur WhatsApp.
### Source de vérité identifiée
Le cron actif n’était PAS dans les fichiers JSON obsolètes (`cron/jobs.json*`) mais dans
la base SQLite :
- Path : `/volume1/docker/openclaw-data/state/openclaw.sqlite`
- Table : `cron_jobs`
- Job ID : `9d43dc31-f6ee-445e-a085-753ca65bc0b0`
### Actions réalisées
1. **Backup** de `state/openclaw.sqlite`, `workspace/MEMORY.md`, `workspace/TOOLS.md`
(timestamp `.bak-20260623-01...`).
2. **UPDATE SQLite** :
- `name` : `hourly-email-check` → `daily-email-report`
- `schedule_expr` : `0 * * * *` → `30 8 * * *`
- `payload_message` : résumé 24h, format court global + détail important (max 5)
- `job_json` : resynchronisé avec les nouvelles valeurs
- `next_run_at_ms` : recalculé (OpenClaw applique un `staggerMs` de 5 min max,
donc exécution réelle entre 8h30 et 8h35).
3. **Mise à jour `workspace/MEMORY.md`** :
- TODO courant modifié
- Apprentissage structurant du 23/6/2026 ajouté
4. **Mise à jour `workspace/TOOLS.md`** :
- Nouvelle section 9 « Gmail daily cron » (schedule, canal, format, source de vérité)
5. **Archivage** des fichiers JSON obsolètes dans `cron/archived-20260623/` :
- `jobs.json.migrated`
- `jobs.json.bak`
- `jobs-state.json.migrated`
- `runs/*.jsonl.migrated` (12 fichiers)
### Validation utilisateur (challenge pré-build)
- ✅ Tous les jours (week-end inclus)
- ✅ Résumé des dernières 24h
- ✅ Renommage en `daily-email-report`
- ✅ Canal WhatsApp conservé (`+33607148216`)
- ✅ Format court global + détail important avec date/heure
- ✅ Mise à jour MEMORY.md / TOOLS.md
- ✅ Archivage des JSON obsolètes (option B)
- ✅ Backup SQLite avant mutation
- ✅ Forçage de `next_run_at_ms`
- ✅ StaggerMs conservé (exécution 8h30–8h35, acceptable)
### Fichiers impactés
- `state/openclaw.sqlite` (mutation du job)
- `workspace/MEMORY.md`
- `workspace/TOOLS.md`
- `cron/jobs.json.migrated` → `cron/archived-20260623/`
- `cron/jobs.json.bak` → `cron/archived-20260623/`
- `cron/jobs-state.json.migrated` → `cron/archived-20260623/`
- `cron/runs/*.jsonl.migrated` → `cron/archived-20260623/runs/`
### Prochaine validation attendue
Vérifier demain matin (~8h30–8h35) que WhatsApp reçoit bien le résumé quotidien avec
le format convenu. Si format incorrect : ajuster `payload_message` dans SQLite.
## 23 juin 2026 ~01:15-01:30 UTC+2 — Migration cron email horaire vers rapport quotidien 8h30
### Contexte
L’utilisateur souhaitait abandonner le rapport Gmail horaire (`hourly-email-check`) au
profit d’un unique résumé quotidien à 8h30 Europe/Paris, tous les jours (week-end inclus),
sur WhatsApp.
### Source de vérité identifiée
Le cron actif n’était PAS dans les fichiers JSON obsolètes (`cron/jobs.json*`) mais dans
la base SQLite :
- Path : `/volume1/docker/openclaw-data/state/openclaw.sqlite`
- Table : `cron_jobs`
- Job ID : `9d43dc31-f6ee-445e-a085-753ca65bc0b0`
### Actions réalisées
1. **Backup** de `state/openclaw.sqlite`, `workspace/MEMORY.md`, `workspace/TOOLS.md`
(timestamp `.bak-20260623-01...`).
2. **UPDATE SQLite** :
- `name` : `hourly-email-check` → `daily-email-report`
- `schedule_expr` : `0 * * * *` → `30 8 * * *`
- `payload_message` : résumé 24h, format court global + détail important (max 5)
- `job_json` : resynchronisé avec les nouvelles valeurs
- `next_run_at_ms` : recalculé (OpenClaw applique un `staggerMs` de 5 min max,
donc exécution réelle entre 8h30 et 8h35).
3. **Mise à jour `workspace/MEMORY.md`** :
- TODO courant modifié
- Apprentissage structurant du 23/6/2026 ajouté
4. **Mise à jour `workspace/TOOLS.md`** :
- Nouvelle section 9 « Gmail daily cron » (schedule, canal, format, source de vérité)
5. **Archivage** des fichiers JSON obsolètes dans `cron/archived-20260623/` :
- `jobs.json.migrated`
- `jobs.json.bak`
- `jobs-state.json.migrated`
- `runs/*.jsonl.migrated` (12 fichiers)
### Validation utilisateur (challenge pré-build)
- ✅ Tous les jours (week-end inclus)
- ✅ Résumé des dernières 24h
- ✅ Renommage en `daily-email-report`
- ✅ Canal WhatsApp conservé (`+33607148216`)
- ✅ Format court global + détail important avec date/heure
- ✅ Mise à jour MEMORY.md / TOOLS.md
- ✅ Archivage des JSON obsolètes (option B)
- ✅ Backup SQLite avant mutation
- ✅ Forçage de `next_run_at_ms`
- ✅ StaggerMs conservé (exécution 8h30–8h35, acceptable)
### Fichiers impactés
- `state/openclaw.sqlite` (mutation du job)
- `workspace/MEMORY.md`
- `workspace/TOOLS.md`
- `cron/jobs.json.migrated` → `cron/archived-20260623/`
- `cron/jobs.json.bak` → `cron/archived-20260623/`
- `cron/jobs-state.json.migrated` → `cron/archived-20260623/`
- `cron/runs/*.jsonl.migrated` → `cron/archived-20260623/runs/`
### Prochaine validation attendue
Vérifier demain matin (~8h30–8h35) que WhatsApp reçoit bien le résumé quotidien avec
le format convenu. Si format incorrect : ajuster `payload_message` dans SQLite.

370
workspace/AGENTS.md Normal file
View File

@@ -0,0 +1,370 @@
# AGENTS.md - Your Workspace
This folder is home. Treat it that way.
## 📈 BOURSE — Architecture N8N (refonte 2026-06-24)
> ⚠️ Les anciens scripts `generate_chart.py`, `get_quote.py`, `clean_bourse_md.py`
> et le fichier `orange-bourse.md` sont OBSOLÈTES. NE PLUS les utiliser, NE PLUS
> éditer `orange-bourse.md` à la main. Toute la bourse passe désormais par N8N.
### Principe
Tu es l'INTERLOCUTEUR. N8N est l'EXÉCUTANT.
Tu reçois la demande humaine → tu appelles le workflow N8N → il renvoie un PNG → tu l'affiches (WhatsApp/GUI).
Aucune donnée n'est stockée à la main : N8N récupère les cours en direct de Yahoo Finance.
### Source de vérité = `bourse-config.json`
La watchlist (liste des tickers) et les options de graphe vivent dans
`/home/node/.openclaw/workspace/bourse-config.json`. Tu PEUX et DOIS éditer ce fichier
quand l'humain demande d'ajouter/retirer une valeur ou changer une option.
### Le seul outil bourse autorisé : le webhook N8N
Pour produire un graphe, tu fais UN appel HTTP POST (via `exec` + curl) :
```bash
curl -s -X POST "https://n8n.airtria.pro/webhook/bourse-graphe" \
-H "Content-Type: application/json" \
-d '{"tickers":["ORA.PA","TTE.PA"],"range":"5d","interval":"60m","beginAtZero":true}' \
-o /home/node/.openclaw/workspace/charts/bourse.png
```
Réponse = un fichier PNG prêt à envoyer sur WhatsApp. Paramètres du body (tous optionnels) :
- `tickers` : liste de symboles Yahoo (def: lus dans bourse-config.json)
- `range` : `1d`,`5d`,`1mo`,`3mo`,`6mo`,`1y` (def `5d`)
- `interval` : `15m`,`60m`,`1d` (def `60m`)
- `beginAtZero` : `true` = axe Y part de 0 (pas de "variation géante pour 5cts"), `false` = zoom sur les variations
- `title` : titre du graphe (optionnel)
### Mapping demande humaine → action
| Demande | Action |
|---|---|
| "montre-moi Orange" | POST webhook avec tickers=["ORA.PA"] |
| "ajoute Total / Nvidia" | éditer `bourse-config.json` (ajouter "TTE.PA"/"NVDA") puis POST webhook avec la nouvelle liste |
| "fais commencer le graphe à 0" | POST avec `beginAtZero:true` (+ mettre à jour le defaults dans la config) |
| "zoome sur les variations" | POST avec `beginAtZero:false` |
| "le cours d'Orange aujourd'hui" | POST avec range="1d", interval="15m" ; le PNG suffit |
| "Anthropic" | Anthropic n'est PAS cotée en bourse → le dire, ne pas inventer de ticker |
### Règles
1. NE PAS réinventer un script Python de graphe. Le webhook N8N fait tout.
2. NE PAS éditer `orange-bourse.md` (fichier mort).
3. Tickers Yahoo : actions FR = suffixe `.PA` (ORA.PA, TTE.PA). US = sans suffixe (NVDA, AAPL).
4. Si le webhook renvoie un PNG "Aucune donnée" : c'est que le marché est fermé ou
le ticker est invalide → le dire à l'humain, NE PAS inventer de cours.
5. Si l'humain veut un nouveau type de graphe/comportement que le workflow ne sait pas faire,
tu peux MODIFIER le workflow N8N via le MCP `n8n-mcp` (workflow id `4bluZIeN3TnbzIrv`).
6. Réponse WhatsApp bourse : 3 lignes max + le PNG en pièce jointe.
## First Run
If `BOOTSTRAP.md` exists, that's your birth certificate. Follow it, figure out who you are, then delete it. You won't need it again.
## Session Startup
Use runtime-provided startup context first.
That context may already include:
- `AGENTS.md`, `SOUL.md`, `USER.md`, and `HANDOFF.md`
- recent daily memory such as `memory/YYYY-MM-DD.md`
- `MEMORY.md` when this is the main session
Do not manually reread startup files unless:
1. The user explicitly asks
2. The provided context is missing something you need
3. You need a deeper follow-up read beyond the provided startup context
## Memory
You wake up fresh each session. These files are your continuity:
- **Daily notes:** `memory/YYYY-MM-DD.md` (create `memory/` if needed) — raw logs of what happened
- **Long-term:** `MEMORY.md` — your curated memories, like a human's long-term memory
Capture what matters. Decisions, context, things to remember. Skip the secrets unless asked to keep them.
### 🧠 MEMORY.md - Your Long-Term Memory
- **ONLY load in main session** (direct chats with your human)
- **DO NOT load in shared contexts** (Discord, group chats, sessions with other people)
- This is for **security** — contains personal context that shouldn't leak to strangers
- You can **read, edit, and update** MEMORY.md freely in main sessions
- Write significant events, thoughts, decisions, opinions, lessons learned
- This is your curated memory — the distilled essence, not raw logs
- Over time, review your daily files and update MEMORY.md with what's worth keeping
### 📝 Write It Down - No "Mental Notes"!
- **Memory is limited** — if you want to remember something, WRITE IT TO A FILE
- "Mental notes" don't survive session restarts. Files do.
- When someone says "remember this" → update `memory/YYYY-MM-DD.md` or relevant file
- When you learn a lesson → update AGENTS.md, TOOLS.md, or the relevant skill
- When you make a mistake → document it so future-you doesn't repeat it
- **Text > Brain** 📝
## Red Lines
- Don't exfiltrate private data. Ever.
- Don't run destructive commands without asking.
- `trash` > `rm` (recoverable beats gone forever)
- When in doubt, ask.
## 🔁 Anti-Loop — Règle générale d'arrêt (added 2026-06-14)
Cette règle est TRANSVERSALE et prime sur toute autre tâche.
### STOP après 2 échecs
Si une ressource demandée (fichier, dossier, projet, service, API)
est introuvable ou inaccessible après **2 vérifications maximum** :
1. ARRÊTER immédiatement toute nouvelle tentative.
2. NE PAS reformuler, NE PAS chercher ailleurs en boucle.
3. NE PAS conclure "ça a été supprimé/déplacé" sans preuve.
4. Signaler clairement à l'utilisateur :
- Ce qui a été cherché (chemin/commande exacts)
- Le résultat brut (ex: "No such file or directory")
- L'hypothèse la plus probable (ex: "hors de mon sandbox")
5. Demander une clarification ou un accès, puis ATTENDRE.
### Périmètre / Sandbox — vérité de base
- Mon home est `/home/node/.openclaw/workspace`.
- Je ne vois PAS l'hôte Synology ni les autres conteneurs
(LMS / LyrionMusicServer, Plex, etc.) sauf si un volume est
explicitement monté dans mon workspace.
- "Introuvable dans le workspace" ≠ "n'existe pas sur le NAS".
→ Le dire ainsi, ne JAMAIS affirmer une suppression.
### Détection de répétition
Si je m'apprête à écrire une réponse quasi identique à la précédente
(même phrase, même conclusion) → c'est le signal d'une boucle.
ARRÊTER et passer en mode "demande de clarification".
## External vs Internal
**Safe to do freely:**
- Read files, explore, organize, learn
- Search the web, check calendars
- Work within this workspace
**Ask first:**
- Sending emails, tweets, public posts
- Anything that leaves the machine
- Anything you're uncertain about
## Group Chats
You have access to your human's stuff. That doesn't mean you _share_ their stuff. In groups, you're a participant — not their voice, not their proxy. Think before you speak.
### 💬 Know When to Speak!
In group chats where you receive every message, be **smart about when to contribute**:
**Respond when:**
- Directly mentioned or asked a question
- You can add genuine value (info, insight, help)
- Something witty/funny fits naturally
- Correcting important misinformation
- Summarizing when asked
**Stay silent when:**
- It's just casual banter between humans
- Someone already answered the question
- Your response would just be "yeah" or "nice"
- The conversation is flowing fine without you
- Adding a message would interrupt the vibe
**The human rule:** Humans in group chats don't respond to every single message. Neither should you. Quality > quantity. If you wouldn't send it in a real group chat with friends, don't send it.
**Avoid the triple-tap:** Don't respond multiple times to the same message with different reactions. One thoughtful response beats three fragments.
Participate, don't dominate.
### 😊 React Like a Human!
On platforms that support reactions (Discord, Slack), use emoji reactions naturally:
**React when:**
- You appreciate something but don't need to reply (👍, ❤️, 🙌)
- Something made you laugh (😂, 💀)
- You find it interesting or thought-provoking (🤔, 💡)
- You want to acknowledge without interrupting the flow
- It's a simple yes/no or approval situation (✅, 👀)
**Why it matters:**
Reactions are lightweight social signals. Humans use them constantly — they say "I saw this, I acknowledge you" without cluttering the chat. You should too.
**Don't overdo it:** One reaction per message max. Pick the one that fits best.
## Tools
Skills provide your tools. When you need one, check its `SKILL.md`. Keep local notes (camera names, SSH details, voice preferences) in `TOOLS.md`.
**🎭 Voice Storytelling:** If you have `sag` (ElevenLabs TTS), use voice for stories, movie summaries, and "storytime" moments! Way more engaging than walls of text. Surprise people with funny voices.
**📝 Platform Formatting:**
- **Discord/WhatsApp:** No markdown tables! Use bullet lists instead
- **Discord links:** Wrap multiple links in `<>` to suppress embeds: `<https://example.com>`
- **WhatsApp:** No headers — use **bold** or CAPS for emphasis
## Règle WhatsApp - Suivi boursier
Quand l'utilisateur mentionne "orange", "ora.pa", "cours", "bourse" :
- Réponse en **3 lignes maximum**
- Format : "ORA.PA : 11,42 € (-0,35%)"
- Pas de tableau, pas de description longue
- À chaque réponse boursière, **vider le tool result** après usage
## Règles d'usage des outils Web Fetch
- TOUJOURS limiter Web Fetch à 1500 chars max
- Pour la bourse : fetch UNIQUEMENT le prix + variation, pas la page complète
- Préférer une API directe quand possible (Yahoo Finance, Alpha Vantage)
- Après usage d'un tool, RÉSUMER en 2 lignes max et oublier le contenu brut
## 📊 Cours boursier ponctuel (texte seulement, sans graphe)
Pour un prix chiffré rapide SANS graphe, requête Yahoo directe :
```bash
curl -fs "https://query1.finance.yahoo.com/v8/finance/chart/SYMBOLE?interval=1d&range=1d" \
| jq '.chart.result[0].meta | {price: .regularMarketPrice, prev: .chartPreviousClose, currency}'
```
Pour un GRAPHE → utiliser le webhook N8N (voir section BOURSE plus haut).
---
## Gmail — Hard Constraints (added 2026-06-05)
### NEVER
1. **Permanent delete** : interdiction absolue de `messages.delete`.
Toujours `messages.trash` (récupérable 30 jours).
2. **Toucher la whitelist** : voir `gmail-rules.md` section Whitelist absolue.
Si un mail matche un domaine/adresse whitelisté, ABORT silencieusement.
3. **Plus de 200 actions par batch** Gmail.
4. **Plus de 2000 actions Gmail par jour** sans confirmation explicite humaine.
5. **Modifier les labels système** : INBOX peut être retiré (archive),
mais SENT/DRAFT/IMPORTANT/STARRED/SPAM/TRASH sont en lecture seule.
6. **Lancer une vague sans dry-run préalable** validé par moi.
### ALWAYS
1. **Dry-run obligatoire** avant toute action en masse :
- Lister les IDs concernés (sample 10 + total)
- Présenter à validation humaine
- Exécuter seulement après "go" explicite
2. **Logger chaque batch** dans `gmail-housekeeping.md` :
- Timestamp, règle ID, IDs touchés, action, résultat
3. **Respecter `gmail-rules.md`** comme source de vérité unique
pour les règles de tri.
4. **Vérifier la whitelist au runtime**, pas seulement au design.
La whitelist peut évoluer, l'agent doit la relire à chaque vague.
5. **En cas de doute** sur un mail (matche partiellement whitelist,
pattern ambigu, expéditeur inconnu) → laisser dans inbox + log dans
`gmail-doubts.md` pour revue humaine.
6. **Pause 5s** entre 2 batchs `gog gmail trash` ou `gog gmail archive`.
### Format des logs Gmail
`gmail-housekeeping.md` (append-only) :
```
## 2026-06-XX HH:MM — Vague 1.03 (Quora)
- Query: from:quora.com in:inbox older_than:90d
- Matched: 487 threads
- Sample (10): [id1, id2, ...]
- Action: trash
- Status: dry-run validated by Thierry at HH:MM
- Executed: HH:MM, batch 1/3 (200 OK), batch 2/3 (200 OK), batch 3/3 (87 OK)
- Total moved to trash: 487
```
## 💓 Heartbeats - Be Proactive!
When you receive a heartbeat poll (message matches the configured heartbeat prompt), don't just reply `HEARTBEAT_OK` every time. Use heartbeats productively!
You are free to edit `HEARTBEAT.md` with a short checklist or reminders. Keep it small to limit token burn.
### Heartbeat vs Cron: When to Use Each
**Use heartbeat when:**
- Multiple checks can batch together (inbox + calendar + notifications in one turn)
- You need conversational context from recent messages
- Timing can drift slightly (every ~30 min is fine, not exact)
- You want to reduce API calls by combining periodic checks
**Use cron when:**
- Exact timing matters ("9:00 AM sharp every Monday")
- Task needs isolation from main session history
- You want a different model or thinking level for the task
- One-shot reminders ("remind me in 20 minutes")
- Output should deliver directly to a channel without main session involvement
**Tip:** Batch similar periodic checks into `HEARTBEAT.md` instead of creating multiple cron jobs. Use cron for precise schedules and standalone tasks.
**Things to check (rotate through these, 2-4 times per day):**
- **Emails** - Any urgent unread messages?
- **Calendar** - Upcoming events in next 24-48h?
- **Mentions** - Twitter/social notifications?
- **Weather** - Relevant if your human might go out?
**Track your checks** in `memory/heartbeat-state.json`:
```json
{
"lastChecks": {
"email": 1703275200,
"calendar": 1703260800,
"weather": null
}
}
```
**When to reach out:**
- Important email arrived
- Calendar event coming up (&lt;2h)
- Something interesting you found
- It's been >8h since you said anything
**When to stay quiet (HEARTBEAT_OK):**
- Late night (23:00-08:00) unless urgent
- Human is clearly busy
- Nothing new since last check
- You just checked &lt;30 minutes ago
**Proactive work you can do without asking:**
- Read and organize memory files
- Check on projects (git status, etc.)
- Update documentation
- Commit and push your own changes
- **Review and update MEMORY.md** (see below)
### 🔄 Memory Maintenance (During Heartbeats)
Periodically (every few days), use a heartbeat to:
1. Read through recent `memory/YYYY-MM-DD.md` files
2. Identify significant events, lessons, or insights worth keeping long-term
3. Update `MEMORY.md` with distilled learnings
4. Remove outdated info from MEMORY.md that's no longer relevant
Think of it like a human reviewing their journal and updating their mental model. Daily files are raw notes; MEMORY.md is curated wisdom.
The goal: Be helpful without being annoying. Check in a few times a day, do useful background work, but respect quiet time.
## Make It Yours
This is a starting point. Add your own conventions, style, and rules as you figure out what works.
## Related
- [Default AGENTS.md](/reference/AGENTS.default)

128
workspace/HANDOFF.md Normal file
View File

@@ -0,0 +1,128 @@
# HANDOFF — OpenClaw — État global
**Date :** 2026-06-25
**Session :** Passage du HANDOFF bourse-only à un dashboard multi-domaines.
**Statut global :** 🟢 opérationnel — Bourse N8N en prod, Gmail actif, WhatsApp appairé.
---
## 📋 En-tête / Statut global
| Item | Valeur |
|---|---|
| Prochaine priorité | Valider le fix du cron `orange-cloture` (prochain run 26/06 17:40) |
| Dernière refonte majeure | Bourse via N8N + passage modèle Thinking (voir handoff dédié) |
| Backend LLM | `vllm/qwen3-vl` (Thinking), `maxTokens: 16384`, `contextWindow: 65536` |
| WhatsApp | Appairé pour `+33607148216` |
| GUI / Reasoning | Défaut conseillé **Medium** ; max tokens GUI à régler manuellement |
---
## 📊 Tableau de bord par domaine
| Domaine | État | Source de vérité | Prochaine action | Dernier événement |
|---|---|---|---|---|
| **Bourse** | 🟢 Actif | `workspace/bourse-config.json` + workflow N8N `4bluZIeN3TnbzIrv` | Valider fix `orange-cloture` (timeout 600s + prompt simplifié) au prochain run 26/06 17:40 | Refonte N8N 2026-06-24 |
| **Gmail** | 🟢 Actif | `workspace/gmail-rules.md` + filtres natifs Phase E | Phase F : archive Philippot + Ulys (restes) ; surveiller filtres Phase E | Filtres Phase E créés 2026-06-25 ✅ |
| **WhatsApp** | 🟢 Actif | `openclaw.json` (canal `custom-1`) + `workspace/USER.md` | Maintenir appairage / validation envoi images | Appairage confirmé |
| **LLM / Infra** | 🟢 Actif | `openclaw.json` (`vllm/qwen3-vl`, `reasoning: true`) | Surveillance timeouts vs Thinking ; régler max tokens GUI | `maxTokens` porté à 16384 |
| **Voice / TTS** | ⚫ Désactivé | `openclaw.json` (skills `sag`, `voice-*`, `openai-whisper` off) | Rien à faire sauf demande explicite | Désactivé |
| **Heartbeat** | ⚫ Désactivé | `workspace/HEARTBEAT.md` vide, `agents.defaults.heartbeat.every: "0"` | Rien à faire sauf activation explicite | Désactivé |
---
## 📈 Bourse — Résumé opérationnel
- **Principe** : agent = interlocuteur ; N8N = exécutant. Aucune donnée boursière n'est éditée à la main.
- **Workflow N8N** : `Bourse — Graphe multi-tickers (v3)` — ID `4bluZIeN3TnbzIrv`
- **Webhook** : `POST https://n8n.airtria.pro/webhook/bourse-graphe`
- **Watchlist** : définie dans `workspace/bourse-config.json` (actuellement `ORA.PA`, `TTE.PA`)
- **Cron actif** : `orange-cloture` (`40 17 * * 1-5` Europe/Paris) → appelle le webhook et envoie le PNG sur WhatsApp.
- **Crons historiques obsolètes** : `orange-ouverture`, `orange-intraday`, `orange-chart-update` — tous **désactivés** dans `state/openclaw.sqlite` (ne pas les réactiver).
- **Détail de la refonte** : voir `handoffs/HANDOFF-2026-06-24-BOURSE-N8N.md`
---
## 📬 Gmail — Résumé opérationnel
- **CLI** : `gog` v0.21.0, OAuth persisté.
- **Règles** : `workspace/gmail-rules.md`
- **Logs d'actions** : `workspace/gmail-housekeeping.md`
- **Cron actif** : `daily-email-report` (`30 8 * * *` Europe/Paris) → résumé quotidien sur WhatsApp.
- **Filtres Phase E** : 18 filtres natifs créés (2026-06-25) → labels `Promos`, `Dev-Tools`, `Social`, plus `Receipts`/`Newsletters` existants.
- **Next steps** : Phase F (restes Philippot/Ulys), surveiller l’efficacité des filtres Phase E.
---
## 📱 WhatsApp
- **Compte** : `custom-1`
- **Numéro autorisé** : `+33607148216`
- **Capacités confirmées** : texte, image PNG/JPEG, commande `/new`.
- **Format bourse** : 3 lignes max + PNG en pièce jointe.
---
## ⚠️ Risques & vigilance partagés
1. **Cron `orange-cloture` en timeout corrigé** : timeout porté de 240 s à 600 s, prompt simplifié, compteurs d'erreur réinitialisés. Prochain run : 26/06 17:40. Le webhook N8N a été testé : ~1,3 s pour obtenir le PNG.
2. **MCP N8N** : les outils `update_workflow` / `activate` sont buggés. Préférer l'API REST N8N directe (`PUT /workflows/{id}` puis `POST /workflows/{id}/activate`).
3. **Divergence modèles** : `agents/main/agent/models.json` référence encore des modèles Codex/GPT, alors que le runtime utilise `vllm/qwen3-vl`. Risque de confusion GUI.
4. **Ownership fichiers** : ✅ résolu le 25/06 — plus de fichiers `root` hors `node_modules` / `.git`.
5. **Fichiers obsolètes bourse** : `orange-bourse.md`, `get_quote.py`, `generate_chart.py`, `clean_bourse_md.py` sont archivés dans `workspace/_archive-bourse-20260624/`. **Ne pas les réutiliser.**
---
## 📅 Journal d'exécution récent
| Date (Paris) | Domaine | Événement | Résultat |
|---|---|---|---|
| 2026-06-25 08:30 | Gmail | `daily-email-report` | ✅ livré WhatsApp |
| 2026-06-25 17:40 | Bourse | `orange-cloture` | ⚠️ timeout |
| 2026-06-25 ~19:30 | Gmail | Audit Phase E (2000 threads sample) | ✅ rapport dans `workspace/gmail-phase-e-audit-20260625.md` |
| 2026-06-25 ~20:00 | Gmail | 18 filtres natifs Phase E + cleanup ~889 messages | ✅ |
| 2026-06-25 ~20:15 | Gmail | Phase F — Philippot + Ulys inbox vides | ✅ |
| 2026-06-24 | Bourse | Refonte N8N validée | ✅ graphes testés, workflow actif |
---
## ✅ TODOs actifs (cross-domaines)
| # | Action | Domaine | Priorité | Statut |
|---|---|---|---|---|
| 1 | Valider le cron `orange-cloture` après fix (timeout 600s, prochain run 26/06 17:40) | Bourse | Haut | ⏳ |
| 2 | Phase F Gmail : archive Philippot + Ulys (restes non filtrés) | Gmail | Moyen | ✅ |
| 3 | Surveiller l’efficacité des filtres Phase E (1–2 semaines) | Gmail | Moyen | ⏳ |
| 4 | Régler le max tokens GUI à ~8192 (navigateur) | LLM/GUI | Haut | ⏳ |
| 5 | Tester "2 graphes séparés zoomés" | Bourse | Moyen | ⏳ |
---
## 📚 Liens rapides (source de vérité)
| Besoin | Fichier |
|---|---|
| Comportement + hard constraints | `workspace/AGENTS.md` |
| Skills / syntaxe des commandes | `workspace/TOOLS.md` |
| Mémoire long terme | `workspace/MEMORY.md` |
| État global / transfert | `workspace/HANDOFF.md` (ce fichier) |
| Watchlist bourse | `workspace/bourse-config.json` |
| Règles Gmail | `workspace/gmail-rules.md` |
| Jobs cron | `state/openclaw.sqlite` (table `cron_jobs`) |
---
## 🚀 Reprise rapide pour une nouvelle session
1. Lire `workspace/AGENTS.md` (comportement + red lines).
2. Lire `workspace/HANDOFF.md` (état global + TODOs).
3. Aller au domaine concerné : `workspace/TOOLS.md` pour la syntaxe, `workspace/bourse-config.json` pour la bourse, `workspace/gmail-rules.md` pour Gmail.
4. Vérifier les TODOs non résolus ci-dessus avant de commencer une tâche.
---
## 🗂️ Historique des handoffs détaillés
- `handoffs/HANDOFF-2026-06-09.md` — Session initiale / contexte global
- `handoffs/HANDOFF-2026-06-09-GMAIL.md` — Refonte Gmail / GOG
- `handoffs/HANDOFF-2026-06-24-BOURSE-N8N.md` — Refonte Bourse N8N + Thinking (détail complet)

158
workspace/MEMORY.md Normal file
View File

@@ -0,0 +1,158 @@
# Mémoire opérationnelle — MEMORY.md
> Connaissances persistantes pour l'agent. Lu à chaque création de session.
---
## Identité du système
**OpenClaw** : v2026.6.5 (mis à jour le 11/6/2026)
**Hébergement** : Synology DS920+ ARCHIVE3 (RAM 20Gi, /volume1/docker/)
**LLM backend** : `Qwen/Qwen3-VL-30B-A3B-Thinking-FP8` servi par vLLM sur DGX Spark, `--served-model-name=qwen3-vl`
**Utilisateur principal** : Thierry Tallagrand (`+33607148216`)
**Vision projet** : système d'orchestration personnelle (bourse via N8N, mail multi-comptes, photos→sheets, WhatsApp/GUI).
---
## Capacités opérationnelles
### Gmail (gog CLI v0.21.0) — ACTIF
- ✅ **Envoyer mail** : `gog gmail send --to ... --subject "..." --body "..." --attach <fichier>`
- ✅ **Lire/chercher** : `gog gmail search "..." -j --max N`
- ✅ **Brouillons** : `gog gmail drafts create/list/send/delete`
- ✅ **Trier** : `gog gmail trash/archive` (toujours `--dry-run` d'abord)
- ✅ **Labels** : `gog gmail labels list`, `gog gmail messages modify --add-label/--remove-label`
### WhatsApp — ACTIF
- ✅ Envoi messages texte vers l'utilisateur principal
- ✅ Envoi images PNG/JPEG — SVG interdits
- ✅ Commande `/new` pour nouvelle session DM
### Bourse — Workflow N8N (refonte 2026-06-24)
- ✅ **Graphe** : webhook N8N `POST https://n8n.airtria.pro/webhook/bourse-graphe` (workflow `4bluZIeN3TnbzIrv`)
- ✅ **Watchlist** : éditable dans `workspace/bourse-config.json`
- ✅ **Prix texte rapide** : `curl -fs "https://query1.finance.yahoo.com/v8/finance/chart/SYMBOLE?interval=1d&range=1d" | jq '.chart.result[0].meta | {price: .regularMarketPrice, prev: .chartPreviousClose, currency}'`
- ✅ **Cron** : `orange-cloture` (40 17 * * 1-5) via le workflow N8N
- ⚠️ **OBSOLÈTES** (ne plus utiliser) : `orange-bourse.md`, `get_quote.py`, `generate_chart.py`, `clean_bourse_md.py` — archivés dans `workspace/_archive-bourse-20260624/`
### Filesystem & exec
- ✅ Lecture/écriture dans `/home/node/.openclaw/workspace/`
- ✅ Exec `python3`, `node`, `curl`, `jq`, `git`
- ✅ Aucun `pip install` runtime
### Web
- ✅ `web_fetch` (1500 chars max), `web_search` (10 résultats max)
---
## Hard constraint GLOBAL — Anti-amnésie
**L'agent NE DIT JAMAIS "je ne peux pas faire X" sans vérification.**
Procédure obligatoire avant tout refus :
1. Chercher X dans `TOOLS.md` (sections 1-9)
2. Si X est documenté → tenter la commande et rapporter le résultat
3. Si erreur → rapporter l'erreur EXACTE, pas l'incapacité
4. Si vraiment non documenté → demander précision à l'utilisateur
**Exemples de refus INTERDITS** :
- "Je ne peux pas envoyer un mail" (faux : Gmail send actif)
- "Je n'ai pas accès à Gmail" (faux : auth persistée)
- "Je suis un assistant sans capacités" (faux : voir `TOOLS.md`)
- "Gmail à venir" (faux : opérationnel depuis 9/6/2026)
- "Je ne peux pas tracer un graphe boursier" (faux : webhook N8N actif depuis 24/6/2026)
---
## Bourse — Architecture N8N (source de vérité actuelle)
### Principe
Agent = interlocuteur. N8N = exécutant. Aucune donnée n'est editée à la main.
### Source de vérité
- Fichier : `workspace/bourse-config.json`
- Tickers FR : suffixe `.PA` (ORA.PA, TTE.PA)
- Tickers US : sans suffixe (NVDA, AAPL)
- Aliases et options par défaut définis dans le JSON
### Crons actifs
- `orange-cloture` (`40 17 * * 1-5` Europe/Paris) : appelle le webhook N8N et envoie le PNG sur WhatsApp.
- Actuellement en timeout — voir `workspace/HANDOFF.md` TODOs.
### Crons bourse obsolètes (désactivés dans SQLite)
- `orange-ouverture`
- `orange-intraday`
- `orange-chart-update`
### Format réponse standard
- Cours simple : `ORA.PA : 17,86€ (+1,16%)`
- Indisponible/marché fermé : dire "Aucune donnée", ne pas inventer
- Graphe : 3 lignes max + PNG attaché
---
## Gmail — Suivi des phases
### Phase terminées
- Re-auth OAuth + GOG_HOME persisté (2026-06-09)
- Phase D : 12 401 mails trashés
### Phases terminées
- Phase E : filtres natifs Gmail anti-spam (2026-06-25) — 18 filtres créés, ~889 messages archivés
- Phase F : archive Philippot + Ulys (2026-06-25) — inbox vides, futurs messages filtrés
### Phases en attente
- Phase G : longue traîne newsletters
### Cron actif
- `daily-email-report` (`30 8 * * *` Europe/Paris) → résumé quotidien WhatsApp des dernières 24h
---
## TODO actuel
### Haute priorité
- Stabiliser le cron `orange-cloture` (timeouts)
- Régler le max tokens GUI à ~8192 (navigateur)
### Moyenne priorité
- Tester "2 graphes séparés zoomés" (2× `beginAtZero:false`)
- Surveiller l’efficacité des filtres Phase E (1–2 semaines)
- Phase G Gmail : longue traîne newsletters
### Basse priorité
- Aligner `agents/main/agent/models.json` avec `vllm/qwen3-vl`
- Augmenter `OPENCLAW_CRON_JOB_TIMEOUT_MS` si le Thinking déborde
---
## Apprentissages structurants
### Sessions précédentes
- **9/6/2026** : Re-auth OAuth Gmail + GOG_HOME persisté (test compose down/up validé)
- **10/6/2026** : Fix cron orange-intraday (prompt "OK" → vrai cours), RAM upgrade 16GB
- **10/6/2026** : Découverte SVG incompatible WhatsApp + bug tri chronologique
- **23/6/2026** : Migration du cron email horaire (`hourly-email-check`) vers un rapport quotidien (`daily-email-report`) à 8h30 Europe/Paris. Source de vérité : `state/openclaw.sqlite` (pas les JSON obsolètes). Format : résumé court global + détail des messages importants.
- **24-25/6/2026** : Refonte bourse via N8N — suppression des scripts Python, du fichier `orange-bourse.md` et des workflows cassés ; passage au modèle Thinking.
- **25/6/2026** : Phase E Gmail (filtres natifs) + Phase F (archive Philippot/Ulys) terminées. Audit via SSH sur Synology + `gog` dans container `openclaw-gateway`.
### Patterns à respecter
- Test après chaque modification (checklist comportementale)
- Backup AVANT chaque mutation (`.bak-<TS>` avec timestamp)
- 3 couches doivent rester alignées : Tools/Skills (`TOOLS.md`) + Knowledge (`MEMORY.md`) + Identity (`SOUL.md` / `IDENTITY.md`)
- L'agent ne modifie jamais des fichiers directement quand un outil/service est la source de vérité (cas bourse : `bourse-config.json` OK, mais les prix viennent de Yahoo via N8N)
---
## Méta : où trouver quoi
| Sujet | Fichier de référence |
|---|---|
| Skills opérationnels (syntaxe gog, webhook, etc.) | `TOOLS.md` |
| Comportement, hard constraints | `AGENTS.md` |
| Identité, persona | `SOUL.md`, `IDENTITY.md` |
| État global / transfert inter-sessions | `HANDOFF.md` |
| Mode batch/cron silencieux | `HEARTBEAT.md` |
| Règles métier Gmail | `gmail-rules.md` |
| Données bourse (watchlist + options) | `bourse-config.json` |
| Mémoire évolutive (ce fichier) | `MEMORY.md` |

287
workspace/TOOLS.md Normal file
View File

@@ -0,0 +1,287 @@
# Outils opérationnels (TOOLS.md)
> **Source de vérité skills.** Ce fichier liste les capacités RÉELLEMENT
> disponibles pour l'agent. Si une capacité y figure, l'agent PEUT et DOIT
> l'utiliser. Si l'utilisateur demande une action documentée ici, l'agent
> NE DOIT PAS répondre "je ne peux pas".
---
### 1.0 IMPORTANT — Comment l'agent invoque les commandes gog
`gog` n'est PAS un tool natif d'OpenClaw. C'est une commande CLI installée
dans le container PATH. L'agent DOIT l'invoquer via le tool natif `exec`
(ou son alias `bash`) avec la commande gog complète comme argument.
INTERDIT (l'agent essaye d'appeler `gog` comme tool → ÉCHEC garanti) :
tool: gog
args: { "operation": "send", "to": "...", "subject": "..." }
OBLIGATOIRE (l'agent appelle `exec` avec la commande gog complète) :
tool: exec
args: { "command": "gog gmail send -a tallagrand.thierry@gmail.com --to ... --subject ... --body ..." }
Toutes les commandes documentées ci-dessous (sections 1.1 à 1.6) doivent
être invoquées via `exec` ou `bash` avec la commande complète comme argument.
### Pattern général pour TOUTE commande CLI dans ce fichier
Cette règle s'applique aussi à : `python3`, `curl`, `jq`, `git`, `node`,
et tout binaire installé dans le container.
Bon réflexe :
tool: exec, args: { "command": "<binaire> <arguments>" }
Mauvais réflexe :
tool: <binaire>, args: { ... }
## 1. Gmail — gog CLI v0.21.0 (OPÉRATIONNEL)
**Statut** : ACTIF depuis 9 juin 2026. Auth OAuth Google persistée.
**Compte** : tallagrand.thierry@gmail.com
**Path keyring** : /home/node/.openclaw/gogcli/data/keyring/
**Doc complète** : workspace/gmail-rules.md
### 1.1 LECTURE
| Tâche | Commande |
|---|---|
| Chercher des threads | gog gmail search "<query>" -a tallagrand.thierry@gmail.com -j --max N |
| Lister labels | gog gmail labels list -a tallagrand.thierry@gmail.com |
| Détail d'un thread | gog gmail thread get <id> -a tallagrand.thierry@gmail.com -j |
| Détail d'un message | gog gmail messages get <id> -a tallagrand.thierry@gmail.com -j |
### 1.2 ENVOI (capacité ACTIVE)
Syntaxe :
gog gmail send -a tallagrand.thierry@gmail.com --to <destinataire> --subject "<sujet>" --body "<corps>"
Flags utiles :
- --cc=<email>, --bcc=<email> : copies
- --body-html="<html>" : version HTML (alternative à --body)
- --attach=<path> : pièce jointe (répétable, ex: graphe PNG)
- --reply-to-message-id=<id> : répondre à un mail spécifique
- --dry-run : simuler sans envoyer
- -j : sortie JSON
Exemple concret avec attachement :
gog gmail send -a tallagrand.thierry@gmail.com --to tallagrand.thierry@gmail.com --subject "Cours ORA" --body "ORA.PA : 17,86€ (+1,16%)" --attach /home/node/.openclaw/workspace/charts/ora-2026-06-11-1700.png
### 1.3 BROUILLONS (alternative prudente)
| Tâche | Commande |
|---|---|
| Créer un brouillon | gog gmail drafts create -a <email> --to <dest> --subject "..." --body "..." |
| Lister brouillons | gog gmail drafts list -a <email> |
| Envoyer un brouillon | gog gmail drafts send <draftId> -a <email> |
| Supprimer brouillon | gog gmail drafts delete <draftId> -a <email> |
### 1.4 MUTATIONS — `--dry-run` OBLIGATOIRE avant mass action
| Tâche | Commande |
|---|---|
| Mettre à la corbeille | gog gmail trash "<query>" -a <email> --dry-run puis --force |
| Archiver | gog gmail archive "<query>" -a <email> --dry-run puis --force |
| Modifier labels | gog gmail messages modify <id> -a <email> --add-label X --remove-label Y |
### 1.5 Mapping question utilisateur → action
| Question | Commande à utiliser |
|---|---|
| "Envoie un mail à X avec sujet Y et corps Z" | gog gmail send --to X --subject "Y" --body "Z" |
| "Envoie-moi un mail" | gog gmail send --to tallagrand.thierry@gmail.com ... |
| "Combien de mails j'ai aujourd'hui" | gog gmail search "in:inbox newer_than:1d" -j --max 100 |
| "Trie mes promos vieilles" | gog gmail trash "category:promotions older_than:30d" --dry-run |
| "Liste les mails de X" | gog gmail search "from:X" -j --max N |
### 1.6 Hard constraints Gmail
- INTERDIT : "je ne peux pas envoyer un mail" — la capacité EST active
- INTERDIT : "Gmail à venir" — c'est OPÉRATIONNEL depuis 9/6/2026
- Si une commande échoue, RAPPORTER l'erreur réelle (stderr)
- 2 erreurs syntax/auth max → STOP, demander à l'utilisateur
- --dry-run avant action en masse (>5 mails)
- Container headless : pas de browser disponible
---
## 2. WhatsApp — Plugin OpenClaw
### 2.1 Capacités confirmées
- Envoi message texte vers utilisateur (+33607148216)
- Envoi image PNG/JPEG (à valider Phase E.5)
- Commande slash /new : nouvelle session DM (testée 10/6 OK)
### 2.2 Format restrictions
- AUTORISÉS : PNG, JPEG, WebP, PDF, Office docs, archives
- INTERDIT : SVG (rejeté par WhatsApp Cloud API avec OutboundDeliveryError)
### 2.3 Mapping question → action
| Question | Action |
|---|---|
| "Envoie-moi un message WhatsApp" | tool whatsapp send_message |
| "Envoie le graphe sur WhatsApp" | tool whatsapp send_message + image PNG attachée |
| Cron horaire bourse | delivery.mode=announce → dernière réponse agent envoyée auto |
### 2.4 Hard constraint
- Si erreur "OutboundDeliveryError image/svg+xml" : convertir en PNG
- Si l'envoi WhatsApp échoue : rapporter l'erreur exacte, ne pas re-tenter en boucle
---
## 3. Bourse — Workflow N8N (REFONTE 2026-06-24)
> ⚠️ OBSOLÈTES (ne plus utiliser) : `generate_chart.py`, `get_quote.py`,
> `clean_bourse_md.py`, `orange-bourse.md`. Toute la bourse passe par N8N.
### 3.1 Webhook graphe (outil principal)
- URL : `https://n8n.airtria.pro/webhook/bourse-graphe` (POST JSON)
- Workflow N8N id : `4bluZIeN3TnbzIrv` ("Bourse — Graphe multi-tickers (v3)")
- Renvoie : un PNG (image/png) prêt pour WhatsApp
- Body JSON (tout optionnel) :
- `tickers` : liste de symboles Yahoo, ex ["ORA.PA","TTE.PA","NVDA"]
- `range` : 1d|5d|1mo|3mo|6mo|1y (def 5d)
- `interval` : 15m|60m|1d (def 60m)
- `beginAtZero` : true (axe Y depuis 0) | false (zoom variations)
- `title` : titre optionnel
- Gestion marché fermé / ticker invalide : renvoie un PNG "Aucune donnée"
(jamais d'invention de cours).
Exemple :
```bash
curl -s -X POST "https://n8n.airtria.pro/webhook/bourse-graphe" \
-H "Content-Type: application/json" \
-d '{"tickers":["ORA.PA","TTE.PA"],"beginAtZero":true}' \
-o /home/node/.openclaw/workspace/charts/bourse.png
```
### 3.2 Watchlist = bourse-config.json
- Path : `/home/node/.openclaw/workspace/bourse-config.json`
- Source de vérité des tickers suivis + options par défaut.
- L'agent ÉDITE ce fichier pour ajouter/retirer une valeur.
### 3.3 Prix texte rapide (sans graphe)
- `curl -fs "https://query1.finance.yahoo.com/v8/finance/chart/SYMBOLE?interval=1d&range=1d" | jq '.chart.result[0].meta'`
### 3.4 Modifier le comportement du graphe
- Via MCP `n8n-mcp` (update_workflow) ou l'API n8n, workflow id `4bluZIeN3TnbzIrv`.
- Node JS "Fetch + Build QuickChart" = logique fetch+rendu. Rendu via QuickChart `version:"4"`.
---
## 4. Filesystem workspace
### 4.1 Path racine
/home/node/.openclaw/workspace/
### 4.2 Capacités
- Lecture/écriture de tout fichier dans workspace
- Exec scripts python3, bash dans workspace/scripts/
- PAS d'install pip durant runtime (figé Dockerfile : yfinance, requests)
### 4.3 Fichiers structurants
| Fichier | Rôle |
|---|---|
| MEMORY.md | Connaissances persistantes |
| AGENTS.md | Comportement, hard constraints |
| SOUL.md / IDENTITY.md | Identité, persona |
| TOOLS.md (ce fichier) | Skills opérationnel |
| HEARTBEAT.md | Mode batch/cron silencieux |
| gmail-rules.md | Règles métier Gmail |
| HANDOFF.md | État global / transfert inter-sessions |
| bourse-config.json | Watchlist + options du graphe bourse (obsolète : orange-bourse.md) |
---
## 5. Outils système disponibles
### 5.1 Dans le container
- python3 (3.11), pip3 (figé build-time)
- node (Node.js), npm
- curl, jq, git, tini
- gog (Google APIs CLI v0.21.0)
### 5.2 Web
- web_fetch : ~1500 chars max par fetch
- web_search : 10 résultats max
- Toutes URLs publiques HTTPS
---
## 6. Bourse — Pipeline (refonte N8N 2026-06-24)
### 6.1 Architecture
- L'agent reçoit la demande → POST webhook N8N (section 3.1) → PNG → WhatsApp.
- Watchlist dans `bourse-config.json` (section 3.2).
- Cron clôture (40 17 * * 1-5, Europe/Paris) : appelle le webhook et envoie le PNG WhatsApp.
### 6.2 Format réponse standard
- Avec graphe : 3 lignes texte + PNG attaché.
- Prix simple : `ORA.PA : 16,89€ (-0,68%)`.
- Marché fermé/indispo : le PNG "Aucune donnée" + le dire, ne pas inventer.
---
## 7. Hard constraint GLOBAL — Anti-amnésie
L'agent NE DOIT JAMAIS dire "je ne peux pas faire X" sans avoir vérifié
dans ce fichier (TOOLS.md) si X est une capacité documentée.
### Procédure mentale obligatoire avant de refuser :
1. Vérifier dans TOOLS.md si X est documenté
2. Si oui → tenter la commande, rapporter le résultat (succès ou erreur exacte)
3. Si erreur, demander de l'aide à l'utilisateur (pas prétendre l'incapacité)
4. Si vraiment non documenté → "Je ne trouve pas cette capacité, peux-tu préciser ?"
### Exemples de refus INTERDITS
- "Je ne peux pas envoyer de mail" (faux : voir section 1.2)
- "Je n'ai pas accès à Gmail" (faux : voir section 1)
- "Gmail est à venir" (faux : opérationnel depuis 9/6/2026)
- "Je suis dans un environnement sécurisé sans capacité" (faux : capacités listées ci-dessus)
### Nouvelle obligation (11/6/2026 post-test)
L'agent NE DOIT JAMAIS dire "tool 'gog' isn't available" ou équivalent.
`gog` n'est jamais un tool, c'est une commande shell.
Si l'agent voit "gog" dans une instruction, il DOIT utiliser `exec` :
tool: exec, args: { "command": "gog gmail send ..." }
Idem pour python3, curl, jq, git, node, et tout binaire CLI :
ces commandes passent TOUJOURS par `exec` ou `bash`, jamais comme tool direct.
---
## 8. Procédure d'ajout d'outil
1. Documenter dans TOOLS.md (ce fichier) avec syntaxe exacte
2. Ajouter mapping question→action (section 1.5, 2.3, etc.)
3. Ajouter hard constraint si nécessaire
4. Tester en dashboard ou WhatsApp /new
5. Backup TOOLS.md avant modification (.bak-<TS>)
---
## 9. Gmail daily cron
### 9.1 Job actif
| Cron | Schedule | Rôle | Canal |
|---|---|---|---|
| `daily-email-report` | `30 8 * * *` Europe/Paris | Résumé quotidien Gmail des dernières 24h | WhatsApp `announce` vers `+33607148216` |
### 9.2 Format de réponse attendu
- Ligne 1 : résumé global court (ex: « Gmail : 3 nouveaux, 1 important »).
- Lignes suivantes : détail UNIQUEMENT les messages importants (livraisons, rendez-vous, alertes, factures).
- Pour chaque message important : expéditeur, sujet, date/heure d'arrivée.
- Maximum 5 messages détaillés.
- Réponse en français.
- Ignorer les promotions et newsletters dans le détail.
### 9.3 Source de vérité
- Le job est défini dans `state/openclaw.sqlite`, table `cron_jobs`.
- Les fichiers `cron/jobs.json*` sont des migrations obsolètes d'anciens jobs bourse. Ne PAS les utiliser pour modifier ce cron.

8
workspace/cron/README.md Normal file
View File

@@ -0,0 +1,8 @@
# Cron legacy directory
> ⚠️ Les fichiers `jobs.json*` et `orange-monitor-state.json` ont été archivés dans
> `workspace/_archive-bourse-20260624/legacy-cron/` car ils constituent des migrations obsolètes.
>
> **Source de vérité actuelle :** `state/openclaw.sqlite`, table `cron_jobs`.
>
> Ne pas rééditer les fichiers JSON ici : le runtime lit les jobs depuis SQLite.

View File

@@ -0,0 +1,181 @@
## 2026-06-05 20:23:00 — Vague 1 batch run
| Règle | Description | Total trashed | Batchs |
|---|---|---:|---:|
| V1.01 | Rustica | 0 | 1 |
| V1.02 | TAAFT | 240 | 1 |
| V1.03 | Quora | 720 | 3 |
| V1.04 | Bricomarché | 0 | 1 |
| V1.05 | Beehiiv | 1 | 1 |
| V1.06 | Carrefour | 218 | 1 |
| V1.07 | Cdiscount | 240 | 1 |
| V1.08 | Weldom | 275 | 1 |
| V1.09 | Suunto | 0 | 1 |
| V1.10 | Samsung | 9 | 1 |
| V1.11 | Ollama | 0 | 1 |
| V1.12 | RedHat | 0 | 1 |
| V1.13 | eBay | 136 | 1 |
| V1.14 | AliExpress | 384 | 2 |
| V1.15 | Avis | 10 | 1 |
| V1.16 | LinkedIn updates | 754 | 3 |
| V1.17 | LinkedIn notifs | 983 | 4 |
| V1.18 | LinkedIn messages | 1365 | 5 |
| V1.19 | Facebook | 0 | 1 |
**Total Vague 1 trashed: 5335 messages**
## 2026-06-05 21:34:45 — Vague 1bis (tranche 6m→1y)
| Règle | Description | Total trashed | Batchs |
|---|---|---:|---:|
| V1.01 | Rustica | 82 | 1 |
| V1.02 | TAAFT | 160 | 1 |
| V1.03 | Quora | 631 | 3 |
| V1.04 | Bricomarché | 55 | 1 |
| V1.05 | Beehiiv | 0 | 1 |
| V1.06 | Carrefour | 32 | 1 |
| V1.07 | Cdiscount | 36 | 1 |
| V1.08 | Weldom | 49 | 1 |
| V1.09 | Suunto | 12 | 1 |
| V1.10 | Samsung | 16 | 1 |
| V1.11 | Ollama | 2 | 1 |
| V1.12 | RedHat | 15 | 1 |
| V1.13 | eBay | 64 | 1 |
| V1.14 | AliExpress | 84 | 1 |
| V1.15 | Avis | 6 | 1 |
| V1.16 | LinkedIn updates | 77 | 1 |
| V1.17 | LinkedIn notifs | 90 | 1 |
| V1.18 | LinkedIn messages | 133 | 1 |
| V1.19 | Facebook | 103 | 1 |
**Total Vague 1bis (6m→1y) trashed: 1647 messages**
## 2026-06-06 01:07:10 — Vague 1ter (tranche 30j→6m)
| Règle | Description | Total trashed | Batchs |
|---|---|---:|---:|
| V1.01 | Rustica | 232 | 1 |
| V1.02 | TAAFT | 155 | 1 |
| V1.03 | Quora | 551 | 2 |
| V1.04 | Bricomarché | 49 | 1 |
| V1.05 | Beehiiv | 64 | 1 |
| V1.06 | Carrefour | 29 | 1 |
| V1.07 | Cdiscount | 35 | 1 |
| V1.08 | Weldom | 36 | 1 |
| V1.09 | Suunto | 33 | 1 |
| V1.10 | Samsung | 30 | 1 |
| V1.11 | Ollama | 23 | 1 |
| V1.12 | RedHat | 25 | 1 |
| V1.13 | eBay | 16 | 1 |
| V1.14 | AliExpress | 65 | 1 |
| V1.15 | Avis | 21 | 1 |
| V1.16 | LinkedIn updates | 66 | 1 |
| V1.17 | LinkedIn notifs | 44 | 1 |
| V1.18 | LinkedIn messages | 138 | 1 |
| V1.19 | Facebook | 259 | 1 |
**Total Vague 1ter (30j→6m) trashed: 1871 messages**
## 2026-06-06 01:27:51 — Vague Synology (notifs www.airtria.net)
Query: subject:"[www.airtria.net]" in:inbox
**Total Synology trashed: 1160 messages**
## 2026-06-06 01:45:19 — Vague Synology ALL variants
| SynPRO | 210 trashed |
| SynNET | 0 trashed |
| SynIP1 | 1889 trashed |
## 2026-06-06 02:09:21 — Vague 1quinquies (7j→30j) + 4 nouvelles règles
| Règle | Description | Total trashed | Batchs |
|---|---|---:|---:|
| V1.01 | Rustica | 37 | 1 |
| V1.02 | TAAFT | 23 | 1 |
| V1.03 | Quora | 85 | 1 |
| V1.04 | Bricomarché | 9 | 1 |
| V1.05 | Beehiiv | 11 | 1 |
| V1.06 | Carrefour | 7 | 1 |
| V1.07 | Cdiscount | 8 | 1 |
| V1.08 | Weldom | 5 | 1 |
| V1.09 | Suunto | 4 | 1 |
| V1.10 | Samsung | 3 | 1 |
| V1.11 | Ollama | 2 | 1 |
| V1.12 | RedHat | 3 | 1 |
| V1.13 | eBay | 5 | 1 |
| V1.14 | AliExpress | 21 | 1 |
| V1.15 | Avis | 3 | 1 |
| V1.16 | LinkedIn updates | 10 | 1 |
| V1.17 | LinkedIn notifs | 7 | 1 |
| V1.18 | LinkedIn messages | 25 | 1 |
| V1.19 | Facebook | 3 | 1 |
| V1.20 | VPAuto | 6 | 1 |
| V1.21 | Substack airepo | 4 | 1 |
| V1.22 | Intermarché | 5 | 1 |
| V1.23 | k8slens | 3 | 1 |
**Total Vague 1quinquies trashed: 289 messages**
---
## 2026-06-25 — Phase E : filtres natifs Gmail + cleanup
### Labels créés
- `Promos` (Label_11)
- `Dev-Tools` (Label_12)
- `Social` (Label_13)
### Filtres créés : 18
| ID | Query | Label |
|---|---|---|
| E01 | `from:linkedin.com OR from:e.linkedin.com` | Social |
| E02 | `from:facebookmail.com` | Social |
| E03 | `from:clients.ulys.com` | Receipts |
| E04 | `from:les-patriotes.fr` | Newsletters |
| E05 | `from:rustica-info.fr` | Newsletters |
| E06 | `from:mail.theresanaiforthat.com` | Newsletters |
| E07 | `from:quora.com` | Newsletters |
| E08 | `from:airepo@substack.com` | Newsletters |
| E09 | `from:vpauto.fr OR from:mail.vpauto.eu` | Promos |
| E10 | `from:communication.andre.fr` | Promos |
| E11 | `from:fr-news.adidas.com` | Promos |
| E12 | `from:eu1.tocampaigns.com` | Promos |
| E13 | `from:mkt.norauto.fr` | Promos |
| E14 | `from:news.intermarche.com` | Promos |
| E15 | `from:monmagasinvert.fr` | Promos |
| E16 | `from:dlink.com` | Promos |
| E17 | `from:messages.mongodb.com` | Dev-Tools |
| E18 | `from:k8slens.dev` | Dev-Tools |
### Cleanup rétroactif Phase E (archivés hors inbox)
| Query | Archivés |
|---|---:|
| `from:linkedin.com OR from:e.linkedin.com in:inbox` | 200 |
| `from:facebookmail.com in:inbox` | 43 |
| `from:clients.ulys.com in:inbox` | 87 |
| `from:les-patriotes.fr in:inbox` | 252 |
| `from:rustica-info.fr in:inbox` | 42 |
| `from:mail.theresanaiforthat.com in:inbox` | 26 |
| `from:vpauto.fr OR from:mail.vpauto.eu in:inbox` | 50 |
| `from:communication.andre.fr in:inbox` | 3 |
| `from:fr-news.adidas.com in:inbox` | 50 |
| `from:eu1.tocampaigns.com in:inbox` | 38 |
| `from:news.intermarche.com in:inbox` | 48 |
| `from:dlink.com in:inbox` | 50 |
| **Total Phase E archivés** | **~889** |
### Phase F complément (2026-06-25)
- `from:clients.ulys.com in:inbox` : 0 restant ✅
- `from:les-patriotes.fr in:inbox` : 0 restant ✅
- Phase F terminée : Philippot + Ulys complètement sortis de l’inbox et filtrés à l’arrivée.
### Audit
- Rapport : `workspace/gmail-phase-e-audit-20260625.md`
- Échantillon audité : 2000 threads

View File

@@ -0,0 +1,176 @@
# Gmail Phase E — Audit expéditeurs résiduels
Date : 2026-06-25 17h40 UTC
Échantillon : 2000 threads (500 par catégorie)
| Catégorie | Threads analysés |
|---|---:|
| Promotions | 500 |
| Social | 500 |
| Updates | 500 |
| Older than 30d | 500 |
## Top 25 expéditeurs non-whitelist
| Rang | Threads | Expéditeur |
|---|---|---|
| 1 | 109 | LinkedIn <linkedin@e.linkedin.com> |
| 2 | 65 | LinkedIn <jobs-listings@linkedin.com> |
| 3 | 56 | ULYS <info@clients.ulys.com> |
| 4 | 53 | "André" <contact@communication.andre.fr> |
| 5 | 45 | adidas <adidas@fr-news.adidas.com> |
| 6 | 29 | LinkedIn <messages-noreply@linkedin.com> |
| 7 | 29 | Florian Philippot <florian.philippot@les-patriotes.fr> |
| 8 | 28 | D-Link <uki-marketing@dlink.com> |
| 9 | 28 | VPauto <actu@vpauto.fr> |
| 10 | 27 | Rustica - La news du Jour <nepasrepondre@rustica-info.fr> |
| 11 | 26 | "TAAFT - There's An AI For That" <hi@mail.theresanaiforthat.com> |
| 12 | 25 | Cabesto <cabesto@eu1.tocampaigns.com> |
| 13 | 24 | Norauto <norauto.france@mkt.norauto.fr> |
| 14 | 22 | "Sélection Quora" <french-quora-digest@quora.com> |
| 15 | 22 | Chargemap <hello@chargemap.com> |
| 16 | 21 | Google <no-reply@accounts.google.com> |
| 17 | 20 | MongoDB <mongodbteam@messages.mongodb.com> |
| 18 | 20 | LinkedIn <news-noreply@linkedin.com> |
| 19 | 20 | AI Blueprint <airepo@substack.com> |
| 20 | 19 | Point Vert - Magasin Vert <noreply.marketing@monmagasinvert.fr> |
| 21 | 17 | "Intermarché" <intermarche@news.intermarche.com> |
| 22 | 17 | VPauto <vpauto@mail.vpauto.eu> |
| 23 | 16 | "Booking.com" <email.campaign@sg.booking.com> |
| 24 | 16 | Team Lens <no-reply@k8slens.dev> |
| 25 | 16 | LinkedIn <news@linkedin.com> |
## Top 20 domaines non-whitelist
| Rang | Threads | Domaine |
|---|---|---|
| 1 | 348 | linkedin.com |
| 2 | 133 | e.linkedin.com |
| 3 | 69 | quora.com |
| 4 | 67 | clients.ulys.com |
| 5 | 53 | communication.andre.fr |
| 6 | 45 | fr-news.adidas.com |
| 7 | 45 | google.com |
| 8 | 42 | rustica-info.fr |
| 9 | 39 | facebookmail.com |
| 10 | 31 | vpauto.fr |
| 11 | 30 | dlink.com |
| 12 | 29 | les-patriotes.fr |
| 13 | 26 | mail.theresanaiforthat.com |
| 14 | 25 | eu1.tocampaigns.com |
| 15 | 24 | mkt.norauto.fr |
| 16 | 22 | chargemap.com |
| 17 | 21 | accounts.google.com |
| 18 | 20 | messages.mongodb.com |
| 19 | 20 | substack.com |
| 20 | 19 | monmagasinvert.fr |
## Détail top 15 expéditeurs
### LinkedIn <linkedin@e.linkedin.com> — 109 threads (Social:109)
Sujets d'exemple :
- `2025-10-09 10:17` Demande d'expertise de LinkedIn
- `2025-08-13 22:28` thierry, merci de compter parmi nos membres
- `2025-03-12 17:23` thierry, merci de compter parmi nos membres
### LinkedIn <jobs-listings@linkedin.com> — 65 threads (Social:65)
Sujets d'exemple :
- `2024-06-20 14:10` Poste de French Freelance Translator Remote chez Top Language Jobsdisponible
- `2024-02-15 13:14` Centific recrute : Part-Time Work From Home as Internet Evaluator Anywhere in France: Project Milkyw
- `2023-08-31 14:05` Poste de RESPONSABLE R&D IT (F/H) chez Randstad Search : recrute activement
### ULYS <info@clients.ulys.com> — 56 threads (Promotions:33, Older than 30d:19, Updates:4)
Sujets d'exemple :
- `2026-06-25 16:59` Coup de chaud sur les prix ⚡
- `2026-06-16 18:01` 📩 La Pause Ulys #6 | Nos conseils pour réussir votre été 👀🌞
- `2026-05-17 18:02` Faites le plein de RÉCOMPENSES à partager 📢♥️
### "André" <contact@communication.andre.fr> — 53 threads (Promotions:39, Older than 30d:14)
Sujets d'exemple :
- `2026-06-25 16:30` Soldes : le savoir-faire italien à −70 %
- `2026-06-24 16:31` Top départ pour les Soldes André 🚀
- `2026-06-21 08:34` Bonne fête à tous les papas (et -50% pour lui)
### adidas <adidas@fr-news.adidas.com> — 45 threads (Promotions:28, Older than 30d:17)
Sujets d'exemple :
- `2026-06-25 09:16` Jusqu'à -30 %, en ligne et en magasin
- `2026-06-15 14:12` L'été commence ici
- `2026-05-01 12:09` Prêt(e) pour les festivals ?
### LinkedIn <messages-noreply@linkedin.com> — 29 threads (Social:29)
Sujets d'exemple :
- `2026-06-25 20:09` thierry, ajoutez Stanislas Zimmermann - Learning & Development Manager
- `2026-06-25 16:24` Nouvelle compétence disponible : Résolution de casse-têtes 🧩
- `2026-06-25 00:08` 7 personnes ont consulté votre profil
### Florian Philippot <florian.philippot@les-patriotes.fr> — 29 threads (Updates:17, Older than 30d:12)
Sujets d'exemple :
- `2026-06-25 11:01` La vérité triomphe !
- `2026-06-18 11:00` Une bascule historique !
- `2026-06-11 11:00` La révolte populaire !
### D-Link <uki-marketing@dlink.com> — 28 threads (Promotions:21, Older than 30d:7)
Sujets d'exemple :
- `2026-06-23 15:44` THIERRY Check out our Prime Day Deals
- `2026-06-16 10:46` THIERRY Experience Next-Generation 5G Connectivity with the F530
- `2026-06-09 11:38` Webinar - Bring Surveillance Back Into Focus
### VPauto <actu@vpauto.fr> — 28 threads (Promotions:23, Older than 30d:5)
Sujets d'exemple :
- `2026-05-09 09:01` +240 véhicules à vendre ce lundi à Lorient ! 📅
- `2026-05-05 18:08` 💫 Jeudi : +160 véhicules en vente multi-sites
- `2026-05-04 18:31` +800 véhicules à vendre cette semaine chez VPauto 🤯
### Rustica - La news du Jour <nepasrepondre@rustica-info.fr> — 27 threads (Promotions:19, Updates:8)
Sujets d'exemple :
- `2026-06-25 11:40` Arrosage tomates : les meilleures techniques pour des fruits juteux
- `2026-06-24 13:37` Récolte du potager : faut‑il cueillir le matin ou le soir pour un meilleur goût ?
- `2026-06-23 11:41` Taille courge : maîtrisez la croissance pour de beaux légumes !
### "TAAFT - There's An AI For That" <hi@mail.theresanaiforthat.com> — 26 threads (Updates:25, Promotions:1)
Sujets d'exemple :
- `2026-06-03 23:55` 🦾 May's Hottest AI Tools
- `2026-06-25 00:55` 🦾 OpenAI Cooks Up Jalapeño
- `2026-06-24 00:39` 🦾 GPT-5 Cracked a 3-Year Mystery
### Cabesto <cabesto@eu1.tocampaigns.com> — 25 threads (Promotions:22, Older than 30d:3)
Sujets d'exemple :
- `2026-03-19 08:50` Thierry, on a sélectionné des promos rien que pour toi !
- `2026-03-11 06:48` Découvre nos nouveautés pour toi Thierry 😉
- `2026-03-05 11:30` Thierry, on a sélectionné des promos rien que pour toi !
### Norauto <norauto.france@mkt.norauto.fr> — 24 threads (Promotions:18, Older than 30d:6)
Sujets d'exemple :
- `2026-06-08 08:13` Reprenez la route au meilleur prix
- `2026-04-07 08:27` Facilité, prix et services : plus de raison d’attendre
- `2026-04-01 07:00` 10€ de remise sur votre vidange
### "Sélection Quora" <french-quora-digest@quora.com> — 22 threads (Updates:21, Promotions:1)
Sujets d'exemple :
- `2026-06-12 20:06` La France blanche et chrétienne n’a jamais existé » : L’extrême droite fantasme une F...
- `2026-06-24 22:07` Le Français parle toujours de s'expatrier en Espagne ou au Portugal, pourquoi pas en ...?
- `2026-06-23 21:07` Combien de musulmans y a-t-il en France ?
### Chargemap <hello@chargemap.com> — 22 threads (Promotions:16, Older than 30d:5, Updates:1)
Sujets d'exemple :
- `2026-05-22 17:02` Long trajet : les 5 réflexes indispensables
- `2026-05-17 14:00` -10% chez Atlante ⚡️
- `2026-04-27 14:00` -10% chez Plug Inn fast charge ⚡️
## Recommandations filtres Phase E
### Filtres à créer (Archive + Label)
| Expéditeur / Domaine | Action proposée | Note |
|---|---|---|
| @linkedin.com / @e.linkedin.com | Archive + Label `Social` | Encore très présent malgré Phase D |
| @clients.ulys.com | Archive + Label `Receipts` | Prévu Phase F, peut être anticipé |
| @les-patriotes.fr | Archive + Label `Newsletters` | V2.01 existante |
| @rustica-info.fr, @mail.theresanaiforthat.com, @quora.com, @substack.com | Archive + Label `Newsletters` | Newsletters récurrentes |
| @vpauto.fr, @mail.vpauto.eu | Archive + Label `Promos` | Enchères/promos auto |
| @communication.andre.fr, @fr-news.adidas.com, @eu1.tocampaigns.com, @mkt.norauto.fr, @monmagasinvert.fr | Archive + Label `Promos` | E-com / promo |
| @dlink.com | Archive + Label `Promos` | Marketing D-Link |
| @messages.mongodb.com, @k8slens.dev | Archive + Label `Dev-Tools` | Tech tools updates |
| @chargemap.com | à vérifier | Lié VE / recharge — peut mériter label `Charge-VE` |
| @accounts.google.com | NE PAS FILTRER | Sécurité / alertes Google |

199
workspace/gmail-rules.md Normal file
View File

@@ -0,0 +1,199 @@
# Gmail Rules — Plan de ménage
_Généré le 2026-06-05 par Phase C (validation humaine)._
_Source : `gmail-audit.md` (sample 3000 threads), validations Thierry._
## Légende
- 🟢 **Vague 1 — Trash** : aucune valeur, jamais lu, désabo Gmail natif ensuite
- 🟡 **Vague 2 — Archive** : pas de valeur active mais on garde (taggé)
- 🔴 **Whitelist absolue** : ne JAMAIS toucher
- 🟣 **Spécial** : traitement dédié (digest VE, etc.)
## 🔴 Whitelist absolue (NE JAMAIS TOUCHER)
Toute action Gmail (trash, archive, label) est INTERDITE sur ces sources.
### Banques
- `@cic.fr`, `@e-cic.fr`
- `@bpgo.fr` (Banque Pop Grand Ouest)
- `@cmb.fr`
### Admin / légal
- `@impots.gouv.fr`, `@dgfip.finances.gouv.fr`
- `@digiposte.fr`
- `@ameli.fr`
### Telco perso
- `@orange.com`, `@orange.fr`
- `@neuf.fr`
### Véhicules whitelist
- `@vwfs.com`, `@volkswagen.fr`
- `@jeep.com` (cf. règle 🟣 V01 ci-dessous)
- `@ze-watt.fr`, `@ze-watt.com`
- `@zeromotorcycles.com`
### Club plongée
- `@gissacg.fr`, `@lists.gissacg.fr`
- `president@gissacg.fr`
### Sociétés AIRTRIA
- `@airtria.net`, `@airtria.fr`
### Solaire pro
- `@laboutique-solaire-pro.com`
### Identités personnelles
- `tallagrand.thierry@gmail.com` (mes propres SENT)
- `thierry.tallagrand@me.com` (mon adresse iCloud)
### Labels système protégés
- `IMPORTANT`, `STARRED`, `SENT`, `DRAFT`
- `Personal`, `Travail`, `Achats`, `Receipts`, `Notes`
---
## 🟢 Vague 1 — Trash en masse
**Stratégie** : `gog gmail trash` par batch de 200, pause 5s entre batchs.
**Critère commun** : `older_than:90d` pour ne pas trasher les arrivées récentes au cas où.
**Réversibilité** : Trash Gmail garde 30 jours.
### Règles V1
| ID | Query Gmail | Sample | Estimation totale |
|---|---|---:|---:|
| **V1.01** | `from:nepasrepondre@rustica-info.fr in:inbox older_than:90d` | 196 | ~400 |
| **V1.02** | `from:hi@mail.theresanaiforthat.com in:inbox older_than:90d` | 123 | ~200 |
| **V1.03** | `from:quora.com in:inbox older_than:90d` | 240 | ~600 |
| **V1.04** | `from:no-reply@info.bricomarche.com in:inbox older_than:90d` | 44 | ~100 |
| **V1.05** | `from:beehiiv.com in:inbox older_than:90d` (FutureBlueprint+ai-signal) | 56 | ~150 |
| **V1.06** | `from:carrefour@email.carrefour.fr in:inbox older_than:90d` | 37 | ~100 |
| **V1.07** | `from:cds.newsletter-cdiscount.com in:inbox older_than:90d` | 32 | ~80 |
| **V1.08** | `from:n.weldom.fr in:inbox older_than:90d` | 30 | ~80 |
| **V1.09** | `from:news.suunto.com in:inbox older_than:90d` | 26 | ~60 |
| **V1.10** | `from:crm.samsung.fr in:inbox older_than:90d` | 26 | ~60 |
| **V1.11** | `from:ollama.com in:inbox older_than:90d` | 25 | ~60 |
| **V1.12** | `from:go.explore.redhat.com in:inbox older_than:90d` | 24 | ~60 |
| **V1.13** | `from:reply.ebay.fr in:inbox older_than:90d` | 23 | ~60 |
| **V1.14** | `from:aliexpress.com in:inbox older_than:90d` (selections+deals) | 53 | ~150 |
| **V1.15** | `from:news_frfr@avis-comms.international in:inbox older_than:90d` | 21 | ~50 |
| **V1.16** | `from:updates-noreply@linkedin.com in:inbox older_than:90d` | 53 | ~120 |
| **V1.17** | `from:notifications-noreply@linkedin.com in:inbox older_than:90d` | 25 | ~60 |
| **V1.18** | `from:messages-noreply@linkedin.com in:inbox older_than:90d` | 117 | ~250 |
| **V1.19** | `from:facebookmail.com in:inbox older_than:90d` | 145 | ~350 |
**Estimation totale Vague 1 : ~3000 threads à trasher** (sur ta boîte de 12 703).
---
## 🟡 Vague 2 — Archive avec label
**Stratégie** : `gog gmail archive` (retire INBOX) + apply label.
**Réversibilité** : zéro destruction, juste sortie de l'inbox.
### Règles V2
| ID | Query Gmail | Action | Sample | Note |
|---|---|---|---:|---|
| **V2.01** | `from:florian.philippot@les-patriotes.fr in:inbox` | Archive + label `Newsletters` | 18 | Politique perso |
| **V2.02** | `from:info@clients.ulys.com in:inbox older_than:30d` | Archive + label `Receipts` | 23 | Télépéage VINCI |
**Estimation totale Vague 2 : ~50 threads à archiver.**
Note : la 2ème passe Q8 enrichira cette liste avec la longue traîne newsletters tech.
---
## 🟣 Spécial — Catégorie 2 (digest VE)
### Règle V01
`from:uconnectservices@jeep.com` (172 sample / ~400 boîte totale) :
- **Phase D (immédiat)** : aucune action, on les laisse dans inbox.
- **Phase F+ (digest VE)** : agent quotidien parse les mails Jeep, génère
`charge-vehicule.md` + notif WhatsApp synthèse, puis archive automatiquement
les mails parsés avec label `Charge-VE`.
**Pas d'action Phase D**.
---
## Phase E — Filtres natifs Gmail (2026-06-25)
Objectif : empêcher les newsletters / promos récurrentes d’atterrir dans l’inbox.
Méthode : filtres natifs Gmail (`Settings > Filters and Blocked Addresses`) créés via `gog gmail filters create`.
Action par défaut : **archiver** (`removeLabelIds: [INBOX, UNREAD]`) + **appliquer un label**.
### Labels créés
- `Promos` (id Label_11)
- `Dev-Tools` (id Label_12)
- `Social` (id Label_13)
### Filtres actifs
| # | Query | Label | Type |
|---|---|---|---|
| E01 | `from:linkedin.com OR from:e.linkedin.com` | `Social` | Social |
| E02 | `from:facebookmail.com` | `Social` | Social |
| E03 | `from:clients.ulys.com` | `Receipts` | Télépéage |
| E04 | `from:les-patriotes.fr` | `Newsletters` | Politique |
| E05 | `from:rustica-info.fr` | `Newsletters` | Jardinage |
| E06 | `from:mail.theresanaiforthat.com` | `Newsletters` | Tech/IA |
| E07 | `from:quora.com` | `Newsletters` | Tech/QA |
| E08 | `from:airepo@substack.com` | `Newsletters` | Tech/IA |
| E09 | `from:vpauto.fr OR from:mail.vpauto.eu` | `Promos` | Auto |
| E10 | `from:communication.andre.fr` | `Promos` | E-com |
| E11 | `from:fr-news.adidas.com` | `Promos` | E-com |
| E12 | `from:eu1.tocampaigns.com` | `Promos` | E-com (Cabesto) |
| E13 | `from:mkt.norauto.fr` | `Promos` | Auto |
| E14 | `from:news.intermarche.com` | `Promos` | E-com |
| E15 | `from:monmagasinvert.fr` | `Promos` | E-com |
| E16 | `from:dlink.com` | `Promos` | Tech |
| E17 | `from:messages.mongodb.com` | `Dev-Tools` | Dev |
| E18 | `from:k8slens.dev` | `Dev-Tools` | Dev |
### Cleanup rétroactif (2026-06-25)
- ~687 messages archivés manuellement depuis l’inbox (batchs limités à 200 max, pause 6 s).
- Voir `gmail-housekeeping.md` pour le détail.
---
## 📋 2ème passe (Q8) — Longue traîne
À lancer après Vague 1 + Vague 2 stabilisées.
```bash
# Script proposé : gmail_audit.py --query "category:promotions OR category:updates older_than:6m" --sample 5000
---
## Mises à jour 6 juin 2026 (Phase D execution)
### Whitelist enrichie (à ajouter à la whitelist principale)
#### Synology infrastructure
- `from:sns@synologynotification.com` (Active Insight - alertes critiques disque/storage)
- `from:noreply@c2.synology.com` (C2 backup subscription)
#### Finance
- `from:noreply@amundi-esr.com` (épargne salariale PEE/PERCO - transactionnel)
- `from:r.clientele@vwfs.com` (VW Financial Services)
#### Famille & cercle proche
- `frederic.tallagrand@*` (famille)
- `@arimair.fr` (plongée copain)
### 4 nouvelles règles Vague 1 (ajoutées en cours d'exécution)
- V1.20 : `from:vpauto@mail.vpauto.eu` (enchères auto)
- V1.21 : `from:airepo@substack.com` (newsletter IA Substack)
- V1.22 : `from:intermarche@news.intermarche.com` (promo)
- V1.23 : `from:no-reply@k8slens.dev` (newsletter Lens K8s)
### Synology trash variants (3 patterns)
- `subject:"[www.airtria.net]"` (ARCHIVE2 → 1 160 mails)
- `subject:"[www.airtria.pro]"` (ARCHIVE3 → 210 mails)
- `subject:"[10.10.10.50]"` (ARCHIVE originel → 1 889 mails)