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,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.