Implementation Plan: Importation de photos depuis une carte mémoire
Branch: 001-import-photos | Date: 2026-09-18 | Spec: spec.md
Input: Feature specification from /specs/001-import-photos/spec.md
Summary
Pipeline complet depuis une carte mémoire jusqu'au premier archivage : copie vérifiée par somme de contrôle (une seule lecture de la carte), analyse des dates de prise de vue et découpage en groupes, choix de destination (dossier simple / sous-dossier / fusion / nouveau dossier parent, plus la catégorisation racine de specs/004-categorisation-dossiers), renommage synchronisé des fichiers maîtres et associés, désambiguïsation de boîtiers en cas de collision (specs/002-profil-boitiers-optionnel), attribution d'un identifiant pérenne, puis confirmation explicite et transfert vers l'archive. Approche technique : un nouveau module regine_core.import_carte, premier consommateur réel de regine_core.dossier.root (specs/004), regine_core.camera_profile (specs/002) et regine_core.metadata.exif, exposé via une première commande CLI concrète regine import dans regine-cli.
Technical Context
Language/Version: Python 3.11+ (cohérent avec regine-core, cf. specs/002, specs/003, specs/004)
Primary Dependencies: exiftool (déjà une dépendance actée par specs/002-profil-boitiers-optionnel pour regine_core.metadata.exif, étendu ici pour la lecture de la date de prise de vue et l'écriture de l'identifiant pérenne) ; bibliothèque standard uniquement sinon (hashlib pour les sommes de contrôle, pathlib/shutil pour la copie et le renommage, difflib pour la recherche de dossiers candidats par titre proche, réutilisant la même approche que specs/004-categorisation-dossiers)
Storage: ce module n'introduit aucune nouvelle base ; il consomme la base de contexte centralisée via regine_core.camera_profile (specs/002) et regine_core.config.categories/regine_core.dossier.root (specs/004). Le manifeste persistant par dossier (checksums, réconciliation) est désormais spécifié et planifié par specs/005-checkout-reconciliation (regine_core.archive/regine_core.integrity) ; ce module l'utilise pour FR-009 sans le redéfinir
Testing: pytest ; tests unitaires sur le découpage jour par jour et la détection de dates aberrantes, sur le renommage synchronisé, sur la construction du chemin final (délégué à specs/004) ; tests d'intégration sur le pipeline complet copie→analyse→destination→renommage→confirmation, en répertoires temporaires simulant carte/local/archive (aucune écriture réseau réelle)
Target Platform: poste de travail de bureau, identique aux autres modules de regine-core
Project Type: Monorepo existant (specs/002, specs/003, specs/004) — nouveau module regine_core/import_carte/ et première commande CLI concrète (regine import) dans regine-cli
Performance Goals: aucune lecture de la carte mémoire ne doit dépasser une seule passe par fichier (FR-001/Edge Case déjà tranché) ; pas d'autre cible chiffrée spécifique
Constraints: le sous-scénario de fusion vers un dossier déjà archivé sur le NAS (FR-009, Acceptance Scenario 4 de User Story 3) appelle regine_core.archive.checkout.checkout (specs/005-checkout-reconciliation) sur le dossier ciblé avant d'y intégrer les nouveaux fichiers ; ce plan consomme cette API sans la redéfinir
Scale/Scope: import typique de quelques dizaines à quelques milliers de fichiers par carte mémoire, usage mono-utilisateur
Constitution Check
GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.
| Principe / contrainte | Évaluation | Justification |
|---|---|---|
| I. Fichier maître intouchable | PASS | Un fichier maître n'est renommé qu'une seule fois, avant son premier archivage (FR-013) ; aucune modification après archivage n'est effectuée par ce module (la vérification d'anomalie ultérieure relève de specs/005-checkout-reconciliation, qui l'implémente désormais). |
| II. Confirmation explicite avant toute action à risque | PASS | FR-018 : résumé complet (fichiers, taille, dossier de destination, répertoire racine) présenté et confirmé avant toute écriture sur l'archive ; FR-012 : collision de nom traitée par suffixe ou confirmation, jamais écrasement silencieux. |
| III. Identité par contenu, jamais par nom de fichier seul | PASS | FR-004 : seuls les fichiers réellement nouveaux (par somme de contrôle) entrent dans l'analyse ; FR-015 : désambiguïsation de boîtiers déléguée à specs/002, elle-même fondée sur les métadonnées, jamais sur le seul nom de fichier. |
| IV. Métadonnées ouvertes et embarquées | PASS | FR-017 : l'identifiant pérenne est écrit dans les métadonnées XMP embarquées du fichier (réutilisation du champ standard xmpMM:DocumentID, cf. research.md § 3), pas dans une base séparée. |
| V. L'utilisateur décide, Régine suggère | PASS | FR-006 (candidat de détachement suggéré, jamais imposé), FR-011 (lieu GPS suggéré, jamais imposé), FR-007 (catégorie/année toujours une décision explicite, délégué à specs/004). |
| VI. Bibliothèque centrale, façades minces | PASS | Toute la logique vit dans regine_core.import_carte, qui consomme regine_core.dossier, regine_core.camera_profile et regine_core.metadata sans dupliquer leur logique ; regine-cli n'orchestre que l'appel et l'affichage. |
| CLI-first | PASS | regine import est la première façade construite pour ce pipeline, avant toute GUI. |
| Exécution sans démon | PASS | Le pipeline s'exécute intégralement dans le processus de la commande CLI, sans état en arrière-plan. |
| Formats ouverts et documentés | PASS | XMP pour l'identifiant pérenne ; aucune base propriétaire introduite. |
| Vérification d'intégrité systématique | PASS | FR-001 : vérification par somme de contrôle sur toute copie carte→local et sur le transfert local→archive (FR-019). |
Aucune violation identifiée ; la section Complexity Tracking reste vide.
Complexity Tracking
Aucune violation de gate à justifier — section laissée vide intentionnellement.
Re-check post Phase 1 (après génération de data-model.md, contracts/, quickstart.md) : le modèle de données (Groupe d'import, Destination, Renommage) et les contrats (CLI regine import, API interne regine_core.import_carte) confirment chaque évaluation ci-dessus. Le sous-scénario FR-009 est désormais implémentable via specs/005-checkout-reconciliation (cf. contracts/cli-import.md et quickstart.md, mis à jour en conséquence) — plus aucune dépendance manquante.
Project Structure
Documentation (this feature)
specs/001-import-photos/
├── plan.md # This file (/speckit-plan command output)
├── research.md # Phase 0 output (/speckit-plan command)
├── data-model.md # Phase 1 output (/speckit-plan command)
├── quickstart.md # Phase 1 output (/speckit-plan command)
├── contracts/ # Phase 1 output (/speckit-plan command)
│ ├── cli-import.md
│ └── regine-core-api.md
└── tasks.md # Phase 2 output (/speckit-tasks command - NOT created by /speckit-plan)
Source Code (repository root) — extension du monorepo posé par specs/002/003/004
packages/regine-core/
├── src/regine_core/
│ ├── metadata/
│ │ └── exif.py # (existant, specs/002) étendu : read_capture_date(), write_document_id()
│ └── import_carte/ # NOUVEAU module
│ ├── __init__.py
│ ├── copie.py # copie vérifiée carte→local, une seule lecture (FR-001), filtrage nouveaux fichiers (FR-004)
│ ├── groupage.py # répartition jour par jour, détection dates aberrantes, découpage en groupes (FR-002/003/005/006)
│ ├── destination.py # orchestration destination : simple/sous-dossier/fusion/parent + catégorie (FR-007/008/009), délègue à regine_core.dossier.root et, pour une fusion vers un dossier déjà archivé, à regine_core.archive.checkout (specs/005)
│ ├── nommage.py # construction titre/nom dossier, collision (FR-010/012), renommage synchronisé (FR-013/014)
│ ├── identifiant.py # génération + écriture identifiant pérenne (FR-017)
│ └── push.py # résumé + confirmation + transfert final (FR-018/019)
│
└── tests/
├── unit/
│ ├── test_copie_checksum.py # une seule lecture carte, échec de vérification, carte lente
│ ├── test_groupage_dates.py # découpage par défaut, détachement, dates aberrantes, fichiers déjà vus
│ ├── test_nommage.py # formats de nom, collision, renommage synchronisé fichiers associés
│ └── test_identifiant.py # génération, écriture XMP DocumentID
└── integration/
├── test_pipeline_import_simple.py # US1 : carte → dossier archivé, résumé confirmé
├── test_pipeline_multi_jours.py # US2 : détachement, groupes multiples
└── test_pipeline_voyage.py # US3 : dossier parent + sous-dossier + fusion locale ET fusion vers dossier archivé (via specs/005-checkout-reconciliation) + désambiguïsation boîtiers
packages/regine-cli/
└── src/regine_cli/
└── import_cmd.py # NOUVEAU : commande `regine import <carte>`, premier point d'intégration réel (dossier.root, camera_profile, metadata.exif)
Structure Decision: Extension du monorepo existant — nouveau module regine_core/import_carte/ (aucun code existant avant ce plan pour ce module), et première commande CLI concrète du projet (regine import), qui devient le point d'intégration réel des API déjà contractées par specs/002-profil-boitiers-optionnel et specs/004-categorisation-dossiers (jusqu'ici documentées mais non consommées). regine_core/metadata/exif.py (créé par specs/002) est étendu plutôt que dupliqué. Mise à jour du 2026-09-19 : le sous-scénario FR-009 (fusion vers un dossier déjà archivé) consomme désormais regine_core.archive.checkout (specs/005-checkout-reconciliation, planifiée) au lieu d'être documenté comme bloqué.
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 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
|