Research: Importation de photos depuis une carte mémoire
1. Copie vérifiée sans seconde lecture de la carte
Decision: Copier chaque fichier par lecture en flux (chunks), en calculant une somme SHA-256 de la source au fil de la lecture (hashlib.sha256, mise à jour à chaque chunk lu depuis la carte puis écrit sur disque local) ; une fois la copie terminée, relire uniquement le fichier local (rapide) pour recalculer sa somme et la comparer à celle obtenue pendant le flux source.
Rationale: Répond exactement à FR-001 et à l'Edge Case "carte lente" déjà tranchés dans la spec : une seule lecture de la carte par fichier, la seconde vérification portant uniquement sur le disque local. Entièrement réalisable avec la bibliothèque standard (hashlib, lecture par blocs), cohérent avec la préférence du projet pour des dépendances minimales.
Alternatives considered:
- Copier puis relire la carte une seconde fois pour vérifier — rejeté explicitement par la spec (Edge Case, SC-001).
- Bibliothèque tierce de copie vérifiée — rejeté, la stdlib suffit pour un besoin aussi direct.
2. Lecture de la date de prise de vue
Decision: Étendre regine_core.metadata.exif (créé par specs/002-profil-boitiers-optionnel) avec read_capture_date(chemin) -> datetime | None, lisant le tag EXIF DateTimeOriginal via exiftool (même mécanisme que la lecture de Model/BodySerialNumber).
Rationale: Réutilise le module de lecture EXIF déjà décidé plutôt que d'introduire un second mécanisme ; cohérent avec le Principe VI (pas de logique dupliquée) et avec le choix déjà justifié de exiftool pour sa fiabilité sur les formats RAW propriétaires (specs/002-profil-boitiers-optionnel/research.md § 1).
Alternatives considered: aucune réellement — la décision de specs/002 s'applique directement ici, pas de nouveau choix technique à faire.
3. Identifiant pérenne : quel champ de métadonnées écrire
Decision: Réutiliser le champ XMP standard xmpMM:DocumentID (schéma XMP Media Management), en générant un UUID à l'import et en l'écrivant via exiftool une seule fois, à la création du fichier maître dans l'archive.
Rationale: Les notes de conception du projet (docs/archivage-photo-elements-cles.md section 3 et section 13) identifient déjà DocumentID/OriginalDocumentID/DerivedFrom (XMP Media Management) comme piste à privilégier avant de construire un champ maison, précisément pour ce besoin d'identifiant indépendant du nom de fichier. Utiliser directement ce standard répond au Principe IV (métadonnées ouvertes) sans attendre la vérification (non encore faite) de son renseignement automatique par DxO à l'export — cette vérification reste utile pour le besoin différent de traçabilité d'un export dérivé (section 13), mais n'est pas bloquante ici : Régine écrit elle-même ce champ à l'import, elle n'a pas besoin qu'un outil tiers le fasse à sa place pour cette fonctionnalité.
Alternatives considered:
- Champ XMP maison (ex.
regine:PermanentId) — rejeté : un standard existant couvre déjà ce besoin, l'utiliser évite d'imposer un vocabulaire propriétaire de plus dans les fichiers de l'utilisateur. - Stocker l'identifiant uniquement dans une base Régine, sans l'écrire dans le fichier — rejeté explicitement par FR-017 et par le Principe IV (métadonnées ouvertes et embarquées).
4. Recherche de dossiers candidats (FR-008)
Decision: Lister directement les dossiers présents sous la racine de l'espace de travail local et sous chaque répertoire racine de l'archive (année et catégories déjà connues, via regine_core.config.categories.list_known_categories), puis filtrer par proximité de titre (difflib.get_close_matches, même approche que specs/004-categorisation-dossiers) et de date. Pas d'index persistant construit pour ce besoin.
Rationale: Le volume de dossiers candidats pertinents pour une recherche à l'import (titre/date proches) reste faible en pratique ; un parcours direct des répertoires suffit et évite de construire par anticipation l'index inter-dossiers en lecture seule déjà identifié comme "travail futur" dans les notes de conception (section 12/13), qui répond à un besoin plus large (recherche globale dans toute l'archive) que celui, ciblé, de cette étape d'import.
Alternatives considered:
- Construire l'index inter-dossiers dès ce plan — rejeté : hors périmètre de cette spec, complexité non justifiée pour ce seul besoin (YAGNI, cohérent avec les décisions précédentes du projet).
5. Détection d'un jour "candidat au détachement" (FR-006)
Decision: Heuristique simple — un jour est mis en avant comme candidat si son nombre de photos s'écarte fortement de la médiane des autres jours de la plage (ex. facteur ×3) et qu'il est entouré d'un intervalle sans photo d'au moins un jour de part et d'autre. Reste une suggestion strictement indicative (FR-006), jamais un détachement automatique.
Rationale: FR-006 n'exige qu'une mise en avant plausible, pas une détection parfaite ; une heuristique simple et explicable (pas de dépendance à une bibliothèque de statistiques) suffit et reste cohérente avec le Principe V (Régine suggère, l'utilisateur décide) — une heuristique imparfaite est acceptable puisque la décision finale reste humaine.
Alternatives considered:
- Bibliothèque de détection d'anomalies (ex. détection de pics par écart-type glissant plus sophistiquée) — rejeté : complexité non justifiée pour une simple suggestion que l'utilisateur peut ignorer.
6. Fusion vers un dossier déjà archivé (FR-009)
Decision: Appeler regine_core.archive.checkout.checkout(dossier_cible, dest_locale) (specs/005-checkout-reconciliation) avant d'intégrer les nouveaux fichiers, puis suivre le cycle normal de réconciliation (regine_core.archive.reconciliation) pour réarchiver. Mise à jour du 2026-09-19 : ce mécanisme a désormais sa propre spec et son propre plan (specs/005-checkout-reconciliation) — ce sous-scénario n'est plus bloqué.
Rationale: Ce mécanisme est maintenant formalisé (manifeste persistant, verrouillage, réconciliation par hash) ; le réimplémenter ici dupliquerait une logique déjà spécifiée et planifiée ailleurs, contraire au Principe VI.
Alternatives considered:
- Implémenter un checkout minimal ad hoc dans ce module plutôt que de consommer
specs/005— rejeté : dupliquerait un mécanisme déjà spécifié, avec un risque de divergence de conception.
Résumé
Tous les points du Technical Context sont résolus. Aucune dépendance tierce Python nouvelle (exiftool déjà acté). Un sous-scénario (FR-009, fusion vers dossier déjà archivé) reste explicitement documenté comme bloqué plutôt que contourné.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
|