fonzarely/regine-photos-archiverpublic⑂ Fork 0
⑂ 3d729f0
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.

spec

Fabien Champigny committed 2026-09-18T23:35:04+02:00 Browse files
3d729f0 parent: a196f68
added specs/005-checkout-reconciliation/checklists/requirements.md +47 -0
new file mode 100644
@@ -0,0 +1,47 @@
1+# Specification Quality Checklist: Checkout et réconciliation d'un dossier de l'archive
2+
3+**Purpose**: Validate specification completeness and quality before proceeding to planning
4+**Created**: 2026-09-18
5+**Feature**: [spec.md](../spec.md)
6+
7+## Content Quality
8+
9+- [x] No implementation details (languages, frameworks, APIs)
10+- [x] Focused on user value and business needs
11+- [x] Written for non-technical stakeholders
12+- [x] All mandatory sections completed
13+
14+## Requirement Completeness
15+
16+- [x] No [NEEDS CLARIFICATION] markers remain
17+- [x] Requirements are testable and unambiguous
18+- [x] Success criteria are measurable
19+- [x] Success criteria are technology-agnostic (no implementation details)
20+- [x] All acceptance scenarios are defined
21+- [x] Edge cases are identified
22+- [x] Scope is clearly bounded
23+- [x] Dependencies and assumptions identified
24+
25+## Feature Readiness
26+
27+- [x] All functional requirements have clear acceptance criteria
28+- [x] User scenarios cover primary flows
29+- [x] Feature meets measurable outcomes defined in Success Criteria
30+- [x] No implementation details leak into specification
31+
32+## Notes
33+
34+- Spécification dérivée de `docs/archivage-photo-elements-cles.md` section 8 (et sections 11/12
35+ pour le mécanisme de hash à deux niveaux et la persistance versionnée de l'état de référence),
36+ ainsi que de la constitution du projet (Principes I, II, III, V ; § Workflow d'archivage et
37+ Contraintes techniques), qui répondaient déjà à la quasi-totalité des questions de périmètre —
38+ aucun marqueur [NEEDS CLARIFICATION] n'a été nécessaire.
39+- Un point explicitement laissé ouvert par les notes de conception elles-mêmes ("politique à
40+ définir" pour un nouveau fichier sans correspondance) a été tranché par un défaut cohérent avec
41+ le Principe V déjà établi (décision explicite de l'utilisateur au cas par cas, jamais un défaut
42+ imposé silencieusement) plutôt que par une nouvelle question — documenté en FR-012 et Edge Cases.
43+- Débloque le sous-scénario FR-009 de `specs/001-import-photos` (fusion vers un dossier déjà
44+ archivé) et la User Story 4 de `specs/004-categorisation-dossiers` (recatégorisation a
45+ posteriori), tous deux explicitement documentés comme bloqués en attendant cette spécification.
46+- La vérification périodique indépendante du checkout (scrub) et le déverrouillage forcé restent
47+ hors périmètre, documentés en Assumptions — à couvrir par des spécifications distinctes.
new file mode 100644
@@ -0,0 +1,47 @@
1+# Specification Quality Checklist: Checkout et réconciliation d'un dossier de l'archive
2+
3+**Purpose**: Validate specification completeness and quality before proceeding to planning
4+**Created**: 2026-09-18
5+**Feature**: [spec.md](../spec.md)
6+
7+## Content Quality
8+
9+- [x] No implementation details (languages, frameworks, APIs)
10+- [x] Focused on user value and business needs
11+- [x] Written for non-technical stakeholders
12+- [x] All mandatory sections completed
13+
14+## Requirement Completeness
15+
16+- [x] No [NEEDS CLARIFICATION] markers remain
17+- [x] Requirements are testable and unambiguous
18+- [x] Success criteria are measurable
19+- [x] Success criteria are technology-agnostic (no implementation details)
20+- [x] All acceptance scenarios are defined
21+- [x] Edge cases are identified
22+- [x] Scope is clearly bounded
23+- [x] Dependencies and assumptions identified
24+
25+## Feature Readiness
26+
27+- [x] All functional requirements have clear acceptance criteria
28+- [x] User scenarios cover primary flows
29+- [x] Feature meets measurable outcomes defined in Success Criteria
30+- [x] No implementation details leak into specification
31+
32+## Notes
33+
34+- Spécification dérivée de `docs/archivage-photo-elements-cles.md` section 8 (et sections 11/12
35+ pour le mécanisme de hash à deux niveaux et la persistance versionnée de l'état de référence),
36+ ainsi que de la constitution du projet (Principes I, II, III, V ; § Workflow d'archivage et
37+ Contraintes techniques), qui répondaient déjà à la quasi-totalité des questions de périmètre —
38+ aucun marqueur [NEEDS CLARIFICATION] n'a été nécessaire.
39+- Un point explicitement laissé ouvert par les notes de conception elles-mêmes ("politique à
40+ définir" pour un nouveau fichier sans correspondance) a été tranché par un défaut cohérent avec
41+ le Principe V déjà établi (décision explicite de l'utilisateur au cas par cas, jamais un défaut
42+ imposé silencieusement) plutôt que par une nouvelle question — documenté en FR-012 et Edge Cases.
43+- Débloque le sous-scénario FR-009 de `specs/001-import-photos` (fusion vers un dossier déjà
44+ archivé) et la User Story 4 de `specs/004-categorisation-dossiers` (recatégorisation a
45+ posteriori), tous deux explicitement documentés comme bloqués en attendant cette spécification.
46+- La vérification périodique indépendante du checkout (scrub) et le déverrouillage forcé restent
47+ hors périmètre, documentés en Assumptions — à couvrir par des spécifications distinctes.
added specs/005-checkout-reconciliation/spec.md +172 -0
new file mode 100644
@@ -0,0 +1,172 @@
1+# Feature Specification: Checkout et réconciliation d'un dossier de l'archive
2+
3+**Feature Branch**: `[005-checkout-reconciliation]`
4+
5+**Created**: 2026-09-18
6+
7+**Status**: Draft
8+
9+**Input**: User description: "spécifie le mécanisme de checkout/réconciliation (section 8)"
10+
11+## User Scenarios & Testing *(mandatory)*
12+
13+### User Story 1 - Checkout d'un dossier pour édition (Priority: P1)
14+
15+Un photographe veut retoucher les photos d'un dossier déjà archivé sur le NAS. Il demande à Régine de le sortir vers un espace de travail local : Régine copie le contenu, enregistre un état de référence de chaque fichier, et marque le dossier comme en cours d'édition côté archive.
16+
17+**Why this priority**: C'est le point d'entrée de tout le cycle d'édition sécurisé — sans lui, aucune modification d'un dossier déjà archivé n'est possible autrement qu'en touchant directement le NAS, ce que le principe même de ce mécanisme cherche à éviter (cf. `docs/archivage-photo-elements-cles.md` section 8).
18+
19+**Independent Test**: Peut être testé en effectuant un checkout d'un dossier archivé existant, puis en vérifiant que la copie locale est identique au contenu archivé, qu'un état de référence complet (chemin, taille, empreinte de contenu, identifiant pérenne par fichier) a été enregistré, et que le dossier apparaît comme verrouillé côté archive.
20+
21+**Acceptance Scenarios**:
22+
23+1. **Given** un dossier archivé (simple, ou dossier parent avec ses sous-dossiers), **When** l'utilisateur demande son checkout, **Then** Régine copie l'intégralité de son contenu — dossier parent et tous ses sous-dossiers ensemble, jamais un sous-dossier isolément — vers un espace de travail local, en vérifiant chaque fichier par empreinte de contenu.
24+2. **Given** une copie locale nouvellement créée par checkout, **When** le checkout se termine, **Then** un état de référence est enregistré pour chaque fichier (chemin, taille, empreinte de contenu, identifiant pérenne).
25+3. **Given** un checkout terminé avec succès, **When** l'utilisateur consulte l'archive, **Then** le dossier concerné apparaît marqué comme en cours d'édition (verrouillé), pour empêcher qu'une autre instance ou personne ne le modifie en parallèle.
26+4. **Given** une copie de travail locale issue d'un checkout, **When** l'utilisateur l'édite avec l'outil de son choix (renommage, suppression de RAW, création/modification de sidecars, génération d'exports dérivés), **Then** aucune de ces actions ne modifie l'archive sur le NAS, qui reste inchangée jusqu'à une réconciliation explicite.
27+
28+---
29+
30+### User Story 2 - Réconciliation normale et point avant archive (Priority: P2)
31+
32+Après avoir retouché ses photos (nouveaux réglages enregistrés dans des sidecars, quelques exports générés), le photographe demande à Régine de renvoyer ses changements vers l'archive. Régine compare la copie de travail à l'état de référence, présente un récapitulatif clair de ce qui va changer, et n'écrit sur l'archive qu'après confirmation explicite.
33+
34+**Why this priority**: C'est la valeur centrale du mécanisme — refermer le cycle checkout/édition en toute sécurité. Sans elle, un checkout ne serait qu'une copie sans retour possible.
35+
36+**Independent Test**: Peut être testé en effectuant un checkout, en modifiant uniquement des sidecars dans la copie de travail (aucun fichier maître touché), en déclenchant une réconciliation, et en vérifiant qu'un récapitulatif est présenté et qu'aucune écriture ne survient sur l'archive avant confirmation explicite.
37+
38+**Acceptance Scenarios**:
39+
40+1. **Given** une copie de travail où un fichier maître est resté inchangé et où son sidecar a été créé ou modifié, **When** l'utilisateur déclenche la réconciliation, **Then** Régine classe ce changement comme normal, directement archivable.
41+2. **Given** un ensemble de changements classés (normaux, ou nécessitant une décision), **When** la réconciliation est prête, **Then** Régine présente à l'utilisateur un récapitulatif complet de tous les changements avant d'écrire quoi que ce soit sur l'archive.
42+3. **Given** ce récapitulatif présenté, **When** l'utilisateur ne confirme pas, **Then** aucune écriture ne survient sur l'archive et la copie de travail locale reste disponible pour être reprise ou réconciliée plus tard.
43+4. **Given** un récapitulatif confirmé par l'utilisateur, **When** Régine écrit les changements sur l'archive, **Then** elle vérifie chaque transfert par empreinte de contenu avant de le considérer réussi.
44+5. **Given** une réconciliation menée à bien, **When** l'écriture sur l'archive est terminée, **Then** le verrou du dossier est levé, le rendant à nouveau disponible pour un futur checkout.
45+
46+---
47+
48+### User Story 3 - Détection d'une anomalie sur un fichier maître (Priority: P3)
49+
50+Pendant une session d'édition, un fichier maître se retrouve, par erreur logicielle ou manipulation involontaire, avec un contenu différent de celui archivé. À la réconciliation, Régine doit détecter ce changement et le signaler comme une anomalie, sans jamais l'archiver silencieusement.
51+
52+**Why this priority**: C'est la garantie de sécurité centrale de toute l'archive (cf. Principe I de la constitution du projet) ; elle ne s'active que dans le cas anormal, ce qui en fait un raffinement de la réconciliation normale (P2) plutôt qu'un chemin séparé.
53+
54+**Independent Test**: Peut être testé en modifiant délibérément le contenu image d'un fichier maître dans la copie de travail (pas seulement ses métadonnées), en réconciliant, et en vérifiant que ce fichier est signalé comme anomalie nécessitant une décision explicite, jamais réarchivé sans confirmation.
55+
56+**Acceptance Scenarios**:
57+
58+1. **Given** un fichier RAW propriétaire dont le contenu (au-delà des métadonnées) a changé depuis le checkout, **When** la réconciliation compare les empreintes, **Then** Régine le signale comme anomalie, jamais comme un changement normal.
59+2. **Given** un fichier DNG, TIFF ou JPEG maître dont seules les métadonnées ont été modifiées par un outil d'édition (réglages non destructifs), **When** la réconciliation compare les empreintes, **Then** Régine ne le signale PAS comme anomalie — la comparaison porte sur l'empreinte des données image uniquement, pas sur l'empreinte du fichier entier, pour ces formats.
60+3. **Given** un fichier DNG, TIFF ou JPEG maître dont les données image elles-mêmes ont changé, **When** la réconciliation compare les empreintes, **Then** Régine le signale comme anomalie.
61+4. **Given** une anomalie signalée, **When** l'utilisateur choisit de résoudre ce point, **Then** il peut soit confirmer explicitement l'écriture malgré l'anomalie, soit demander la restauration du fichier depuis l'archive — jamais un choix effectué par Régine à sa place.
62+5. **Given** un récapitulatif contenant à la fois des changements normaux et une anomalie non encore tranchée, **When** l'utilisateur confirme les changements normaux, **Then** ceux-ci sont archivés sans attendre que l'anomalie soit résolue, qui reste un point distinct à trancher séparément.
63+
64+---
65+
66+### User Story 4 - Détection de renommage ou déplacement par le contenu (Priority: P4)
67+
68+Le photographe renomme un fichier, le déplace de son dossier de format vers la racine de sélection (promotion), ou déplace un dossier entier d'un répertoire d'année vers un répertoire de catégorie thématique. Dans tous ces cas, Régine doit reconnaître qu'il s'agit du même contenu déplacé, pas d'une suppression suivie d'un nouveau fichier.
69+
70+**Why this priority**: Évite de fausses suppressions/créations à chaque réorganisation légitime (promotion à la racine, recatégorisation) ; raffine la réconciliation normale (P2) pour un cas fréquent mais pas bloquant pour le fonctionnement de base.
71+
72+**Independent Test**: Peut être testé en renommant un fichier ou en le déplaçant vers la racine de sélection dans la copie de travail, puis en réconciliant : le changement doit être classé comme un déplacement à contenu inchangé, jamais comme une suppression et une création distinctes. Un second test déplace le dossier entier d'un répertoire d'année vers un répertoire de catégorie et vérifie la même détection au niveau du dossier.
73+
74+**Acceptance Scenarios**:
75+
76+1. **Given** un fichier renommé dans la copie de travail, contenu inchangé, **When** la réconciliation compare les empreintes, **Then** Régine le reconnaît comme le même fichier déplacé/renommé, par son empreinte de contenu, pas par son nom.
77+2. **Given** un fichier déplacé de son dossier de format vers la racine de sélection du dossier (promotion), **When** la réconciliation a lieu, **Then** ce déplacement est traité par le même mécanisme de détection par contenu, sans traitement spécial.
78+3. **Given** un dossier entier déplacé d'un répertoire racine vers un autre (ex. d'une année vers une catégorie thématique, cf. `specs/004-categorisation-dossiers`), **When** la réconciliation a lieu, **Then** ce déplacement est détecté par le même mécanisme, sans mécanisme de recatégorisation dédié.
79+
80+---
81+
82+### User Story 5 - Refus d'un double-checkout concurrent (Priority: P5)
83+
84+Pendant qu'un dossier est en cours d'édition (checkouté par un premier utilisateur ou une première instance de Régine), une seconde tentative de checkout sur ce même dossier doit être refusée, pas silencieusement autorisée.
85+
86+**Why this priority**: Protège l'intégrité de l'archive contre une édition concurrente incontrôlée ; scénario de protection plutôt que de fonctionnement courant.
87+
88+**Independent Test**: Peut être testé en effectuant un checkout d'un dossier, puis en tentant un second checkout du même dossier avant réconciliation du premier : le second doit être refusé avec une explication claire.
89+
90+**Acceptance Scenarios**:
91+
92+1. **Given** un dossier déjà verrouillé par un checkout en cours, **When** un second checkout du même dossier est tenté, **Then** Régine le refuse et explique clairement que le dossier est déjà en cours d'édition.
93+2. **Given** un dossier dont la réconciliation vient d'aboutir, **When** un nouveau checkout est tenté, **Then** il est accepté normalement, le verrou précédent ayant été levé.
94+
95+---
96+
97+### User Story 6 - Checkout partiel par format pour aller vite (Priority: P6)
98+
99+Pour un tri rapide (ex. sélection en vacances), le photographe ne veut sortir que les JPEG et la racine de sélection d'un dossier, sans les RAW correspondants, pour économiser du temps et de l'espace disque.
100+
101+**Why this priority**: Optimisation de confort sur un cas d'usage identifié, mais le checkout complet (P1) couvre déjà tous les besoins fonctionnels ; ce raffinement reste secondaire.
102+
103+**Independent Test**: Peut être testé en demandant un checkout limité à un sous-ensemble de formats (ex. jpeg uniquement) plus la racine de sélection d'un dossier, et en vérifiant que seuls ces fichiers sont copiés localement, que les RAW restent uniquement dans l'archive, et que la réconciliation ultérieure ne signale aucune absence anormale pour les fichiers volontairement exclus.
104+
105+**Acceptance Scenarios**:
106+
107+1. **Given** un dossier archivé contenant plusieurs sous-répertoires de format, **When** l'utilisateur demande un checkout limité à un ou plusieurs formats, **Then** seuls les fichiers de ces formats et de la racine de sélection sont copiés localement.
108+2. **Given** un checkout partiel réalisé, **When** l'utilisateur réconcilie ensuite ses changements, **Then** les fichiers volontairement exclus du checkout ne sont jamais signalés comme supprimés ou anormaux.
109+
110+---
111+
112+### Edge Cases
113+
114+- Que se passe-t-il si la connexion à l'archive est interrompue pendant l'écriture d'un réarchivage ? Aucune écriture partielle ne DOIT être considérée comme définitive : Régine DOIT soit compléter le transfert et le vérifier intégralement, soit signaler clairement l'échec sans laisser l'archive dans un état ambigu.
115+- Que se passe-t-il si deux fichiers de la copie de travail, autrefois distincts, se retrouvent avec la même empreinte de contenu (doublon involontaire créé localement) ? Régine DOIT signaler la situation à l'utilisateur plutôt que de fusionner silencieusement les deux entrées.
116+- Que se passe-t-il si une réconciliation est demandée sur un dossier qui n'a jamais fait l'objet d'un checkout (aucun état de référence disponible) ? Régine DOIT refuser et indiquer qu'un checkout préalable est requis.
117+- Que se passe-t-il si un dossier reste verrouillé anormalement longtemps (utilisateur qui a oublié de réconcilier) ? Ce cas n'est pas couvert par un déverrouillage automatique dans cette itération (cf. Assumptions) ; seule une action manuelle et explicite de l'utilisateur peut lever ce verrou.
118+- Que se passe-t-il pour un fichier de la copie de travail sans aucune correspondance dans l'état de référence (export dérivé généré localement, par exemple) ? Il DOIT être présenté explicitement dans le récapitulatif avant archive, avec un choix laissé à l'utilisateur de l'archiver ou de le laisser local — jamais une décision par défaut imposée silencieusement.
119+
120+## Requirements *(mandatory)*
121+
122+### Functional Requirements
123+
124+- **FR-001**: Le système DOIT permettre de sortir (checkout) l'intégralité du contenu d'un dossier de l'archive vers un espace de travail local — dossier parent et tous ses sous-dossiers ensemble s'il y en a, jamais un sous-dossier isolément.
125+- **FR-002**: Au moment du checkout, le système DOIT enregistrer un état de référence pour chaque fichier du dossier (chemin, taille, empreinte de contenu, identifiant pérenne).
126+- **FR-003**: Au moment du checkout, le système DOIT marquer le dossier comme verrouillé côté archive.
127+- **FR-004**: Lorsqu'un checkout est tenté sur un dossier déjà verrouillé, le système DOIT le refuser et en informer clairement l'utilisateur.
128+- **FR-005**: Pendant la phase d'édition locale, le système ne DOIT imposer aucune contrainte sur la copie de travail et ne DOIT modifier l'archive d'aucune façon tant qu'aucune réconciliation n'a été déclenchée.
129+- **FR-006**: À la réconciliation, le système DOIT recalculer les empreintes de contenu de la copie de travail et les comparer à l'état de référence pour classer chaque fichier selon les catégories suivantes : inchangé/sidecar nouveau ou modifié (normal), fichier maître modifié (anomalie), renommage ou déplacement à contenu inchangé, suppression, nouveau fichier sans correspondance.
130+- **FR-007**: Le système DOIT fonder la détection d'un fichier maître modifié sur l'empreinte pertinente selon son format — empreinte du fichier entier pour les RAW propriétaires ; empreinte portant uniquement sur les données image pour le DNG, le TIFF et le JPEG maîtres — conformément au Principe I de la constitution du projet.
131+- **FR-008**: Le système DOIT signaler tout fichier maître modifié comme anomalie et ne DOIT JAMAIS le réarchiver silencieusement.
132+- **FR-009**: Le système DOIT détecter par le contenu (empreinte inchangée) tout renommage ou déplacement de fichier au sein d'un dossier, y compris une promotion vers la racine de sélection, plutôt que de le traiter comme une suppression suivie d'un nouveau fichier.
133+- **FR-010**: Le système DOIT détecter de la même façon, par le contenu, le déplacement d'un dossier entier d'un répertoire racine vers un autre (ex. année vers catégorie thématique), sans mécanisme dédié distinct de la détection de renommage/déplacement de fichier.
134+- **FR-011**: Le système ne DOIT jamais propager automatiquement une suppression détectée (fichier de l'état de référence absent de la copie de travail) ; une confirmation explicite de l'utilisateur est requise avant de supprimer quoi que ce soit de l'archive.
135+- **FR-012**: Pour tout fichier de la copie de travail sans correspondance dans l'état de référence, le système DOIT laisser l'utilisateur décider explicitement de l'archiver ou de le laisser local, sans politique par défaut imposée silencieusement.
136+- **FR-013**: Avant d'écrire quoi que ce soit sur l'archive, le système DOIT présenter à l'utilisateur un récapitulatif complet de tous les changements classés et attendre une confirmation explicite.
137+- **FR-014**: Le système DOIT permettre de confirmer et d'archiver les changements normaux sans attendre la résolution d'une anomalie distincte présente dans le même récapitulatif, tant que cette anomalie reste un point séparé non mélangé aux autres changements.
138+- **FR-015**: Le système DOIT vérifier par empreinte de contenu toute copie effectuée pendant le checkout et pendant le réarchivage, avant de considérer la source comme sûre et la destination comme fiable.
139+- **FR-016**: Une fois toutes les écritures d'une réconciliation confirmées et effectuées, le système DOIT libérer le verrou du dossier concerné.
140+- **FR-017**: Le système DOIT stocker l'état de référence de façon persistante et atomique, sans jamais laisser un état partiellement écrit observable après une interruption, plutôt que de le recréer à chaque checkout.
141+- **FR-018**: Le format de l'état de référence DOIT porter un numéro de version distinguant une évolution additive (tolérée par une version antérieure du logiciel) d'une évolution structurelle (refusée explicitement plutôt qu'interprétée à tort).
142+- **FR-019**: Le système DOIT permettre de restreindre un checkout à un sous-ensemble de répertoires de format (ex. jpeg seul) plus la racine de sélection, sans que cela ne constitue un sous-dossier isolé au sens de FR-001.
143+- **FR-020**: Les fichiers volontairement exclus d'un checkout partiel ne DOIVENT jamais être signalés comme supprimés ou anormaux lors de la réconciliation qui suit.
144+
145+### Key Entities
146+
147+- **État de référence (manifeste)** : instantané pris au checkout pour chaque fichier d'un dossier (chemin, taille, empreinte de contenu, identifiant pérenne), stocké de façon persistante et versionnée, pas recréé à chaque checkout.
148+- **Verrou de dossier** : marqueur côté archive posé au checkout et levé à la réconciliation réussie, empêchant un accès concurrent à l'ensemble du dossier (parent + sous-dossiers).
149+- **Copie de travail locale** : espace d'édition libre issu d'un checkout, sans contrainte, jamais synchronisé avec l'archive avant une réconciliation explicite.
150+- **Changement classé** : résultat de la comparaison entre l'état de référence et la copie de travail — normal, anomalie, renommage/déplacement, suppression, ou nouveau fichier.
151+- **Point avant archive** : récapitulatif de tous les changements classés, présenté à l'utilisateur et validé explicitement avant toute écriture sur l'archive.
152+- **Anomalie** : fichier maître dont le contenu pertinent a changé par rapport à l'état de référence — jamais réarchivée silencieusement, toujours soumise à une décision explicite (confirmer ou restaurer).
153+
154+## Success Criteria *(mandatory)*
155+
156+### Measurable Outcomes
157+
158+- **SC-001**: 100% des checkouts produisent un état de référence complet avant que la copie de travail ne soit considérée utilisable.
159+- **SC-002**: 100% des tentatives de checkout sur un dossier déjà verrouillé sont refusées avec un message explicite.
160+- **SC-003**: 100% des fichiers maîtres modifiés détectés à la réconciliation sont signalés comme anomalie, jamais réarchivés silencieusement.
161+- **SC-004**: 100% des renommages ou déplacements (fichier ou dossier entier) à contenu inchangé sont détectés comme tels, jamais comme une suppression suivie d'une création.
162+- **SC-005**: Aucune suppression ni aucun nouveau fichier n'est archivé sans confirmation explicite de l'utilisateur.
163+- **SC-006**: 100% des réconciliations menées à bien libèrent le verrou du dossier concerné, le rendant à nouveau disponible pour un futur checkout.
164+- **SC-007**: Une interruption survenant pendant un réarchivage ne laisse jamais l'état de référence ou l'archive dans un état partiellement écrit observable.
165+
166+## Assumptions
167+
168+- Le premier archivage d'un dossier nouvellement importé (`specs/001-import-photos`) ne passe pas par ce mécanisme de réconciliation : il n'existe pas encore d'état de référence à comparer, seulement une création initiale. Ce mécanisme s'applique aux dossiers déjà archivés que l'on ré-édite.
169+- Le travail à plusieurs avec verrouillage fin (édition concurrente de deux sous-dossiers d'un même dossier parent) reste hors périmètre de cette itération, cohérent avec les notes de conception du projet : le verrouillage porte toujours sur le dossier complet (parent et tous ses sous-dossiers), jamais à un niveau plus fin.
170+- La vérification périodique indépendante du checkout (scrub, cf. constitution § Contraintes techniques) est une capacité distincte, hors périmètre de cette spécification ; elle réutilisera le même mécanisme d'empreintes de contenu sans dépendre d'un checkout.
171+- Le déverrouillage forcé d'un dossier resté verrouillé anormalement longtemps (oubli utilisateur) reste une action manuelle et avertie, hors périmètre détaillé de cette itération ; aucun mécanisme de récupération automatique n'est couvert ici.
172+- La désambiguïsation de boîtiers (`specs/002-profil-boitiers-optionnel`) et la catégorisation racine (`specs/004-categorisation-dossiers`) restent celles déjà spécifiées ; cette spécification s'appuie sur FR-008/FR-010 de `specs/004-categorisation-dossiers` (détection de déplacement de dossier par hash) sans les redéfinir, et les concrétise ici.
new file mode 100644
@@ -0,0 +1,172 @@
1+# Feature Specification: Checkout et réconciliation d'un dossier de l'archive
2+
3+**Feature Branch**: `[005-checkout-reconciliation]`
4+
5+**Created**: 2026-09-18
6+
7+**Status**: Draft
8+
9+**Input**: User description: "spécifie le mécanisme de checkout/réconciliation (section 8)"
10+
11+## User Scenarios & Testing *(mandatory)*
12+
13+### User Story 1 - Checkout d'un dossier pour édition (Priority: P1)
14+
15+Un photographe veut retoucher les photos d'un dossier déjà archivé sur le NAS. Il demande à Régine de le sortir vers un espace de travail local : Régine copie le contenu, enregistre un état de référence de chaque fichier, et marque le dossier comme en cours d'édition côté archive.
16+
17+**Why this priority**: C'est le point d'entrée de tout le cycle d'édition sécurisé — sans lui, aucune modification d'un dossier déjà archivé n'est possible autrement qu'en touchant directement le NAS, ce que le principe même de ce mécanisme cherche à éviter (cf. `docs/archivage-photo-elements-cles.md` section 8).
18+
19+**Independent Test**: Peut être testé en effectuant un checkout d'un dossier archivé existant, puis en vérifiant que la copie locale est identique au contenu archivé, qu'un état de référence complet (chemin, taille, empreinte de contenu, identifiant pérenne par fichier) a été enregistré, et que le dossier apparaît comme verrouillé côté archive.
20+
21+**Acceptance Scenarios**:
22+
23+1. **Given** un dossier archivé (simple, ou dossier parent avec ses sous-dossiers), **When** l'utilisateur demande son checkout, **Then** Régine copie l'intégralité de son contenu — dossier parent et tous ses sous-dossiers ensemble, jamais un sous-dossier isolément — vers un espace de travail local, en vérifiant chaque fichier par empreinte de contenu.
24+2. **Given** une copie locale nouvellement créée par checkout, **When** le checkout se termine, **Then** un état de référence est enregistré pour chaque fichier (chemin, taille, empreinte de contenu, identifiant pérenne).
25+3. **Given** un checkout terminé avec succès, **When** l'utilisateur consulte l'archive, **Then** le dossier concerné apparaît marqué comme en cours d'édition (verrouillé), pour empêcher qu'une autre instance ou personne ne le modifie en parallèle.
26+4. **Given** une copie de travail locale issue d'un checkout, **When** l'utilisateur l'édite avec l'outil de son choix (renommage, suppression de RAW, création/modification de sidecars, génération d'exports dérivés), **Then** aucune de ces actions ne modifie l'archive sur le NAS, qui reste inchangée jusqu'à une réconciliation explicite.
27+
28+---
29+
30+### User Story 2 - Réconciliation normale et point avant archive (Priority: P2)
31+
32+Après avoir retouché ses photos (nouveaux réglages enregistrés dans des sidecars, quelques exports générés), le photographe demande à Régine de renvoyer ses changements vers l'archive. Régine compare la copie de travail à l'état de référence, présente un récapitulatif clair de ce qui va changer, et n'écrit sur l'archive qu'après confirmation explicite.
33+
34+**Why this priority**: C'est la valeur centrale du mécanisme — refermer le cycle checkout/édition en toute sécurité. Sans elle, un checkout ne serait qu'une copie sans retour possible.
35+
36+**Independent Test**: Peut être testé en effectuant un checkout, en modifiant uniquement des sidecars dans la copie de travail (aucun fichier maître touché), en déclenchant une réconciliation, et en vérifiant qu'un récapitulatif est présenté et qu'aucune écriture ne survient sur l'archive avant confirmation explicite.
37+
38+**Acceptance Scenarios**:
39+
40+1. **Given** une copie de travail où un fichier maître est resté inchangé et où son sidecar a été créé ou modifié, **When** l'utilisateur déclenche la réconciliation, **Then** Régine classe ce changement comme normal, directement archivable.
41+2. **Given** un ensemble de changements classés (normaux, ou nécessitant une décision), **When** la réconciliation est prête, **Then** Régine présente à l'utilisateur un récapitulatif complet de tous les changements avant d'écrire quoi que ce soit sur l'archive.
42+3. **Given** ce récapitulatif présenté, **When** l'utilisateur ne confirme pas, **Then** aucune écriture ne survient sur l'archive et la copie de travail locale reste disponible pour être reprise ou réconciliée plus tard.
43+4. **Given** un récapitulatif confirmé par l'utilisateur, **When** Régine écrit les changements sur l'archive, **Then** elle vérifie chaque transfert par empreinte de contenu avant de le considérer réussi.
44+5. **Given** une réconciliation menée à bien, **When** l'écriture sur l'archive est terminée, **Then** le verrou du dossier est levé, le rendant à nouveau disponible pour un futur checkout.
45+
46+---
47+
48+### User Story 3 - Détection d'une anomalie sur un fichier maître (Priority: P3)
49+
50+Pendant une session d'édition, un fichier maître se retrouve, par erreur logicielle ou manipulation involontaire, avec un contenu différent de celui archivé. À la réconciliation, Régine doit détecter ce changement et le signaler comme une anomalie, sans jamais l'archiver silencieusement.
51+
52+**Why this priority**: C'est la garantie de sécurité centrale de toute l'archive (cf. Principe I de la constitution du projet) ; elle ne s'active que dans le cas anormal, ce qui en fait un raffinement de la réconciliation normale (P2) plutôt qu'un chemin séparé.
53+
54+**Independent Test**: Peut être testé en modifiant délibérément le contenu image d'un fichier maître dans la copie de travail (pas seulement ses métadonnées), en réconciliant, et en vérifiant que ce fichier est signalé comme anomalie nécessitant une décision explicite, jamais réarchivé sans confirmation.
55+
56+**Acceptance Scenarios**:
57+
58+1. **Given** un fichier RAW propriétaire dont le contenu (au-delà des métadonnées) a changé depuis le checkout, **When** la réconciliation compare les empreintes, **Then** Régine le signale comme anomalie, jamais comme un changement normal.
59+2. **Given** un fichier DNG, TIFF ou JPEG maître dont seules les métadonnées ont été modifiées par un outil d'édition (réglages non destructifs), **When** la réconciliation compare les empreintes, **Then** Régine ne le signale PAS comme anomalie — la comparaison porte sur l'empreinte des données image uniquement, pas sur l'empreinte du fichier entier, pour ces formats.
60+3. **Given** un fichier DNG, TIFF ou JPEG maître dont les données image elles-mêmes ont changé, **When** la réconciliation compare les empreintes, **Then** Régine le signale comme anomalie.
61+4. **Given** une anomalie signalée, **When** l'utilisateur choisit de résoudre ce point, **Then** il peut soit confirmer explicitement l'écriture malgré l'anomalie, soit demander la restauration du fichier depuis l'archive — jamais un choix effectué par Régine à sa place.
62+5. **Given** un récapitulatif contenant à la fois des changements normaux et une anomalie non encore tranchée, **When** l'utilisateur confirme les changements normaux, **Then** ceux-ci sont archivés sans attendre que l'anomalie soit résolue, qui reste un point distinct à trancher séparément.
63+
64+---
65+
66+### User Story 4 - Détection de renommage ou déplacement par le contenu (Priority: P4)
67+
68+Le photographe renomme un fichier, le déplace de son dossier de format vers la racine de sélection (promotion), ou déplace un dossier entier d'un répertoire d'année vers un répertoire de catégorie thématique. Dans tous ces cas, Régine doit reconnaître qu'il s'agit du même contenu déplacé, pas d'une suppression suivie d'un nouveau fichier.
69+
70+**Why this priority**: Évite de fausses suppressions/créations à chaque réorganisation légitime (promotion à la racine, recatégorisation) ; raffine la réconciliation normale (P2) pour un cas fréquent mais pas bloquant pour le fonctionnement de base.
71+
72+**Independent Test**: Peut être testé en renommant un fichier ou en le déplaçant vers la racine de sélection dans la copie de travail, puis en réconciliant : le changement doit être classé comme un déplacement à contenu inchangé, jamais comme une suppression et une création distinctes. Un second test déplace le dossier entier d'un répertoire d'année vers un répertoire de catégorie et vérifie la même détection au niveau du dossier.
73+
74+**Acceptance Scenarios**:
75+
76+1. **Given** un fichier renommé dans la copie de travail, contenu inchangé, **When** la réconciliation compare les empreintes, **Then** Régine le reconnaît comme le même fichier déplacé/renommé, par son empreinte de contenu, pas par son nom.
77+2. **Given** un fichier déplacé de son dossier de format vers la racine de sélection du dossier (promotion), **When** la réconciliation a lieu, **Then** ce déplacement est traité par le même mécanisme de détection par contenu, sans traitement spécial.
78+3. **Given** un dossier entier déplacé d'un répertoire racine vers un autre (ex. d'une année vers une catégorie thématique, cf. `specs/004-categorisation-dossiers`), **When** la réconciliation a lieu, **Then** ce déplacement est détecté par le même mécanisme, sans mécanisme de recatégorisation dédié.
79+
80+---
81+
82+### User Story 5 - Refus d'un double-checkout concurrent (Priority: P5)
83+
84+Pendant qu'un dossier est en cours d'édition (checkouté par un premier utilisateur ou une première instance de Régine), une seconde tentative de checkout sur ce même dossier doit être refusée, pas silencieusement autorisée.
85+
86+**Why this priority**: Protège l'intégrité de l'archive contre une édition concurrente incontrôlée ; scénario de protection plutôt que de fonctionnement courant.
87+
88+**Independent Test**: Peut être testé en effectuant un checkout d'un dossier, puis en tentant un second checkout du même dossier avant réconciliation du premier : le second doit être refusé avec une explication claire.
89+
90+**Acceptance Scenarios**:
91+
92+1. **Given** un dossier déjà verrouillé par un checkout en cours, **When** un second checkout du même dossier est tenté, **Then** Régine le refuse et explique clairement que le dossier est déjà en cours d'édition.
93+2. **Given** un dossier dont la réconciliation vient d'aboutir, **When** un nouveau checkout est tenté, **Then** il est accepté normalement, le verrou précédent ayant été levé.
94+
95+---
96+
97+### User Story 6 - Checkout partiel par format pour aller vite (Priority: P6)
98+
99+Pour un tri rapide (ex. sélection en vacances), le photographe ne veut sortir que les JPEG et la racine de sélection d'un dossier, sans les RAW correspondants, pour économiser du temps et de l'espace disque.
100+
101+**Why this priority**: Optimisation de confort sur un cas d'usage identifié, mais le checkout complet (P1) couvre déjà tous les besoins fonctionnels ; ce raffinement reste secondaire.
102+
103+**Independent Test**: Peut être testé en demandant un checkout limité à un sous-ensemble de formats (ex. jpeg uniquement) plus la racine de sélection d'un dossier, et en vérifiant que seuls ces fichiers sont copiés localement, que les RAW restent uniquement dans l'archive, et que la réconciliation ultérieure ne signale aucune absence anormale pour les fichiers volontairement exclus.
104+
105+**Acceptance Scenarios**:
106+
107+1. **Given** un dossier archivé contenant plusieurs sous-répertoires de format, **When** l'utilisateur demande un checkout limité à un ou plusieurs formats, **Then** seuls les fichiers de ces formats et de la racine de sélection sont copiés localement.
108+2. **Given** un checkout partiel réalisé, **When** l'utilisateur réconcilie ensuite ses changements, **Then** les fichiers volontairement exclus du checkout ne sont jamais signalés comme supprimés ou anormaux.
109+
110+---
111+
112+### Edge Cases
113+
114+- Que se passe-t-il si la connexion à l'archive est interrompue pendant l'écriture d'un réarchivage ? Aucune écriture partielle ne DOIT être considérée comme définitive : Régine DOIT soit compléter le transfert et le vérifier intégralement, soit signaler clairement l'échec sans laisser l'archive dans un état ambigu.
115+- Que se passe-t-il si deux fichiers de la copie de travail, autrefois distincts, se retrouvent avec la même empreinte de contenu (doublon involontaire créé localement) ? Régine DOIT signaler la situation à l'utilisateur plutôt que de fusionner silencieusement les deux entrées.
116+- Que se passe-t-il si une réconciliation est demandée sur un dossier qui n'a jamais fait l'objet d'un checkout (aucun état de référence disponible) ? Régine DOIT refuser et indiquer qu'un checkout préalable est requis.
117+- Que se passe-t-il si un dossier reste verrouillé anormalement longtemps (utilisateur qui a oublié de réconcilier) ? Ce cas n'est pas couvert par un déverrouillage automatique dans cette itération (cf. Assumptions) ; seule une action manuelle et explicite de l'utilisateur peut lever ce verrou.
118+- Que se passe-t-il pour un fichier de la copie de travail sans aucune correspondance dans l'état de référence (export dérivé généré localement, par exemple) ? Il DOIT être présenté explicitement dans le récapitulatif avant archive, avec un choix laissé à l'utilisateur de l'archiver ou de le laisser local — jamais une décision par défaut imposée silencieusement.
119+
120+## Requirements *(mandatory)*
121+
122+### Functional Requirements
123+
124+- **FR-001**: Le système DOIT permettre de sortir (checkout) l'intégralité du contenu d'un dossier de l'archive vers un espace de travail local — dossier parent et tous ses sous-dossiers ensemble s'il y en a, jamais un sous-dossier isolément.
125+- **FR-002**: Au moment du checkout, le système DOIT enregistrer un état de référence pour chaque fichier du dossier (chemin, taille, empreinte de contenu, identifiant pérenne).
126+- **FR-003**: Au moment du checkout, le système DOIT marquer le dossier comme verrouillé côté archive.
127+- **FR-004**: Lorsqu'un checkout est tenté sur un dossier déjà verrouillé, le système DOIT le refuser et en informer clairement l'utilisateur.
128+- **FR-005**: Pendant la phase d'édition locale, le système ne DOIT imposer aucune contrainte sur la copie de travail et ne DOIT modifier l'archive d'aucune façon tant qu'aucune réconciliation n'a été déclenchée.
129+- **FR-006**: À la réconciliation, le système DOIT recalculer les empreintes de contenu de la copie de travail et les comparer à l'état de référence pour classer chaque fichier selon les catégories suivantes : inchangé/sidecar nouveau ou modifié (normal), fichier maître modifié (anomalie), renommage ou déplacement à contenu inchangé, suppression, nouveau fichier sans correspondance.
130+- **FR-007**: Le système DOIT fonder la détection d'un fichier maître modifié sur l'empreinte pertinente selon son format — empreinte du fichier entier pour les RAW propriétaires ; empreinte portant uniquement sur les données image pour le DNG, le TIFF et le JPEG maîtres — conformément au Principe I de la constitution du projet.
131+- **FR-008**: Le système DOIT signaler tout fichier maître modifié comme anomalie et ne DOIT JAMAIS le réarchiver silencieusement.
132+- **FR-009**: Le système DOIT détecter par le contenu (empreinte inchangée) tout renommage ou déplacement de fichier au sein d'un dossier, y compris une promotion vers la racine de sélection, plutôt que de le traiter comme une suppression suivie d'un nouveau fichier.
133+- **FR-010**: Le système DOIT détecter de la même façon, par le contenu, le déplacement d'un dossier entier d'un répertoire racine vers un autre (ex. année vers catégorie thématique), sans mécanisme dédié distinct de la détection de renommage/déplacement de fichier.
134+- **FR-011**: Le système ne DOIT jamais propager automatiquement une suppression détectée (fichier de l'état de référence absent de la copie de travail) ; une confirmation explicite de l'utilisateur est requise avant de supprimer quoi que ce soit de l'archive.
135+- **FR-012**: Pour tout fichier de la copie de travail sans correspondance dans l'état de référence, le système DOIT laisser l'utilisateur décider explicitement de l'archiver ou de le laisser local, sans politique par défaut imposée silencieusement.
136+- **FR-013**: Avant d'écrire quoi que ce soit sur l'archive, le système DOIT présenter à l'utilisateur un récapitulatif complet de tous les changements classés et attendre une confirmation explicite.
137+- **FR-014**: Le système DOIT permettre de confirmer et d'archiver les changements normaux sans attendre la résolution d'une anomalie distincte présente dans le même récapitulatif, tant que cette anomalie reste un point séparé non mélangé aux autres changements.
138+- **FR-015**: Le système DOIT vérifier par empreinte de contenu toute copie effectuée pendant le checkout et pendant le réarchivage, avant de considérer la source comme sûre et la destination comme fiable.
139+- **FR-016**: Une fois toutes les écritures d'une réconciliation confirmées et effectuées, le système DOIT libérer le verrou du dossier concerné.
140+- **FR-017**: Le système DOIT stocker l'état de référence de façon persistante et atomique, sans jamais laisser un état partiellement écrit observable après une interruption, plutôt que de le recréer à chaque checkout.
141+- **FR-018**: Le format de l'état de référence DOIT porter un numéro de version distinguant une évolution additive (tolérée par une version antérieure du logiciel) d'une évolution structurelle (refusée explicitement plutôt qu'interprétée à tort).
142+- **FR-019**: Le système DOIT permettre de restreindre un checkout à un sous-ensemble de répertoires de format (ex. jpeg seul) plus la racine de sélection, sans que cela ne constitue un sous-dossier isolé au sens de FR-001.
143+- **FR-020**: Les fichiers volontairement exclus d'un checkout partiel ne DOIVENT jamais être signalés comme supprimés ou anormaux lors de la réconciliation qui suit.
144+
145+### Key Entities
146+
147+- **État de référence (manifeste)** : instantané pris au checkout pour chaque fichier d'un dossier (chemin, taille, empreinte de contenu, identifiant pérenne), stocké de façon persistante et versionnée, pas recréé à chaque checkout.
148+- **Verrou de dossier** : marqueur côté archive posé au checkout et levé à la réconciliation réussie, empêchant un accès concurrent à l'ensemble du dossier (parent + sous-dossiers).
149+- **Copie de travail locale** : espace d'édition libre issu d'un checkout, sans contrainte, jamais synchronisé avec l'archive avant une réconciliation explicite.
150+- **Changement classé** : résultat de la comparaison entre l'état de référence et la copie de travail — normal, anomalie, renommage/déplacement, suppression, ou nouveau fichier.
151+- **Point avant archive** : récapitulatif de tous les changements classés, présenté à l'utilisateur et validé explicitement avant toute écriture sur l'archive.
152+- **Anomalie** : fichier maître dont le contenu pertinent a changé par rapport à l'état de référence — jamais réarchivée silencieusement, toujours soumise à une décision explicite (confirmer ou restaurer).
153+
154+## Success Criteria *(mandatory)*
155+
156+### Measurable Outcomes
157+
158+- **SC-001**: 100% des checkouts produisent un état de référence complet avant que la copie de travail ne soit considérée utilisable.
159+- **SC-002**: 100% des tentatives de checkout sur un dossier déjà verrouillé sont refusées avec un message explicite.
160+- **SC-003**: 100% des fichiers maîtres modifiés détectés à la réconciliation sont signalés comme anomalie, jamais réarchivés silencieusement.
161+- **SC-004**: 100% des renommages ou déplacements (fichier ou dossier entier) à contenu inchangé sont détectés comme tels, jamais comme une suppression suivie d'une création.
162+- **SC-005**: Aucune suppression ni aucun nouveau fichier n'est archivé sans confirmation explicite de l'utilisateur.
163+- **SC-006**: 100% des réconciliations menées à bien libèrent le verrou du dossier concerné, le rendant à nouveau disponible pour un futur checkout.
164+- **SC-007**: Une interruption survenant pendant un réarchivage ne laisse jamais l'état de référence ou l'archive dans un état partiellement écrit observable.
165+
166+## Assumptions
167+
168+- Le premier archivage d'un dossier nouvellement importé (`specs/001-import-photos`) ne passe pas par ce mécanisme de réconciliation : il n'existe pas encore d'état de référence à comparer, seulement une création initiale. Ce mécanisme s'applique aux dossiers déjà archivés que l'on ré-édite.
169+- Le travail à plusieurs avec verrouillage fin (édition concurrente de deux sous-dossiers d'un même dossier parent) reste hors périmètre de cette itération, cohérent avec les notes de conception du projet : le verrouillage porte toujours sur le dossier complet (parent et tous ses sous-dossiers), jamais à un niveau plus fin.
170+- La vérification périodique indépendante du checkout (scrub, cf. constitution § Contraintes techniques) est une capacité distincte, hors périmètre de cette spécification ; elle réutilisera le même mécanisme d'empreintes de contenu sans dépendre d'un checkout.
171+- Le déverrouillage forcé d'un dossier resté verrouillé anormalement longtemps (oubli utilisateur) reste une action manuelle et avertie, hors périmètre détaillé de cette itération ; aucun mécanisme de récupération automatique n'est couvert ici.
172+- La désambiguïsation de boîtiers (`specs/002-profil-boitiers-optionnel`) et la catégorisation racine (`specs/004-categorisation-dossiers`) restent celles déjà spécifiées ; cette spécification s'appuie sur FR-008/FR-010 de `specs/004-categorisation-dossiers` (détection de déplacement de dossier par hash) sans les redéfinir, et les concrétise ici.