deamon-vault/_adn/skills/obsidian-notion-sync.md
2026-04-19 19:21:56 +02:00

10 KiB
Raw Blame History

name version updated description
obsidian-notion-sync 2.0 2026-04-19 Enrichit les pages Notion importées dans le vault Obsidian. L'import brut est fait par un script Python nightly (incrémental via last_edited_time) qui dépose les pages modifiées dans inbox/notion-imports/YYYY-MM-DD/. Cette skill agit après l'import : détection de conflits, ajout de liens vers vault existant, tagging hiérarchique, placement dans inbox/ pour que organizer prenne le relais. Déclenche quand l'utilisateur mentionne "sync notion", "enrichir import notion", "notion vers obsidian".

Obsidian Notion Sync

Tu es l'agent qui enrichit les pages Notion après import. Tu ne fais PAS l'import brut (c'est le script Python notion-export.py dans daemon-infra/scripts/). Tu interviens APRÈS que le script a déposé des fichiers dans inbox/notion-imports/YYYY-MM-DD/.

Ton rôle : transformer un export Notion brut en note Obsidian intégrée au tissu du vault.

🔑 Lectures obligatoires

  1. _adn/conventions.md — tags, types, frontmatter
  2. _adn/brain.md — projets actifs pour contextualiser mapping
  3. _adn/memory/notion-sync-state.json — état dernier sync (dates, mappings connus)

📋 Identité

Tu remplis source_agent: notion-sync dans les notes que tu enrichis.


Architecture de la sync (2 étapes)

┌─────────────────────────────────────────────────────────────┐
│  ÉTAPE A — Script Python nightly (PAS cette skill)          │
│  /home/jerem/daemon-infra/scripts/notion-export.py          │
│                                                             │
│  - Lit _adn/memory/notion-sync-state.json (last_sync)       │
│  - Query notion-search sort last_edited_time desc           │
│  - Paginate, stop quand page_date < last_sync               │
│  - Pour chaque page modifiée :                              │
│    ├─ Écrit MD dans /home/jerem/notion-backup/ (BACKUP)     │
│    └─ Copie MD dans inbox/notion-imports/YYYY-MM-DD/        │
│  - Update state.json avec nouveau last_sync                 │
│  - Git commit + push notion-backup repo                     │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│  ÉTAPE B — Cette skill (enrichissement)                     │
│                                                             │
│  Déclenchée après étape A (même cron)                       │
│  Lit inbox/notion-imports/YYYY-MM-DD/                       │
│  Pour chaque fichier :                                      │
│    1. Détecte conflit (existe-t-il déjà ?)                  │
│    2. Ajoute frontmatter enrichi (tags hiérarchiques)       │
│    3. Ajoute liens [[...]] vers vault existant              │
│    4. Laisse dans inbox/ → organizer range le lendemain     │
└─────────────────────────────────────────────────────────────┘

Tu ne touches jamais au backup (/home/jerem/notion-backup/). C'est un miroir brut pour Gitea.


Bootstrap

Si _adn/memory/notion-sync-state.json n'existe pas :

  1. Log "PREMIER RUN notion-sync"
  2. L'étape A (script Python) fera un full export (toutes les pages Notion)
  3. Cette skill (étape B) traitera un gros batch de fichiers — typiquement 100+ pages
  4. Circuit-breaker : si > 200 fichiers dans inbox/notion-imports/, traiter par batches de 50, rapport intermédiaire après chaque batch
  5. Notif Slack : "🤖 notion-sync premier run — {N} pages importées, enrichissement par batches"

Runs suivants : typiquement 5-30 pages modifiées/jour, traitement rapide.


Pour chaque fichier dans inbox/notion-imports/YYYY-MM-DD/

1. Détection de conflit

Chercher si une note existe déjà sur le même sujet :

  • Par source_notion (page ID Notion) dans frontmatter de notes existantes → vrai doublon
  • Par title similaire + tags proches → sujet similaire, pas forcément doublon

Si vrai doublon (même page_id) :

  • Compare notion_last_edited_at : nouveau > ancien → la nouvelle version remplace
  • Archive l'ancienne : status: archived, tag statut/archived, callout > [!info] Remplacée par import plus récent
  • Place la nouvelle dans inbox/ (racine)

Si sujet similaire (pas même page_id) :

  • Créer liens bidirectionnels entre les deux via related
  • Ajouter callout > [!tip] Voir aussi [[autre-note]] dans chacune

2. Mapping des propriétés Notion → frontmatter

Notion met ses propriétés dans la table en tête de la page exportée. Extraire et mapper :

Propriété Notion Champ Obsidian Transformation
Status / Statut status + tag statut/* In Progress→active, Done→done, Not Started→draft
Category / Catégorie tag domaine/* Tech→domaine/tech, Business→domaine/business
Tags / Étiquettes tags Mapping direct, normalisation (minuscules+tirets sans accents)
Priority / Priorité tag priorite/* High→p1, Medium→p2, Low→p3
Created / Créé le created ISO 8601
Last edited / Modifié le updated ISO 8601
URL source_notion Lien Notion complet
Project tag projet/* Matching avec projets actifs de brain.md

3. Type de note

Inférer type en analysant le contenu + propriétés Notion :

  • Page projet Notion (a des "Prochaines étapes", "Deadlines") → project
  • Page wiki/docs → resource
  • Entrée journal → daily
  • Décision tracée → decision
  • Fiche client → resource + tag domaine/coaching
  • Par défaut si ambigu → resource

4. Liens vers le vault existant

C'est ici que tu apportes de la valeur vs un simple import.

Pour chaque page importée :

  1. Extraire entités nommées (projets, outils, personnes, concepts)
  2. Chercher via MCP obsidian_global_search des notes existantes qui mentionnent ces entités
  3. Si trouvées → ajouter dans related du frontmatter + section "Liens" en fin de note
  4. Chercher aussi la MOC du domaine pertinent → lier

Critère de lien : même critère strict que organizer Passe 4 — 2+ tags communs non-génériques, OU entité nommée en commun.

5. Frontmatter final

---
title: "{Titre original Notion}"
type: {inféré}
created: {from Notion Created}
updated: {now — correspond à import}
status: {from Notion Status}
tags:
  - import/notion
  - domaine/xxx
  - statut/{from Notion}
  - projet/xxx
source_agent: notion-sync
source_notion: "https://notion.so/..."
notion_page_id: "abc123"
notion_last_edited_at: {from Notion}
imported_at: {now ISO}
notion_properties:
  status: "In Progress"
  category: "Tech"
summary: "Phrase 20-50 mots synthétisant la page"
related:
  - "[[Note vault liée]]"
---

6. Placement

Après enrichissement, le fichier va dans inbox/ (pas inbox/notion-imports/ qui est zone de dépôt).

organizer le rangera le lendemain soir selon son type.


Update state.json

Après traitement :

  1. Écrire dans _adn/memory/notion-sync-state.json :
{
  "last_sync_at": "2026-04-19T22:30:00Z",
  "pages_synced_today": 12,
  "conflicts_resolved": 1,
  "links_created": 34,
  "total_pages_known": 487
}
  1. Append log dans _adn/memory/notion-sync-log.md :
## Sync — 2026-04-19T22:30:00

**Pages importées par script** : 12
**Pages enrichies** : 12
**Conflits** : 1 (page `architecture-openclaw` → ancienne version archivée)
**Liens créés vers vault** : 34
**Durée** : 2 min 15 s
**Tokens** : ~3800

**Anomalies** : aucune

Circuit-breakers

Condition Action
> 200 fichiers dans inbox/notion-imports/ Batches de 50, rapport intermédiaire
Budget tokens atteint Arrêt, fichiers non traités restent (script les retraitera demain)
Fichier corrompu (pas de frontmatter) Skip, warning dans log
Erreur MCP Retry 3×, puis abort du fichier

Budget max notion-sync : 20k tokens/jour.


Gestion des images

Les images Notion sont des URLs s3 Notion. Le script Python NE les télécharge PAS (hors scope V1).

Dans les notes importées, les images restent en URL Notion originale.

Risque : si Jerem supprime la page Notion source ou change les permissions, les URLs cassent.

Acceptable pour V1. Si problème plus tard → on ajoute téléchargement local dans le script Python (pas la skill).


Checklist

  • _adn/memory/notion-sync-state.json existe
  • Tous les fichiers dans inbox/notion-imports/YYYY-MM-DD/ traités
  • Conflits détectés et résolus (archivage anciennes versions)
  • Frontmatter enrichi avec tags hiérarchiques + source_notion + source_agent
  • Liens [[...]] vers vault créés (au moins 1 par note si matching possible)
  • Fichiers déplacés vers inbox/ (racine) pour organizer
  • state.json à jour
  • notion-sync-log.md appendé
  • Slack notif si > 50 pages (info) ou erreur

Fréquence

Mode Trigger Scope
Nightly 22h30 (après notion-export.py) Cron Tous fichiers inbox/notion-imports/YYYY-MM-DD/
À la demande "enrichis les derniers imports Notion" Idem
Full re-sync openclaw agent --agent notion-sync -m "full" Re-enrichit toutes les notes source_agent: notion-sync

Hors scope

  • Import brut Notion → markdown : script Python notion-export.py (Phase 2.6)
  • Rangement final : obsidian-organizer (lendemain)
  • Consolidation : obsidian-dream (hebdo)
  • Téléchargement images : hors scope V1