description: "Task list for feature implementation"
Tasks: Profil de boîtiers optionnel, déclaré à la demande
Input: Design documents from /specs/002-profil-boitiers-optionnel/
Prerequisites: plan.md, spec.md, research.md, data-model.md, contracts/, quickstart.md
Tests: Incluses — plan.md § Project Structure nomme explicitement les fichiers de test attendus, ce qui vaut demande explicite au sens des règles de génération.
Organisation: Tâches groupées par user story (spec.md) pour une implémentation et une validation indépendantes de chacune.
Dépendances inter-specs
| Dépendance | Fournit | État |
|---|---|---|
specs/004-categorisation-dossiers/tasks.md |
Squelette du monorepo (packages/regine-core), regine_core.config.db.open_context_db (base de contexte centralisée) |
tasks.md existe — à exécuter avant la Phase 1 si ce n'est pas déjà fait |
Aucune autre dépendance externe : exiftool est un binaire système à installer sur le poste (pas une tâche de ce fichier).
Phase 1: Setup
- T001 Vérifier que
packages/regine-core/src/regine_core/config/db.pyexiste déjà (créé parspecs/004-categorisation-dossiers/tasks.md, T009) ; si absent, exécuter d'abord ce fichier de tâches - T002 [P] Créer
packages/regine-core/src/regine_core/metadata/__init__.pyetpackages/regine-core/src/regine_core/metadata/exif.py(squelette) - T003 [P] Créer
packages/regine-core/src/regine_core/camera_profile/__init__.py - T004 [P] Vérifier que
exiftoolest disponible sur le poste de développement (exiftool -ver) —exiftool 13.55présent, aucune documentation supplémentaire nécessaire
Phase 2: Foundational (Blocking Prerequisites)
Purpose: Infrastructure partagée requise par les trois user stories.
⚠️ CRITICAL: Aucune user story ne peut être implémentée avant la fin de cette phase.
- T005 Implémenter le wrapper de processus
exiftool -stay_open(ouverture, envoi de commandes, fermeture propre) danspackages/regine-core/src/regine_core/metadata/exif.py(cf.research.md§ 1) - T006 Implémenter
read_camera_tags(chemin: Path) -> CameraTagsdansmetadata/exif.py(litModel/BodySerialNumber, retourneNonesi absent/inexploitable) - T007 [P] Test unitaire de
read_camera_tagsdanspackages/regine-core/tests/unit/test_exif_reader.py(modèle présent, numéro de série absent, métadonnées effacées) — validé avec de vrais appelsexiftoolsur fixture JPEG - T008 Ajouter la table
boitiers(id,modele,numero_serienullable,nom_lisiblenullable,premiere_rencontre,source) au schéma depackages/regine-core/src/regine_core/config/db.py(dépend de T001 ; unicité sur(modele, numero_serie)cf.data-model.md) — implémentée danscamera_profile/db.py(ensure_schema), cohérent avec le placement décidé en research.md § 2 (le fichier reste ouvert viaconfig.db.open_context_db) - T009 [P] Créer
packages/regine-core/src/regine_core/camera_profile/db.py:get_or_create_boitier(modele, numero_serie=None) -> int,list_boitiers() -> list[Boitier],rename_boitier(id, nom) -> None(dépend de T008)
Checkpoint: Fondations prêtes — les phases User Story peuvent commencer.
Phase 3: User Story 1 - Premier import sans configuration préalable (Priority: P1) 🎯 MVP
Goal: Garantir qu'aucun profil de boîtiers déclaré n'est requis avant un import, et que la désambiguïsation par défaut (sans collision) ne pose aucune question (FR-001/002/008).
Independent Test: Lire les tags de fichiers de modèles différents sans jamais appeler resolve_collision (puisqu'aucune collision n'existe) ; vérifier qu'aucune entrée boitiers n'est créée tant qu'aucune collision réelle ne survient.
Tests for User Story 1
- T010 [P] [US1] Test unitaire : la détection d'un modèle jamais rencontré, sans collision, ne crée aucune entrée dans
boitierset ne lève aucune exception, danspackages/regine-core/tests/unit/test_resolve_collision.py
Implementation for User Story 1
- T011 [US1] Documenter (docstring) dans
packages/regine-core/src/regine_core/camera_profile/resolve.pyle contrat d'appel deresolve_collision: ne DOIT être invoquée par l'appelant (futurspecs/001-import-photos) que pour des fichiers déjà identifiés en collision réelle par somme de contrôle (FR-003/FR-008) — aucune détection de collision n'est de la responsabilité de ce module
Checkpoint: User Story 1 fonctionnelle et testable indépendamment (MVP — garantit l'absence de friction par défaut).
Phase 4: User Story 2 - Résolution ponctuelle d'une collision réelle entre boîtiers (Priority: P2)
Goal: Distinguer automatiquement deux fichiers en collision par leur tag de modèle, et réutiliser une résolution déjà établie (FR-002/003/006).
Independent Test: Deux fichiers de même nom d'origine, modèles EXIF différents → résolus automatiquement sans question ; un fichier ultérieur du même modèle/numéro de série réutilise le même boitiers.id.
Tests for User Story 2
- T012 [P] [US2] Test unitaire :
resolve_collisionavec deux fichiers de modèles différents →a_etiquetervide,iddistincts, danstest_resolve_collision.py - T013 [P] [US2] Test unitaire : réutilisation d'un
boitiers.iddéjà créé pour un modèle/numéro de série déjà rencontré, danstest_resolve_collision.py - T014 [US2] Test d'intégration : persistance d'une résolution entre deux appels successifs (simulant deux imports), dans
packages/regine-core/tests/integration/test_boitier_persistence.py
Implementation for User Story 2
- T015 [US2] Implémenter
resolve_collision(fichiers: list[Path]) -> CollisionResolutiondanspackages/regine-core/src/regine_core/camera_profile/resolve.py— regroupement parmodele, résolution automatique quand les modèles diffèrent (dépend de T006, T009) - T016 [US2] Implémenter la réutilisation automatique d'un
boitiers.iddéjà connu (mêmemodele/numero_serie) sans nouvelle question, dansresolve.py(FR-006)
Checkpoint: User Stories 1 ET 2 fonctionnelles indépendamment.
Phase 5: User Story 3 - Repli sur numéro de série pour deux boîtiers identiques (Priority: P3)
Goal: Distinguer deux fichiers du même modèle par leur numéro de série ; à défaut, demander un étiquetage manuel (FR-004/005/007).
Independent Test: Collision entre deux fichiers de même modèle, numéros de série différents et exploitables → résolution automatique ; numéros de série absents/identiques → groupe renvoyé dans a_etiqueter, résolu ensuite par assign_manual_source.
Tests for User Story 3
- T017 [P] [US3] Test unitaire :
resolve_collisionavec même modèle, numéros de série différents et exploitables → résolution automatique, danstest_resolve_collision.py - T018 [P] [US3] Test unitaire : même modèle, numéro de série absent/identique/non exploitable → groupe dans
a_etiqueter, jamais résolu arbitrairement, danstest_resolve_collision.py— bug trouvé et corrigé en cours d'implémentation : les fichiers indistincts partageant le même modèle doivent former un seul groupe, pas un groupe par fichier - T019 [US3] Test unitaire de
assign_manual_source(crée une nouvelle entrée siboitier_id=None, réutilise sinon) danstest_resolve_collision.py - T020 [US3] Test unitaire de
list_boitiers/rename_boitier(consultation et modification à tout moment, FR-007) danspackages/regine-core/tests/unit/test_camera_profile_db.py
Implementation for User Story 3
- T021 [US3] Étendre
resolve_collision: repli surnumero_serieau sein d'un mêmemodele(FR-004), dansresolve.py(dépend de T015) - T022 [US3] Implémenter la construction du groupe
a_etiqueterquand ni le modèle ni le numéro de série ne suffisent (FR-005), dansresolve.py - T023 [US3] Implémenter
assign_manual_source(fichiers, boitier_id=None) -> intdanspackages/regine-core/src/regine_core/camera_profile/resolve.py(dépend de T009)
Checkpoint: Les trois user stories fonctionnelles indépendamment.
Phase 6: Polish & Cross-Cutting Concerns
- T024 [P] Exécuter manuellement les 5 scénarios de
specs/002-profil-boitiers-optionnel/quickstart.mdet consigner le résultat — 2026-09-19 : les 5 scénarios passent ; le scénario 5 (réutilisation) a révélé un bug réel (numéro de série ignoré dans la branche "modèle unique"), corrigé et couvert par un test de non-régression - T025 [P]
ruff check --fixsurpackages/regine-core— 0 erreur restante, code formaté - T026 Mettre à jour
contracts/regine-core-api.mdsi l'implémentation révèle un écart avec les signatures documentées
Dependencies & Execution Order
Phase Dependencies
- Setup (Phase 1) : dépend de
specs/004-categorisation-dossiers/tasks.md(packages,config.db) déjà exécutées. - Foundational (Phase 2) : dépend de Setup — BLOQUE toutes les user stories.
- User Stories (Phase 3–5) : dépendent toutes de Foundational.
- US1 (P1) : aucune dépendance sur une autre user story.
- US2 (P2) : étend
resolve.pyinitié en US1 (documentation du contrat) mais reste testable indépendamment. - US3 (P3) : étend
resolve_collisionde US2 (T015 → T021/T022) ; livrable séparément.
- Polish (Phase 6) : dépend des user stories livrées (au minimum US1+US2).
Parallel Opportunities
- T002–T004 (Phase 1) : fichiers/vérifications distincts.
- T007, T009 (Phase 2) : parallélisables une fois T006/T008 terminés respectivement.
- Tests marqués [P] au sein de chaque story.
Parallel Example: User Story 3
Task: "Test unitaire repli numéro de série dans packages/regine-core/tests/unit/test_resolve_collision.py"
Task: "Test unitaire groupe a_etiqueter dans packages/regine-core/tests/unit/test_resolve_collision.py"
Task: "Test unitaire list_boitiers/rename_boitier dans packages/regine-core/tests/unit/test_camera_profile_db.py"
Implementation Strategy
MVP First (User Story 1 uniquement)
- Setup + Foundational.
- US1 : garantir l'absence de friction par défaut (documentation de contrat + test de non-régression).
- Arrêt et validation : Scénario 1 de
quickstart.md.
Livraison incrémentale
- Setup + Foundational → socle prêt (lecture EXIF, table
boitiers). - US1 → aucune question par défaut → valider Scénario 1.
- US2 → résolution par modèle → valider Scénarios 2 et 5.
- US3 → repli numéro de série + étiquetage manuel → valider Scénarios 3 et 4.
Notes
- [P] = fichiers différents, sans dépendance non résolue.
- Ce module n'a pas de surface CLI propre (cf.
plan.md) : son intégration réelle relève despecs/001-import-photos(T034 de son propre tasks.md) et despecs/003-config-contexte-travail(écran de nommage des boîtiers). - Ne pas recréer le squelette monorepo ni
regine_core.config.db: à étendre (T008), jamais dupliquer.
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 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
|