description: "Task list for feature implementation"
Tasks: Catégorisation des dossiers à la racine de l'archive
Input: Design documents from /specs/004-categorisation-dossiers/
Prerequisites: plan.md, spec.md, research.md, data-model.md, contracts/regine-core-api.md, quickstart.md
Tests: Incluses — plan.md § Project Structure nomme explicitement les fichiers de test attendus (test_root_resolution.py, test_categories_cache.py, test_root_inheritance.py), 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.
État du dépôt au moment de la génération
Aucun code n'existe encore dans ce dépôt (seuls docs/, specs/, .specify/ sont présents). Cette fonctionnalité étant la première à atteindre /speckit-tasks, la Phase 1 crée le squelette du monorepo déjà décrit dans specs/003-config-contexte-travail/plan.md (bibliothèque centrale + 3 façades). Ce squelette, une fois créé, est réutilisable tel quel par les futures tâches de specs/001, 002 et 003 — pas à recréer.
Décision de conception prise à ce stade (raffinement par rapport à contracts/regine-core-api.md) : determine_root reçoit archive_root et local_root en paramètres explicites plutôt que de les lire depuis le contexte de travail de specs/003-config-contexte-travail (pas encore implémenté). Ceci garde le module dossier testable et livrable indépendamment de specs/003. Le futur code d'intégration (CLI d'import, specs/001-import-photos) sera responsable de lire le contexte de travail et de le passer à determine_root.
Phase 1: Setup (Shared Infrastructure)
Purpose: Initialisation du monorepo — aucun paquet n'existe encore.
- T001 Créer le squelette du monorepo à la racine du dépôt :
packages/regine-core/,packages/regine-cli/,packages/regine-gui/,packages/regine-agent/, plus unpyproject.tomlracine déclarant un workspaceuvréférençant les 4 paquets (cf.specs/003-config-contexte-travail/plan.md§ Project Structure etresearch.md§ 5) - T002 [P] Initialiser
packages/regine-core/pyproject.toml(nomregine-core, aucune dépendance tierce) etpackages/regine-core/src/regine_core/__init__.py - T003 [P] Initialiser
packages/regine-cli/pyproject.toml(dépendance versregine-core) etpackages/regine-cli/src/regine_cli/__init__.py - T004 [P] Créer
packages/regine-gui/pyproject.tomletpackages/regine-agent/pyproject.tomlcomme paquets vides (dépendance déclarée versregine-core, aucun code métier), conformément àspecs/003-config-contexte-travail/plan.md - T005 [P] Configurer
ruff(lint + format) au niveau dupyproject.tomlracine du workspace - T006 [P] Configurer
pytestpourpackages/regine-core([tool.pytest.ini_options], création des dossierstests/unit/,tests/integration/,tests/contract/)
Phase 2: Foundational (Blocking Prerequisites)
Purpose: Infrastructure partagée requise par toutes les user stories de cette fonctionnalité.
⚠️ CRITICAL: Aucune user story ne peut être implémentée avant la fin de cette phase.
- T007 Créer
packages/regine-core/src/regine_core/dossier/__init__.py(premier code du moduledossier, cf.docs/interface-cli-gui-architecture.md) - T008 Définir le dataclass
RootLocation(type: Literal["annee", "categorie"],nom: str,chemin_archive: Path,chemin_local: Path) et la signature dedetermine_root(date, categorie=None, *, archive_root, local_root)(corps non implémenté) danspackages/regine-core/src/regine_core/dossier/root.py - T009 Créer
packages/regine-core/src/regine_core/config/db.py: fonctionopen_context_db(path) -> sqlite3.Connectionavec bootstrapPRAGMA user_version/PRAGMA application_idet écriture transactionnelle — infrastructure partagée quespecs/003-config-contexte-travailréutilisera pour sa propre tableboitiers(cf.research.md§ 1,specs/003-config-contexte-travail/research.md§ 2) - T010 [P] Test unitaire du bootstrap de la base de contexte dans
packages/regine-core/tests/unit/test_db_bootstrap.py(vérifiePRAGMA user_version/application_idaprès initialisation, réouverture idempotente sans perte de données)
Checkpoint: Fondations prêtes — les phases User Story peuvent commencer.
Phase 3: User Story 1 - Placement par année par défaut (Priority: P1) 🎯 MVP
Goal: Un dossier importé sans catégorie choisie est placé sous un répertoire d'année, identique dans l'archive et l'espace de travail local (FR-002).
Independent Test: Appeler determine_root(date(2026, 8, 15), archive_root=..., local_root=...) et vérifier type == "annee", nom == "2026", chemin_archive et chemin_local en miroir sous 2026/ — sans dépendre d'aucune autre user story.
Tests for User Story 1
- T011 [P] [US1] Test unitaire :
determine_rootsans catégorie retournetype="annee",nomdérivé de l'année de la date, chemins archive/local en miroir, danspackages/regine-core/tests/unit/test_root_resolution.py
Implementation for User Story 1
- T012 [US1] Implémenter la branche par défaut (année) de
determine_rootdanspackages/regine-core/src/regine_core/dossier/root.py(dépend de T008) - T013 [US1] Garantir par construction que
chemin_archive.name == chemin_local.name == nom(miroir archive/local, FR-002) — pas de synchronisation a posteriori
Checkpoint: User Story 1 fonctionnelle et testable indépendamment (MVP).
Phase 4: User Story 2 - Import relevant d'une catégorie thématique (Priority: P2)
Goal: Un dossier pour lequel l'utilisateur choisit une catégorie est placé directement sous le répertoire de cette catégorie, sans répertoire d'année (FR-003, FR-004, FR-005).
Independent Test: Appeler determine_root(date, categorie="mariage", ...) et vérifier type == "categorie", nom == "mariage", aucun répertoire d'année dans le chemin ; vérifier que suggest_categories("Mariage") retourne ["mariage"] après un premier register_category_usage("mariage").
Tests for User Story 2
- T014 [P] [US2] Test unitaire :
determine_rootaveccategorieretournetype="categorie", aucun répertoire d'année, danspackages/regine-core/tests/unit/test_root_resolution.py - T015 [P] [US2] Test unitaire :
list_known_categories,suggest_categories,register_category_usagedanspackages/regine-core/tests/unit/test_categories_cache.py(liste vide au départ ;suggest_categories("Mariage")retrouve"mariage"après enregistrement ; pas de doublon silencieux)
Implementation for User Story 2
- T016 [US2] Ajouter la table
categories(nomUNIQUE,premiere_utilisation) au schéma depackages/regine-core/src/regine_core/config/db.py(dépend de T009) — implémentée dansconfig/categories.py(_ensure_schema), le fichiercategoriesdu contexte centralisé reste ouvert viadb.open_context_db - T017 [P] [US2] Implémenter
list_known_categories()danspackages/regine-core/src/regine_core/config/categories.py(dépend de T016) - T018 [P] [US2] Implémenter
suggest_categories(saisie)avecdifflib.get_close_matchesdanspackages/regine-core/src/regine_core/config/categories.py(dépend de T016 ; cf.research.md§ 2) - T019 [US2] Implémenter
register_category_usage(nom)(idempotent ; à n'appeler qu'après confirmation explicite d'archivage, cf. Principe II de la constitution) danspackages/regine-core/src/regine_core/config/categories.py(dépend de T016) - T020 [US2] Implémenter la branche catégorie de
determine_rootdansroot.py(dépend de T012) - T021 [US2] Test de non-régression : la signature de
determine_rootn'accepte qu'un seul paramètrecategorie(jamais une liste) — garantit FR-005 (une seule catégorie à la fois) danstest_root_resolution.py
Checkpoint: User Stories 1 ET 2 fonctionnelles indépendamment.
Phase 5: User Story 3 - Héritage de la catégorie par les sous-dossiers d'un voyage (Priority: P3)
Goal: Un sous-dossier ajouté à un dossier parent existant hérite automatiquement de son RootLocation, sans nouvel appel à determine_root (FR-006).
Independent Test: Résoudre un RootLocation pour un dossier parent, puis vérifier qu'un sous-dossier réutilise cet objet tel quel (même nom, même type) sans recalcul.
Tests for User Story 3
- T022 [P] [US3] Test d'intégration : le
RootLocationd'un dossier parent est réutilisé tel quel pour un sous-dossier, sans nouvel appel àdetermine_root, danspackages/regine-core/tests/integration/test_root_inheritance.py
Implementation for User Story 3
- T023 [US3] Documenter (docstring) dans
root.pyquedetermine_rootne DOIT être appelée qu'une seule fois par dossier parent — le futur code appelant (import,specs/001-import-photos) réutilise l'objetRootLocationdéjà résolu pour tout sous-dossier ; aucune nouvelle logique de calcul requise ici
Checkpoint: User Stories 1, 2 et 3 fonctionnelles indépendamment.
Phase 6: User Story 4 - Recatégorisation a posteriori (Priority: P4)
Goal: Un déplacement d'un dossier entre répertoires racines est reconnu comme tel par le mécanisme de réconciliation par hash (FR-008) — pas de mécanisme dédié à construire ici.
Statut : Mise à jour du 2026-09-19 — le mécanisme de détection de déplacement par somme de contrôle a désormais sa propre spec et son propre plan (specs/005-checkout-reconciliation, dont FR-010 couvre exactement ce cas). Ce n'est plus une dépendance bloquante au niveau spécification : seulement une dépendance d'ordonnancement (l'implémentation de specs/005 doit précéder la validation de bout en bout de cette user story).
- T024 [US4] Documenter (docstring) dans
packages/regine-core/src/regine_core/dossier/root.pyqu'il n'existe aucune opération d'écriture directe surRootLocation: tout changement de répertoire racine passe exclusivement parregine_core.archive.reconciliation.comparer(specs/005-checkout-reconciliation), qui classe un déplacement de dossier entier commedeplacementsans code supplémentaire ici - T024b [US4] Test d'intégration : déplacer un dossier de travail entre deux répertoires racine (année → catégorie) et vérifier que
regine_core.archive.reconciliation.comparerle classedeplacement, danspackages/regine-core/tests/integration/test_root_recategorisation.py— écart avec l'intitulé initial constaté à l'implémentation (2026-09-20) :comparerne raisonne que sur des chemins relatifs internes à un dossier, jamais sur son répertoire racine (cf. docstring detest_whole_folder_move_detected_as_move_for_every_file, specs/005) ; recatégoriser un dossier entier en conservant sa structure interne n'est donc PAS classédeplacement, mais totalement invisible pourcomparer(chaque fichier reste « inchangé », omis du rapport) — c'est le comportement correct et recherché (aucune anomalie ni signalement erroné). Test écrit en conséquence avecdetermine_root(specs/004) pour les deux racines etrapport.changements == []comme assertion ; passe du premier coup, 135/135 tests
Checkpoint: US4 documentée et validée par test d'intégration — toutes les user stories de cette spec sont désormais complètes (28/28).
Phase 7: Polish & Cross-Cutting Concerns
- T025 [P] Exécuter manuellement les scénarios 1 à 4 de
specs/004-categorisation-dossiers/quickstart.mdet consigner le résultat — 2026-09-19 : les 4 scénarios passent (déroulés viauv run python3, cf. session d'implémentation) - T026 [P]
ruff check --fixsurpackages/regine-core— 0 erreur restante, code formaté - T027 Mettre à jour
specs/004-categorisation-dossiers/contracts/regine-core-api.mdpour refléter la signature définitive dedetermine_root(paramètresarchive_root/local_rootexplicites, cf. Note en tête de ce fichier)
Dependencies & Execution Order
Phase Dependencies
- Setup (Phase 1) : aucune dépendance — peut démarrer immédiatement.
- Foundational (Phase 2) : dépend de Setup — BLOQUE toutes les user stories.
- User Stories (Phase 3–6) : dépendent toutes de Foundational.
- US1 (P1) : aucune dépendance sur une autre user story.
- US2 (P2) : dépend techniquement de T012 (branche année déjà en place dans
determine_root) mais reste testable et livrable indépendamment de US1 côté utilisateur. - US3 (P3) : dépend de US1 et US2 étant données (réutilise leurs
RootLocation), mais n'ajoute aucune nouvelle logique de calcul. - US4 (P4) : dépend de l'implémentation de
specs/005-checkout-reconciliation(désormais spécifiée et planifiée) pour sa validation de bout en bout ; la tâche de documentation T024 reste exécutable dès maintenant.
- Polish (Phase 7) : dépend des user stories livrées (au minimum US1+US2).
Parallel Opportunities
- T002–T006 (Phase 1) : tous marqués [P], fichiers/paquets distincts.
- T010 (Phase 2) : parallélisable une fois T009 terminé.
- T011 (US1), T014/T015 (US2), T022 (US3) : tests marqués [P], fichiers distincts.
- T017/T018 (US2) : parallélisables (même fichier
categories.pymais fonctions indépendantes sans état partagé en cours d'écriture — à fusionner avec attention si exécutées par deux agents en parallèle).
Parallel Example: User Story 2
# Lancer les tests de la User Story 2 ensemble :
Task: "Test unitaire determine_root avec catégorie dans packages/regine-core/tests/unit/test_root_resolution.py"
Task: "Test unitaire cache de catégories dans packages/regine-core/tests/unit/test_categories_cache.py"
# Lancer les fonctions indépendantes de config/categories.py ensemble :
Task: "Implémenter list_known_categories() dans packages/regine-core/src/regine_core/config/categories.py"
Task: "Implémenter suggest_categories(saisie) dans packages/regine-core/src/regine_core/config/categories.py"
Implementation Strategy
MVP First (User Story 1 uniquement)
- Compléter Phase 1 (Setup) et Phase 2 (Foundational).
- Compléter Phase 3 (US1) : placement par année par défaut.
- Arrêt et validation : exécuter le Scénario 1 de
quickstart.md. - Ce socle (monorepo +
RootLocation+ base de contexte) sert aussi de fondation aux futures tâches despecs/001,002et003.
Livraison incrémentale
- Setup + Foundational → socle prêt.
- US1 → placement par année (MVP) → valider Scénario 1.
- US2 → catégories thématiques → valider Scénario 2 et 3.
- US3 → héritage voyage → valider Scénario 4.
- US4 → documentation exécutable dès maintenant (T024) ; validation de bout en bout (T024b) une fois
specs/005-checkout-reconciliationimplémentée.
Notes
- [P] = fichiers différents, sans dépendance non résolue.
- Chaque user story est livrable et testable indépendamment ; US4 dépend de l'implémentation de
specs/005-checkout-reconciliation(désormais spécifiée et planifiée) pour sa validation de bout en bout, mais sa tâche de documentation (T024) ne l'est pas. - Committer après chaque tâche ou groupe logique de tâches.
- Le squelette monorepo (Phase 1) et la base de contexte (T009) sont des fondations partagées : ne pas les recréer lors des futures exécutions de
/speckit-taskssurspecs/001,002ou003— les étendre.
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 |
|