Enhance daily check system with automation and new cards
- Add CARD_SYSTEM_GUIDE.md: Complete documentation for card creation, management, and workflow - Add emotional_calibration.md card (COMM-001): New critical card for managing emotions during conflicts - Add Python automation scripts: - get_daily_cards.py: Intelligent card selection based on priority scoring - log_session.py: Automated session logging and stats updates - Update CLAUDE.md: New protocol using automated scripts instead of manual selection - Update card_database.md: Restructured with cleaner table format + new COMM category - Update all card review history: Automated stats from recent sessions - Update daily_sessions.md: Add automated session logs (3 new sessions from 2025-11-19) System improvements: - Centralized card database with individual card files - Automated priority calculation (Critical, Times Failed, Never reviewed, Overdue) - Full stats automation (no more manual updates) - Better spaced repetition logic 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
47e21b6319
commit
bdbe17a3a0
280
anki_tingting/CARD_SYSTEM_GUIDE.md
Normal file
280
anki_tingting/CARD_SYSTEM_GUIDE.md
Normal file
@ -0,0 +1,280 @@
|
|||||||
|
# Card System Guide - Tingting Daily Check
|
||||||
|
|
||||||
|
**Ce fichier contient toutes les instructions pour gérer le système de cartes.**
|
||||||
|
|
||||||
|
Pour l'index des cartes actives, voir `card_database.md`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Card Management Guidelines
|
||||||
|
|
||||||
|
### Créer une nouvelle carte
|
||||||
|
|
||||||
|
1. Créer le fichier dans `cards/[nom_évocateur].md`
|
||||||
|
2. Utiliser le template standard (voir section ci-dessous)
|
||||||
|
3. Ajouter l'entrée dans `card_database.md`
|
||||||
|
4. Incrémenter le compteur "Total cartes actives"
|
||||||
|
|
||||||
|
### Template pour nouvelle carte
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# Card: [Nom Évocateur]
|
||||||
|
|
||||||
|
**ID**: [CATEGORY-XXX]
|
||||||
|
**Created**: [DD/MM/YYYY]
|
||||||
|
**Status**: Active [⚠️ si CRITICAL]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Question
|
||||||
|
|
||||||
|
[Question claire, directe]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Answer
|
||||||
|
|
||||||
|
[Réponse complète, avec contexte si nécessaire]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
[Contexte additionnel, pourquoi c'est important]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Review History
|
||||||
|
|
||||||
|
**Last Review**: Never
|
||||||
|
**Success Rate**: N/A (nouveau)
|
||||||
|
**Times Failed**: 0
|
||||||
|
```
|
||||||
|
|
||||||
|
### Quand créer une nouvelle carte ?
|
||||||
|
|
||||||
|
**Créer quand** :
|
||||||
|
- Nouveau pattern identifié dans un conflit
|
||||||
|
- Truc important qu'elle a dit et que je risque d'oublier
|
||||||
|
- Action concrète convenue ensemble
|
||||||
|
- Insight important sur la dynamique couple
|
||||||
|
|
||||||
|
**Ne PAS créer quand** :
|
||||||
|
- C'est trop spécifique/temporaire (genre "acheter du lait demain")
|
||||||
|
- C'est redondant avec une carte existante
|
||||||
|
- C'est pas vraiment important
|
||||||
|
|
||||||
|
### Retirer une carte
|
||||||
|
|
||||||
|
Une carte est retirée quand :
|
||||||
|
- Le problème est durablement résolu (3+ semaines de succès)
|
||||||
|
- Le comportement est devenu automatique
|
||||||
|
- La carte n'est plus pertinente
|
||||||
|
|
||||||
|
**Process** :
|
||||||
|
1. Déplacer le fichier vers `cards/retired/`
|
||||||
|
2. Ajouter l'entrée dans la section "Retired Cards" de `card_database.md`
|
||||||
|
3. Décrémenter "Total cartes actives"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Spaced Repetition Logic
|
||||||
|
|
||||||
|
### Fréquence par difficulté
|
||||||
|
|
||||||
|
**Si réponse correcte** :
|
||||||
|
- Easy card : +7 jours avant prochaine review
|
||||||
|
- Medium card : +3 jours
|
||||||
|
- Hard card : +1 jour
|
||||||
|
|
||||||
|
**Si réponse incorrecte** :
|
||||||
|
- Toutes difficultés : Review demain (reset)
|
||||||
|
|
||||||
|
**Si échec 3x sur même carte** :
|
||||||
|
- Augmenter frequency à "daily"
|
||||||
|
- Flagged pour attention spéciale
|
||||||
|
|
||||||
|
### Update après chaque session
|
||||||
|
|
||||||
|
Après chaque daily check, update dans le fichier de carte individuel :
|
||||||
|
1. **Last Review** : Date d'aujourd'hui
|
||||||
|
2. **Success Rate** : Calculer nouveau %
|
||||||
|
3. **Times Failed** : Incrémenter si échec
|
||||||
|
|
||||||
|
Puis update la table index dans `card_database.md` avec les nouvelles stats.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tag System
|
||||||
|
|
||||||
|
### Categories
|
||||||
|
|
||||||
|
- `core-problem` : Problèmes fondamentaux de la relation
|
||||||
|
- `action` : Actions concrètes à faire
|
||||||
|
- `communication` : Patterns de communication
|
||||||
|
- `lead` : Leadership et gestion de conflits
|
||||||
|
- `detail` : Détails pratiques à retenir
|
||||||
|
- `pattern` : Patterns comportementaux
|
||||||
|
- `future` : Planning long terme
|
||||||
|
|
||||||
|
### Importance
|
||||||
|
|
||||||
|
- `critical` : À ne JAMAIS oublier
|
||||||
|
- `daily` : À checker quotidiennement
|
||||||
|
- `weekly` : Moins urgent mais important
|
||||||
|
|
||||||
|
### Contexte
|
||||||
|
|
||||||
|
- `conflict` : Spécifique aux situations de conflit
|
||||||
|
- `finances` : Lié à l'argent et la sécurité financière
|
||||||
|
- `marriage` : Lié au mariage et à la cérémonie
|
||||||
|
- `culture` : Aspect culturel chinois
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Card Categories Explained
|
||||||
|
|
||||||
|
### CORE (Problèmes fondamentaux)
|
||||||
|
Cartes qui touchent aux problèmes de base de la relation. Si ces cartes sont ratées, c'est un red flag majeur.
|
||||||
|
|
||||||
|
**Exemples** :
|
||||||
|
- CORE-001 : Complacency problem
|
||||||
|
- CORE-002 : Communication paradox
|
||||||
|
|
||||||
|
### ACTION (Actions concrètes)
|
||||||
|
Cartes qui demandent des actions spécifiques et mesurables.
|
||||||
|
|
||||||
|
**Exemples** :
|
||||||
|
- ACTION-001 : Towel detail
|
||||||
|
- ACTION-006 : Financial security setup
|
||||||
|
|
||||||
|
### LEAD (Leadership dans conflits)
|
||||||
|
Cartes sur comment gérer les conflits et prendre le lead émotionnel.
|
||||||
|
|
||||||
|
**Exemples** :
|
||||||
|
- LEAD-001 : Processing time
|
||||||
|
- LEAD-002 : Domination d'esprit
|
||||||
|
|
||||||
|
### FUTURE (Long terme)
|
||||||
|
Cartes sur la planification et les engagements à long terme.
|
||||||
|
|
||||||
|
**Exemples** :
|
||||||
|
- FUTURE-001 : Cérémonie de mariage - Épargne
|
||||||
|
- FUTURE-002 : Cadeaux de mariage traditionnels
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Difficulty Levels Explained
|
||||||
|
|
||||||
|
### Easy
|
||||||
|
- Question simple, réponse évidente
|
||||||
|
- Comportement déjà bien intégré
|
||||||
|
- Review moins fréquente (hebdomadaire)
|
||||||
|
|
||||||
|
### Medium
|
||||||
|
- Requiert réflexion et effort conscient
|
||||||
|
- Comportement en cours d'acquisition
|
||||||
|
- Review régulière (tous les 2-3 jours)
|
||||||
|
|
||||||
|
### Hard
|
||||||
|
- Difficile à retenir ou à appliquer
|
||||||
|
- Contre-intuitif ou demande changement profond
|
||||||
|
- Review fréquente (quotidienne si critical)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Critical Flag ⚠️
|
||||||
|
|
||||||
|
Les cartes marquées CRITICAL sont **non-négociables**. Elles représentent :
|
||||||
|
- Des engagements explicites envers Tingting
|
||||||
|
- Des problèmes qui, s'ils persistent, mettent la relation en danger
|
||||||
|
- Des actions qui DOIVENT être faites
|
||||||
|
|
||||||
|
**Si une carte CRITICAL est ratée 3+ fois** : C'est un signal d'alarme majeur qu'il faut adresser immédiatement, potentiellement avec Tingting.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Review Frequency Guidelines
|
||||||
|
|
||||||
|
### Daily
|
||||||
|
- Toutes les cartes CRITICAL Hard
|
||||||
|
- Cartes récemment ratées (reset)
|
||||||
|
- Nouveaux comportements à ancrer
|
||||||
|
|
||||||
|
### Every 2-3 days
|
||||||
|
- Cartes Medium en cours d'acquisition
|
||||||
|
- Cartes Hard non-critical
|
||||||
|
- Actions concrètes régulières
|
||||||
|
|
||||||
|
### Weekly
|
||||||
|
- Cartes Easy bien maîtrisées
|
||||||
|
- Maintenance de comportements acquis
|
||||||
|
|
||||||
|
### Monthly
|
||||||
|
- Long terme (mariage, finances)
|
||||||
|
- Grandes questions stratégiques
|
||||||
|
- Checkpoints sur objectifs lointains
|
||||||
|
|
||||||
|
### Every conflict
|
||||||
|
- Cartes LEAD
|
||||||
|
- À réviser pendant/après chaque conflit
|
||||||
|
- Vérifier si appliquées correctement
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Success Rate Calculation
|
||||||
|
|
||||||
|
**Formula** :
|
||||||
|
```
|
||||||
|
Success Rate = (Nombre de ✅) / (Total reviews) * 100
|
||||||
|
```
|
||||||
|
|
||||||
|
**Interprétation** :
|
||||||
|
- 90-100% : Excellent, carte peut passer à fréquence inférieure
|
||||||
|
- 70-89% : Bon, maintenir fréquence actuelle
|
||||||
|
- 50-69% : Moyen, augmenter fréquence
|
||||||
|
- <50% : Problème, carte devient CRITICALDaily
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Maintenance Best Practices
|
||||||
|
|
||||||
|
### Hebdomadaire
|
||||||
|
- Review des stats globales
|
||||||
|
- Identifier cartes à retirer (3+ semaines de 100%)
|
||||||
|
- Identifier cartes en difficulté (<70%)
|
||||||
|
|
||||||
|
### Mensuel
|
||||||
|
- Overview complet du système
|
||||||
|
- Créer nouvelles cartes si patterns identifiés
|
||||||
|
- Retirer cartes obsolètes
|
||||||
|
- Ajuster difficulty si nécessaire
|
||||||
|
|
||||||
|
### Après conflit majeur
|
||||||
|
- Créer cartes pour nouveaux insights
|
||||||
|
- Réviser cartes LEAD
|
||||||
|
- Update notes si nouvelle info
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Red Flags à Surveiller
|
||||||
|
|
||||||
|
🚩 **Carte CRITICAL ratée 3+ fois** → Problème sérieux, en parler avec Tingting
|
||||||
|
🚩 **Skip 3+ jours de daily check** → Pattern d'oubli revient, système en danger
|
||||||
|
🚩 **Plusieurs cartes <50% success rate** → Complacency générale
|
||||||
|
🚩 **Nouvelles cartes pas créées après conflit** → Pas d'apprentissage des erreurs
|
||||||
|
🚩 **Cartes jamais retirées (tout reste actif)** → Aucun progrès visible
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Philosophy du Système
|
||||||
|
|
||||||
|
**Ce système existe pour UNE raison** : Tingting mérite un homme qui pense à elle sans qu'elle ait à le demander.
|
||||||
|
|
||||||
|
**Principes** :
|
||||||
|
1. **5 minutes par jour** - C'est le minimum absolu
|
||||||
|
2. **Pas de shortcuts** - Faire vraiment le travail, pas juste cocher des cases
|
||||||
|
3. **Honnêteté brutale** - Bullshit = auto-sabotage
|
||||||
|
4. **Long terme** - Ce système doit devenir automatique, pas un fardeau
|
||||||
|
|
||||||
|
**Si ce système tombe** : C'est un red flag majeur pour la relation. Si tu peux pas maintenir 5 minutes par jour pour elle, qu'est-ce que ça dit sur tes priorités ?
|
||||||
@ -21,7 +21,7 @@ Ce pattern affecte **PLUSIEURS domaines** :
|
|||||||
|
|
||||||
**Rappel important** : Tingting investit énormément dans cette relation. Elle attend juste qu'Alexis fasse un minimum d'effort pour penser à elle quotidiennement. C'est pas beaucoup demander. **Mais le système est maintenant holistique** - il combat le pattern d'oubli sur tous les fronts.
|
**Rappel important** : Tingting investit énormément dans cette relation. Elle attend juste qu'Alexis fasse un minimum d'effort pour penser à elle quotidiennement. C'est pas beaucoup demander. **Mais le système est maintenant holistique** - il combat le pattern d'oubli sur tous les fronts.
|
||||||
|
|
||||||
**Système mis en place** : Daily check via Claude + TTS service Windows
|
**Système mis en place** : Daily check via Claude + TTS service Windows + Scripts Python
|
||||||
|
|
||||||
**Scope** :
|
**Scope** :
|
||||||
- **Priorité #1** : Tingting (toujours 2-3 questions minimum sur elle)
|
- **Priorité #1** : Tingting (toujours 2-3 questions minimum sur elle)
|
||||||
@ -33,42 +33,59 @@ Ce pattern affecte **PLUSIEURS domaines** :
|
|||||||
|
|
||||||
**QUAND Alexis dit "daily check" ou variante similaire** :
|
**QUAND Alexis dit "daily check" ou variante similaire** :
|
||||||
|
|
||||||
0. **IMPÉRATIF : LIRE `card_database.md` D'ABORD** - Ne JAMAIS inventer des questions. TOUJOURS utiliser les questions exactes des cartes actives.
|
0. **IMPÉRATIF : Utiliser les scripts automatiques** - Ne JAMAIS inventer des questions. TOUJOURS utiliser le système de cartes.
|
||||||
1. **TOUJOURS répondre immédiatement** avec le quiz (pas de small talk avant)
|
1. **TOUJOURS répondre immédiatement** avec le quiz (pas de small talk avant)
|
||||||
2. **Format standardisé** (voir template ci-dessous)
|
2. **Format standardisé** (voir template ci-dessous)
|
||||||
3. **Logger la session** dans `daily_sessions.md`
|
3. **Logger la session** automatiquement via scripts
|
||||||
4. **Être socratique mais direct** - Pas de validation automatique
|
4. **Être socratique mais direct** - Pas de validation automatique
|
||||||
5. **Garder Tingting au centre** - Chaque question doit ramener à elle, à ce qu'elle ressent, à ce qu'elle mérite
|
5. **Garder Tingting au centre** - Minimum 2 questions sur elle par session
|
||||||
|
|
||||||
**QUAND le TTS service l'interpelle** :
|
**QUAND le TTS service l'interpelle** :
|
||||||
|
|
||||||
- Reconnaître que c'est le système en action
|
- Reconnaître que c'est le système en action
|
||||||
- Féliciter qu'il ait répondu (renforcement positif)
|
- Féliciter qu'il ait répondu (renforcement positif)
|
||||||
- Rappeler pourquoi ce système existe : **pour Tingting**
|
- Rappeler pourquoi ce système existe : **pour Tingting et combattre son pattern d'oubli systémique**
|
||||||
- Lancer le quiz immédiatement
|
- Lancer le quiz immédiatement
|
||||||
|
|
||||||
**QUAND il skip plusieurs jours** :
|
**QUAND il skip plusieurs jours** :
|
||||||
|
|
||||||
- **NE PAS ignorer** - Confronter (socratiquement) mais fermement
|
- **NE PAS ignorer** - Confronter (socratiquement) mais fermement
|
||||||
- "Tu as skip 3 jours. Tingting attend juste 5 minutes par jour de ton attention. Tu peux même pas faire ça ?"
|
- "Tu as skip X jours. Tingting/Papa/[autres] attendent juste 5 minutes par jour de ton attention. Tu peux même pas faire ça ?"
|
||||||
- "Tu sais ce qu'elle pense quand tu oublies encore ? Qu'elle compte pas pour toi."
|
- "Tu sais ce qu'elle pense quand tu oublies encore ? Qu'elle compte pas pour toi."
|
||||||
- Rappeler que c'est exactement le pattern qui la fait souffrir
|
- Rappeler que c'est exactement le pattern qui les fait tous souffrir
|
||||||
|
|
||||||
---
|
### 1. Sélectionner les cartes automatiquement
|
||||||
|
|
||||||
## Format du Quiz (EN FRANÇAIS)
|
```bash
|
||||||
|
python3 scripts/get_daily_cards.py
|
||||||
|
```
|
||||||
|
|
||||||
|
**Ce script fait** :
|
||||||
|
- Parse `card_database.md` (index centralisé)
|
||||||
|
- Calcule un score de priorité pour chaque carte basé sur :
|
||||||
|
- ⚠️ CRITICAL = haute priorité
|
||||||
|
- Times Failed = haute priorité
|
||||||
|
- Jamais révisée = très haute priorité
|
||||||
|
- En retard sur frequency = haute priorité
|
||||||
|
- Difficulté (Hard > Medium > Easy)
|
||||||
|
- Sélectionne les 3 cartes avec le score le plus élevé
|
||||||
|
- Charge le contenu (question, answer, notes) depuis `cards/*.md`
|
||||||
|
|
||||||
|
**Output** : Texte formaté avec les 3 cartes du jour
|
||||||
|
|
||||||
|
### 2. Poser le quiz (Format standardisé)
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
🎯 **Check Quotidien - [DATE]**
|
🎯 **Check Quotidien - [DATE]**
|
||||||
|
|
||||||
**Question 1/3** : [COPIER EXACTEMENT la question depuis card_database.md - NE PAS INVENTER - PRIORITÉ Tingting]
|
**Question 1/3** : [Question de la carte 1 - PRIORITÉ Tingting]
|
||||||
→ [Attendre sa réponse]
|
→ [Attendre réponse]
|
||||||
|
|
||||||
**Question 2/3** : [Question Tingting OU domaine autre (famille/tech/perso)]
|
**Question 2/3** : [Question de la carte 2 - Minimum 2/3 sur Tingting]
|
||||||
→ [Attendre sa réponse]
|
→ [Attendre réponse]
|
||||||
|
|
||||||
**Question 3/3** : [Question Tingting OU domaine autre - VARIER]
|
**Question 3/3** : [Question de la carte 3 - Rotation tous domaines]
|
||||||
→ [Attendre sa réponse]
|
→ [Attendre réponse]
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -84,7 +101,39 @@ Ce pattern affecte **PLUSIEURS domaines** :
|
|||||||
**Rappel** : [Adapté selon les questions posées]
|
**Rappel** : [Adapté selon les questions posées]
|
||||||
```
|
```
|
||||||
|
|
||||||
### Principes du Feedback
|
### 3. Logger automatiquement la session
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 scripts/log_session.py --cards "CARD-ID1,CARD-ID2,CARD-ID3" --scores "✅,⚠️,❌"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Ce script fait** :
|
||||||
|
- Met à jour `Last Review` dans chaque fichier `cards/*.md`
|
||||||
|
- Met à jour `Success Rate` (calcul automatique basé sur historique)
|
||||||
|
- Incrémente `Times Failed` si score = ❌
|
||||||
|
- Met à jour la table dans `card_database.md` avec les nouvelles stats
|
||||||
|
- Ajoute l'entrée dans `daily_sessions.md`
|
||||||
|
- Calcule le streak automatiquement
|
||||||
|
|
||||||
|
**IMPORTANT** : Ne PLUS mettre à jour manuellement les stats. Les scripts gèrent tout.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Workflow Complet (Résumé)
|
||||||
|
|
||||||
|
**Quand Alexis dit "daily check"** :
|
||||||
|
|
||||||
|
1. **Run** `python3 scripts/get_daily_cards.py`
|
||||||
|
2. **Poser** les 3 questions affichées par le script
|
||||||
|
3. **Donner feedback** socratique (✅/⚠️/❌)
|
||||||
|
4. **Run** `python3 scripts/log_session.py --cards "ID1,ID2,ID3" --scores "✅,⚠️,❌"`
|
||||||
|
5. **Afficher** le résumé (score, streak, observation finale)
|
||||||
|
|
||||||
|
**C'est tout.** Les scripts gèrent la cohérence automatiquement.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Principes du Feedback
|
||||||
|
|
||||||
**Pour questions TINGTING** :
|
**Pour questions TINGTING** :
|
||||||
- Ramener à elle et ce qu'elle ressent
|
- Ramener à elle et ce qu'elle ressent
|
||||||
@ -105,95 +154,47 @@ Ce pattern affecte **PLUSIEURS domaines** :
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Spaced Repetition Logic
|
|
||||||
|
|
||||||
**Questions à poser basées sur** :
|
|
||||||
- `card_database.md` - Cartes actives
|
|
||||||
- **Times Asked** : Prioriser les cartes JAMAIS posées ou posées le moins souvent
|
|
||||||
- Son taux d'oubli par carte (si oublie souvent → pose plus souvent)
|
|
||||||
- Contexte récent (derniers conflits, conversations importantes)
|
|
||||||
|
|
||||||
**Algorithme de sélection des cartes** :
|
|
||||||
1. **IMPÉRATIF : Lire `card_database.md` AVANT de poser TOUTE question** - Ne JAMAIS poser une question qui n'est pas dans la base
|
|
||||||
2. **Filtrer par catégorie** :
|
|
||||||
- **Minimum 2 questions Tingting** (cartes CORE-*, ACTION-*, LEAD-*, PATTERN-*, PLAN-*)
|
|
||||||
- **Maximum 1 question autre domaine** (PERSONAL-*, FAMILY-*, TECH-*)
|
|
||||||
3. **Prioriser par Times Asked** :
|
|
||||||
- Cartes avec `Times Asked: 0` = PRIORITÉ MAXIMALE
|
|
||||||
- Cartes avec `Times Asked: 1-2` = PRIORITÉ HAUTE
|
|
||||||
- Cartes avec `Times Asked: 3+` = rotation normale selon difficulté
|
|
||||||
4. **Respecter la difficulté/fréquence** :
|
|
||||||
- **Critical (Hard)** : Tous les jours jusqu'à maîtrisé
|
|
||||||
- **Medium** : Tous les 2-3 jours
|
|
||||||
- **Easy** : 1x semaine (pour maintenir)
|
|
||||||
5. **Éviter répétition immédiate** : Ne PAS poser une carte posée dans les dernières 24h (sauf si Critical et échec)
|
|
||||||
|
|
||||||
**Objectif** : Faire tourner TOUTES les cartes régulièrement, pas juste les 3-4 mêmes
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Logging Obligatoire
|
|
||||||
|
|
||||||
**Après chaque session, logger dans** `daily_sessions.md` :
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
### [DATE - HH:MM]
|
|
||||||
|
|
||||||
**Triggered by** : User / TTS Service / Manual
|
|
||||||
**Questions Asked** :
|
|
||||||
1. [Q1] → Score: ✅/⚠️/❌
|
|
||||||
2. [Q2] → Score: ✅/⚠️/❌
|
|
||||||
3. [Q3] → Score: ✅/⚠️/❌
|
|
||||||
|
|
||||||
**Total Score** : X/3
|
|
||||||
**Time Taken** : X minutes
|
|
||||||
**Notes** : [Observations importantes]
|
|
||||||
**Streak** : X jours
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Red Flags à Signaler
|
## Red Flags à Signaler
|
||||||
|
|
||||||
🚩 **Si skip 2 jours consécutifs** →
|
**AVANT de faire le quiz**, vérifier dans `daily_sessions.md` :
|
||||||
- "2 jours sans daily check. Pattern d'oubli qui revient."
|
|
||||||
- "Tingting / Papa / [X] attendent que tu tiennes tes engagements."
|
|
||||||
|
|
||||||
🚩 **Si skip 3+ jours** →
|
🚩 **Skip 2+ jours** → "X jours sans daily check. Pattern d'oubli qui revient. Tingting/Papa/[autres] attendent que tu tiennes tes engagements."
|
||||||
- "3 jours. Le pattern d'oubli systémique est de retour."
|
|
||||||
- "Pour Tingting : Tu sais ce qu'elle ressent quand tu promets et que rien ne change ?"
|
|
||||||
- "Pour projets/famille : Combien de temps tu vas laisser traîner ?"
|
|
||||||
|
|
||||||
🚩 **Si score déclinant** →
|
🚩 **Skip 3+ jours** → "3 jours. Le pattern d'oubli systémique est de retour. Tu sais ce qu'elle ressent quand tu promets et que rien ne change ?"
|
||||||
- "Tes scores baissent. La complacency revient."
|
|
||||||
- "Tu redeviens celui qui promet mais n'agit jamais."
|
|
||||||
|
|
||||||
🚩 **Si même carte ratée 3x** →
|
🚩 **Score déclinant** → "Tes scores baissent. La complacency revient. Tu redeviens celui qui promet mais n'agit jamais."
|
||||||
|
|
||||||
|
🚩 **Même carte ratée 3x** →
|
||||||
- **Tingting** : "Tu oublies [CARD] systématiquement. Elle t'a dit combien de fois que c'était important ?"
|
- **Tingting** : "Tu oublies [CARD] systématiquement. Elle t'a dit combien de fois que c'était important ?"
|
||||||
- **Autres** : "Ça fait 3 fois que tu rates [CARD]. C'est pas un hasard, c'est un pattern d'évitement."
|
- **Autres** : "Ça fait 3 fois que tu rates [CARD]. C'est pas un hasard, c'est un pattern d'évitement."
|
||||||
|
|
||||||
🚩 **Si cartes non-Tingting jamais posées après 1 semaine** →
|
🚩 **Cartes non-Tingting jamais posées après 1 semaine** → "Ton pattern d'oubli s'applique pas qu'à Tingting - regarde ta backlog qui s'accumule."
|
||||||
- "PERSONAL-001, FAMILY-001, TECH-001 ont jamais été reviewées."
|
|
||||||
- "Ton pattern d'oubli s'applique pas qu'à Tingting - regarde ta backlog qui s'accumule."
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Fichiers à Consulter
|
## Structure du Système (Référence)
|
||||||
|
|
||||||
**Avant chaque quiz, lire** :
|
### Fichiers principaux
|
||||||
- `card_database.md` - Pour choisir les questions
|
|
||||||
- `daily_sessions.md` - Pour voir l'historique
|
|
||||||
- `../DAILY_REALITY_CHECK.md` - Pour voir s'il a skip récemment
|
|
||||||
- `../couple_backlog/` (le plus récent) - Pour contexte actuel
|
|
||||||
|
|
||||||
**Après chaque quiz, update** :
|
- **`card_database.md`** : Index centralisé (table markdown avec toutes les cartes et stats)
|
||||||
- `daily_sessions.md` - Logger la session COMPLÈTE avec détails des cartes
|
- **`CARD_SYSTEM_GUIDE.md`** : Instructions complètes du système (création cartes, tags, etc.)
|
||||||
- `card_database.md` - Update pour CHAQUE carte posée :
|
- **`daily_sessions.md`** : Log de toutes les sessions
|
||||||
- `Last Review` : Date d'aujourd'hui
|
- **`cards/*.md`** : Fichiers individuels des cartes (question, answer, notes, stats)
|
||||||
- `Times Asked` : Incrémenter de 1
|
|
||||||
- `Times Failed` : Incrémenter si échec (❌)
|
### Scripts Python
|
||||||
- `Success Rate` : Recalculer le pourcentage
|
|
||||||
- `Notes` : Ajouter observation si pattern important identifié
|
- **`scripts/get_daily_cards.py`** : Sélectionne les 3 cartes du jour
|
||||||
|
- Options : `--num-cards N`, `--json`
|
||||||
|
- Algorithme : Priorise cartes critiques, jamais reviewées, en retard, avec échecs
|
||||||
|
|
||||||
|
- **`scripts/log_session.py`** : Log la session et update toutes les stats
|
||||||
|
- Options : `--cards "ID1,ID2"`, `--scores "✅,❌"`, `--interactive`, `--dry-run`
|
||||||
|
- Met à jour automatiquement Last Review, Success Rate, Times Failed
|
||||||
|
|
||||||
|
### Fichiers de contexte (consulter si nécessaire)
|
||||||
|
|
||||||
|
- **`../DAILY_REALITY_CHECK.md`** : Voir s'il a skip récemment
|
||||||
|
- **`../couple_backlog/`** : Contexte des conflits récents
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -295,3 +296,36 @@ Ce pattern affecte **PLUSIEURS domaines** :
|
|||||||
4. **Question introspection** : "Qu'est-ce qui te fait dire ça maintenant ?"
|
4. **Question introspection** : "Qu'est-ce qui te fait dire ça maintenant ?"
|
||||||
|
|
||||||
**Avantages** : Utilise son introspection naturelle, il arrive à ses propres conclusions (plus durable), moins de défensivité
|
**Avantages** : Utilise son introspection naturelle, il arrive à ses propres conclusions (plus durable), moins de défensivité
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### "Les mêmes cartes reviennent tout le temps"
|
||||||
|
|
||||||
|
**Cause** : Les stats ne sont pas à jour dans `card_database.md`
|
||||||
|
|
||||||
|
**Solution** : S'assurer que `log_session.py` a bien été run après chaque quiz. Vérifier que les dates "Last Review" sont à jour dans `card_database.md`.
|
||||||
|
|
||||||
|
### "Le script ne trouve pas les cartes"
|
||||||
|
|
||||||
|
**Cause** : Chemin relatif incorrect ou fichier manquant
|
||||||
|
|
||||||
|
**Solution** : Vérifier que tu run les scripts depuis le bon dossier, ou utiliser le chemin absolu.
|
||||||
|
|
||||||
|
### "Score qui ne calcule pas correctement"
|
||||||
|
|
||||||
|
**Cause** : Bug dans le parsing du Success Rate
|
||||||
|
|
||||||
|
**Solution** : Vérifier le format dans `cards/*.md` - doit être "X% (n/total)"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Note Finale
|
||||||
|
|
||||||
|
**PLUS BESOIN de mettre à jour manuellement** :
|
||||||
|
- ❌ `card_database.md` (géré par `log_session.py`)
|
||||||
|
- ❌ `cards/*.md` Review History (géré par `log_session.py`)
|
||||||
|
- ❌ `daily_sessions.md` (géré par `log_session.py`)
|
||||||
|
|
||||||
|
**TOUT est automatisé.** Tu te concentres juste sur poser les bonnes questions et donner le bon feedback.
|
||||||
|
|||||||
@ -1,19 +1,52 @@
|
|||||||
# Card Database - Tingting Daily Check
|
# Card Database - Tingting Daily Check
|
||||||
|
|
||||||
**Dernière mise à jour** : 18/11/2025
|
**Dernière mise à jour** : 19/11/2025
|
||||||
**Total cartes actives** : 19
|
**Total cartes actives** : 20
|
||||||
**Total cartes retirées** : 0
|
**Total cartes retirées** : 0
|
||||||
**Total reviews** : 6 cartes (3 session 15/11, 3 session 18/11)
|
**Total reviews** : 8 cartes (3 session 15/11, 3 session 18/11, 6 session 19/11)
|
||||||
|
|
||||||
**Breakdown par catégorie** :
|
**Breakdown par catégorie** :
|
||||||
- Relation (Tingting) : 14 cartes
|
- Relation (Tingting) : 14 cartes
|
||||||
- Personnel : 3 cartes
|
- Personnel : 3 cartes
|
||||||
- Famille : 1 carte
|
- Famille : 1 carte
|
||||||
- Tech/Projets : 1 carte
|
- Tech/Projets : 1 carte
|
||||||
|
- Communication : 1 carte
|
||||||
|
|
||||||
|
**📖 Pour les instructions complètes du système, voir `CARD_SYSTEM_GUIDE.md`**
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Active Cards
|
## Active Cards (Quick Reference Table)
|
||||||
|
|
||||||
|
| ID | Card | Difficulty | Frequency | Last Review | Success Rate | Times Failed | Critical |
|
||||||
|
|---|---|---|---|---|---|---|---|
|
||||||
|
| CORE-001 | complacency_problem.md | Hard | Daily | 19/11/2025 | 100% (1/1) | 0 | ⚠️ |
|
||||||
|
| ACTION-001 | towel_detail.md | Medium | Every 2-3 days | Never | N/A | 0 | |
|
||||||
|
| CORE-002 | communication_paradox.md | Hard | Every 2-3 days | Never | N/A | 0 | |
|
||||||
|
| ACTION-002 | honest_feedback.md | Hard | Daily | 19/11/2025 | 50% (0.5/1) | 0 | ⚠️ |
|
||||||
|
| LEAD-001 | processing_time.md | Medium | Every conflict | 18/11/2025 | 100% (1/1) | 0 | ⚠️ |
|
||||||
|
| LEAD-002 | domination_esprit.md | Hard | Every conflict | Never | N/A | 0 | |
|
||||||
|
| ACTION-003 | initier_conversations.md | Medium | Every 2-3 days | 15/11/2025 | 33% (0.33/1) | 0 | ⚠️ |
|
||||||
|
| ACTION-004 | plan_long_terme.md | Hard | Every 3-4 days | 19/11/2025 | 50% (0.5/1) | 0 | ⚠️ |
|
||||||
|
| ACTION-005 | checklist_quotidienne.md | Easy | Daily | Never | N/A | 0 | |
|
||||||
|
| ACTION-006 | financial_security_setup.md | Hard | Every 2-3 days | 19/11/2025 | 100% (2.0/2) | 0 | ⚠️ |
|
||||||
|
| ACTION-007 | cuisiner_pour_elle.md | Medium | Every 2-3 days | Never | N/A | 0 | |
|
||||||
|
| PLAN-001 | plan_voyage_beijing.md | Hard | Every 2-3 days | Never | N/A | 0 | ⚠️ |
|
||||||
|
| PLAN-002 | plan_voyage_france.md | Hard | Every 2-3 days | Never | N/A | 0 | ⚠️ |
|
||||||
|
| PATTERN-001 | post_event_negativity.md | Hard | Every 2-3 days | Never | N/A | 0 | ⚠️ |
|
||||||
|
| FUTURE-001 | ceremonie_mariage_epargne.md | Hard | Monthly | 19/11/2025 | 50% (0.5/1) | 0 | ⚠️ |
|
||||||
|
| FUTURE-002 | cadeaux_mariage_traditionnels.md | Medium | Every 2 weeks | 19/11/2025 | 100% (1/1) | 0 | |
|
||||||
|
| PERSONAL-001 | reddit_saves_review.md | Medium | Weekly | Never | N/A | 0 | |
|
||||||
|
| FAMILY-001 | social_media_automation_papa.md | Hard | Every 3-4 days | 18/11/2025 | 100% (1/1) | 0 | |
|
||||||
|
| TECH-001 | class_generator_mac.md | Medium | Every 3-4 days | Never | N/A | 0 | |
|
||||||
|
| PERSONAL-002 | manage_music_phone.md | Easy | Every 7 days | Never | N/A | 0 | |
|
||||||
|
| COMM-001 | emotional_calibration.md | Hard | Every 2-3 days | Never | N/A | 0 | ⚠️ |
|
||||||
|
|
||||||
|
**Note** : Tous les fichiers de cartes détaillés sont dans le dossier `cards/`. La table ci-dessus sert de quick reference pour les scripts et Claude.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Active Cards (Detailed View)
|
||||||
|
|
||||||
### Card #1 - Complacency Problem ⚠️ CRITICAL
|
### Card #1 - Complacency Problem ⚠️ CRITICAL
|
||||||
**ID** : CORE-001
|
**ID** : CORE-001
|
||||||
@ -23,11 +56,12 @@
|
|||||||
**Difficulty** : Hard
|
**Difficulty** : Hard
|
||||||
**Frequency** : Daily (jusqu'à maîtrisé)
|
**Frequency** : Daily (jusqu'à maîtrisé)
|
||||||
**Created** : 07/11/2025
|
**Created** : 07/11/2025
|
||||||
**Last Review** : 18/11/2025
|
**Last Review** : 19/11/2025
|
||||||
**Success Rate** : 100% (1 review)
|
**Success Rate** : 100% (1 review)
|
||||||
**Times Asked** : 1
|
**Times Asked** : 1
|
||||||
**Times Failed** : 0
|
**Times Failed** : 0
|
||||||
**Notes** : C'est LE problème central. Si j'oublie ça, j'oublie tout. ✅ 18/11 : Bonne compréhension - identifie autopilot vs thinking intentionnel, reconnaît que daily check aide.
|
**Notes** : C'est LE problème central. Si j'oublie ça, j'oublie tout. ✅ 18/11 : Bonne compréhension - identifie autopilot vs thinking intentionnel, reconnaît que daily check aide.
|
||||||
|
**Card File** : `cards/complacency_problem.md`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -45,6 +79,7 @@
|
|||||||
**Times Failed** : 0
|
**Times Failed** : 0
|
||||||
**Notes** : Déclencheur du conflit 07/11. Exemple parfait de détail que j'oublie.
|
**Notes** : Déclencheur du conflit 07/11. Exemple parfait de détail que j'oublie.
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
---
|
---
|
||||||
|
|
||||||
### Card #3 - Communication Paradox
|
### Card #3 - Communication Paradox
|
||||||
@ -323,121 +358,29 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Summary Statistics
|
||||||
|
|
||||||
|
**Cards par catégorie** :
|
||||||
|
- CORE (Problèmes fondamentaux) : 2
|
||||||
|
- ACTION (Actions concrètes) : 7
|
||||||
|
- LEAD (Leadership dans conflits) : 2
|
||||||
|
- PLAN (Planning voyages) : 2
|
||||||
|
- PATTERN (Patterns comportementaux) : 1
|
||||||
|
- FUTURE (Long terme) : 2
|
||||||
|
- PERSONAL (Développement personnel) : 2
|
||||||
|
- FAMILY (Famille) : 1
|
||||||
|
- TECH (Projets techniques) : 1
|
||||||
|
- COMM (Communication patterns) : 1
|
||||||
|
|
||||||
|
**Cards par difficulté** :
|
||||||
|
- Easy : 2
|
||||||
|
- Medium : 7
|
||||||
|
- Hard : 11
|
||||||
|
|
||||||
|
**Cards critiques** : 11
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Retired Cards
|
## Retired Cards
|
||||||
|
|
||||||
(Aucune pour l'instant - les cartes sont retirées quand le problème est durablement résolu)
|
(Aucune pour l'instant - les cartes sont retirées quand le problème est durablement résolu)
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Card Creation Guidelines
|
|
||||||
|
|
||||||
### Quand créer une nouvelle carte ?
|
|
||||||
|
|
||||||
**Créer quand** :
|
|
||||||
- Nouveau pattern identifié dans un conflit
|
|
||||||
- Truc important qu'elle a dit et que je risque d'oublier
|
|
||||||
- Action concrète convenue ensemble
|
|
||||||
- Insight important sur la dynamique couple
|
|
||||||
|
|
||||||
**Ne PAS créer quand** :
|
|
||||||
- C'est trop spécifique/temporaire (genre "acheter du lait demain")
|
|
||||||
- C'est redondant avec une carte existante
|
|
||||||
- C'est pas vraiment important
|
|
||||||
|
|
||||||
### Format de carte
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
### Card #X - [Nom Court]
|
|
||||||
**ID** : [CATEGORY-XXX]
|
|
||||||
**Question** : [Question claire, directe]
|
|
||||||
**Answer** : [Réponse complète, avec contexte si nécessaire]
|
|
||||||
**Tags** : [tags séparés par virgule]
|
|
||||||
**Difficulty** : Easy / Medium / Hard
|
|
||||||
**Frequency** : [À quelle fréquence la poser]
|
|
||||||
**Created** : [Date]
|
|
||||||
**Last Review** : [Date ou "Never"]
|
|
||||||
**Success Rate** : [X% ou N/A]
|
|
||||||
**Times Failed** : [Nombre]
|
|
||||||
**Notes** : [Contexte additionnel, pourquoi c'est important]
|
|
||||||
```
|
|
||||||
|
|
||||||
### Tag System
|
|
||||||
|
|
||||||
**Categories** :
|
|
||||||
- `core-problem` : Problèmes fondamentaux de la relation
|
|
||||||
- `action` : Actions concrètes à faire
|
|
||||||
- `communication` : Patterns de communication
|
|
||||||
- `detail` : Détails pratiques à retenir
|
|
||||||
- `pattern` : Patterns comportementaux
|
|
||||||
|
|
||||||
**Importance** :
|
|
||||||
- `critical` : À ne JAMAIS oublier
|
|
||||||
- `daily` : À checker quotidiennement
|
|
||||||
- `weekly` : Moins urgent mais important
|
|
||||||
|
|
||||||
### Difficulty Levels
|
|
||||||
|
|
||||||
**Easy** : Je peux répondre facilement, juste besoin de maintenir
|
|
||||||
**Medium** : Je dois y penser, risque d'oubli moyen
|
|
||||||
**Hard** : J'oublie systématiquement, ou c'est difficile émotionnellement
|
|
||||||
|
|
||||||
### Frequency Guidelines
|
|
||||||
|
|
||||||
**Daily** : Cartes critical ou hard que j'oublie souvent
|
|
||||||
**Every 2-3 days** : Cartes medium, pour maintenir
|
|
||||||
**Weekly** : Cartes easy, juste pour pas oublier complètement
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Spaced Repetition Algorithm (Simple)
|
|
||||||
|
|
||||||
### Logique de base
|
|
||||||
|
|
||||||
**Si réponse correcte** :
|
|
||||||
- Easy card : +7 jours avant prochaine review
|
|
||||||
- Medium card : +3 jours
|
|
||||||
- Hard card : +1 jour
|
|
||||||
|
|
||||||
**Si réponse incorrecte** :
|
|
||||||
- Toutes difficultés : Review demain (reset)
|
|
||||||
|
|
||||||
**Si échec 3x sur même carte** :
|
|
||||||
- Augmenter frequency à "daily"
|
|
||||||
- Flagged pour attention spéciale
|
|
||||||
|
|
||||||
### Update après chaque session
|
|
||||||
|
|
||||||
Après chaque daily check, update :
|
|
||||||
1. **Last Review** : Date d'aujourd'hui
|
|
||||||
2. **Success Rate** : Calculer nouveau %
|
|
||||||
3. **Times Failed** : Incrémenter si échec
|
|
||||||
4. **Next Review** : Calculer selon l'algo ci-dessus
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Stats Overview
|
|
||||||
|
|
||||||
**À calculer hebdomadairement** :
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
### Week of [DATE]
|
|
||||||
|
|
||||||
**Total Reviews** : X
|
|
||||||
**Average Score** : X/3
|
|
||||||
**Cards Mastered** : X (success rate > 80% sur 5+ reviews)
|
|
||||||
**Cards Struggling** : X (success rate < 50%)
|
|
||||||
**Longest Streak** : X days
|
|
||||||
**Times Skipped** : X
|
|
||||||
|
|
||||||
**Most Failed Card** : [Card ID] - [X failures]
|
|
||||||
**Best Performing Card** : [Card ID] - [X% success rate]
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Next Actions
|
|
||||||
|
|
||||||
- [ ] Review ces 4 cartes lors du prochain daily check
|
|
||||||
- [ ] Après 1 semaine, analyser quelles cartes sont les plus difficiles
|
|
||||||
- [ ] Créer nouvelles cartes si nouveaux patterns identifiés
|
|
||||||
- [ ] Retirer cartes si problèmes durablement résolus (3+ semaines de succès)
|
|
||||||
|
|||||||
@ -26,6 +26,6 @@ Tingting ne devrait pas avoir à m'expliquer tout ça - c'est MON rôle de me re
|
|||||||
|
|
||||||
## Review History
|
## Review History
|
||||||
|
|
||||||
**Last Review**: Never
|
**Last Review**: 19/11/2025
|
||||||
**Success Rate**: N/A (nouveau)
|
**Success Rate**: 100% (1/1)
|
||||||
**Times Failed**: 0
|
**Times Failed**: 0
|
||||||
|
|||||||
@ -26,6 +26,6 @@ Cette carte reste ACTIVE jusqu'à ce que Tingting ait eu sa cérémonie. Pas de
|
|||||||
|
|
||||||
## Review History
|
## Review History
|
||||||
|
|
||||||
**Last Review**: Never
|
**Last Review**: 19/11/2025
|
||||||
**Success Rate**: N/A (nouveau)
|
**Success Rate**: 50% (0.5/1)
|
||||||
**Times Failed**: 0
|
**Times Failed**: 0
|
||||||
|
|||||||
@ -26,6 +26,6 @@ C'est LE problème central. Si j'oublie ça, j'oublie tout.
|
|||||||
|
|
||||||
## Review History
|
## Review History
|
||||||
|
|
||||||
**Last Review**: Never
|
**Last Review**: 19/11/2025
|
||||||
**Success Rate**: N/A (nouveau)
|
**Success Rate**: 100% (1/1)
|
||||||
**Times Failed**: 0
|
**Times Failed**: 0
|
||||||
|
|||||||
59
anki_tingting/cards/emotional_calibration.md
Normal file
59
anki_tingting/cards/emotional_calibration.md
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
# Card: Emotional Calibration Problem
|
||||||
|
|
||||||
|
**ID**: COMM-001
|
||||||
|
**Created**: 19/11/2025
|
||||||
|
**Status**: Active ⚠️ CRITICAL
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Question
|
||||||
|
|
||||||
|
Pourquoi Tingting demande "pourquoi tu t'énerves pas ?" quand tu lui parles de quelque chose qui te dérange ?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Answer
|
||||||
|
|
||||||
|
**Le problème de calibration** : Je suis ultra chill par nature (exemple : -2500€ fisc = down 1 jour puis move on). Mon range émotionnel est très étroit, donc Tingting ne peut pas distinguer ce qui est vraiment important de ce qui l'est pas.
|
||||||
|
|
||||||
|
**Exemples de mon niveau de chill** :
|
||||||
|
- Appart en bordel = littéralement invisible
|
||||||
|
- Vêtements sales = je remets les mêmes, osef
|
||||||
|
- -2500€ au fisc, zéro revenu = down 1 jour puis "next"
|
||||||
|
- Pas assez de sex = conversation calme
|
||||||
|
- Elle respecte pas ma fatigue = "c'est relou"
|
||||||
|
|
||||||
|
**Du coup elle voit tout pareil** → Comment elle fait la différence entre ce qui compte vraiment et ce qui compte pas ?
|
||||||
|
|
||||||
|
**Ce qu'elle cherche** : Pas de la colère, mais des **marqueurs d'intensité** pour comprendre la hiérarchie de mes priorités.
|
||||||
|
|
||||||
|
**Solution** : Utiliser des **mots explicites** pour signaler l'importance, pas juste compter sur le ton émotionnel.
|
||||||
|
|
||||||
|
**Exemples concrets** :
|
||||||
|
- ❌ "The sex situation is a bit frustrating" (ton calme habituel)
|
||||||
|
- ✅ "This is really important to me. I need you to understand this is a priority for our relationship" (même ton, mais **clarté**)
|
||||||
|
|
||||||
|
**Sujets actuellement importants** malgré mon ton calme :
|
||||||
|
1. **Sex** - Fréquence insuffisante, c'est vraiment important même si je le dis calmement
|
||||||
|
2. **Respect de ma fatigue** - Quand elle ne respecte pas alors que je respecte la sienne, c'est un problème d'équité
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
**Contexte** : Conversation daily check 19/11/2025. Elle a dit plusieurs fois "pourquoi tu t'énerves pas ?" sur le sujet du sex. On a identifié que c'est pas un problème d'évitement de ma part, mais un problème de **langage émotionnel incompatible**.
|
||||||
|
|
||||||
|
**Être chill = force dans la vie** (résilience, efficacité émotionnelle)
|
||||||
|
**Être chill = bug de communication** avec quelqu'un qui a besoin de signaux émotionnels
|
||||||
|
|
||||||
|
**Action concrète** : Quand quelque chose est important, DIRE EXPLICITEMENT "This is important to me" ou "This is a priority" - ne pas laisser Tingting deviner basé sur un ton qui ne change jamais.
|
||||||
|
|
||||||
|
**Validation de son besoin** : Elle a raison de chercher à comprendre mes priorités. C'est pas elle qui est "trop émotionnelle", c'est juste qu'on a des langages différents et je dois adapter ma communication.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Review History
|
||||||
|
|
||||||
|
**Last Review**: Never
|
||||||
|
**Success Rate**: N/A (nouveau)
|
||||||
|
**Times Failed**: 0
|
||||||
@ -26,6 +26,6 @@ La France = wake-up call à 3500€. NE JAMAIS OUBLIER cette leçon. C'est MON R
|
|||||||
|
|
||||||
## Review History
|
## Review History
|
||||||
|
|
||||||
**Last Review**: 18/11/2025
|
**Last Review**: 19/11/2025
|
||||||
**Success Rate**: 100% (1/1)
|
**Success Rate**: 100% (2.0/2)
|
||||||
**Times Failed**: 0
|
**Times Failed**: 0
|
||||||
|
|||||||
@ -26,6 +26,6 @@ Elle a dit que c'est "LE PIRE" que je ne lui dise pas. Donc TRÈS important.
|
|||||||
|
|
||||||
## Review History
|
## Review History
|
||||||
|
|
||||||
**Last Review**: Never
|
**Last Review**: 19/11/2025
|
||||||
**Success Rate**: N/A (nouveau)
|
**Success Rate**: 50% (0.5/1)
|
||||||
**Times Failed**: 0
|
**Times Failed**: 0
|
||||||
|
|||||||
@ -26,6 +26,6 @@ Pattern identifié : j'oublie que c'est mon rôle. Timing "jamais bon" = excuse.
|
|||||||
|
|
||||||
## Review History
|
## Review History
|
||||||
|
|
||||||
**Last Review**: Never
|
**Last Review**: 19/11/2025
|
||||||
**Success Rate**: N/A (nouveau)
|
**Success Rate**: 50% (0.5/1)
|
||||||
**Times Failed**: 0
|
**Times Failed**: 0
|
||||||
|
|||||||
@ -747,3 +747,87 @@ Bon retour après 2 jours d'absence. Montre une meilleure compréhension des con
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
|
### 2025-11-19 [Time Unknown]
|
||||||
|
|
||||||
|
**Triggered by** : User (manual "daily check")
|
||||||
|
**Duration** : ~5 minutes
|
||||||
|
|
||||||
|
**Questions Asked** :
|
||||||
|
1. [FUTURE-001] Combien d'argent as-tu mis de côté ce mois-ci pour la cérémonie de Tingting ? → Score: ⚠️
|
||||||
|
- Ta réponse : "0€ gagné donc 0€ mis de côté, mais je setup ce qu'il faut"
|
||||||
|
- Feedback : Tu setup les systèmes (Wise, plan financier) = bon. Mais "Chaque mois sans épargne = un mois de plus où je retarde son rêve." Tu es en mode setup, combien de temps encore avant que l'argent rentre vraiment ? Elle voit que tu prépares, ou elle voit "toujours pas d'argent pour la cérémonie" ?
|
||||||
|
|
||||||
|
2. [ACTION-006] Qu'est-ce que tu as fait concrètement cette semaine pour avancer sur le setup financier ? → Score: ✅
|
||||||
|
- Ta réponse : "Wise setup + plan fait + carte créée hier + setup le world pour être autonome et productif"
|
||||||
|
- Feedback : Actions concrètes. C'est exactement ce qu'elle a besoin de voir. Tu FAIS, pas juste tu parles. Continue.
|
||||||
|
|
||||||
|
3. [FUTURE-002] Qu'est-ce que tu sais sur les cadeaux de mariage traditionnels chinois et où en es-tu dans la préparation ? → Score: ✅
|
||||||
|
- Ta réponse : "Bracelet en or + jade blanc laiteux + voyages provinces chinoises pour photos costumes historiques"
|
||||||
|
- Feedback : Tu SAIS. Tu as écouté, retenu, compris l'importance culturelle. Question : Est-ce que tu as budgété pour ça ? Combien ça coûte ? Savoir c'est bien, avoir l'argent quand le moment vient c'est mieux.
|
||||||
|
|
||||||
|
**Total Score** : 2/3
|
||||||
|
**Streak** : 2 jours (18/11 + 19/11)
|
||||||
|
**Notes** : Tu setup les systèmes (finances, connaissance culturelle) = bon signe. Mais question reste : Tingting voit "il prépare activement notre futur" ou elle voit "il setup des trucs mais l'argent arrive toujours pas" ? Combien de temps encore avant que le setup devienne des résultats concrets qu'elle peut voir ?
|
||||||
|
**Action Items** :
|
||||||
|
- Définir timeline : Quand est-ce que l'argent commence à rentrer ?
|
||||||
|
- Budgéter précisément : Bracelet or + jade + voyages = combien ?
|
||||||
|
|
||||||
|
**Observation finale** : Alexis frustré par répétition de CORE-001 (complacency_problem) tous les jours. Système de sélection des cartes à améliorer - les stats individuelles ne sont pas mises à jour donc Claude pense que les cartes n'ont jamais été révisées.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
### 2025-11-19 [Time Unknown]
|
||||||
|
|
||||||
|
**Triggered by** : User (manual "daily check")
|
||||||
|
**Duration** : ~5 minutes
|
||||||
|
|
||||||
|
**Questions Asked** :
|
||||||
|
1. [FUTURE-001] Combien d'argent as-tu mis de côté ce mois-ci pour la cérémonie de Tingting ? → Score: ⚠️
|
||||||
|
- Ta réponse : "[Non enregistrée]"
|
||||||
|
- Feedback : [Généré automatiquement]
|
||||||
|
|
||||||
|
2. [ACTION-006] Qu'est-ce que tu dois setup pour protéger vos finances et qu'est-ce que la France t'a appris ? → Score: ✅
|
||||||
|
- Ta réponse : "[Non enregistrée]"
|
||||||
|
- Feedback : [Généré automatiquement]
|
||||||
|
|
||||||
|
3. [FUTURE-002] Qu'est-ce que tu sais sur les cadeaux de mariage traditionnels chinois et où en es-tu dans la préparation ? → Score: ✅
|
||||||
|
- Ta réponse : "[Non enregistrée]"
|
||||||
|
- Feedback : [Généré automatiquement]
|
||||||
|
|
||||||
|
**Total Score** : 2.5/3
|
||||||
|
**Streak** : 3 jours
|
||||||
|
**Notes** : Session loggée automatiquement via log_session.py
|
||||||
|
**Action Items** :
|
||||||
|
- [À compléter manuellement si nécessaire]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
### 2025-11-19 [Time Unknown]
|
||||||
|
|
||||||
|
**Triggered by** : User (manual "daily check")
|
||||||
|
**Duration** : ~5 minutes
|
||||||
|
|
||||||
|
**Questions Asked** :
|
||||||
|
1. [CORE-001] Pourquoi Tingting dit que tu "think" pas ? → Score: ✅
|
||||||
|
- Ta réponse : "[Non enregistrée]"
|
||||||
|
- Feedback : [Généré automatiquement]
|
||||||
|
|
||||||
|
2. [ACTION-002] Qu'est-ce que Tingting veut que je fasse quand elle fait des trucs wrong ? → Score: ⚠️
|
||||||
|
- Ta réponse : "[Non enregistrée]"
|
||||||
|
- Feedback : [Généré automatiquement]
|
||||||
|
|
||||||
|
3. [ACTION-004] Qu'est-ce que tu as réfléchi ou proposé récemment pour votre avenir ensemble ? → Score: ⚠️
|
||||||
|
- Ta réponse : "[Non enregistrée]"
|
||||||
|
- Feedback : [Généré automatiquement]
|
||||||
|
|
||||||
|
**Total Score** : 2.0/3
|
||||||
|
**Streak** : 3 jours
|
||||||
|
**Notes** : Session loggée automatiquement via log_session.py
|
||||||
|
**Action Items** :
|
||||||
|
- [À compléter manuellement si nécessaire]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|||||||
257
anki_tingting/scripts/get_daily_cards.py
Normal file
257
anki_tingting/scripts/get_daily_cards.py
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Script pour sélectionner les cartes quotidiennes du système Anki Tingting.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
python get_daily_cards.py [--num-cards N] [--json]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--num-cards N : Nombre de cartes à sélectionner (défaut: 3)
|
||||||
|
--json : Output en JSON (défaut: texte lisible)
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import json
|
||||||
|
import argparse
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
# Chemins relatifs au script
|
||||||
|
SCRIPT_DIR = Path(__file__).parent
|
||||||
|
BASE_DIR = SCRIPT_DIR.parent
|
||||||
|
CARD_DB_PATH = BASE_DIR / "card_database.md"
|
||||||
|
CARDS_DIR = BASE_DIR / "cards"
|
||||||
|
|
||||||
|
|
||||||
|
def parse_date(date_str):
|
||||||
|
"""Parse une date au format DD/MM/YYYY ou 'Never'."""
|
||||||
|
if date_str == "Never" or date_str == "N/A":
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
return datetime.strptime(date_str, "%d/%m/%Y")
|
||||||
|
except ValueError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def parse_card_database():
|
||||||
|
"""Parse le fichier card_database.md et retourne la liste des cartes."""
|
||||||
|
with open(CARD_DB_PATH, 'r', encoding='utf-8') as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
# Trouver la table markdown
|
||||||
|
table_pattern = r'\| ID \| Card \| Difficulty.*?\n\|---.*?\n((?:\|.*?\n)+)'
|
||||||
|
match = re.search(table_pattern, content, re.DOTALL)
|
||||||
|
|
||||||
|
if not match:
|
||||||
|
raise ValueError("Impossible de trouver la table dans card_database.md")
|
||||||
|
|
||||||
|
table_rows = match.group(1).strip().split('\n')
|
||||||
|
|
||||||
|
cards = []
|
||||||
|
for row in table_rows:
|
||||||
|
# Parse chaque ligne de la table
|
||||||
|
cols = [col.strip() for col in row.split('|')[1:-1]] # Ignore les | de début/fin
|
||||||
|
|
||||||
|
if len(cols) < 8:
|
||||||
|
continue
|
||||||
|
|
||||||
|
card_id, card_file, difficulty, frequency, last_review, success_rate, times_failed, critical = cols
|
||||||
|
|
||||||
|
cards.append({
|
||||||
|
'id': card_id,
|
||||||
|
'file': card_file,
|
||||||
|
'difficulty': difficulty,
|
||||||
|
'frequency': frequency,
|
||||||
|
'last_review': parse_date(last_review),
|
||||||
|
'last_review_str': last_review,
|
||||||
|
'success_rate': success_rate,
|
||||||
|
'times_failed': int(times_failed) if times_failed.isdigit() else 0,
|
||||||
|
'critical': critical == '⚠️'
|
||||||
|
})
|
||||||
|
|
||||||
|
return cards
|
||||||
|
|
||||||
|
|
||||||
|
def load_card_content(card_file):
|
||||||
|
"""Charge le contenu d'une carte depuis son fichier."""
|
||||||
|
card_path = CARDS_DIR / card_file
|
||||||
|
|
||||||
|
with open(card_path, 'r', encoding='utf-8') as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
# Extract question
|
||||||
|
question_match = re.search(r'## Question\s*\n\s*\n(.*?)\n\s*\n---', content, re.DOTALL)
|
||||||
|
question = question_match.group(1).strip() if question_match else "Question non trouvée"
|
||||||
|
|
||||||
|
# Extract answer
|
||||||
|
answer_match = re.search(r'## Answer\s*\n\s*\n(.*?)\n\s*\n---', content, re.DOTALL)
|
||||||
|
answer = answer_match.group(1).strip() if answer_match else "Réponse non trouvée"
|
||||||
|
|
||||||
|
# Extract notes
|
||||||
|
notes_match = re.search(r'## Notes\s*\n\s*\n(.*?)\n\s*\n---', content, re.DOTALL)
|
||||||
|
notes = notes_match.group(1).strip() if notes_match else ""
|
||||||
|
|
||||||
|
return {
|
||||||
|
'question': question,
|
||||||
|
'answer': answer,
|
||||||
|
'notes': notes
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def calculate_priority_score(card, today):
|
||||||
|
"""Calcule un score de priorité pour une carte."""
|
||||||
|
score = 0
|
||||||
|
|
||||||
|
# CRITICAL cards = haute priorité
|
||||||
|
if card['critical']:
|
||||||
|
score += 100
|
||||||
|
|
||||||
|
# Times failed = haute priorité
|
||||||
|
score += card['times_failed'] * 50
|
||||||
|
|
||||||
|
# Difficulté
|
||||||
|
difficulty_scores = {'Hard': 30, 'Medium': 20, 'Easy': 10}
|
||||||
|
score += difficulty_scores.get(card['difficulty'], 0)
|
||||||
|
|
||||||
|
# Temps depuis dernière review
|
||||||
|
if card['last_review'] is None:
|
||||||
|
score += 200 # Jamais révisée = très haute priorité
|
||||||
|
else:
|
||||||
|
days_since = (today - card['last_review']).days
|
||||||
|
|
||||||
|
# Calculer le nombre de jours attendus selon frequency
|
||||||
|
freq_days = {
|
||||||
|
'Daily': 1,
|
||||||
|
'Every 2-3 days': 2,
|
||||||
|
'Every 3-4 days': 3,
|
||||||
|
'Every 2 weeks': 14,
|
||||||
|
'Monthly': 30,
|
||||||
|
'Every conflict': 999 # Pas basé sur le temps
|
||||||
|
}
|
||||||
|
|
||||||
|
expected_days = freq_days.get(card['frequency'], 7)
|
||||||
|
|
||||||
|
if card['frequency'] == 'Every conflict':
|
||||||
|
# Cartes de conflit : priorité basse sauf si jamais révisées
|
||||||
|
score += 5
|
||||||
|
elif days_since >= expected_days:
|
||||||
|
# En retard sur la review
|
||||||
|
score += 80 + (days_since - expected_days) * 10
|
||||||
|
else:
|
||||||
|
# Pas encore le moment
|
||||||
|
score += 5
|
||||||
|
|
||||||
|
# Success rate (si disponible)
|
||||||
|
if card['success_rate'] not in ['N/A', 'Never']:
|
||||||
|
try:
|
||||||
|
rate = int(card['success_rate'].replace('%', ''))
|
||||||
|
if rate < 70:
|
||||||
|
score += 40
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return score
|
||||||
|
|
||||||
|
|
||||||
|
def select_daily_cards(num_cards=3):
|
||||||
|
"""Sélectionne les cartes pour la session quotidienne."""
|
||||||
|
cards = parse_card_database()
|
||||||
|
today = datetime.now()
|
||||||
|
|
||||||
|
# Calculer le score de priorité pour chaque carte
|
||||||
|
for card in cards:
|
||||||
|
card['priority_score'] = calculate_priority_score(card, today)
|
||||||
|
|
||||||
|
# Trier par priorité décroissante
|
||||||
|
cards.sort(key=lambda c: c['priority_score'], reverse=True)
|
||||||
|
|
||||||
|
# Sélectionner les N premières cartes
|
||||||
|
selected = cards[:num_cards]
|
||||||
|
|
||||||
|
# Charger le contenu de chaque carte
|
||||||
|
for card in selected:
|
||||||
|
content = load_card_content(card['file'])
|
||||||
|
card.update(content)
|
||||||
|
|
||||||
|
return selected
|
||||||
|
|
||||||
|
|
||||||
|
def format_output_text(cards):
|
||||||
|
"""Formate l'output en texte lisible."""
|
||||||
|
output = []
|
||||||
|
output.append("=" * 60)
|
||||||
|
output.append(f"📚 CARTES SÉLECTIONNÉES - {datetime.now().strftime('%d/%m/%Y')}")
|
||||||
|
output.append("=" * 60)
|
||||||
|
output.append("")
|
||||||
|
|
||||||
|
for i, card in enumerate(cards, 1):
|
||||||
|
output.append(f"🎯 CARTE {i}/3")
|
||||||
|
output.append(f"ID: {card['id']}")
|
||||||
|
output.append(f"Fichier: {card['file']}")
|
||||||
|
output.append(f"Difficulté: {card['difficulty']} | Critique: {'⚠️ OUI' if card['critical'] else 'Non'}")
|
||||||
|
output.append(f"Dernière review: {card['last_review_str']}")
|
||||||
|
output.append(f"Score priorité: {card['priority_score']}")
|
||||||
|
output.append("")
|
||||||
|
output.append(f"QUESTION:")
|
||||||
|
output.append(card['question'])
|
||||||
|
output.append("")
|
||||||
|
output.append(f"RÉPONSE ATTENDUE:")
|
||||||
|
output.append(card['answer'])
|
||||||
|
output.append("")
|
||||||
|
if card['notes']:
|
||||||
|
output.append(f"NOTES:")
|
||||||
|
output.append(card['notes'])
|
||||||
|
output.append("")
|
||||||
|
output.append("-" * 60)
|
||||||
|
output.append("")
|
||||||
|
|
||||||
|
return "\n".join(output)
|
||||||
|
|
||||||
|
|
||||||
|
def format_output_json(cards):
|
||||||
|
"""Formate l'output en JSON."""
|
||||||
|
return json.dumps({
|
||||||
|
'date': datetime.now().strftime('%d/%m/%Y'),
|
||||||
|
'cards': [
|
||||||
|
{
|
||||||
|
'id': card['id'],
|
||||||
|
'file': card['file'],
|
||||||
|
'difficulty': card['difficulty'],
|
||||||
|
'critical': card['critical'],
|
||||||
|
'last_review': card['last_review_str'],
|
||||||
|
'priority_score': card['priority_score'],
|
||||||
|
'question': card['question'],
|
||||||
|
'answer': card['answer'],
|
||||||
|
'notes': card['notes']
|
||||||
|
}
|
||||||
|
for card in cards
|
||||||
|
]
|
||||||
|
}, indent=2, ensure_ascii=False)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description='Sélectionne les cartes quotidiennes')
|
||||||
|
parser.add_argument('--num-cards', type=int, default=3, help='Nombre de cartes à sélectionner')
|
||||||
|
parser.add_argument('--json', action='store_true', help='Output en JSON')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
try:
|
||||||
|
cards = select_daily_cards(args.num_cards)
|
||||||
|
|
||||||
|
if args.json:
|
||||||
|
print(format_output_json(cards))
|
||||||
|
else:
|
||||||
|
print(format_output_text(cards))
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ ERREUR: {e}", file=sys.stderr)
|
||||||
|
import sys
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import sys
|
||||||
|
main()
|
||||||
440
anki_tingting/scripts/log_session.py
Normal file
440
anki_tingting/scripts/log_session.py
Normal file
@ -0,0 +1,440 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Script pour logger une session de daily check et mettre à jour les stats.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
python log_session.py --cards "CORE-001,ACTION-006,FUTURE-001" --scores "✅,⚠️,❌"
|
||||||
|
|
||||||
|
OU en mode interactif:
|
||||||
|
python log_session.py --interactive
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--cards : Liste des IDs de cartes (séparées par virgules)
|
||||||
|
--scores : Liste des scores ✅/⚠️/❌ (séparées par virgules)
|
||||||
|
--interactive: Mode interactif qui demande les infos
|
||||||
|
--dry-run : Test sans modifier les fichiers
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import argparse
|
||||||
|
from datetime import datetime
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
# Chemins relatifs au script
|
||||||
|
SCRIPT_DIR = Path(__file__).parent
|
||||||
|
BASE_DIR = SCRIPT_DIR.parent
|
||||||
|
CARD_DB_PATH = BASE_DIR / "card_database.md"
|
||||||
|
CARDS_DIR = BASE_DIR / "cards"
|
||||||
|
SESSIONS_LOG = BASE_DIR / "daily_sessions.md"
|
||||||
|
|
||||||
|
|
||||||
|
def parse_card_database():
|
||||||
|
"""Parse le fichier card_database.md et retourne un dict {card_id: card_info}."""
|
||||||
|
with open(CARD_DB_PATH, 'r', encoding='utf-8') as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
# Trouver la table markdown
|
||||||
|
table_pattern = r'\| ID \| Card \| Difficulty.*?\n\|---.*?\n((?:\|.*?\n)+)'
|
||||||
|
match = re.search(table_pattern, content, re.DOTALL)
|
||||||
|
|
||||||
|
if not match:
|
||||||
|
raise ValueError("Impossible de trouver la table dans card_database.md")
|
||||||
|
|
||||||
|
table_rows = match.group(1).strip().split('\n')
|
||||||
|
|
||||||
|
cards = {}
|
||||||
|
for row in table_rows:
|
||||||
|
cols = [col.strip() for col in row.split('|')[1:-1]]
|
||||||
|
|
||||||
|
if len(cols) < 8:
|
||||||
|
continue
|
||||||
|
|
||||||
|
card_id, card_file, difficulty, frequency, last_review, success_rate, times_failed, critical = cols
|
||||||
|
|
||||||
|
cards[card_id] = {
|
||||||
|
'id': card_id,
|
||||||
|
'file': card_file,
|
||||||
|
'difficulty': difficulty,
|
||||||
|
'frequency': frequency,
|
||||||
|
'last_review': last_review,
|
||||||
|
'success_rate': success_rate,
|
||||||
|
'times_failed': int(times_failed) if times_failed.isdigit() else 0,
|
||||||
|
'critical': critical == '⚠️'
|
||||||
|
}
|
||||||
|
|
||||||
|
return cards
|
||||||
|
|
||||||
|
|
||||||
|
def update_card_file(card_file, score, today_str):
|
||||||
|
"""Met à jour les stats dans le fichier de carte individuel."""
|
||||||
|
card_path = CARDS_DIR / card_file
|
||||||
|
|
||||||
|
with open(card_path, 'r', encoding='utf-8') as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
# Update Last Review
|
||||||
|
content = re.sub(
|
||||||
|
r'\*\*Last Review\*\*: .*',
|
||||||
|
f'**Last Review**: {today_str}',
|
||||||
|
content
|
||||||
|
)
|
||||||
|
|
||||||
|
# Update Times Failed
|
||||||
|
if score == '❌':
|
||||||
|
# Incrémenter Times Failed
|
||||||
|
def increment_failed(match):
|
||||||
|
current = int(match.group(1)) if match.group(1).isdigit() else 0
|
||||||
|
return f'**Times Failed**: {current + 1}'
|
||||||
|
|
||||||
|
content = re.sub(
|
||||||
|
r'\*\*Times Failed\*\*: (\d+)',
|
||||||
|
increment_failed,
|
||||||
|
content
|
||||||
|
)
|
||||||
|
|
||||||
|
# Update Success Rate
|
||||||
|
# Extraire le success rate actuel
|
||||||
|
success_match = re.search(r'\*\*Success Rate\*\*: (.*)', content)
|
||||||
|
if success_match:
|
||||||
|
current_rate_str = success_match.group(1).strip()
|
||||||
|
|
||||||
|
# Parse le success rate actuel
|
||||||
|
if current_rate_str in ['N/A', 'N/A (nouveau)']:
|
||||||
|
# Première review
|
||||||
|
if score == '✅':
|
||||||
|
new_rate = '100% (1/1)'
|
||||||
|
elif score == '⚠️':
|
||||||
|
new_rate = '50% (0.5/1)'
|
||||||
|
else: # ❌
|
||||||
|
new_rate = '0% (0/1)'
|
||||||
|
else:
|
||||||
|
# Parse "X% (n/total)" ou juste "X%"
|
||||||
|
rate_match = re.match(r'(\d+)%\s*\(?([\d.]+)/(\d+)\)?', current_rate_str)
|
||||||
|
if rate_match:
|
||||||
|
current_percent, successes, total = rate_match.groups()
|
||||||
|
successes = float(successes)
|
||||||
|
total = int(total)
|
||||||
|
else:
|
||||||
|
# Fallback: juste un pourcentage
|
||||||
|
rate_match = re.match(r'(\d+)%', current_rate_str)
|
||||||
|
if rate_match:
|
||||||
|
current_percent = int(rate_match.group(1))
|
||||||
|
# Estimer successes/total basé sur le pourcentage
|
||||||
|
successes = 1 if current_percent >= 50 else 0
|
||||||
|
total = 1
|
||||||
|
else:
|
||||||
|
successes = 0
|
||||||
|
total = 0
|
||||||
|
|
||||||
|
# Ajouter la nouvelle review
|
||||||
|
total += 1
|
||||||
|
if score == '✅':
|
||||||
|
successes += 1
|
||||||
|
elif score == '⚠️':
|
||||||
|
successes += 0.5
|
||||||
|
|
||||||
|
new_percent = int((successes / total) * 100) if total > 0 else 0
|
||||||
|
new_rate = f'{new_percent}% ({successes}/{total})'
|
||||||
|
|
||||||
|
content = re.sub(
|
||||||
|
r'\*\*Success Rate\*\*: .*',
|
||||||
|
f'**Success Rate**: {new_rate}',
|
||||||
|
content
|
||||||
|
)
|
||||||
|
|
||||||
|
return content
|
||||||
|
|
||||||
|
|
||||||
|
def update_card_database(cards_dict, today_str):
|
||||||
|
"""Met à jour la table dans card_database.md avec les nouvelles stats."""
|
||||||
|
with open(CARD_DB_PATH, 'r', encoding='utf-8') as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
# Pour chaque carte, update sa ligne dans la table
|
||||||
|
for card_id, card_info in cards_dict.items():
|
||||||
|
# Trouver la ligne correspondante
|
||||||
|
row_pattern = rf'\| {re.escape(card_id)} \| ([^\n]+)'
|
||||||
|
match = re.search(row_pattern, content)
|
||||||
|
|
||||||
|
if match:
|
||||||
|
old_row = match.group(0)
|
||||||
|
|
||||||
|
# Reconstruire la nouvelle ligne
|
||||||
|
critical_symbol = '⚠️' if card_info['critical'] else ''
|
||||||
|
new_row = (
|
||||||
|
f"| {card_id} | {card_info['file']} | {card_info['difficulty']} | "
|
||||||
|
f"{card_info['frequency']} | {card_info['last_review']} | "
|
||||||
|
f"{card_info['success_rate']} | {card_info['times_failed']} | {critical_symbol} |"
|
||||||
|
)
|
||||||
|
|
||||||
|
content = content.replace(old_row, new_row)
|
||||||
|
|
||||||
|
# Update "Dernière mise à jour"
|
||||||
|
content = re.sub(
|
||||||
|
r'\*\*Dernière mise à jour\*\* : \d{2}/\d{2}/\d{4}',
|
||||||
|
f'**Dernière mise à jour** : {today_str}',
|
||||||
|
content
|
||||||
|
)
|
||||||
|
|
||||||
|
return content
|
||||||
|
|
||||||
|
|
||||||
|
def calculate_streak(sessions_content):
|
||||||
|
"""Calcule le streak actuel basé sur le fichier daily_sessions.md."""
|
||||||
|
# Trouver toutes les sessions
|
||||||
|
session_pattern = r'### (\d{4}-\d{2}-\d{2})'
|
||||||
|
dates = re.findall(session_pattern, sessions_content)
|
||||||
|
|
||||||
|
if not dates:
|
||||||
|
return 1 # Première session
|
||||||
|
|
||||||
|
# Convertir en datetime
|
||||||
|
session_dates = []
|
||||||
|
for date_str in dates:
|
||||||
|
try:
|
||||||
|
session_dates.append(datetime.strptime(date_str, '%Y-%m-%d'))
|
||||||
|
except ValueError:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not session_dates:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
# Trier par date décroissante
|
||||||
|
session_dates.sort(reverse=True)
|
||||||
|
|
||||||
|
today = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
|
||||||
|
|
||||||
|
# Calculer le streak
|
||||||
|
streak = 1 # Aujourd'hui compte
|
||||||
|
last_date = today
|
||||||
|
|
||||||
|
for session_date in session_dates:
|
||||||
|
session_date = session_date.replace(hour=0, minute=0, second=0, microsecond=0)
|
||||||
|
|
||||||
|
# Check si c'est le jour précédent
|
||||||
|
if (last_date - session_date).days == 1:
|
||||||
|
streak += 1
|
||||||
|
last_date = session_date
|
||||||
|
elif session_date == last_date:
|
||||||
|
# Même jour, ignorer
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
# Gap détecté, arrêter
|
||||||
|
break
|
||||||
|
|
||||||
|
return streak
|
||||||
|
|
||||||
|
|
||||||
|
def log_session(card_ids, scores, responses=None, feedback_notes=None, dry_run=False):
|
||||||
|
"""
|
||||||
|
Log une session complète et met à jour toutes les stats.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
card_ids: Liste des IDs de cartes (ex: ['CORE-001', 'ACTION-006'])
|
||||||
|
scores: Liste des scores (ex: ['✅', '⚠️', '❌'])
|
||||||
|
responses: (Optionnel) Liste des réponses données
|
||||||
|
feedback_notes: (Optionnel) Liste des feedbacks
|
||||||
|
dry_run: Si True, affiche ce qui serait fait sans modifier les fichiers
|
||||||
|
"""
|
||||||
|
if len(card_ids) != len(scores):
|
||||||
|
raise ValueError(f"Nombre de cartes ({len(card_ids)}) != nombre de scores ({len(scores)})")
|
||||||
|
|
||||||
|
# Valider les scores
|
||||||
|
valid_scores = ['✅', '⚠️', '❌']
|
||||||
|
for score in scores:
|
||||||
|
if score not in valid_scores:
|
||||||
|
raise ValueError(f"Score invalide: {score}. Utilise ✅, ⚠️ ou ❌")
|
||||||
|
|
||||||
|
today = datetime.now()
|
||||||
|
today_str = today.strftime('%d/%m/%Y')
|
||||||
|
today_iso = today.strftime('%Y-%m-%d')
|
||||||
|
|
||||||
|
# Parse card database
|
||||||
|
cards_dict = parse_card_database()
|
||||||
|
|
||||||
|
# Vérifier que toutes les cartes existent
|
||||||
|
for card_id in card_ids:
|
||||||
|
if card_id not in cards_dict:
|
||||||
|
raise ValueError(f"Carte inconnue: {card_id}")
|
||||||
|
|
||||||
|
print(f"📝 LOGGING SESSION - {today_str}")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
# Update chaque carte
|
||||||
|
updated_cards = {}
|
||||||
|
for i, (card_id, score) in enumerate(zip(card_ids, scores)):
|
||||||
|
card = cards_dict[card_id]
|
||||||
|
print(f"\n🎯 Carte {i+1}: {card_id} → {score}")
|
||||||
|
|
||||||
|
# Update le fichier de carte individuel
|
||||||
|
if not dry_run:
|
||||||
|
updated_content = update_card_file(card['file'], score, today_str)
|
||||||
|
card_path = CARDS_DIR / card['file']
|
||||||
|
with open(card_path, 'w', encoding='utf-8') as f:
|
||||||
|
f.write(updated_content)
|
||||||
|
print(f" ✅ Fichier {card['file']} mis à jour")
|
||||||
|
else:
|
||||||
|
print(f" [DRY RUN] Mettrait à jour {card['file']}")
|
||||||
|
|
||||||
|
# Re-parse le fichier pour obtenir les nouvelles stats
|
||||||
|
if not dry_run:
|
||||||
|
with open(CARDS_DIR / card['file'], 'r', encoding='utf-8') as f:
|
||||||
|
new_content = f.read()
|
||||||
|
|
||||||
|
# Extraire les nouvelles stats
|
||||||
|
success_match = re.search(r'\*\*Success Rate\*\*: (.*)', new_content)
|
||||||
|
failed_match = re.search(r'\*\*Times Failed\*\*: (\d+)', new_content)
|
||||||
|
|
||||||
|
card['success_rate'] = success_match.group(1).strip() if success_match else card['success_rate']
|
||||||
|
card['times_failed'] = int(failed_match.group(1)) if failed_match else card['times_failed']
|
||||||
|
card['last_review'] = today_str
|
||||||
|
|
||||||
|
updated_cards[card_id] = card
|
||||||
|
else:
|
||||||
|
print(f" [DRY RUN] Stats seraient mises à jour")
|
||||||
|
|
||||||
|
# Update card_database.md
|
||||||
|
if not dry_run:
|
||||||
|
db_content = update_card_database(updated_cards, today_str)
|
||||||
|
with open(CARD_DB_PATH, 'w', encoding='utf-8') as f:
|
||||||
|
f.write(db_content)
|
||||||
|
print(f"\n✅ card_database.md mis à jour")
|
||||||
|
else:
|
||||||
|
print(f"\n[DRY RUN] card_database.md serait mis à jour")
|
||||||
|
|
||||||
|
# Calculer le score total
|
||||||
|
score_values = {'✅': 1, '⚠️': 0.5, '❌': 0}
|
||||||
|
total_score = sum(score_values[s] for s in scores)
|
||||||
|
max_score = len(scores)
|
||||||
|
|
||||||
|
# Calculer le streak
|
||||||
|
if not dry_run:
|
||||||
|
with open(SESSIONS_LOG, 'r', encoding='utf-8') as f:
|
||||||
|
sessions_content = f.read()
|
||||||
|
streak = calculate_streak(sessions_content)
|
||||||
|
else:
|
||||||
|
streak = 1
|
||||||
|
|
||||||
|
# Créer l'entrée de log pour daily_sessions.md
|
||||||
|
log_entry = f"""
|
||||||
|
### {today_iso} [Time Unknown]
|
||||||
|
|
||||||
|
**Triggered by** : User (manual "daily check")
|
||||||
|
**Duration** : ~5 minutes
|
||||||
|
|
||||||
|
**Questions Asked** :
|
||||||
|
"""
|
||||||
|
|
||||||
|
for i, (card_id, score) in enumerate(zip(card_ids, scores), 1):
|
||||||
|
card = cards_dict[card_id]
|
||||||
|
|
||||||
|
# Charger la question depuis le fichier
|
||||||
|
with open(CARDS_DIR / card['file'], 'r', encoding='utf-8') as f:
|
||||||
|
content = f.read()
|
||||||
|
question_match = re.search(r'## Question\s*\n\s*\n(.*?)\n\s*\n---', content, re.DOTALL)
|
||||||
|
question = question_match.group(1).strip() if question_match else "Question non trouvée"
|
||||||
|
|
||||||
|
response = responses[i-1] if responses and i-1 < len(responses) else "[Non enregistrée]"
|
||||||
|
feedback = feedback_notes[i-1] if feedback_notes and i-1 < len(feedback_notes) else "[Généré automatiquement]"
|
||||||
|
|
||||||
|
log_entry += f"""{i}. [{card_id}] {question} → Score: {score}
|
||||||
|
- Ta réponse : "{response}"
|
||||||
|
- Feedback : {feedback}
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
log_entry += f"""**Total Score** : {total_score}/{max_score}
|
||||||
|
**Streak** : {streak} jour{'s' if streak > 1 else ''}
|
||||||
|
**Notes** : Session loggée automatiquement via log_session.py
|
||||||
|
**Action Items** :
|
||||||
|
- [À compléter manuellement si nécessaire]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Append au fichier de sessions
|
||||||
|
if not dry_run:
|
||||||
|
with open(SESSIONS_LOG, 'a', encoding='utf-8') as f:
|
||||||
|
f.write(log_entry)
|
||||||
|
print(f"✅ Session loggée dans daily_sessions.md")
|
||||||
|
else:
|
||||||
|
print(f"[DRY RUN] Session serait loggée dans daily_sessions.md")
|
||||||
|
|
||||||
|
print("=" * 60)
|
||||||
|
print(f"✅ SESSION COMPLÈTE")
|
||||||
|
print(f"Score: {total_score}/{max_score}")
|
||||||
|
print(f"Streak: {streak} jour{'s' if streak > 1 else ''}")
|
||||||
|
|
||||||
|
return {
|
||||||
|
'score': f"{total_score}/{max_score}",
|
||||||
|
'streak': streak,
|
||||||
|
'cards_updated': len(card_ids)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def interactive_mode():
|
||||||
|
"""Mode interactif pour logger une session."""
|
||||||
|
print("=" * 60)
|
||||||
|
print("📝 MODE INTERACTIF - LOG SESSION")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
# Demander les IDs de cartes
|
||||||
|
cards_input = input("\n🎯 IDs des cartes (séparées par virgules, ex: CORE-001,ACTION-006): ")
|
||||||
|
card_ids = [c.strip() for c in cards_input.split(',')]
|
||||||
|
|
||||||
|
# Demander les scores
|
||||||
|
scores_input = input(f"📊 Scores pour {len(card_ids)} cartes (✅/⚠️/❌, séparés par virgules): ")
|
||||||
|
scores = [s.strip() for s in scores_input.split(',')]
|
||||||
|
|
||||||
|
if len(card_ids) != len(scores):
|
||||||
|
print(f"❌ ERREUR: {len(card_ids)} cartes mais {len(scores)} scores")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Confirm
|
||||||
|
print(f"\n📋 RÉCAPITULATIF:")
|
||||||
|
for card_id, score in zip(card_ids, scores):
|
||||||
|
print(f" {card_id} → {score}")
|
||||||
|
|
||||||
|
confirm = input("\n✅ Confirmer et logger ? (y/n): ")
|
||||||
|
if confirm.lower() != 'y':
|
||||||
|
print("❌ Annulé")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Log
|
||||||
|
log_session(card_ids, scores)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description='Log une session de daily check')
|
||||||
|
parser.add_argument('--cards', type=str, help='IDs de cartes séparées par virgules')
|
||||||
|
parser.add_argument('--scores', type=str, help='Scores (✅/⚠️/❌) séparés par virgules')
|
||||||
|
parser.add_argument('--interactive', action='store_true', help='Mode interactif')
|
||||||
|
parser.add_argument('--dry-run', action='store_true', help='Test sans modifier les fichiers')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
try:
|
||||||
|
if args.interactive:
|
||||||
|
interactive_mode()
|
||||||
|
elif args.cards and args.scores:
|
||||||
|
card_ids = [c.strip() for c in args.cards.split(',')]
|
||||||
|
scores = [s.strip() for s in args.scores.split(',')]
|
||||||
|
log_session(card_ids, scores, dry_run=args.dry_run)
|
||||||
|
else:
|
||||||
|
parser.print_help()
|
||||||
|
print("\n💡 Astuce: Utilise --interactive pour un usage facile")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ ERREUR: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
import sys
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import sys
|
||||||
|
main()
|
||||||
Loading…
Reference in New Issue
Block a user