Implementation Plan: Checkout et réconciliation d'un dossier de l'archive
Branch: 005-checkout-reconciliation | Date: 2026-09-18 | Spec: spec.md
Input: Feature specification from /specs/005-checkout-reconciliation/spec.md
Summary
Implémente le cycle complet checkout → édition libre → réconciliation → réarchivage pour un dossier déjà présent dans l'archive : copie vérifiée vers un espace de travail local avec enregistrement d'un état de référence persistant, verrouillage côté archive, comparaison par empreinte de contenu classant chaque changement (normal, anomalie sur fichier maître, renommage/déplacement, suppression, nouveau fichier), présentation d'un « point avant archive » et écriture confirmée uniquement. Approche technique : deux nouveaux modules de la bibliothèque centrale déjà nommés dans l'architecture du projet — regine_core.integrity (hash à deux niveaux, décision anomalie/pas-anomalie) et regine_core.archive (manifeste persistant par dossier, verrouillage, checkout, réconciliation) — consommés par une nouvelle façade CLI (regine checkout, regine reconcile). Débloque le sous-scénario FR-009 de specs/001-import-photos et la User Story 4 de specs/004-categorisation-dossiers, tous deux documentés comme bloqués en attendant ce plan.
Technical Context
Language/Version: Python 3.11+ (cohérent avec regine-core, cf. specs/002/003/004)
Primary Dependencies: exiftool (déjà acté par specs/002-profil-boitiers-optionnel, étendu ici pour le calcul de ImageDataHash sur DNG/TIFF/JPEG) ; bibliothèque standard uniquement sinon (hashlib pour l'empreinte fichier entier SHA-256, sqlite3 pour le manifeste persistant, pathlib/shutil pour les copies vérifiées)
Storage: SQLite — un fichier de manifeste par dossier principal (parent + tous ses sous-dossiers), à sa racine sur l'archive, selon les conventions déjà actées par la constitution (PRAGMA user_version/application_id, écriture transactionnelle) ; le verrou de dossier vit dans la même base (table dédiée), pas un fichier séparé (cf. research.md § 2)
Testing: pytest ; tests unitaires sur la classification de réconciliation (les 5 catégories de changement), sur la décision anomalie/pas-anomalie par format, sur le versionnement de schéma ; tests d'intégration sur le cycle complet checkout→édition simulée→réconciliation→réarchivage en répertoires temporaires (archive et local simulés par le système de fichiers)
Target Platform: poste de bureau, identique aux autres modules ; l'archive est accédée comme un partage réseau monté (cf. specs/003-config-contexte-travail), aucune primitive de verrouillage réseau spécifique supposée disponible (cf. research.md § 3, limitation documentée)
Project Type: Monorepo existant — deux nouveaux modules regine_core/integrity/ et regine_core/archive/ (derniers modules de la bibliothèque centrale nommés dans docs/interface-cli-gui-architecture.md mais pas encore construits), plus une nouvelle commande CLI
Performance Goals: la réconciliation d'un dossier de quelques centaines à quelques milliers de fichiers DOIT rester praticable (minutes, pas heures) ; pas de cible chiffrée au-delà, cohérent avec l'absence de cible chiffrée dans la spec elle-même
Constraints: aucune primitive de verrouillage distribué fiable n'est supposée disponible sur un partage SMB ordinaire — le verrouillage reste une protection applicative de bonne foi (toutes les instances de Régine le respectent), pas une garantie absolue contre une écriture concurrente hors de Régine (cf. research.md § 3, limitation déjà acceptée par la constitution : « protections filesystem... en filet de sécurité complémentaire ») ; le travail à plusieurs avec verrouillage fin reste hors périmètre (Assumptions de la spec)
Scale/Scope: dossier archivé typique de quelques dizaines à quelques milliers de fichiers ; usage mono-utilisateur avec protection best-effort contre une seconde instance
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 | C'est l'implémentation directe de ce principe : FR-007/FR-008 appliquent exactement le mécanisme de hash à deux niveaux déjà décrit par le Principe I (empreinte fichier entier pour RAW propriétaires, empreinte image-only pour DNG/TIFF/JPEG), et ne réarchivent jamais silencieusement une anomalie. |
| II. Confirmation explicite avant toute action à risque | PASS | FR-013 : aucune écriture sur l'archive sans confirmation explicite du « point avant archive » ; FR-011 : aucune suppression propagée automatiquement. |
| III. Identité par contenu, jamais par nom de fichier seul | PASS | C'est également une implémentation directe : FR-009/FR-010 détectent tout renommage/déplacement par empreinte de contenu, jamais par chemin ou nom. |
| IV. Métadonnées ouvertes et embarquées | N/A | Ce module ne touche pas aux métadonnées descriptives/de droits (légende, mots-clés, etc.) ; il lit l'identifiant pérenne déjà embarqué (specs/001) sans le redéfinir. |
| V. L'utilisateur décide, Régine suggère | PASS | FR-012 : tout fichier sans correspondance reste une décision explicite de l'utilisateur, jamais un défaut imposé (cf. spec.md Assumptions, tranché sur ce principe précisément). |
| VI. Bibliothèque centrale, façades minces | PASS | regine_core.integrity et regine_core.archive portent toute la logique ; la façade CLI n'orchestre que l'appel et l'affichage du récapitulatif. |
| CLI-first | PASS | regine checkout/regine reconcile sont les premières façades construites pour ce mécanisme. |
| Exécution sans démon | PASS | Chaque commande est un processus isolé ; le verrou est un état persistant en base, pas un service actif. |
| Vérification d'intégrité systématique | PASS | FR-015 : toute copie (checkout et réarchivage) vérifiée par empreinte de contenu. |
| Vérification périodique indépendante (scrub) | N/A (hors périmètre) | Explicitement exclu par les Assumptions de la spec ; ce plan ne le construit pas, mais regine_core.integrity (hash à deux niveaux) est conçu pour être réutilisé par un futur scrub sans redéfinition. |
| Formats ouverts et documentés | PASS | SQLite, déjà retenu par la constitution pour ce besoin précis (manifeste persistant). |
Aucune violation identifiée ; la section Complexity Tracking reste vide.
Re-check post Phase 1 (après génération de data-model.md, contracts/, quickstart.md) : le schéma du manifeste (une table par dossier principal, versionnée) et les contrats CLI/API interne (classification en 5 catégories exposée comme objets structurés, jamais de texte à parser) confirment chaque évaluation PASS ci-dessus. Aucune violation nouvelle.
Project Structure
Documentation (this feature)
specs/005-checkout-reconciliation/
├── 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-checkout-reconcile.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_image_data_hash() pour DNG/TIFF/JPEG
│ │
│ ├── integrity/ # NOUVEAU module (dernier module nommé dans l'architecture, pas encore construit)
│ │ ├── __init__.py
│ │ ├── hash.py # hash_fichier_entier() [SHA-256 stdlib], hash_image_only() [délègue à metadata.exif]
│ │ └── anomalie.py # est_maitre_modifie(format, ref, actuel) -> bool (FR-007/FR-008, Principe I)
│ │
│ └── archive/ # NOUVEAU module
│ ├── __init__.py
│ ├── manifest.py # ouverture/initialisation SQLite par dossier principal, PRAGMA user_version/application_id (FR-002/017/018)
│ ├── verrou.py # pose/vérifie/lève le verrou dans la même base (FR-003/004/016)
│ ├── checkout.py # checkout(dossier, dest_locale, formats=None) -> ManifestSnapshot (FR-001/019/020)
│ └── reconciliation.py # comparer() -> RapportReconciliation (FR-006/009/010/011/012/014), archiver() (FR-013/015/016)
│
└── tests/
├── unit/
│ ├── test_hash_deux_niveaux.py # RAW propriétaire vs DNG/TIFF/JPEG, anomalie vs édition légitime
│ ├── test_manifest_versioning.py # PRAGMA user_version, refus sur évolution structurelle, tolérance additive
│ ├── test_verrou.py # pose, refus de double checkout, levée après réconciliation
│ └── test_reconciliation_classification.py # les 5 catégories, y compris déplacement de dossier entier (specs/004)
└── integration/
├── test_cycle_checkout_reconciliation.py # US1+US2 : checkout → édition simulée → réconciliation → réarchivage
└── test_checkout_partiel.py # US6 : formats exclus jamais signalés comme anormaux
packages/regine-cli/
└── src/regine_cli/
└── archive_cmd.py # NOUVEAU : commandes `regine checkout <dossier>` / `regine reconcile <dossier>`
Structure Decision: Extension du monorepo existant — deux modules qui achèvent la liste des modules de bibliothèque centrale déjà documentée (docs/interface-cli-gui-architecture.md : metadata, archive, import, dossier, integrity, camera_profile — seuls archive et integrity manquaient encore). regine_core.metadata.exif (specs/002) est étendu plutôt que dupliqué pour le calcul ImageDataHash. Ce plan complète aussi les points d'intégration laissés en attente par specs/001-import-photos (FR-009) et specs/004-categorisation-dossiers (User Story 4).
Complexity Tracking
Aucune violation de gate à justifier — section laissée vide intentionnellement.
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 |
|