modified
README.md +205 -32 | @@ -1,50 +1,223 @@ | ||
| 1 | -# Regine Photo Archiver | |
| 1 | +# 📸 Régine | |
| 2 | 2 | |
| 3 | -Regine est une application qui aide à préparer l'archivage de photos RAW + JPEG. | |
| 3 | +**L'archiviste qui protège vos photos comme un musée protège ses négatifs.** | |
| 4 | 4 | |
| 5 | -Elle prend beaucoup de photos et a besoin de pouvoir retrouver facilement une photo, ou retrouver l'origine d'une photo pour la revoir dans son contexte. Pour cela, les photos doivent avoir un nom de fichier unifié qui indique : | |
| 5 | +Régine range, nomme et sécurise vos photos RAW + JPEG selon les pratiques des grandes collections professionnelles (Magnum Photos, ICP, Getty, archives nationales) — appliquées à votre NAS personnel. Vous continuez à trier et retoucher avec l'outil de votre choix (DxO, Lightroom...) ; Régine s'occupe du reste : import depuis la carte mémoire, nommage lisible, structure de dossiers cohérente, et un aller-retour sécurisé entre votre archive et votre espace de travail qui garantit qu'**un fichier maître n'est jamais modifié ni perdu sans confirmation explicite**. | |
| 6 | 6 | |
| 7 | -- la **date de prise de vue** | |
| 8 | -- le **contexte** (thème donné par l'utilisateur) | |
| 9 | -- le **nom original du fichier**, conservé pour préserver l'ordre de prise de vue | |
| 7 | +CLI-first aujourd'hui, avec une interface graphique et un agent IA prévus comme façades sur la même bibliothèque — cf. [Feuille de route](#-feuille-de-route). | |
| 10 | 8 | |
| 11 | -## Exemple | |
| 9 | +--- | |
| 12 | 10 | |
| 13 | -Photos prises par un Fuji X70 lors du weekend du 11 septembre 2026 à Deauville, stockées dans le répertoire `2026-09-11` : | |
| 11 | +## Pourquoi Régine ? | |
| 14 | 12 | |
| 15 | -| Avant | Après | | |
| 16 | -| --------------- | ------------------------------------------ | | |
| 17 | -| `R0018279.JPG` | `2026-09-11_Weekend_Deauville_R0018279.JPG` | | |
| 18 | -| `R0018279.RAF` | `2026-09-11_Weekend_Deauville_R0018279.RAF` | | |
| 13 | +Après quelques années de prises de vue régulières, la plupart des photothèques personnelles finissent dans le même état : des dossiers `IMG_2024`, `Export_final_v2`, `Untitled Folder` ; des RAW et des JPEG mélangés sans lien visible ; aucune certitude sur ce qui a déjà été trié, sauvegardé, ou modifié par erreur. | |
| 19 | 14 | |
| 20 | -| Élément | Origine | | |
| 21 | -| ------------------ | ------------------------------------------------------------- | | |
| 22 | -| `2026-09-11` | Date de prise de vue, lue dans les métadonnées EXIF du fichier | | |
| 23 | -| `Weekend_Deauville` | Thème donné par l'utilisateur | | |
| 24 | -| `R0018279` | Référence générée par le boîtier photo, conservée pour l'ordre des photos dans le répertoire | | |
| 15 | +Régine part des principes qu'utilisent les collections professionnelles — organisation dès la source, métadonnées embarquées, identité par contenu plutôt que par nom de fichier, jamais d'écrasement silencieux — et les rend accessibles à un·e photographe seul·e, sans infrastructure d'archives. Voir [`docs/archivage-photo-elements-cles.md`](docs/archivage-photo-elements-cles.md) pour les notes de recherche complètes qui fondent ces choix. | |
| 25 | 16 | |
| 26 | -Le répertoire contenant les photos peut ensuite être renommé `2026-09-11_Weekend_Deauville`, ou `2026-09-11-12_Weekend_Deauville` si les photos couvrent deux jours du weekend. | |
| 17 | +## Le cycle de vie d'une photo dans Régine | |
| 27 | 18 | |
| 28 | -## Démarrage | |
| 19 | +```mermaid | |
| 20 | +flowchart LR | |
| 21 | + CARD(["📷 Carte mémoire"]) | |
| 29 | 22 | |
| 30 | -Ce projet utilise [spec-kit](https://github.com/) pour piloter le développement avec Claude Code. | |
| 23 | + subgraph IMPORT["1 · Import — specs/001"] | |
| 24 | + direction TB | |
| 25 | + COPY["Copie vérifiée<br/>(une seule lecture de la carte)"] | |
| 26 | + SPLIT["Regroupement<br/>jour par jour"] | |
| 27 | + NAME["Nommage lisible<br/>AAAA-MM-JJ_Titre_nomOrigine"] | |
| 28 | + COPY --> SPLIT --> NAME | |
| 29 | + end | |
| 31 | 30 | |
| 32 | -1. Se placer dans le dossier du projet : `cd regine-photos-archiver` | |
| 33 | -2. Démarrer Claude dans ce dossier — les skills spec-kit sont installés dans `.claude/skills` | |
| 34 | -3. Utiliser les skills avec l'agent de code : | |
| 35 | - 1. `/speckit-constitution` — établir les principes du projet | |
| 36 | - 2. `/speckit-specify` — créer la spécification de base | |
| 37 | - 3. `/speckit-plan` — créer le plan d'implémentation | |
| 38 | - 4. `/speckit-tasks` — générer les tâches concrètes | |
| 39 | - 5. `/speckit-implement` — exécuter l'implémentation | |
| 40 | - 6. `/speckit-converge` — évaluer le code existant et ajouter les tâches manquantes | |
| 31 | + subgraph ARCHIVE["🗄️ Archive · NAS"] | |
| 32 | + DOSSIER["Dossier immuable<br/>raw/ · jpeg/ · tiff/ · racine de sélection"] | |
| 33 | + end | |
| 41 | 34 | |
| 42 | -### Skills complémentaires | |
| 35 | + subgraph LOCAL["💻 Espace de travail local"] | |
| 36 | + direction TB | |
| 37 | + OUT["Checkout<br/>specs/005"] | |
| 38 | + EDIT["Tri & retouche<br/>(DxO, Lightroom, votre outil…)"] | |
| 39 | + RECON["Réconciliation<br/>par hash, avant tout réarchivage"] | |
| 40 | + OUT --> EDIT --> RECON | |
| 41 | + end | |
| 42 | + | |
| 43 | + CARD --> COPY | |
| 44 | + NAME -->|premier archivage| DOSSIER | |
| 45 | + DOSSIER -->|sort une copie de travail| OUT | |
| 46 | + RECON -->|réarchivage vérifié, jamais silencieux| DOSSIER | |
| 47 | +``` | |
| 48 | + | |
| 49 | +Deux garanties structurent tout ce cycle : | |
| 50 | + | |
| 51 | +- **Le fichier maître (RAW, TIFF de scan, ou JPEG seul) n'est jamais modifié dans l'archive.** Vos retouches vivent dans des sidecars (`.xmp`, `.dop`) ou, pour le DNG, dans des métadonnées séparées des pixels — jamais dans les données image elles-mêmes. | |
| 52 | +- **Rien n'est écrit sur l'archive sans un « point avant archive »** : la liste des changements détectés (normal, anomalie, renommage, suppression, nouveau fichier), présentée et validée explicitement avant toute écriture sur le NAS. | |
| 53 | + | |
| 54 | +## Un import, en 30 secondes | |
| 55 | + | |
| 56 | +Prenons des photos prises avec un Fuji X70 le weekend du 11 septembre 2026, à Deauville : | |
| 57 | + | |
| 58 | +| Sur la carte | Dans l'archive | | |
| 59 | +| ---------------- | ---------------------------------------------- | | |
| 60 | +| `R0018279.JPG` | `2026-09-11_Weekend_Deauville_R0018279.JPG` | | |
| 61 | +| `R0018279.RAF` | `2026-09-11_Weekend_Deauville_R0018279.RAF` | | |
| 62 | + | |
| 63 | +| Élément | Origine | | |
| 64 | +| --------------------- | ------------------------------------------------------------------------------ | | |
| 65 | +| `2026-09-11` | Date de prise de vue, lue dans les métadonnées EXIF — jamais la date du fichier | | |
| 66 | +| `Weekend_Deauville` | Titre donné par l'utilisateur au moment de l'import | | |
| 67 | +| `R0018279` | Référence d'origine du boîtier, conservée pour garder l'ordre des prises de vue | | |
| 68 | + | |
| 69 | +Le nom de fichier reste lisible et traçable **même ouvert dans dix ans, hors de Régine**. Deux boîtiers différents produisant par coïncidence le même nom d'origine ? Régine les désambiguïse automatiquement par le tag EXIF du modèle d'appareil, sans configuration préalable requise. | |
| 70 | + | |
| 71 | +## Ce que Régine garantit | |
| 72 | + | |
| 73 | +Cinq principes non négociables, posés dans la [constitution du projet](.specify/memory/constitution.md) : | |
| 74 | + | |
| 75 | +| Principe | En pratique | | |
| 76 | +| --- | --- | | |
| 77 | +| 🔒 **Fichier maître intouchable** | RAW, TIFF de scan, JPEG seul ou jumeau RAW+JPEG : jamais modifié une fois archivé. Toute altération détectée est signalée, jamais réarchivée en silence. | | |
| 78 | +| ✋ **Confirmation explicite avant toute action destructive** | Aucune suppression automatique — anomalie ou déchet identifié à l'import, la décision finale revient toujours à vous. | | |
| 79 | +| 🔗 **Identité par contenu, jamais par nom de fichier seul** | Renommages, déplacements et doublons se détectent par hash SHA-256, jamais par chemin — un fichier reste identifiable même déplacé ou renommé. | | |
| 80 | +| 🌍 **Métadonnées ouvertes et embarquées** | IPTC/XMP/EXIF dans le fichier lui-même, jamais dans une base propriétaire séparée qui ne survivrait pas à un changement d'outil. | | |
| 81 | +| 💡 **L'utilisateur décide, Régine suggère** | Découpage d'un import, détachement d'un jour particulier, désambiguïsation de boîtiers : toujours proposé, jamais imposé d'autorité. | | |
| 82 | + | |
| 83 | +## Vocabulaire essentiel | |
| 84 | + | |
| 85 | +| Terme | Ce que c'est | | |
| 86 | +| --- | --- | | |
| 87 | +| **dossier** | Unité créée à l'import d'une carte mémoire : structure par format (`raw/`, `jpeg/`...) + racine de sélection. L'unité de checkout, de réconciliation et de verrouillage. | | |
| 88 | +| **sous-dossier** | Une étape d'un dossier multi-parties (ex. une ville d'un voyage). Ne se checkout jamais isolément — toujours via son dossier parent. | | |
| 89 | +| **dossier parent** | Regroupe plusieurs sous-dossiers, avec sa propre racine servant de planche-contact globale sur l'ensemble (ex. les meilleures photos de tout le voyage). | | |
| 90 | +| **projet** | Sélection composée par **copie** depuis un ou plusieurs dossiers de l'archive (livre, expo) — en aval, indépendant de la hiérarchie d'archivage. | | |
| 91 | +| **répertoire racine (archive)** | Premier niveau sous l'archive : une année (`2026/`) par défaut, ou une catégorie thématique (`voyage/`, `mariage/`...) si le dossier en relève. | | |
| 92 | + | |
| 93 | +Glossaire complet : [`docs/lexique.md`](docs/lexique.md). | |
| 94 | + | |
| 95 | +## Tour des fonctionnalités | |
| 96 | + | |
| 97 | +| Module | Ce qu'il fait | Spec | Statut | | |
| 98 | +| --- | --- | --- | --- | | |
| 99 | +| **Import carte mémoire** | Copie vérifiée en une seule lecture, regroupement jour par jour, nommage lisible, désambiguïsation automatique de boîtiers | [`specs/001`](specs/001-import-photos) | ✅ Implémenté | | |
| 100 | +| **Profil de boîtiers** | Désambiguïsation multi-appareils par tag EXIF `Model`, en repli sur `BodySerialNumber` ou étiquetage manuel — optionnel, jamais un prérequis | [`specs/002`](specs/002-profil-boitiers-optionnel) | ✅ Implémenté | | |
| 101 | +| **Catégorisation des dossiers** | Placement à la racine par année ou par catégorie thématique extensible (voyage, mariage, vacances...) | [`specs/004`](specs/004-categorisation-dossiers) | ✅ Implémenté | | |
| 102 | +| **Checkout / réconciliation** | Aller-retour sécurisé archive ↔ espace de travail local, manifeste persistant par dossier, classification des changements par hash | [`specs/005`](specs/005-checkout-reconciliation) | ✅ Implémenté | | |
| 103 | +| **Configuration du contexte de travail** | Chemins (temp, local, NAS/SMB), aide au montage, base de travail centralisée | [`specs/003`](specs/003-config-contexte-travail) | 🚧 Spécifiée, implémentation à venir | | |
| 104 | +| **Vérification périodique (scrub)** | Détection de corruption silencieuse (bit rot) indépendamment de tout checkout | [constitution](.specify/memory/constitution.md) | 📝 Prévue | | |
| 105 | +| **Interface graphique** | Tri/culling sur un dossier checké out, consultation en lecture seule de l'archive | [`docs/interface-cli-gui-architecture.md`](docs/interface-cli-gui-architecture.md) | 📝 Prévue | | |
| 106 | +| **Agent IA** | Façade conversationnelle au-dessus de la même bibliothèque centrale | [`docs/interface-agent-ia.md`](docs/interface-agent-ia.md) | 📝 Prévue | | |
| 107 | + | |
| 108 | +## Installation | |
| 109 | + | |
| 110 | +Prérequis : [uv](https://docs.astral.sh/uv/), [ExifTool](https://exiftool.org/) (lecture/écriture des métadonnées). | |
| 111 | + | |
| 112 | +```bash | |
| 113 | +git clone https://github.com/regine-photo/regine-photo.git | |
| 114 | +cd regine-photo | |
| 115 | +uv sync | |
| 116 | +uv run pytest packages/regine-core/tests/ | |
| 117 | +``` | |
| 118 | + | |
| 119 | +## Utiliser Régine | |
| 120 | + | |
| 121 | +> La bibliothèque (`regine-core`) est stable et testée ; la façade CLI (`regine-cli`) s'invoque aujourd'hui module par module (`python -m`), en attendant une commande unifiée `regine` (cf. [Feuille de route](#-feuille-de-route)). Tous les exemples ci-dessous sont exécutables tels quels depuis la racine du dépôt. | |
| 122 | + | |
| 123 | +### Import simple d'une carte mémoire | |
| 43 | 124 | |
| 44 | -Skills optionnels pour améliorer la qualité et la fiabilité des specs : | |
| 125 | +```bash | |
| 126 | +uv run python -m regine_cli.import_cmd import /Volumes/CARTE_SD \ | |
| 127 | + --titre "Sortie parc" --annee --yes \ | |
| 128 | + --archive-root /Volumes/NAS/photos --local-root ~/regine/local | |
| 129 | +``` | |
| 130 | + | |
| 131 | +Régine copie chaque fichier en une seule lecture de la carte (vérification par checksum), détecte la plage de dates, et archive sous `<archive>/2026/2026-08-15_Sortie_parc/`. | |
| 132 | + | |
| 133 | +### Un voyage en plusieurs étapes | |
| 134 | + | |
| 135 | +```bash | |
| 136 | +# Première étape : crée le dossier parent (catégorie "voyage") + sa première étape | |
| 137 | +uv run python -m regine_cli.import_cmd import /Volumes/CARTE_ETAPE1 \ | |
| 138 | + --titre "Montenegro" --categorie voyage --destination parent \ | |
| 139 | + --archive-root /Volumes/NAS/photos --local-root ~/regine/local | |
| 140 | + | |
| 141 | +# Étape suivante : nouveau sous-dossier du même parent, catégorie héritée automatiquement | |
| 142 | +uv run python -m regine_cli.import_cmd import /Volumes/CARTE_ETAPE2 \ | |
| 143 | + --titre "Kotor" --destination sous-dossier:voyage/2026-08_Montenegro \ | |
| 144 | + --archive-root /Volumes/NAS/photos --local-root ~/regine/local | |
| 145 | +``` | |
| 146 | + | |
| 147 | +Résultat : `voyage/2026-08_Montenegro/2026-08-12_Kotor/`, imbriqué sous le dossier parent — dont la racine sert de planche-contact sur l'ensemble du voyage. | |
| 148 | + | |
| 149 | +### Éditer un dossier déjà archivé, en sécurité | |
| 150 | + | |
| 151 | +```bash | |
| 152 | +# Checkout : sort une copie de travail locale, avec verrou côté archive | |
| 153 | +uv run python -m regine_cli.archive_cmd checkout \ | |
| 154 | + /Volumes/NAS/photos/voyage/2026-08_Montenegro/2026-08-12_Kotor \ | |
| 155 | + --local-dest ~/regine/local/2026-08-12_Kotor | |
| 156 | + | |
| 157 | +# ... tri et retouche libres dans DxO, Lightroom, ou l'outil de votre choix ... | |
| 158 | + | |
| 159 | +# Réconciliation : classe chaque changement par hash, affiche le "point avant archive" | |
| 160 | +# et demande confirmation avant toute écriture sur le NAS | |
| 161 | +uv run python -m regine_cli.archive_cmd reconcile \ | |
| 162 | + /Volumes/NAS/photos/voyage/2026-08_Montenegro/2026-08-12_Kotor \ | |
| 163 | + --local-dest ~/regine/local/2026-08-12_Kotor | |
| 164 | +``` | |
| 165 | + | |
| 166 | +## Architecture du monorepo | |
| 167 | + | |
| 168 | +Une bibliothèque centrale porte toute la logique métier ; chaque interface (CLI aujourd'hui, GUI et agent IA demain) n'est qu'une façade fine au-dessus, sans logique dupliquée — Principe VI de la constitution. | |
| 169 | + | |
| 170 | +```mermaid | |
| 171 | +flowchart TB | |
| 172 | + subgraph FACADES [" Façades minces — aucune logique métier "] | |
| 173 | + direction LR | |
| 174 | + CLI["📟 regine-cli<br/>✅ implémentée"] | |
| 175 | + GUI["🖥️ regine-gui<br/>📝 réservée"] | |
| 176 | + AGENT["🤖 regine-agent<br/>📝 réservée"] | |
| 177 | + end | |
| 178 | + | |
| 179 | + CORE["📚 regine-core — bibliothèque centrale<br/>metadata · config · dossier · camera_profile<br/>integrity · archive · import_carte"] | |
| 180 | + | |
| 181 | + CLI --> CORE | |
| 182 | + GUI --> CORE | |
| 183 | + AGENT --> CORE | |
| 184 | +``` | |
| 185 | + | |
| 186 | +``` | |
| 187 | +regine-photos-archiver/ | |
| 188 | +├── packages/ | |
| 189 | +│ ├── regine-core/ # toute la logique métier — testée, sans dépendance aux façades | |
| 190 | +│ ├── regine-cli/ # façade CLI (regine import, regine checkout, regine reconcile) | |
| 191 | +│ ├── regine-gui/ # façade graphique — réservée | |
| 192 | +│ └── regine-agent/ # façade agent IA — réservée | |
| 193 | +├── docs/ # notes de conception (source de vérité du domaine) | |
| 194 | +└── specs/ # spécifications Spec-Kit, une par fonctionnalité | |
| 195 | +``` | |
| 196 | + | |
| 197 | +## 🗺 Feuille de route | |
| 198 | + | |
| 199 | +- [ ] Module de configuration complet (`specs/003`) : montage SMB, base de travail centralisée | |
| 200 | +- [ ] Commande unifiée `regine` (un seul point d'entrée CLI packagé) | |
| 201 | +- [ ] Vérification périodique de l'archive (scrub, indépendante du checkout) | |
| 202 | +- [ ] Interface graphique (tri/culling + consultation en lecture seule) | |
| 203 | +- [ ] Planche-contact JPEG annotée (export statique, indépendant de la GUI) | |
| 204 | +- [ ] Agent IA conversationnel | |
| 205 | + | |
| 206 | +## Développement piloté par les specs | |
| 207 | + | |
| 208 | +Ce projet est construit avec [Spec-Kit](https://github.com/github/spec-kit) : chaque fonctionnalité part d'une spécification validée avant d'être planifiée, découpée en tâches, puis implémentée — jamais l'inverse. Les skills sont installés dans `.claude/skills` et s'utilisent avec Claude Code : | |
| 209 | + | |
| 210 | +1. `/speckit-constitution` — établir les principes du projet | |
| 211 | +2. `/speckit-specify` — créer la spécification d'une fonctionnalité | |
| 212 | +3. `/speckit-plan` — créer le plan d'implémentation | |
| 213 | +4. `/speckit-tasks` — générer les tâches concrètes | |
| 214 | +5. `/speckit-implement` — exécuter l'implémentation | |
| 215 | +6. `/speckit-converge` — évaluer le code existant et combler les tâches manquantes | |
| 216 | + | |
| 217 | +### Skills complémentaires | |
| 45 | 218 | |
| 46 | 219 | | Skill | Rôle | |
| 47 | 220 | | ----- | ---- | |
| 48 | -| `/speckit-clarify` | Pose des questions structurées pour lever les ambiguïtés avant la planification (à lancer avant `/speckit-plan`) | | |
| 221 | +| `/speckit-clarify` | Pose des questions structurées pour lever les ambiguïtés avant la planification (avant `/speckit-plan`) | | |
| 49 | 222 | | `/speckit-analyze` | Rapport de cohérence et d'alignement entre les artefacts (après `/speckit-tasks`, avant `/speckit-implement`) | |
| 50 | 223 | | `/speckit-checklist` | Génère des checklists qualité pour valider la complétude et la clarté des exigences (après `/speckit-plan`) | |
| @@ -1,50 +1,223 @@ | |||
| 1 | -# Regine Photo Archiver | 1 | +# 📸 Régine |
| 2 | 2 | ||
| 3 | -Regine est une application qui aide à préparer l'archivage de photos RAW + JPEG. | 3 | +**L'archiviste qui protège vos photos comme un musée protège ses négatifs.** |
| 4 | 4 | ||
| 5 | -Elle prend beaucoup de photos et a besoin de pouvoir retrouver facilement une photo, ou retrouver l'origine d'une photo pour la revoir dans son contexte. Pour cela, les photos doivent avoir un nom de fichier unifié qui indique : | 5 | +Régine range, nomme et sécurise vos photos RAW + JPEG selon les pratiques des grandes collections professionnelles (Magnum Photos, ICP, Getty, archives nationales) — appliquées à votre NAS personnel. Vous continuez à trier et retoucher avec l'outil de votre choix (DxO, Lightroom...) ; Régine s'occupe du reste : import depuis la carte mémoire, nommage lisible, structure de dossiers cohérente, et un aller-retour sécurisé entre votre archive et votre espace de travail qui garantit qu'**un fichier maître n'est jamais modifié ni perdu sans confirmation explicite**. |
| 6 | 6 | ||
| 7 | -- la **date de prise de vue** | 7 | +CLI-first aujourd'hui, avec une interface graphique et un agent IA prévus comme façades sur la même bibliothèque — cf. [Feuille de route](#-feuille-de-route). |
| 8 | -- le **contexte** (thème donné par l'utilisateur) | ||
| 9 | -- le **nom original du fichier**, conservé pour préserver l'ordre de prise de vue | ||
| 10 | 8 | ||
| 11 | -## Exemple | 9 | +--- |
| 12 | 10 | ||
| 13 | -Photos prises par un Fuji X70 lors du weekend du 11 septembre 2026 à Deauville, stockées dans le répertoire `2026-09-11` : | 11 | +## Pourquoi Régine ? |
| 14 | 12 | ||
| 15 | -| Avant | Après | | 13 | +Après quelques années de prises de vue régulières, la plupart des photothèques personnelles finissent dans le même état : des dossiers `IMG_2024`, `Export_final_v2`, `Untitled Folder` ; des RAW et des JPEG mélangés sans lien visible ; aucune certitude sur ce qui a déjà été trié, sauvegardé, ou modifié par erreur. |
| 16 | -| --------------- | ------------------------------------------ | | ||
| 17 | -| `R0018279.JPG` | `2026-09-11_Weekend_Deauville_R0018279.JPG` | | ||
| 18 | -| `R0018279.RAF` | `2026-09-11_Weekend_Deauville_R0018279.RAF` | | ||
| 19 | 14 | ||
| 20 | -| Élément | Origine | | 15 | +Régine part des principes qu'utilisent les collections professionnelles — organisation dès la source, métadonnées embarquées, identité par contenu plutôt que par nom de fichier, jamais d'écrasement silencieux — et les rend accessibles à un·e photographe seul·e, sans infrastructure d'archives. Voir [`docs/archivage-photo-elements-cles.md`](docs/archivage-photo-elements-cles.md) pour les notes de recherche complètes qui fondent ces choix. |
| 21 | -| ------------------ | ------------------------------------------------------------- | | ||
| 22 | -| `2026-09-11` | Date de prise de vue, lue dans les métadonnées EXIF du fichier | | ||
| 23 | -| `Weekend_Deauville` | Thème donné par l'utilisateur | | ||
| 24 | -| `R0018279` | Référence générée par le boîtier photo, conservée pour l'ordre des photos dans le répertoire | | ||
| 25 | 16 | ||
| 26 | -Le répertoire contenant les photos peut ensuite être renommé `2026-09-11_Weekend_Deauville`, ou `2026-09-11-12_Weekend_Deauville` si les photos couvrent deux jours du weekend. | 17 | +## Le cycle de vie d'une photo dans Régine |
| 27 | 18 | ||
| 28 | -## Démarrage | 19 | +```mermaid |
| 20 | +flowchart LR | ||
| 21 | + CARD(["📷 Carte mémoire"]) | ||
| 29 | 22 | ||
| 30 | -Ce projet utilise [spec-kit](https://github.com/) pour piloter le développement avec Claude Code. | 23 | + subgraph IMPORT["1 · Import — specs/001"] |
| 24 | + direction TB | ||
| 25 | + COPY["Copie vérifiée<br/>(une seule lecture de la carte)"] | ||
| 26 | + SPLIT["Regroupement<br/>jour par jour"] | ||
| 27 | + NAME["Nommage lisible<br/>AAAA-MM-JJ_Titre_nomOrigine"] | ||
| 28 | + COPY --> SPLIT --> NAME | ||
| 29 | + end | ||
| 31 | 30 | ||
| 32 | -1. Se placer dans le dossier du projet : `cd regine-photos-archiver` | 31 | + subgraph ARCHIVE["🗄️ Archive · NAS"] |
| 33 | -2. Démarrer Claude dans ce dossier — les skills spec-kit sont installés dans `.claude/skills` | 32 | + DOSSIER["Dossier immuable<br/>raw/ · jpeg/ · tiff/ · racine de sélection"] |
| 34 | -3. Utiliser les skills avec l'agent de code : | 33 | + end |
| 35 | - 1. `/speckit-constitution` — établir les principes du projet | ||
| 36 | - 2. `/speckit-specify` — créer la spécification de base | ||
| 37 | - 3. `/speckit-plan` — créer le plan d'implémentation | ||
| 38 | - 4. `/speckit-tasks` — générer les tâches concrètes | ||
| 39 | - 5. `/speckit-implement` — exécuter l'implémentation | ||
| 40 | - 6. `/speckit-converge` — évaluer le code existant et ajouter les tâches manquantes | ||
| 41 | 34 | ||
| 42 | -### Skills complémentaires | 35 | + subgraph LOCAL["💻 Espace de travail local"] |
| 36 | + direction TB | ||
| 37 | + OUT["Checkout<br/>specs/005"] | ||
| 38 | + EDIT["Tri & retouche<br/>(DxO, Lightroom, votre outil…)"] | ||
| 39 | + RECON["Réconciliation<br/>par hash, avant tout réarchivage"] | ||
| 40 | + OUT --> EDIT --> RECON | ||
| 41 | + end | ||
| 42 | + | ||
| 43 | + CARD --> COPY | ||
| 44 | + NAME -->|premier archivage| DOSSIER | ||
| 45 | + DOSSIER -->|sort une copie de travail| OUT | ||
| 46 | + RECON -->|réarchivage vérifié, jamais silencieux| DOSSIER | ||
| 47 | +``` | ||
| 48 | + | ||
| 49 | +Deux garanties structurent tout ce cycle : | ||
| 50 | + | ||
| 51 | +- **Le fichier maître (RAW, TIFF de scan, ou JPEG seul) n'est jamais modifié dans l'archive.** Vos retouches vivent dans des sidecars (`.xmp`, `.dop`) ou, pour le DNG, dans des métadonnées séparées des pixels — jamais dans les données image elles-mêmes. | ||
| 52 | +- **Rien n'est écrit sur l'archive sans un « point avant archive »** : la liste des changements détectés (normal, anomalie, renommage, suppression, nouveau fichier), présentée et validée explicitement avant toute écriture sur le NAS. | ||
| 53 | + | ||
| 54 | +## Un import, en 30 secondes | ||
| 55 | + | ||
| 56 | +Prenons des photos prises avec un Fuji X70 le weekend du 11 septembre 2026, à Deauville : | ||
| 57 | + | ||
| 58 | +| Sur la carte | Dans l'archive | | ||
| 59 | +| ---------------- | ---------------------------------------------- | | ||
| 60 | +| `R0018279.JPG` | `2026-09-11_Weekend_Deauville_R0018279.JPG` | | ||
| 61 | +| `R0018279.RAF` | `2026-09-11_Weekend_Deauville_R0018279.RAF` | | ||
| 62 | + | ||
| 63 | +| Élément | Origine | | ||
| 64 | +| --------------------- | ------------------------------------------------------------------------------ | | ||
| 65 | +| `2026-09-11` | Date de prise de vue, lue dans les métadonnées EXIF — jamais la date du fichier | | ||
| 66 | +| `Weekend_Deauville` | Titre donné par l'utilisateur au moment de l'import | | ||
| 67 | +| `R0018279` | Référence d'origine du boîtier, conservée pour garder l'ordre des prises de vue | | ||
| 68 | + | ||
| 69 | +Le nom de fichier reste lisible et traçable **même ouvert dans dix ans, hors de Régine**. Deux boîtiers différents produisant par coïncidence le même nom d'origine ? Régine les désambiguïse automatiquement par le tag EXIF du modèle d'appareil, sans configuration préalable requise. | ||
| 70 | + | ||
| 71 | +## Ce que Régine garantit | ||
| 72 | + | ||
| 73 | +Cinq principes non négociables, posés dans la [constitution du projet](.specify/memory/constitution.md) : | ||
| 74 | + | ||
| 75 | +| Principe | En pratique | | ||
| 76 | +| --- | --- | | ||
| 77 | +| 🔒 **Fichier maître intouchable** | RAW, TIFF de scan, JPEG seul ou jumeau RAW+JPEG : jamais modifié une fois archivé. Toute altération détectée est signalée, jamais réarchivée en silence. | | ||
| 78 | +| ✋ **Confirmation explicite avant toute action destructive** | Aucune suppression automatique — anomalie ou déchet identifié à l'import, la décision finale revient toujours à vous. | | ||
| 79 | +| 🔗 **Identité par contenu, jamais par nom de fichier seul** | Renommages, déplacements et doublons se détectent par hash SHA-256, jamais par chemin — un fichier reste identifiable même déplacé ou renommé. | | ||
| 80 | +| 🌍 **Métadonnées ouvertes et embarquées** | IPTC/XMP/EXIF dans le fichier lui-même, jamais dans une base propriétaire séparée qui ne survivrait pas à un changement d'outil. | | ||
| 81 | +| 💡 **L'utilisateur décide, Régine suggère** | Découpage d'un import, détachement d'un jour particulier, désambiguïsation de boîtiers : toujours proposé, jamais imposé d'autorité. | | ||
| 82 | + | ||
| 83 | +## Vocabulaire essentiel | ||
| 84 | + | ||
| 85 | +| Terme | Ce que c'est | | ||
| 86 | +| --- | --- | | ||
| 87 | +| **dossier** | Unité créée à l'import d'une carte mémoire : structure par format (`raw/`, `jpeg/`...) + racine de sélection. L'unité de checkout, de réconciliation et de verrouillage. | | ||
| 88 | +| **sous-dossier** | Une étape d'un dossier multi-parties (ex. une ville d'un voyage). Ne se checkout jamais isolément — toujours via son dossier parent. | | ||
| 89 | +| **dossier parent** | Regroupe plusieurs sous-dossiers, avec sa propre racine servant de planche-contact globale sur l'ensemble (ex. les meilleures photos de tout le voyage). | | ||
| 90 | +| **projet** | Sélection composée par **copie** depuis un ou plusieurs dossiers de l'archive (livre, expo) — en aval, indépendant de la hiérarchie d'archivage. | | ||
| 91 | +| **répertoire racine (archive)** | Premier niveau sous l'archive : une année (`2026/`) par défaut, ou une catégorie thématique (`voyage/`, `mariage/`...) si le dossier en relève. | | ||
| 92 | + | ||
| 93 | +Glossaire complet : [`docs/lexique.md`](docs/lexique.md). | ||
| 94 | + | ||
| 95 | +## Tour des fonctionnalités | ||
| 96 | + | ||
| 97 | +| Module | Ce qu'il fait | Spec | Statut | | ||
| 98 | +| --- | --- | --- | --- | | ||
| 99 | +| **Import carte mémoire** | Copie vérifiée en une seule lecture, regroupement jour par jour, nommage lisible, désambiguïsation automatique de boîtiers | [`specs/001`](specs/001-import-photos) | ✅ Implémenté | | ||
| 100 | +| **Profil de boîtiers** | Désambiguïsation multi-appareils par tag EXIF `Model`, en repli sur `BodySerialNumber` ou étiquetage manuel — optionnel, jamais un prérequis | [`specs/002`](specs/002-profil-boitiers-optionnel) | ✅ Implémenté | | ||
| 101 | +| **Catégorisation des dossiers** | Placement à la racine par année ou par catégorie thématique extensible (voyage, mariage, vacances...) | [`specs/004`](specs/004-categorisation-dossiers) | ✅ Implémenté | | ||
| 102 | +| **Checkout / réconciliation** | Aller-retour sécurisé archive ↔ espace de travail local, manifeste persistant par dossier, classification des changements par hash | [`specs/005`](specs/005-checkout-reconciliation) | ✅ Implémenté | | ||
| 103 | +| **Configuration du contexte de travail** | Chemins (temp, local, NAS/SMB), aide au montage, base de travail centralisée | [`specs/003`](specs/003-config-contexte-travail) | 🚧 Spécifiée, implémentation à venir | | ||
| 104 | +| **Vérification périodique (scrub)** | Détection de corruption silencieuse (bit rot) indépendamment de tout checkout | [constitution](.specify/memory/constitution.md) | 📝 Prévue | | ||
| 105 | +| **Interface graphique** | Tri/culling sur un dossier checké out, consultation en lecture seule de l'archive | [`docs/interface-cli-gui-architecture.md`](docs/interface-cli-gui-architecture.md) | 📝 Prévue | | ||
| 106 | +| **Agent IA** | Façade conversationnelle au-dessus de la même bibliothèque centrale | [`docs/interface-agent-ia.md`](docs/interface-agent-ia.md) | 📝 Prévue | | ||
| 107 | + | ||
| 108 | +## Installation | ||
| 109 | + | ||
| 110 | +Prérequis : [uv](https://docs.astral.sh/uv/), [ExifTool](https://exiftool.org/) (lecture/écriture des métadonnées). | ||
| 111 | + | ||
| 112 | +```bash | ||
| 113 | +git clone https://github.com/regine-photo/regine-photo.git | ||
| 114 | +cd regine-photo | ||
| 115 | +uv sync | ||
| 116 | +uv run pytest packages/regine-core/tests/ | ||
| 117 | +``` | ||
| 118 | + | ||
| 119 | +## Utiliser Régine | ||
| 120 | + | ||
| 121 | +> La bibliothèque (`regine-core`) est stable et testée ; la façade CLI (`regine-cli`) s'invoque aujourd'hui module par module (`python -m`), en attendant une commande unifiée `regine` (cf. [Feuille de route](#-feuille-de-route)). Tous les exemples ci-dessous sont exécutables tels quels depuis la racine du dépôt. | ||
| 122 | + | ||
| 123 | +### Import simple d'une carte mémoire | ||
| 43 | 124 | ||
| 44 | -Skills optionnels pour améliorer la qualité et la fiabilité des specs : | 125 | +```bash |
| 126 | +uv run python -m regine_cli.import_cmd import /Volumes/CARTE_SD \ | ||
| 127 | + --titre "Sortie parc" --annee --yes \ | ||
| 128 | + --archive-root /Volumes/NAS/photos --local-root ~/regine/local | ||
| 129 | +``` | ||
| 130 | + | ||
| 131 | +Régine copie chaque fichier en une seule lecture de la carte (vérification par checksum), détecte la plage de dates, et archive sous `<archive>/2026/2026-08-15_Sortie_parc/`. | ||
| 132 | + | ||
| 133 | +### Un voyage en plusieurs étapes | ||
| 134 | + | ||
| 135 | +```bash | ||
| 136 | +# Première étape : crée le dossier parent (catégorie "voyage") + sa première étape | ||
| 137 | +uv run python -m regine_cli.import_cmd import /Volumes/CARTE_ETAPE1 \ | ||
| 138 | + --titre "Montenegro" --categorie voyage --destination parent \ | ||
| 139 | + --archive-root /Volumes/NAS/photos --local-root ~/regine/local | ||
| 140 | + | ||
| 141 | +# Étape suivante : nouveau sous-dossier du même parent, catégorie héritée automatiquement | ||
| 142 | +uv run python -m regine_cli.import_cmd import /Volumes/CARTE_ETAPE2 \ | ||
| 143 | + --titre "Kotor" --destination sous-dossier:voyage/2026-08_Montenegro \ | ||
| 144 | + --archive-root /Volumes/NAS/photos --local-root ~/regine/local | ||
| 145 | +``` | ||
| 146 | + | ||
| 147 | +Résultat : `voyage/2026-08_Montenegro/2026-08-12_Kotor/`, imbriqué sous le dossier parent — dont la racine sert de planche-contact sur l'ensemble du voyage. | ||
| 148 | + | ||
| 149 | +### Éditer un dossier déjà archivé, en sécurité | ||
| 150 | + | ||
| 151 | +```bash | ||
| 152 | +# Checkout : sort une copie de travail locale, avec verrou côté archive | ||
| 153 | +uv run python -m regine_cli.archive_cmd checkout \ | ||
| 154 | + /Volumes/NAS/photos/voyage/2026-08_Montenegro/2026-08-12_Kotor \ | ||
| 155 | + --local-dest ~/regine/local/2026-08-12_Kotor | ||
| 156 | + | ||
| 157 | +# ... tri et retouche libres dans DxO, Lightroom, ou l'outil de votre choix ... | ||
| 158 | + | ||
| 159 | +# Réconciliation : classe chaque changement par hash, affiche le "point avant archive" | ||
| 160 | +# et demande confirmation avant toute écriture sur le NAS | ||
| 161 | +uv run python -m regine_cli.archive_cmd reconcile \ | ||
| 162 | + /Volumes/NAS/photos/voyage/2026-08_Montenegro/2026-08-12_Kotor \ | ||
| 163 | + --local-dest ~/regine/local/2026-08-12_Kotor | ||
| 164 | +``` | ||
| 165 | + | ||
| 166 | +## Architecture du monorepo | ||
| 167 | + | ||
| 168 | +Une bibliothèque centrale porte toute la logique métier ; chaque interface (CLI aujourd'hui, GUI et agent IA demain) n'est qu'une façade fine au-dessus, sans logique dupliquée — Principe VI de la constitution. | ||
| 169 | + | ||
| 170 | +```mermaid | ||
| 171 | +flowchart TB | ||
| 172 | + subgraph FACADES [" Façades minces — aucune logique métier "] | ||
| 173 | + direction LR | ||
| 174 | + CLI["📟 regine-cli<br/>✅ implémentée"] | ||
| 175 | + GUI["🖥️ regine-gui<br/>📝 réservée"] | ||
| 176 | + AGENT["🤖 regine-agent<br/>📝 réservée"] | ||
| 177 | + end | ||
| 178 | + | ||
| 179 | + CORE["📚 regine-core — bibliothèque centrale<br/>metadata · config · dossier · camera_profile<br/>integrity · archive · import_carte"] | ||
| 180 | + | ||
| 181 | + CLI --> CORE | ||
| 182 | + GUI --> CORE | ||
| 183 | + AGENT --> CORE | ||
| 184 | +``` | ||
| 185 | + | ||
| 186 | +``` | ||
| 187 | +regine-photos-archiver/ | ||
| 188 | +├── packages/ | ||
| 189 | +│ ├── regine-core/ # toute la logique métier — testée, sans dépendance aux façades | ||
| 190 | +│ ├── regine-cli/ # façade CLI (regine import, regine checkout, regine reconcile) | ||
| 191 | +│ ├── regine-gui/ # façade graphique — réservée | ||
| 192 | +│ └── regine-agent/ # façade agent IA — réservée | ||
| 193 | +├── docs/ # notes de conception (source de vérité du domaine) | ||
| 194 | +└── specs/ # spécifications Spec-Kit, une par fonctionnalité | ||
| 195 | +``` | ||
| 196 | + | ||
| 197 | +## 🗺 Feuille de route | ||
| 198 | + | ||
| 199 | +- [ ] Module de configuration complet (`specs/003`) : montage SMB, base de travail centralisée | ||
| 200 | +- [ ] Commande unifiée `regine` (un seul point d'entrée CLI packagé) | ||
| 201 | +- [ ] Vérification périodique de l'archive (scrub, indépendante du checkout) | ||
| 202 | +- [ ] Interface graphique (tri/culling + consultation en lecture seule) | ||
| 203 | +- [ ] Planche-contact JPEG annotée (export statique, indépendant de la GUI) | ||
| 204 | +- [ ] Agent IA conversationnel | ||
| 205 | + | ||
| 206 | +## Développement piloté par les specs | ||
| 207 | + | ||
| 208 | +Ce projet est construit avec [Spec-Kit](https://github.com/github/spec-kit) : chaque fonctionnalité part d'une spécification validée avant d'être planifiée, découpée en tâches, puis implémentée — jamais l'inverse. Les skills sont installés dans `.claude/skills` et s'utilisent avec Claude Code : | ||
| 209 | + | ||
| 210 | +1. `/speckit-constitution` — établir les principes du projet | ||
| 211 | +2. `/speckit-specify` — créer la spécification d'une fonctionnalité | ||
| 212 | +3. `/speckit-plan` — créer le plan d'implémentation | ||
| 213 | +4. `/speckit-tasks` — générer les tâches concrètes | ||
| 214 | +5. `/speckit-implement` — exécuter l'implémentation | ||
| 215 | +6. `/speckit-converge` — évaluer le code existant et combler les tâches manquantes | ||
| 216 | + | ||
| 217 | +### Skills complémentaires | ||
| 45 | 218 | ||
| 46 | | Skill | Rôle | | 219 | | Skill | Rôle | |
| 47 | | ----- | ---- | | 220 | | ----- | ---- | |
| 48 | -| `/speckit-clarify` | Pose des questions structurées pour lever les ambiguïtés avant la planification (à lancer avant `/speckit-plan`) | | 221 | +| `/speckit-clarify` | Pose des questions structurées pour lever les ambiguïtés avant la planification (avant `/speckit-plan`) | |
| 49 | | `/speckit-analyze` | Rapport de cohérence et d'alignement entre les artefacts (après `/speckit-tasks`, avant `/speckit-implement`) | | 222 | | `/speckit-analyze` | Rapport de cohérence et d'alignement entre les artefacts (après `/speckit-tasks`, avant `/speckit-implement`) | |
| 50 | | `/speckit-checklist` | Génère des checklists qualité pour valider la complétude et la clarté des exigences (après `/speckit-plan`) | | 223 | | `/speckit-checklist` | Génère des checklists qualité pour valider la complétude et la clarté des exigences (après `/speckit-plan`) | |