fonzarely/regine-photos-archiverpublic Fork
⑂ main
Commits
⬇ Clone ▾
git clone https://git.rickub.com/fonzarely/regine-photos-archiver.git
git clone ssh://git@rickub.com/fonzarely/regine-photos-archiver.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Download ZIP
plan all a196f68 · on main · Fabien Champigny · Sep 18, 2026
research.md · 36 lines · 4.3 KBmarkdown
Blame HistoryOpen raw

Research: Profil de boîtiers optionnel, déclaré à la demande

1. Lecture des tags EXIF Model et BodySerialNumber

Decision: Lire ces tags via le binaire externe exiftool, en processus persistant (exiftool -stay_open) plutôt qu'un lancement par fichier, à travers un wrapper léger regine_core/metadata/exif.py.

Rationale: Les notes de conception du projet (docs/archivage-photo-elements-cles.md sections 11 et 13) utilisent déjà exiftool pour toute lecture EXIF avancée sur ce projet (RawDataUniqueID, ImageDataHash, DocumentID/OriginalDocumentID) en raison de son support fiable des RAW propriétaires, que peu de bibliothèques Python pures gèrent correctement. Réutiliser le même outil pour Model/BodySerialNumber évite d'introduire un second mécanisme de lecture EXIF avec un comportement potentiellement différent selon le format. Le mode -stay_open évite le coût de démarrage d'un nouveau processus par fichier sur un import de plusieurs centaines de photos.

Alternatives considered:

  • Bibliothèque Python pure (piexif, exifread, Pillow.ExifTags) — rejeté : support inconsistant des formats RAW propriétaires (RAF, CR2, NEF, ARW...), alors que exiftool est déjà le choix retenu ailleurs dans le projet pour cette même raison.
  • Appel exiftool ponctuel par fichier (sans -stay_open) — rejeté : coût de démarrage du processus non négligeable multiplié par le nombre de fichiers d'un import typique.

2. Emplacement de la table boitiers et de la logique de résolution

Decision: Nouveau module regine_core/camera_profile/, propriétaire de la table boitiers (dans la base de contexte centralisée déjà actée par specs/003-config-contexte-travail) et de l'algorithme de résolution. Corrige un placement provisoire : specs/003-config-contexte-travail/plan.md avait prévu regine_core/config/cameras.py pour cette logique ; ce plan établit camera_profile comme propriétaire, config ne conservant que son écran de nommage proactif (User Story 3 de specs/003), qui appelle camera_profile plutôt que de posséder sa propre logique.

Rationale: docs/interface-cli-gui-architecture.md liste déjà camera_profile comme module de premier niveau distinct de la configuration des chemins de travail. Laisser deux specs (002 et 003) définir chacune leur propre table boitiers contredirait le Principe VI de la constitution (bibliothèque centrale, pas de logique métier dupliquée) et risquerait une divergence de schéma entre les deux.

Alternatives considered:

  • Conserver la table sous regine_core/config/ comme provisoirement planifié en specs/003 — rejeté pour la raison ci-dessus ; specs/003-config-contexte-travail/plan.md est corrigé en conséquence dans la foulée de ce plan.

3. Conception de l'algorithme de résolution

Decision: Fonction pure resolve_collision(files: list[FileWithTags]) -> CollisionResolution, qui prend en entrée un groupe de fichiers déjà identifié en collision (même nom d'origine, sommes de contrôle différentes — détection hors périmètre de ce module, fournie par l'appelant), et qui :

  1. Regroupe les fichiers par tag Model.
  2. Au sein d'un groupe de même modèle, tente de les distinguer par BodySerialNumber (quand présent et exploitable).
  3. Retourne, pour les fichiers encore indistincts après ces deux étapes, un groupe nécessitant un étiquetage manuel (FR-005), plutôt que de choisir arbitrairement.

Rationale: Séparer la détection de collision (par somme de contrôle, module import/integrity) de la désambiguïsation de source (par métadonnées, ce module) garde chaque responsabilité testable indépendamment — cohérent avec la découpe en fonctions pures déjà retenue pour specs/004-categorisation-dossiers.

Alternatives considered:

  • Fusionner détection de collision et résolution de source dans une seule fonction — rejeté : mélangerait deux responsabilités relevant de modules différents (checksum vs métadonnées EXIF).

Résumé

Tous les points du Technical Context sont résolus. Aucune dépendance tierce Python nouvelle ; exiftool est une dépendance externe déjà implicite du projet, pas une addition. Une correction de placement de module est propagée vers specs/003-config-contexte-travail/plan.md.

 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
# Research: Profil de boîtiers optionnel, déclaré à la demande

## 1. Lecture des tags EXIF `Model` et `BodySerialNumber`

**Decision**: Lire ces tags via le binaire externe `exiftool`, en processus persistant (`exiftool -stay_open`) plutôt qu'un lancement par fichier, à travers un wrapper léger `regine_core/metadata/exif.py`.

**Rationale**: Les notes de conception du projet (`docs/archivage-photo-elements-cles.md` sections 11 et 13) utilisent déjà `exiftool` pour toute lecture EXIF avancée sur ce projet (`RawDataUniqueID`, `ImageDataHash`, `DocumentID`/`OriginalDocumentID`) en raison de son support fiable des RAW propriétaires, que peu de bibliothèques Python pures gèrent correctement. Réutiliser le même outil pour `Model`/`BodySerialNumber` évite d'introduire un second mécanisme de lecture EXIF avec un comportement potentiellement différent selon le format. Le mode `-stay_open` évite le coût de démarrage d'un nouveau processus par fichier sur un import de plusieurs centaines de photos.

**Alternatives considered**:
- Bibliothèque Python pure (`piexif`, `exifread`, `Pillow.ExifTags`) — rejeté : support inconsistant des formats RAW propriétaires (RAF, CR2, NEF, ARW...), alors que `exiftool` est déjà le choix retenu ailleurs dans le projet pour cette même raison.
- Appel `exiftool` ponctuel par fichier (sans `-stay_open`) — rejeté : coût de démarrage du processus non négligeable multiplié par le nombre de fichiers d'un import typique.

## 2. Emplacement de la table `boitiers` et de la logique de résolution

**Decision**: Nouveau module `regine_core/camera_profile/`, propriétaire de la table `boitiers` (dans la base de contexte centralisée déjà actée par `specs/003-config-contexte-travail`) et de l'algorithme de résolution. **Corrige un placement provisoire** : `specs/003-config-contexte-travail/plan.md` avait prévu `regine_core/config/cameras.py` pour cette logique ; ce plan établit `camera_profile` comme propriétaire, `config` ne conservant que son écran de nommage proactif (User Story 3 de specs/003), qui appelle `camera_profile` plutôt que de posséder sa propre logique.

**Rationale**: `docs/interface-cli-gui-architecture.md` liste déjà `camera_profile` comme module de premier niveau distinct de la configuration des chemins de travail. Laisser deux specs (002 et 003) définir chacune leur propre table `boitiers` contredirait le Principe VI de la constitution (bibliothèque centrale, pas de logique métier dupliquée) et risquerait une divergence de schéma entre les deux.

**Alternatives considered**:
- Conserver la table sous `regine_core/config/` comme provisoirement planifié en specs/003 — rejeté pour la raison ci-dessus ; `specs/003-config-contexte-travail/plan.md` est corrigé en conséquence dans la foulée de ce plan.

## 3. Conception de l'algorithme de résolution

**Decision**: Fonction pure `resolve_collision(files: list[FileWithTags]) -> CollisionResolution`, qui prend en entrée un groupe de fichiers déjà identifié en collision (même nom d'origine, sommes de contrôle différentes — détection hors périmètre de ce module, fournie par l'appelant), et qui :
1. Regroupe les fichiers par tag `Model`.
2. Au sein d'un groupe de même modèle, tente de les distinguer par `BodySerialNumber` (quand présent et exploitable).
3. Retourne, pour les fichiers encore indistincts après ces deux étapes, un groupe nécessitant un étiquetage manuel (FR-005), plutôt que de choisir arbitrairement.

**Rationale**: Séparer la détection de collision (par somme de contrôle, module import/integrity) de la désambiguïsation de source (par métadonnées, ce module) garde chaque responsabilité testable indépendamment — cohérent avec la découpe en fonctions pures déjà retenue pour `specs/004-categorisation-dossiers`.

**Alternatives considered**:
- Fusionner détection de collision et résolution de source dans une seule fonction — rejeté : mélangerait deux responsabilités relevant de modules différents (checksum vs métadonnées EXIF).

## Résumé

Tous les points du Technical Context sont résolus. Aucune dépendance tierce Python nouvelle ; `exiftool` est une dépendance externe déjà implicite du projet, pas une addition. Une correction de placement de module est propagée vers `specs/003-config-contexte-travail/plan.md`.