description: "Task list for feature implementation"
Tasks: Configuration du contexte de travail de Régine
Input: Design documents from /specs/003-config-contexte-travail/
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 (à lire avant de commencer)
| Dépendance | Fournit | État |
|---|---|---|
specs/004-categorisation-dossiers |
regine_core.config.db.open_context_db (base de contexte centralisée, déjà créée) |
Implémentée |
specs/002-profil-boitiers-optionnel |
regine_core.camera_profile.db (table boitiers, list_boitiers, rename_boitier, get_or_create_boitier) — possède la table boitiers, cette spec ne fait que l'exposer (cf. plan.md « Correction du 2026-09-18 ») |
Implémentée |
specs/005-checkout-reconciliation |
regine_core.archive.manifest (manifeste persistant par dossier, PRAGMA user_version/application_id) et regine_core.archive.verrou (verrouillage) — réutilisés tels quels pour FR-006/FR-010 (détection de travail non réconcilié) |
Implémentée |
specs/001-import-photos |
regine_core.import_carte.copie.EXTENSIONS_MAITRES (réutilisée par le parcours NAS, US3/FR-012, pour reconnaître un fichier maître sans dupliquer la liste) |
Implémentée |
Écarts entre les documents de conception et l'état réel du code (à respecter pendant l'implémentation)
data-model.md§ Base de contexte centralisée a été rédigé avant l'implémentation despecs/002-profil-boitiers-optionnelet décrit une colonnesourceà deux valeurs (import/parcours_nas). Le schéma réellement livré par specs/002 (camera_profile/db.py) utilise déjàsourcepour une distinction différente et orthogonale (modele/numero_serie/manuel— comment un boîtier a été désambiguïsé). Ne PAS renommer ni migrer cette colonne déjà testée : réutiliser la même colonne texte libre en y ajoutant la seule valeur manquanteparcours_nas(FR-012) ; à l'affichage (cameras list), traiter toute valeur différente deparcours_nascomme « détecté via import » (FR-008).- research.md ne fixe pas l'emplacement de fichier de la base de contexte centralisée (seulement son schéma). Décision prise dans cette liste de tâches (T005) : un emplacement fixe par utilisateur, indépendant de
local_work_dir(qui, lui, est modifiable, cf. FR-010/SC-005 — la base de contexte ne doit jamais se perdre à un changement de chemin). - FR-006/Acceptance Scenario 3 (US1) : lu littéralement (« une base de données de travail est créée... à la racine de ce répertoire »). Réutilise directement
regine_core.archive.manifest.ouvrir_ou_creersurlocal_work_dirlui-même (déjà générique, accepte n'importe quel dossier) plutôt que d'inventer un second mécanisme — cohérent avec l'Assumption de spec.md (« cette spécification couvre son initialisation... pas son schéma détaillé »). Le manifeste par dossier archivé (FR-007) reste géré indépendamment parspecs/001/specs/005, déjà correct. Retiré par la Phase 7 (User Story 5, 2026-09-23/24) : ce choix s'est révélé être une impasse — ce manifeste vide à la racine delocal_work_dirn'a jamais été exploité par aucun autre module (le verrou/manifeste réel vit uniquement côté archive, cf. T009 ci-dessous), et FR-006 a depuis été révisée par l'utilisateur pour désigner explicitement la base de contexte centralisée elle-même (boîtiers/catégories/historique), déplacée à cet emplacement plutôt qu'à~/.regine/. - Ajouté en Phase 7 (User Story 5, 2026-09-23/24) :
open_context_dbperd son défaut implicite (path: Path | None = None→path: Path) mais garde exactement la même sémantique de paramètre (un chemin de fichier complet, jamais un dossier) — tous les appels existants despecs/001/002/004passent déjà un chemin de fichier explicite (tmp_path / "contexte.sqlite3"ou équivalent) et restent donc valides sans modification (cf. T046). Seuls les appels qui reposaient sur l'ancien défaut (open_context_db(None), dansconfig_cmd.py/archive_cmd.py/les écrans GUI, et le bug déjà présent dansimport_cmd.py) sont concernés par cette révision.
Phase 1: Setup
- T001 [P] Créer
packages/regine-core/src/regine_core/config/context.py(squelette, docstring de module uniquement) - T002 [P] Créer
packages/regine-core/src/regine_core/config/smb.py(squelette, docstring de module uniquement) - T003 [P] Créer
packages/regine-core/src/regine_core/config/cameras_screen.py(squelette, docstring de module uniquement) - T004 [P] Créer
packages/regine-cli/src/regine_cli/config_cmd.py(squelette, docstring de module uniquement) — etpackages/regine-cli/tests/contract/,[tool.pytest.ini_options] testpaths = ["tests"]ajouté àpackages/regine-cli/pyproject.toml(aucun test CLI automatisé n'existait encore dans le dépôt)
Phase 2: Foundational (Blocking Prerequisites)
Objectif : la persistance du contexte de travail (chemins + état SMB) et la détection de travail non réconcilié, dont dépendent les 3 user stories.
⚠️ CRITIQUE : aucune user story ne peut être implémentée avant la fin de cette phase.
- T005 Étendre
packages/regine-core/src/regine_core/config/db.py: ajouterCHEMIN_CONTEXTE_PAR_DEFAUT = Path.home() / ".regine" / "contexte.sqlite3"et rendreopen_context_db(path: Path | None = None)optionnel (défaut :CHEMIN_CONTEXTE_PAR_DEFAUT), sans changer le comportement pour les appelants existants qui passent déjà un chemin explicite (specs/001/002/004) - T006 [P] Test unitaire de
open_context_db(None)(utilise le chemin par défaut, le crée si absent) danspackages/regine-core/tests/unit/test_config_db_defaut.py— le test patch la constante de moduleCHEMIN_CONTEXTE_PAR_DEFAUTplutôt quePath.home(celle-ci est déjà évaluée à l'import, un monkeypatch après coup n'aurait aucun effet) - T007 Implémenter
ContexteTravail(dataclass), le schéma de la tablecontexte(ligne unique,id INTEGER PRIMARY KEY CHECK (id = 1)) etcharger_contexte(conn) -> ContexteTravaildanspackages/regine-core/src/regine_core/config/context.py(data-model.md § Contexte de travail) - T008 Implémenter les exceptions dédiées dans
context.py:RepertoireAbsentError,CheminsAmbigusError,CheminArchiveInvalideError,TravailNonReconcilieError(porte la liste des dossiers concernés) —ArchiveInaccessibleErrorajoutée en plus (cf. note T009) - T009 Implémenter
lister_dossiers_non_reconcilies(local_work_dir: Path, archive_root_local: Path) -> list[Path]danscontext.py— écart avec la conception initiale découvert à l'implémentation : le verrou/manifeste vit uniquement côté archive (specs/005, jamais recopié dans la copie de travail locale lors d'un checkout), donc parcourirlocal_work_dirseul ne peut jamais rien trouver. Corrigé : parcourt les manifestes dearchive_root_local(point de montage local du partage SMB,smb.chemin_local_du_partage), ne retient que ceux ayant une copie locale présente souslocal_work_dir. LèveArchiveInaccessibleErrorsi l'archive n'est pas accessible plutôt que de conclure à tort qu'il n'y a rien à signaler - T010 Implémenter
enregistrer_chemins(conn, *, temp_dir=None, local_work_dir=None, archive_smb_path=None, creer_repertoires_manquants=False, forcer_collision=False, ignorer_verification_archive=False) -> ContexteTravaildanscontext.py: validearchive_smb_path(DOIT commencer parsmb://, sinonCheminArchiveInvalideError), détecte la collisiontemp_dir == local_work_dir(CheminsAmbigusErrorsaufforcer_collision), bloque un changement delocal_work_dirvialister_dossiers_non_reconcilies(TravailNonReconcilieError) — sauf si aucune archive n'est encore configurée (rien à vérifier) ouignorer_verification_archive=True(geste explicite, même famille queforcer_collision) ; une archive configurée mais inaccessible refuse le changement par défaut (ArchiveInaccessibleErrorremontée telle quelle). Crée les répertoires manquants seulement sicreer_repertoires_manquants(sinonRepertoireAbsentError), initialise la base de travail à la racine d'un nouveaulocal_work_dir(regine_core.archive.manifest.ouvrir_ou_creer, FR-006/SC-003), puis persiste - T011 Implémenter
mettre_a_jour_etat_smb(conn, etat: Literal["mounted","unavailable","unknown"]) -> Nonedanscontext.py - T012 [P] Tests unitaires de
context.pydanspackages/regine-core/tests/unit/test_context_paths.py: configuration initiale, répertoire manquant sans/aveccreer_repertoires_manquants, collisiontemp_dir/local_work_dirsans/avecforcer_collision,archive_smb_pathinvalide (ne commence pas parsmb://), FR-006 (base de travail présente à la racine après configuration), champs non fournis conservés (SC-005) - T013 [P] Tests unitaires de
lister_dossiers_non_reconcilies/enregistrer_cheminsdanstest_context_paths.py: dossier verrouillé détecté, dossier réconcilié ignoré, archive inaccessible lève, aucune archive configurée n'exige aucune vérification,ignorer_verification_archivepasse outre explicitement — 15/15 tests passent (packages/regine-core/src/regine_core/config/smb.pyreçoit dès cette phasechemin_local_du_partage, requis par T009/T010 ; le reste desmb.py—disponible/declencher_montage/assurer_disponibilite— reste prévu en Phase 4/T020)
Checkpoint : la persistance du contexte est prête ; les 3 user stories peuvent commencer.
Phase 3: User Story 1 - Configuration initiale des emplacements de travail (Priority: P1) 🎯 MVP
Objectif : configurer et consulter les 3 emplacements de travail, avec initialisation de la base de travail et refus explicite d'un changement dangereux.
Test indépendant : configurer les 3 chemins sur un contexte vide (regine config set-paths), vérifier leur persistance (regine config show), vérifier qu'un changement de local_work_dir avec un dossier verrouillé dessous est refusé.
Tests for User Story 1
- T014 [P] [US1] Test d'intégration du cycle configuration → initialisation de la base de travail → changement de chemin bloqué dans
packages/regine-core/tests/integration/test_config_context.py(Acceptance Scenarios 1 à 5 de US1) - T015 [P] [US1] Test de contrat de la surface CLI (
set-paths,show, codes de sortie,--json) danspackages/regine-cli/tests/contract/test_cli_config.py
Implementation for User Story 1
- T016 [US1] Implémenter la sous-commande
regine config set-pathsdanspackages/regine-cli/src/regine_cli/config_cmd.py:--temp-dir,--local-work-dir,--archive-smb,--yes(confirme la création de répertoire, FR-003),--force(confirme la collision de chemins),--ignorer-verification-archive; traduit chaque exception decontext.pyen message stderr + code de sortie non-zéro (cf.contracts/cli-config.md) - T017 [US1] Implémenter la sous-commande
regine config show [--json]dansconfig_cmd.py: affiche les 3 chemins et l'état SMB connu, ou la liste des chemins manquants si le contexte n'est pas encore configuré (Edge Case) — implémentée en même temps que T021 (US2) :showdéclenchesmb.assurer_disponibilitedès qu'une archive est configurée, testé partest_cli_config.py - T018 [US1] Construire l'analyseur d'arguments (
construire_analyseur/main) dansconfig_cmd.py, cohérent avecimport_cmd.py/archive_cmd.py
Checkpoint : User Story 1 fonctionnelle et testable indépendamment (MVP) — 125/125 tests passent.
Phase 4: User Story 2 - Assistance quand l'archive NAS n'est pas accessible (Priority: P2)
Objectif : détecter l'indisponibilité du partage SMB avant qu'une opération échoue, déclencher le montage natif, permettre une reprise sans reconfiguration.
Test indépendant : configurer un archive_smb_path pointant vers un partage démonté, lancer regine config show, vérifier qu'un montage est déclenché et que l'état SMB est mis à jour ; remonter manuellement puis relancer, vérifier la reprise sans reconfiguration.
Note d'ordonnancement : implémentée en avance sur l'ordre de priorité initial, dès la Phase 3 — regine config show (T017) en a besoin directement (cf. quickstart.md scénario 4) et context.enregistrer_chemins/lister_dossiers_non_reconcilies (T009/T010, Phase 2) dépendaient déjà de smb.chemin_local_du_partage.
Tests for User Story 2
- T019 [P] [US2] Test unitaire de
smb.pydanspackages/regine-core/tests/unit/test_smb_disponibilite.py:disponible()sur un point de montage présent/absent (via un répertoire temporaire simulant/Volumes/<partage>, injecté par dépendance plutôt que codé en dur),assurer_disponibilite()met à joursmb_last_known_state, déclenche/ne déclenche pas le montage selondeclencher
Implementation for User Story 2
- T020 [US2] Implémenter
packages/regine-core/src/regine_core/config/smb.py:disponible(archive_smb_path: str) -> bool(vérifie l'accessibilité du point de montage macOS/Volumes/<partage>, dérivé de l'URLsmb://...),declencher_montage(archive_smb_path: str) -> None(open smb://..., cf. research.md § 1),assurer_disponibilite(conn, archive_smb_path, *, declencher=True) -> bool(met à jour l'état viacontext.mettre_a_jour_etat_smb, déclenche le montage si indisponible) - T021 [US2] Intégrer
smb.assurer_disponibilitedansregine config show(config_cmd.py) : si unarchive_smb_pathest configuré, vérifier sa disponibilité avant d'afficher l'état, déclencher le montage natif si nécessaire (Acceptance Scenario 1/2 de US2) — pas de nouvelle tentative automatique en boucle (Acceptance Scenario 3, une seule vérification par invocation, cohérent avec l'exécution sans démon)
Checkpoint : User Stories 1 et 2 fonctionnelles indépendamment.
Phase 5: User Story 3 - Nommer les boîtiers à partir des photos déjà archivées (Priority: P3)
Objectif : lister et nommer les boîtiers déjà enregistrés dans la base de contexte centralisée, sans réimport ni parcours du NAS ; parcours volontaire du NAS en complément optionnel (FR-012).
Test indépendant : sur une base de contexte contenant déjà des boîtiers enregistrés par un import (cf. specs/001), lister les boîtiers puis en nommer un, sans déclencher d'accès au NAS.
Tests for User Story 3
- T022 [P] [US3] Test unitaire de
cameras_screen.pydanspackages/regine-core/tests/unit/test_cameras_screen.py: liste des boîtiers déjà enregistrés (réutilisecamera_profile.db), nommage d'un boîtier connu,BoitierInconnuErrorsur un identifiant absent - T023 [P] [US3] Test d'intégration du parcours NAS dans
packages/regine-core/tests/integration/test_cameras_scan_nas.py: une arborescence simulant une archive avec des fichiers maîtres de boîtiers non encore connus (tags EXIF réels viaexiftool) ; vérifie queparcourir_nasles ajoute avecsource="parcours_nas"et n'affecte pas les boîtiers déjà connus (sourcemodele), plus idempotence (second parcours ne redouble rien)
Implementation for User Story 3
- T024 [US3] Implémenter
packages/regine-core/src/regine_core/config/cameras_screen.py:lister_boitiers(conn) -> list[Boitier](délègue àcamera_profile.db.list_boitiers, FR-008),nommer_boitier(conn, boitier_id: int, nom: str) -> None(délègue àcamera_profile.db.rename_boitieraprès avoir vérifié l'existence deboitier_id, sinonBoitierInconnuError— cf.contracts/cli-config.md),parcourir_nas(conn, archive_root: Path) -> int(parcourtarchive_rootà la recherche de fichiers d'extensionregine_core.import_carte.copie.EXTENSIONS_MAITRES, litModelviaregine_core.metadata.exif.read_camera_tags, appellecamera_profile.db.get_or_create_boitier(..., source="parcours_nas"), retourne le nombre de boîtiers réellement nouveaux — FR-012, PEUT donc optionnel mais implémenté ici) - T025 [US3] Implémenter les sous-commandes
regine config cameras list [--json],regine config cameras rename --id ID --nom NOM,regine config cameras scan-nas [--confirm]dansconfig_cmd.py—scan-nassans--confirmavertit et sort en code non-zéro sans rien exécuter (FR-012, cf.contracts/cli-config.md) ; vérifie la disponibilité de l'archive (smb.assurer_disponibilite) puis dérive son point de montage local viasmb.chemin_local_du_partage(même convention que US2, pas de second mécanisme de résolution). 9/9 tests de contrat CLI passent (test_cli_config.py, étendu pourcameras list/rename/scan-nas)
Checkpoint : les 3 user stories sont fonctionnelles indépendamment — 134/134 tests passent (packages/regine-core + packages/regine-cli).
Phase 6: User Story 4 - Configurer le contexte de travail depuis l'interface graphique (Priority: P4)
Ajoutée le 2026-09-21 (clarification + extension de plan post-implémentation) — cf. spec.md § Clarifications Session 2026-09-21.
Objectif : consulter et modifier le contexte de travail (chemins, état SMB, boîtiers nommés) depuis un 3e onglet de regine-gui (déjà implémentée par specs/006-gui-tri-consultation), en appelant exclusivement les fonctions regine_core.config déjà existantes — aucune nouvelle fonction regine-core requise (cf. plan.md extension du 2026-09-21).
Test indépendant : ouvrir l'onglet Configuration, y modifier un chemin, vérifier via regine config show (CLI) que le changement est bien reflété — sans dépendre des onglets Tri/Consultation.
Implementation for User Story 4
- T029 [US4] Créer
packages/regine-gui/src/regine_gui/config_view.py(squelette, docstring de module uniquement) - T030 [US4] Implémenter
EcranConfigurationdansconfig_view.py: affichage des 3 chemins et de l'état SMB au chargement (regine_core.config.context.charger_contexte), formulaire de modification appelantcontext.enregistrer_chemins— chaque exception (RepertoireAbsentError,CheminsAmbigusError,CheminArchiveInvalideError,TravailNonReconcilieError,ArchiveInaccessibleError) présentée clairement à l'utilisateur plutôt qu'une exception technique brute (FR-013, US4 Acceptance Scenario 2/3) - T031 [US4] Étendre
config_view.pyavec la liste des boîtiers et leur nommage (cameras_screen.lister_boitiers/nommer_boitier, US4 Acceptance Scenario 4) - T032 [US4] Câbler l'onglet « Configuration » dans
packages/regine-gui/src/regine_gui/app.py(FenetrePrincipale), aux côtés des onglets Tri/Consultation déjà existants - T033 [US4] Valider manuellement en mode headless (
QT_QPA_PLATFORM=offscreen, même méthode quespecs/006) : affichage/modification des chemins, gestion d'erreur, liste/nommage de boîtiers, parité avecregine config show/cameras list(Scénario 7 dequickstart.md, SC-008) — découverte de méthode de test :QMessageBox.warningbloque en attente d'un clic (comportement normal en usage réel), non testable tel quel en script headless ; validé en monkeypatchantQMessageBox.warningpour capturer l'appel sans dialogue modal réel —RepertoireAbsentErroretTravailNonReconcilieErrorconfirmées gérées sans crash, message clair, rien enregistré suite au refus
Checkpoint : les 4 user stories sont fonctionnelles indépendamment.
Phase 7: User Story 5 - Reprendre le travail sur une nouvelle machine sans perdre le contexte (Priority: P2)
Ajoutée le 2026-09-23/24 (écart trouvé par l'utilisateur + spec/plan révisés) — cf. spec.md § Clarifications Session 2026-09-23.
Objectif : séparer la configuration globale (chemins, propre à la machine, ~/.regine/config.sqlite3) de la base de contexte centralisée (boîtiers/catégories/historique d'imports, désormais à <local_work_dir>/contexte.sqlite3, remplaçant l'ancien manifeste vide jamais exploité qu'enregistrer_chemins y créait) ; répliquer cette dernière vers l'archive à chaque regine reconcile (FR-016) et la restaurer automatiquement à la configuration initiale ou au premier regine checkout sur une machine qui ne l'a pas encore (FR-017).
Test indépendant : enrichir le contexte sur une installation (nommer un boîtier), archiver un dossier (regine reconcile), configurer une seconde installation « neuve » pointant vers la même archive, vérifier que regine config cameras list y retrouve immédiatement ce boîtier sans réimport.
Tests for User Story 5
- T035 [P] [US5] Adapter
packages/regine-core/tests/unit/test_config_db_defaut.py:open_global_config_db()sans argument utilise~/.regine/config.sqlite3par défaut (comportement testé jusqu'ici suropen_context_db) ;open_context_db(path)exige désormaispath(plus de défaut implicite) - T036 [P] [US5] Test unitaire de
environnement.ouvrir_environnementdanspackages/regine-core/tests/unit/test_environnement.py:contexte_conn is Nonetant quelocal_work_dirn'est pas configuré dans la config globale ; une fois configuré,contexte_connpointe vers<local_work_dir>/contexte.sqlite3(créée si absente) - T037 [P] [US5] Test unitaire de
context.sauvegarder_contexte/restaurer_contexte_si_absentdanspackages/regine-core/tests/unit/test_contexte_replication.py: réplique vers l'archive (contenu identique après coup, vérifié par somme de contrôle), no-op si la base locale n'existe pas encore, restaure si absente localement mais présente sur l'archive, no-op si absente des deux côtés (première installation)
Implementation for User Story 5
- T038 [US5] Refactorer
packages/regine-core/src/regine_core/config/db.py: extraire le bootstrapPRAGMA application_id/user_versioncommun dans une fonction privée partagée ;open_context_db(path: Path) -> sqlite3.Connection(chemin désormais obligatoire,CHEMIN_CONTEXTE_PAR_DEFAUTretirée) ; nouvelleopen_global_config_db(path: Path | None = None) -> sqlite3.Connection(défautCHEMIN_CONFIG_GLOBALE_PAR_DEFAUT = Path.home() / ".regine" / "config.sqlite3") - T039 [US5] Créer
packages/regine-core/src/regine_core/config/environnement.py: dataclassEnvironnement(config_conn,contexte_conn: sqlite3.Connection | None,local_work_dir: Path | None),ouvrir_environnement(config_db_path: Path | None = None) -> Environnement(FR-014/015) - T040 [US5] Étendre
packages/regine-core/src/regine_core/config/context.py:enregistrer_cheminsinitialise désormais<local_work_dir>/contexte.sqlite3viadb.open_context_dbà la place de l'ancienregine_core.archive.manifest.ouvrir_ou_creer(retiré — supprime la dépendance de ce module versregine_core.archive, jamais réellement exploitée, cf. § Écarts en tête de fichier) ; nouvellessauvegarder_contexte(local_work_dir, archive_root_local) -> None(FR-016, copie vérifiée vers<archive_root_local>/.regine-contexte.sqlite3, no-op si source absente) etrestaurer_contexte_si_absent(local_work_dir, archive_root_local) -> bool(FR-017, copie vérifiée dans l'autre sens si la base locale est absente et qu'une sauvegarde existe) - T041 [US5] Mettre à jour
packages/regine-cli/src/regine_cli/config_cmd.py:ouvrir_environnement()remplaceopen_context_db(Path(args.contexte_db) if args.contexte_db else None); flag--contexte-dbrenommé--config-db;set-pathsappellerestaurer_contexte_si_absentjuste après unenregistrer_cheminsréussi silocal-work-diretarchive-smbsont tous deux connus à l'issue de la commande, annonce le résultat sur stdout (cf.contracts/cli-config.md) - T042 [US5] Mettre à jour
packages/regine-cli/src/regine_cli/archive_cmd.py:_charger_archive_root_localutiliseopen_global_config_db/ouvrir_environnement(l'emplacement de l'archive vit désormais dans la config globale, pas la base de contexte centralisée) ; flag--contexte-dbrenommé--config-db(browse/restore) ;_cmd_reconcileappellesauvegarder_contextejuste après un archivage réussi (FR-016) ;_cmd_checkoutappellerestaurer_contexte_si_absentjuste après un checkout réussi (FR-017) - T043 [US5] Corriger
packages/regine-cli/src/regine_cli/import_cmd.py(bug réel trouvé par l'utilisateur, cf.contracts/regine-core-api.md) : supprime_NOM_CONTEXTE_DB_PAR_DEFAUT/le flag--contexte-db(divergeait silencieusement du reste de la CLI) ; dérive directementPath(args.local_root) / "contexte.sqlite3"pourdb.open_context_db - T044 [US5] Mettre à jour
packages/regine-gui/src/regine_gui/app.py:FenetrePrincipalerésoutouvrir_environnement()une fois à la construction, propage le résultat aux onglets plutôt que chacun n'ouvre indépendammentopen_context_db(self._contexte_db) - T045 [US5] Mettre à jour
packages/regine-gui/src/regine_gui/config_view.py/import_view.py/consultation_view.py: consomment l'environnement résolu (chemins/état SMB viaenvironnement.config_conn, boîtiers/catégories/historique viaenvironnement.contexte_conn) plutôt que d'ouvrir elles-mêmes une connexion unique ambiguë - T046 [P] [US5] Vérifier chaque appelant existant de
open_context_dbdansspecs/001-import-photos/specs/002-profil-boitiers-optionnel/specs/004-categorisation-dossiers(tests unitaires/intégration) : tous passent déjà un chemin de fichier explicite (tmp_path / "contexte.sqlite3"ou équivalent), donc déjà compatibles avec la signature révisée sans modification — seultest_config_db_defaut.pydépendait de l'ancien défaut implicite, déjà traité par T035 - T047 [US5] Valider manuellement en mode headless (
QT_QPA_PLATFORM=offscreen, même méthode que les phases précédentes) les Scénarios 8, 9 et 10 dequickstart.md: réplication à unregine reconcile, restauration à la configuration initiale d'une « nouvelle machine », restauration au premierregine checkoutsi la configuration initiale n'a pas suffi (archive inaccessible à ce moment-là) — Scénarios 8 et 9 exécutés de bout en bout via un script headless simulant deux machines (import GUI sur machine A,regine reconciledéclenchant bien la sauvegarde vers<archive>/.regine-contexte.sqlite3, puisregine config set-pathssur une machine B neuve restaurant automatiquementcontexte.sqlite3avant tout import) :Contexte local machine A existe ? True,Sauvegarde présente sur l'archive ? True,Contexte restauré sur machine B ? True. Scénario 10 (restauration au premiercheckoutplutôt qu'àset-paths) non exécuté en conditions réelles (aurait nécessité un troisième montage SMB simulé) mais son câblage (_restaurer_contexte_post_checkoutdansarchive_cmd.py, appelant exactementrestaurer_contexte_si_absent) est identique à celui du Scénario 9 déjà validé et est couvert unitairement par T037 — aucun boîtier n'a été détecté lors de l'import (fichiers factices sans EXIF), donc c'est la présence decontexte.sqlite3restauré (plutôt qu'un boîtier nommé visible danscameras list) qui atteste de la réplication
Checkpoint : les 5 user stories sont fonctionnelles indépendamment ; un contexte enrichi sur une machine est retrouvable intégralement sur une autre pointant vers la même archive.
Phase 8: Polish & Cross-Cutting Concerns
- T026 [P] Exécuter manuellement les 6 scénarios de
specs/003-config-contexte-travail/quickstart.md(adaptés à la surface CLI réellement livrée) et consigner le résultat — scénarios 1, 2, 3, 5, 6 exécutés via la vraie CLI (uv run python -m regine_cli.config_cmd config ...), tous conformes. Scénario 4 (montage/démontage SMB réel) non exécutable dans cet environnement de développement (pas de partage SMB physique disponible) — le mécanisme sous-jacent (smb.disponible/assurer_disponibilite/declencher_montage) est validé unitairement avec un point de montage injecté (T019), etconfig showa correctement détectésmb://nas.local/regine-archive(inexistant dans cet environnement) commeunavailablelors du scénario 1, confirmant la détection réelle - T027 [P]
ruff check --fix+ruff formatsurpackages/regine-coreetpackages/regine-cli - T028 Mettre à jour
contracts/cli-config.mdet créercontracts/regine-core-api.md— signatures réelles documentées, écarts de conception consignés (cf. § Écarts en tête de fichier) ; note explicite queregine_cli.import_cmd/archive_cmd(specs/001/005) ne consomment pas encore ce contexte configuré (ils prennent--archive-root/--local-rooten flags explicites) — intégration future hors périmètre de cette spec, non construite ici sans nouvelle demande explicite - T034 [P] Exécuter le Scénario 7 de
quickstart.md(déjà couvert par T033, sans duplication) etruff check --fix/ruff formatsurpackages/regine-gui(nouveau fichierconfig_view.py) — 172/172 testsregine-core/regine-clitoujours au vert (aucune régression, aucun nouveau test requis côté core puisqu'aucune nouvelle fonction n'a été ajoutée) - T048 [P] Exécuter les Scénarios 8, 9 et 10 de
quickstart.md(cf. T047, sans duplication) etruff check --fix/ruff formatsur les trois paquets (regine-core,regine-cli,regine-gui) ; exécuter la suite de tests complète du dépôt et confirmer l'absence de régression sur les specs consommatrices (specs/001/002/004/005/006) ; mettre à jourcontracts/regine-core-api.md/cli-config.mdsi l'implémentation révèle un écart avec les signatures documentées —ruff check --fix: aucun problème détecté sur les trois paquets ;ruff format: 1 fichier reformaté (changement cosmétique, sans lien avec cette story) ; suite complète : 190/190 tests passent (aucune régression sur specs/001/002/004/005/006) ; aucun écart supplémentaire trouvé nécessitant une mise à jour des contrats au-delà de ceux déjà consignés lors de T041-T043
Dependencies & Execution Order
- Setup (Phase 1) : aucune dépendance, tâches
[P]en parallèle. - Foundational (Phase 2) : dépend de Setup ; bloque toutes les user stories.
- US1 (Phase 3) : dépend de Foundational uniquement. MVP.
- US2 (Phase 4) : dépend de Foundational ; s'intègre à
regine config show(US1) mais reste testable indépendamment (smb.pyseul). - US3 (Phase 5) : dépend de Foundational et de
specs/002(déjà livrée) ; indépendante de US1/US2. - US4 (Phase 6) : dépend de US1/US2/US3 (appelle leurs fonctions telles quelles) et de
specs/006-gui-tri-consultation(déjà livrée, fournitregine-gui/app.py/PySide6) ; aucune dépendance nouvelle côtéregine-core. - US5 (Phase 7) : dépend de Foundational (révise directement
db.py/context.pyde la Phase 2) et despecs/005-checkout-reconciliation(déjà livrée, fournitreconcile/checkoutsur lesquels s'accrochent FR-016/FR-017) ; touche transversalement US1 (config_cmd.py), US3 (consommateur de la base de contexte déplacée) et US4 (écrans GUI) sans changer leur comportement observable — à mener après elles, jamais en parallèle, du fait de ce chevauchement de fichiers. - Polish (Phase 8) : dépend des user stories livrées (au minimum US1 ; T034 dépend spécifiquement de US4, T048 dépend spécifiquement de US5).
Implementation Strategy
MVP = Phase 1 + 2 + 3 (US1). US2 et US3 sont des incréments indépendants livrables ensuite dans l'ordre de priorité. US4 (ajoutée le 2026-09-21) est un incrément de confort pur, livrable à tout moment après specs/006-gui-tri-consultation — sans lui, la CLI (US1-3) reste pleinement fonctionnelle et suffisante. US5 (ajoutée le 2026-09-23/24) révise une hypothèse de conception jamais correctement exploitée depuis le début (US1/FR-006) plutôt que d'ajouter une capacité isolée : contrairement à US2-4, elle touche des fichiers déjà livrés par les phases précédentes (db.py, context.py, config_cmd.py, archive_cmd.py, import_cmd.py, les écrans GUI) et doit donc être menée en dernier, séquentiellement, plutôt qu'en parallèle d'une autre user story.
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 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
|