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:
StillHammer 2025-11-19 11:11:03 +08:00
parent 47e21b6319
commit bdbe17a3a0
13 changed files with 1321 additions and 224 deletions

View 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 ?

View File

@ -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.
**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** :
- **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** :
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)
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
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** :
- Reconnaître que c'est le système en action
- 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
**QUAND il skip plusieurs jours** :
- **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."
- 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
🎯 **Check Quotidien - [DATE]**
**Question 1/3** : [COPIER EXACTEMENT la question depuis card_database.md - NE PAS INVENTER - PRIORITÉ Tingting]
→ [Attendre sa réponse]
**Question 1/3** : [Question de la carte 1 - PRIORITÉ Tingting]
→ [Attendre réponse]
**Question 2/3** : [Question Tingting OU domaine autre (famille/tech/perso)]
→ [Attendre sa réponse]
**Question 2/3** : [Question de la carte 2 - Minimum 2/3 sur Tingting]
→ [Attendre réponse]
**Question 3/3** : [Question Tingting OU domaine autre - VARIER]
→ [Attendre sa réponse]
**Question 3/3** : [Question de la carte 3 - Rotation tous domaines]
→ [Attendre réponse]
---
@ -84,7 +101,39 @@ Ce pattern affecte **PLUSIEURS domaines** :
**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** :
- 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
🚩 **Si skip 2 jours consécutifs**
- "2 jours sans daily check. Pattern d'oubli qui revient."
- "Tingting / Papa / [X] attendent que tu tiennes tes engagements."
**AVANT de faire le quiz**, vérifier dans `daily_sessions.md` :
🚩 **Si skip 3+ jours**
- "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 ?"
🚩 **Skip 2+ jours** → "X jours sans daily check. Pattern d'oubli qui revient. Tingting/Papa/[autres] attendent que tu tiennes tes engagements."
🚩 **Si score déclinant**
- "Tes scores baissent. La complacency revient."
- "Tu redeviens celui qui promet mais n'agit jamais."
🚩 **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 ?"
🚩 **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 ?"
- **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**
- "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."
🚩 **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."
---
## Fichiers à Consulter
## Structure du Système (Référence)
**Avant chaque quiz, lire** :
- `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
### Fichiers principaux
**Après chaque quiz, update** :
- `daily_sessions.md` - Logger la session COMPLÈTE avec détails des cartes
- `card_database.md` - Update pour CHAQUE carte posée :
- `Last Review` : Date d'aujourd'hui
- `Times Asked` : Incrémenter de 1
- `Times Failed` : Incrémenter si échec (❌)
- `Success Rate` : Recalculer le pourcentage
- `Notes` : Ajouter observation si pattern important identifié
- **`card_database.md`** : Index centralisé (table markdown avec toutes les cartes et stats)
- **`CARD_SYSTEM_GUIDE.md`** : Instructions complètes du système (création cartes, tags, etc.)
- **`daily_sessions.md`** : Log de toutes les sessions
- **`cards/*.md`** : Fichiers individuels des cartes (question, answer, notes, stats)
### Scripts Python
- **`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 ?"
**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.

View File

@ -1,19 +1,52 @@
# Card Database - Tingting Daily Check
**Dernière mise à jour** : 18/11/2025
**Total cartes actives** : 19
**Dernière mise à jour** : 19/11/2025
**Total cartes actives** : 20
**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** :
- Relation (Tingting) : 14 cartes
- Personnel : 3 cartes
- Famille : 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
**ID** : CORE-001
@ -23,11 +56,12 @@
**Difficulty** : Hard
**Frequency** : Daily (jusqu'à maîtrisé)
**Created** : 07/11/2025
**Last Review** : 18/11/2025
**Last Review** : 19/11/2025
**Success Rate** : 100% (1 review)
**Times Asked** : 1
**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.
**Card File** : `cards/complacency_problem.md`
---
@ -45,6 +79,7 @@
**Times Failed** : 0
**Notes** : Déclencheur du conflit 07/11. Exemple parfait de détail que j'oublie.
<<<<<<< HEAD
---
### 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
(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)

View File

@ -26,6 +26,6 @@ Tingting ne devrait pas avoir à m'expliquer tout ça - c'est MON rôle de me re
## Review History
**Last Review**: Never
**Success Rate**: N/A (nouveau)
**Last Review**: 19/11/2025
**Success Rate**: 100% (1/1)
**Times Failed**: 0

View File

@ -26,6 +26,6 @@ Cette carte reste ACTIVE jusqu'à ce que Tingting ait eu sa cérémonie. Pas de
## Review History
**Last Review**: Never
**Success Rate**: N/A (nouveau)
**Last Review**: 19/11/2025
**Success Rate**: 50% (0.5/1)
**Times Failed**: 0

View File

@ -26,6 +26,6 @@ C'est LE problème central. Si j'oublie ça, j'oublie tout.
## Review History
**Last Review**: Never
**Success Rate**: N/A (nouveau)
**Last Review**: 19/11/2025
**Success Rate**: 100% (1/1)
**Times Failed**: 0

View 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

View File

@ -26,6 +26,6 @@ La France = wake-up call à 3500€. NE JAMAIS OUBLIER cette leçon. C'est MON R
## Review History
**Last Review**: 18/11/2025
**Success Rate**: 100% (1/1)
**Last Review**: 19/11/2025
**Success Rate**: 100% (2.0/2)
**Times Failed**: 0

View File

@ -26,6 +26,6 @@ Elle a dit que c'est "LE PIRE" que je ne lui dise pas. Donc TRÈS important.
## Review History
**Last Review**: Never
**Success Rate**: N/A (nouveau)
**Last Review**: 19/11/2025
**Success Rate**: 50% (0.5/1)
**Times Failed**: 0

View File

@ -26,6 +26,6 @@ Pattern identifié : j'oublie que c'est mon rôle. Timing "jamais bon" = excuse.
## Review History
**Last Review**: Never
**Success Rate**: N/A (nouveau)
**Last Review**: 19/11/2025
**Success Rate**: 50% (0.5/1)
**Times Failed**: 0

View File

@ -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]
---

View 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()

View 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()