Architecture
ISNAD — Architecture cible du repository (E11-T2)
Sur cette page
Statut : proposition officielle soumise à validation du Project Lead. Ce document ne déplace, ne renomme et ne modifie aucun fichier. Il définit où chaque type de fichier doit vivre, et pourquoi, à partir de l'inventaire réel produit en E11-T1.
Principe directeur : la plus petite architecture capable de soutenir ISNAD durablement (§27 de la mission) — pas d'usine à gaz, pas de couche créée « pour faire joli ». Chaque décision ci-dessous part des fichiers réels, pas d'une préférence esthétique.
ACTUAL REPOSITORY
↓
ARCHITECTURAL DECISIONS (ce document, §2-§13)
↓
TARGET STRUCTURE (ce document, §14-§18)
↓
FILE PLACEMENT MATRIX (planning/audits/e11-target-file-placement.md)
↓
VALIDATED MIGRATION PLAN (§21 ci-dessous, à valider avant exécution)
1. Principes#
- Le domaine (
domain/) doit rester du TypeScript pur. Vérifié sur l'existant : aucun fichier soussrc/domain/n'importe React, Next.js,@supabase/supabase-jsoupg(grep exhaustif, 0 résultat). C'est la propriété la plus précieuse du repository actuel — la cible doit la préserver, jamais la régresser. - Une responsabilité, un dossier. Si deux dossiers font la même chose pour des raisons historiques, on documente la distinction réelle plutôt que de forcer une fusion mécanique qui casserait ce qui fonctionne déjà.
- On ne construit pas une couche qui n'a pas encore de justification.
application/n'est pas créé maintenant — voir D3. - La convention existante gagne quand elle est déjà cohérente.
planning/{epic-prefix}-sujet.mdest déjà appliquée à 33 des 53 fichiers deplanning/— la cible formalise cette convention plutôt que d'en inventer une autre. - Aucun fichier ne doit être sans destination. Voir la matrice pour le traitement exhaustif de chaque fichier racine et de chaque grande famille.
2. Décisions architecturales#
D1 — src/infrastructure/ : CONSERVÉ comme couche officielle#
Analyse des 92 fichiers réels (voir T1 §4-5, approfondi ici) :
| Sous-dossier | Fichiers | Nature réelle |
|---|---|---|
knowledge-acquisition/ | 73 | Adapters par source (rijal/ 10, commentary/ 8, terminology/ 7, quran/ 7, muslim-openiti/ 4, bukhari/ 3) + writers Postgres (Postgres*Ledger, PostgresDatasetBindingResolver, …) + moteurs d'orchestration d'acquisition (DefaultKnowledgeAcquisitionEngine, ContextualAcquisitionEngine, ObservedAcquisitionRunner) + __fixtures__/ (11, fixtures de test colocalisées) |
provenance/ | 11 | Postgres*ProvenanceResolver (Commentary/Quran/Rijal/Terminology) + services par défaut (DefaultCitationService, DefaultAssertionEvidenceIntegrityService) |
repositories/ | 4 | Preuve du pattern hexagonal : SupabaseHadithAggregateWriter.ts (implémentation réelle) + FakeHadithAggregateWriter.ts (double de test) — les deux implémentent l'interface HadithAggregateWriter définie dans src/domain/repositories/ |
project-planning/ | 3 | parser.ts/reader.ts/types.ts — lecture de fichiers Markdown de planning depuis le filesystem (alimente le tableau de bord project/planning) |
Verdict : src/infrastructure/ est un véritable étage ports-and-adapters
— chaque port est défini dans src/domain/repositories/*.ts
(HadithAggregateWriter, NarratorRepository, RijalKnowledgeWriter,
CommentaryKnowledgeWriter, QuranTextWriter, TerminologyWriter,
KnowledgeRepository), et src/infrastructure/ fournit les implémentations
concrètes (Postgres réel + doubles de test). C'est exactement la séparation
que la cible §22 de la mission cherchait à obtenir avec domain/ + server/
— sauf qu'elle existe déjà, sous un autre nom, et fonctionne (E2/E3/E4
entièrement construits dessus, tests colocalisés). La supprimer ou la
fusionner arbitrairement romprait ce contrat.
Sous-arborescence proposée (uniquement si l'inventaire post-T1 confirme qu'elle apporte une clarté réelle — proposition légère, voir §7 pour le détail et la justification fichier-par-fichier) :
infrastructure/
├── knowledge-acquisition/ (inchangé — déjà bien organisé par source)
├── repositories/ (implémentations des ports domain/repositories)
├── provenance/ (resolvers Postgres + services de citation)
└── project-planning/ (lecture filesystem des documents de planning)
Aucun renommage interne recommandé : la sous-structure actuelle par
source (rijal/, commentary/, quran/, terminology/, bukhari/,
muslim-openiti/) est déjà la bonne granularité.
D2 — src/server/ : CONSERVÉ, rôle distinct clarifié (pas de fusion avec infrastructure/)#
Vérification factuelle : src/server/ (59 fichiers) n'utilise aucune API
Next.js spécifique (NextResponse/NextRequest : 0 occurrence — celles-ci
vivent dans src/app/api/*/route.ts, pas dans src/server/) et seulement 2
fichiers y importent pg directement.
Rôle réel distinct de infrastructure/ :
infrastructure/= implémentations de ports formels définis dansdomain/repositories/— discipline « on définit l'interface avant l'implémentation ».server/= modules de lecture directement consommés par les Server Components et routes API (openiti/28,live-agent/24,database-explorer/6,commentary/1) pour des fonctionnalités qui n'ont pas encore de portdomain/formel — lecture pragmatique, introduite au fil des missions BETA-DESIGN récentes.
Ce ne sont pas deux dossiers avec le même rôle par accident : ce sont
deux maturités différentes de la même préoccupation (accès aux
données). Fusionner server/ dans infrastructure/ maintenant forcerait
soit la création de ports domain/ prématurés pour OpenITI/commentary/
live-agent (sur-ingénierie), soit un dossier infrastructure/ qui perd sa
cohérence de contrat.
Règle cible : quand une fonctionnalité aujourd'hui servie par
src/server/<feature>/ acquiert un vrai port domain/repositories/, son
implémentation concrète migre vers infrastructure/<feature>/ à ce
moment-là — pas avant. server/ reste le point d'entrée « lecture
Next.js‑server » tant qu'aucun contrat domain ne le justifie.
Gap identifié (à traiter hors E11) : src/server/commentary/commentary-read.ts
est le seul module de server/ sans test dédié — la même remarque que T1
§19.5, non résolue ici (T2 ne modifie pas le code).
D3 — src/application/ : NON CRÉÉ pour l'instant#
Les candidats d'usage cités par la mission (BuildScientificDossier,
ResolveNarratorIdentity, FindTraditionCandidates) n'existent pas encore
comme orchestrations concrètes traversant plusieurs domaines. L'équivalent
le plus proche aujourd'hui est src/domain/services/
(AnalysisService.ts, HadithService.ts, NarratorService.ts) — des
services d'orchestration qui restent purs car ils ne dépendent que
d'interfaces domain/repositories/ injectées, jamais d'une implémentation
concrète. Ce pattern suffit à l'échelle actuelle.
Décision : ne pas créer src/application/ en E11. Réserver le nom
pour E8 (Reasoning) / E9 (Scientific Dossier), quand une orchestration
authentique combinant narrator + hadith + commentary + tradition sur
plusieurs frontières transactionnelles apparaîtra réellement. Créer la
coquille maintenant, sans contenu réel, serait de la sur-architecture
(§27).
D4 — src/domain/ : rôle confirmé, règle formalisée#
domain/ = logique scientifique / métier pure, testable en TypeScript pur
Interdits (vérifiés déjà respectés à 100 % sur l'existant, à faire respecter pour tout futur ajout) :
- aucun import React / JSX
- aucun import
next/* - aucun import
@supabase/supabase-jsoupg - aucun
fetch, aucune API navigateur
Seules dépendances autorisées : TypeScript standard, autres modules
domain/, et — pour les services d'orchestration — des interfaces
domain/repositories/* (jamais leur implémentation concrète).
src/domain/tradition-variant/ (5 fichiers, groundwork E5) reste en place
tel quel : c'est déjà la bonne destination architecturale pour ce code,
même si E5 est gelé. Aucune action requise — voir le risque de gouvernance
déjà noté en T1 (ne pas y toucher pendant le gel, pas un problème de
placement).
D5 — src/features/ : introduit progressivement, pas de big-bang#
features/ = capacités fonctionnelles visibles du produit
Candidats confirmés par l'inventaire réel (chacun a déjà un embryon
cohérent de UI + logique + tests, dispersé aujourd'hui entre
components/, lib/, server/) :
| Feature | UI existante | Logique existante | Tests existants |
|---|---|---|---|
library | components/library/* (5) | lib/library-catalog.ts | lib/library-catalog.test.ts |
reading | components/reading/* (3) | lib/reading-preferences.ts, lib/book-navigation.ts, lib/reading/use-scroll-spy.ts | lib/book-navigation.test.ts |
openiti | components/openiti/* (2) | lib/openiti/* | test:openiti-reading, test:book-workspace |
commentary | components/commentary/* (1) | server/commentary/commentary-read.ts | aucun (gap) |
hadith | pages corpus/*, atelier de lecture | domain/knowledge-acquisition/HadithCorpusProjector | nombreux |
narrator | NarratorProfile.tsx, NarratorHadiths.tsx | domain/narrator-identity/* (32) | nombreux |
tradition | — (E5 gelé) | domain/tradition-variant/* | 1 |
provenance | — (transverse) | domain/provenance/* | colocalisés |
sources | SourcesCatalogue.tsx | data/bibliographic-sources.ts | — |
search | page /search | — | — |
statistics | pages /stats, /statistics | — | — |
admin | app/[locale]/(site)/admin/* | server/database-explorer/* | colocalisés |
labs | components/labs/* (28) | dispersé | variable |
Règle : une feature ne migre vers src/features/<nom>/ que lorsqu'elle
a réellement au moins deux des sous-dossiers components/, services/,
types/, tests/ à regrouper — pas de structure vide créée par
anticipation. labs/ (28 fichiers, expérimentations très hétérogènes)
reste probablement une zone à part (« sandbox produit »), pas une feature
unique — à trancher lot par lot, pas en bloc.
D6 — src/shared/ : règle stricte, contenu limité#
shared/ = utilisé par ≥ 2 features ET sans appartenance fonctionnelle claire
Admissible : composants génériques de layout/UI sans logique métier
(NavBar.tsx, Footer.tsx, Logo.tsx, ThemeToggle.tsx — 4 des 25
fichiers isolés actuels de src/components/ correspondent déjà à ce
profil).
Non admissible (exemples réels du repo à ne pas faire migrer vers
shared/) : ChainAnalyzer.tsx, DataModelExplorer.tsx,
HadithCommentaries.tsx, NarratorProfile.tsx, FathAlBariWorkspace.tsx
— chacun appartient à une seule feature (hadith/narrator/
commentary), même s'il est aujourd'hui rangé au même niveau plat que les
composants génériques.
D7 — src/core/ : rôle limité, pas de fourre-tout#
core/ = configuration, environnement, feature flags, providers globaux, i18n, thème
Exécuté (E11-T7, LOT A) : src/config/ (7 fichiers) → src/core/config/ ;
src/lib/i18n.tsx, src/lib/i18n-data.ts, src/lib/theme.tsx,
src/lib/theme-script.ts, src/lib/fonts.ts, src/lib/supabaseClient.ts →
src/core/ (providers globaux transverses, pas des primitives génériques au
sens de D8).
Limite explicite : core/ ne reçoit que ce qui est transverse à
toute l'application (config, thème, langue, providers). Toute logique
spécifique à une feature reste dans features/<nom>/, même si elle
« semble » générique.
D8 — src/lib/ : réduit aux primitives techniques génériques#
Règle stricte confirmée nécessaire par l'inventaire (44 fichiers actuels, le fourre-tout le plus net du repo — T1 §5) :
lib/ = primitives techniques génériques uniquement
Admissible : normalisation de chaînes, dates, identifiants, validation générique, helpers HTTP/erreurs génériques.
Doit sortir de lib/ vers leur domaine propre (mouvement documenté
dans la matrice, non exécuté en T2) :
tabaqa.ts,isnadMatching.ts,entityResolution.ts,matchTier.ts,nominalTransliteration.ts,narrator-identity.ts,narrator-hadiths.ts,narrator-display.ts,grade-tiers.ts,grade-display.ts,displayResolver.ts,reliability.ts,searchResultMerge.ts→ logique métier narrator/hadith, candidats pourdomain/narrator-identity/ou une nouvelle zonefeatures/narrator/services/.openiti/(déjà un sous-dossier cohérent) →features/openiti/.library-catalog.ts→features/library/.reading-preferences.ts,book-navigation.ts,reading/→features/reading/.hadithrank/→features/hadithrank/(ou souslabs/selon décision produit — HadithRank vit aujourd'hui souslabs/).live-agent/→features/live-agent/(déjà cohérent en sous-dossier).
Reste légitimement dans lib/ (ou migre vers core/ selon D7) :
report-load-error.ts, supabaseClient.ts (client générique, pas de
logique métier), documentation.ts (générique au rendu Markdown).
3. Structure cible évaluée#
La structure proposée par la mission est confirmée avec une correction
majeure : infrastructure/ est réintégré explicitement (elle existe déjà
et fonctionne), et application/ est différé (D3).
src/
├── app/ (Next.js App Router — inchangé)
├── features/ (nouveau — capacités produit, introduites progressivement, D5)
├── domain/ (inchangé dans son contenu — règle de pureté formalisée, D4)
├── infrastructure/ (conservé — adapters des ports domain/repositories, D1)
├── server/ (conservé — lecture Next.js-server pour features sans port domain, D2)
├── shared/ (nouveau, restreint — composants génériques cross-feature, D6)
├── core/ (nouveau — config, i18n, thème, providers globaux, D7)
├── lib/ (conservé mais réduit — primitives techniques génériques seulement, D8)
└── types/ (inchangé — types partagés, aucun problème identifié)
(src/application/ n'existe pas encore — réservé, voir D3)
(src/hooks/ n'est pas recréé comme dossier séparé — les hooks vivent dans
features/<nom>/ ou core/ selon leur portée, pas de dossier hooks/ générique)
(src/tests/ n'est pas créé — les tests unitaires restent colocalisés, voir §20)
4. Responsabilité de chaque couche#
| Couche | Responsabilité | Ne doit JAMAIS contenir |
|---|---|---|
app/ | Routage Next.js, layouts, orchestration de rendu serveur/client | logique métier scientifique, requêtes SQL directes complexes |
features/ | Assemblage produit d'une capacité visible (UI + services + types + tests de la feature) | logique réutilisable par ≥ 2 features (→ shared/core/lib) |
domain/ | Règles scientifiques et métier pures | React, Next.js, Supabase, pg, fetch |
infrastructure/ | Implémentations concrètes des ports domain/repositories/ | logique de décision métier (doit rester dans domain/) |
server/ | Lecture de données server-only consommée par app/ pour des features sans port domain formel | code exécuté côté navigateur |
shared/ | Composants UI génériques cross-feature, sans logique métier | tout composant propre à une seule feature |
core/ | Configuration, environnement, feature flags, i18n, thème, providers globaux | logique spécifique à une feature |
lib/ | Primitives techniques génériques (chaînes, dates, ids, validation générique) | logique métier scientifique |
types/ | Types TypeScript partagés entre couches | implémentations |
5. Dépendances autorisées / interdites#
Voir dependency-rules.md pour le détail complet
et le graphe annoté.
Résumé :
Autorisé
app → features, domain, server, shared, core, lib, types
features → domain, server (temporairement, voir D2), shared, core, lib, types
infrastructure → domain (implémente ses ports), core, lib, types
server → domain (lecture de types), core, lib, types
domain → domain, types (rien d'autre)
shared/core/lib → types (entre eux : lib → core interdit, core → lib interdit — pas de dépendance croisée entre primitives transverses)
Interdit explicitement
domain → features, app, React, Next.js, Supabase, pg, fetch
shared → une feature spécifique
infrastructure → app, features, React
server → React, JSX (server/ produit des données, jamais du JSX)
lib → domain (sens interdit : lib est en-dessous de domain, jamais l'inverse)
core → features (core ne connaît aucune feature)
6. Modèle features/#
Chaque feature peut posséder, seulement si nécessaire :
features/<nom>/
├── components/ (si l'UI est propre à la feature)
├── services/ (logique de projection/agrégation propre à la feature)
├── types/ (si les types ne sont pas déjà dans src/types/)
└── tests/ (ou colocalisés *.test.ts, au choix de la feature — pas de règle unique imposée, voir §20)
Pas de sous-dossier vide créé par anticipation. Une feature avec 3 fichiers
(ex. commentary aujourd'hui) peut rester plate.
7. Modèle domain/#
Inchangé dans le fond — déjà conforme. Rappel de la structure actuelle (à conserver) :
domain/
├── narrator-identity/ (32 — sous-domaine le plus riche, E4)
├── knowledge-acquisition/ (13 — contrats génériques)
├── repositories/ (9 — ports/interfaces)
├── entities/ (9)
├── provenance/ (8)
├── tradition-variant/ (5 — E5, gelé, ne pas toucher)
├── types/ (4)
├── services/ (4 — orchestration pure via ports injectés)
└── openiti/ (2)
8. Décision infrastructure/#
Voir D1. Sous-arborescence actuelle confirmée adéquate, aucun renommage interne recommandé.
9. Décision server/#
Voir D2.
10. Décision application/#
Voir D3 — non créé.
11. Décision shared/#
Voir D6 — restreint à NavBar.tsx, Footer.tsx, Logo.tsx,
ThemeToggle.tsx et tout futur composant réellement générique
cross-feature (ex. un futur Pagination, EmptyState, Modal générique
s'ils apparaissent — aucun composant modal générique n'existe encore
séparément de CollectionLibraryModal.tsx, qui lui est spécifique à
library).
12. Décision core/#
Voir D7 — exécuté en E11-T7 LOT A : src/core/config/*, src/core/i18n.tsx,
src/core/i18n-data.ts, src/core/theme.tsx, src/core/theme-script.ts,
src/core/fonts.ts, src/core/supabaseClient.ts.
13. Décision lib/#
Voir D8.
14. Stratégie tests#
Voir e11-target-file-placement.md
§19 et la synthèse ci-dessous :
| Type de test | Emplacement cible | Emplacement actuel | Changement ? |
|---|---|---|---|
| Unitaire (domain, lib, infra) | colocalisé *.test.ts à côté du code | déjà colocalisé (51 fichiers) | aucun — confirmé comme la bonne convention |
| Intégration / scientifique (scripts) | scripts/test-*.mjs, référencés individuellement dans package.json | déjà le cas (66 fichiers) | aucun structurel — un futur tri par sous-dossier scripts/validation/ reste possible (E11-T3+), pas dans ce document |
| SQL / DB | supabase/tests/*.sql | déjà le cas (37 fichiers) | aucun |
| Audit scientifique manuel | scripts/audit-*.mjs + rapport dans planning/audits/ | déjà largement le cas | clarifier la frontière : un audit-*.mjs ne doit jamais être confondu avec un test automatisé exécuté en CI — voir §16 |
| End-to-end / browser | n'existe pas aujourd'hui | — | non traité en E11-T2 (décision produit distincte : introduire ou non Playwright) |
Principe : ne pas mélanger test automatisé reproductible et audit
scientifique manuel dans le même espace de nommage. Un test-*.mjs doit
pouvoir tourner sans supervision humaine ; un audit-*.mjs produit un
rapport à lire par un humain. Les deux préfixes existent déjà et sont
globalement bien respectés (voir T1 §8) — la cible formalise cette
distinction plutôt que de la réinventer.
15. Stratégie scripts#
scripts/
├── audit/ (audit-*.mjs — rapports scientifiques manuels)
├── import/ (scripts d'ingestion/import de données)
├── validation/ (test-*.mjs référencés par npm run test:*)
├── maintenance/ (db-cold-rebuild.mjs, verify-extension-relocation.mjs, etc.)
├── migration/ (build-*-migration.mjs, generate-*-seed-sql.mjs)
├── quality-engine/ (inchangé — déjà un module cohérent)
├── lib/ (inchangé — modules internes partagés entre scripts)
└── translations/ (inchangé — déjà son propre __tests__/)
182 scripts actuellement à plat, classifiables par préfixe (voir T1 §8). Aucun script n'est déplacé en T2 — cette arborescence est la cible pour une migration ultérieure validée.
16. Stratégie docs / planning#
docs/
├── architecture/ (ce document + dependency-rules.md — nouveau, créé en T2)
├── adr/ (inchangé — déjà correct, 3 fichiers)
├── scientific/ (ISNAD_SCIENTIFIC_PRINCIPLES.md, KNOWLEDGE_MODEL_V1.md, DOMAIN_LAYER_V1.md, etc.)
├── product/ (contenu produit/roadmap si distinct du scientifique)
└── development/ (translations/, standards techniques de dev)
planning/
├── epics/ (les 33 fichiers plats actuels b0-*/e2-*/e3-*/e4-*/e5-*/stab-01-*, déjà nommés par epic)
├── audits/ (inchangé — déjà correct, 20 fichiers)
├── reports/ (rapports ponctuels type HANDOVER, LIVE_AGENT_*, RIJAL_CANONICAL_REFERENCE_*)
└── archive/ (contenu clos sans valeur de référence continue)
docs/ = documentation durable (principes scientifiques, ADR, modèle
de domaine). planning/ = gestion de projet (specs d'epic, audits,
rapports). Aucune donnée brute (JSON d'audit, manifestes) ne devrait rester
dans docs/ — direction cible : planning/audits/ ou un futur
docs/data/ si le volume le justifie (non tranché ici, voir la matrice
pour les cas concrets).
specs/ (Spec Kit) : voir §17.
.specify/ : voir §17.
17. .specify/, specs/, scratch/ — décisions explicites#
.specify/ → KEEP à la racine#
- À quoi sert-il : état local + configuration du workflow GitHub Spec
Kit, intégré à Claude Code (
.specify/integration.jsondéclare"integration": "claude"). - Actif : oui — 10 skills
speckit-*sont committées sous.claude/skills/et listées comme disponibles dans les sessions Claude Code actuelles. - Généré : partiellement (
.specify/.gitignoreexclut déjà les pointeurs locaux commefeature.json). - Doit rester à la racine : oui, contrainte de l'outil (Spec Kit
s'attend à trouver
.specify/au niveau racine du repo, au même titre que.next/outsconfig.json). - Décision : KEEP. Aucune action.
specs/ → KEEP comme emplacement structurel, contenu marqué HISTORICAL#
- Usage réel : sortie du workflow Spec Kit (
spec.md/plan.md/tasks.md/data-model.md/...). C'est la convention imposée par l'outil — toute future exécution de/speckit-specifyy écrira à nouveau sousspecs/NNN-nom-feature/. - Relation avec
planning/: les epics E2 à E10 ont utiliséplanning/e{N}-*.mdà la place, sans repasser par Spec Kit — doncspecs/001-hadith-canonical-projection/est resté seul. - Duplication : aucune duplication active de vérité aujourd'hui (E1 est clos, son contenu ne contredit rien de vivant).
- Décision : KEEP le dossier
specs/comme emplacement structurel réservé au workflow Spec Kit (ne pas le supprimer ni le renommer — l'outil continuerait autrement à recréer un dossierspecs/à la prochaine invocation). Marquerspecs/001-hadith-canonical-projection/spécifiquement comme HISTORICAL dans la matrice (E1, clos, conservé pour traçabilité de la toute première exécution du workflow).
scratch/ (tracké) → ARCHIVE-CANDIDATE, règle de non-reproduction établie#
- 15 fichiers, tous datés du 2026-08-25 (même campagne que
AUDIT-REPORT.md/HUMAN_REVIEW_NARRATORS.jsonà la racine), non référencés depuissrc/niscripts/(vérifié par grep). - Décision : ARCHIVE-CANDIDATE — à déplacer vers
planning/archive/2026-08-e4-night-shift-scratch/(ou équivalent) lors d'une future micro-tâche de migration, jamais supprimé sans confirmation que la campagne E4 correspondante est bien close (elle l'est d'après T1/mémoires de session, mais la confirmation finale reste au Project Lead). - Règle établie pour l'avenir :
scratch/(tracké) ne doit plus recevoir de nouveaux fichiers de travail ponctuel — cet usage est remplacé par le dossier local.scratch/(non tracké, déjà dans.gitignorede facto par convention de nom, à formaliser explicitement dans.gitignorelors d'une future migration) pour tout travail véritablement jetable. Un script qui mérite de survivre va dansscripts/avec un préfixe clair (audit-,test-, etc.), jamais dansscratch/.
18. Politique fichiers racine#
Voir la matrice complète (e11-target-file-placement.md) pour le
traitement fichier par fichier. Règle générale :
La racine ne doit contenir que ce que l'outillage (npm, Next.js,
TypeScript, Git, Vercel) exige explicitement à cet emplacement, plus
README.md comme point d'entrée développeur. Tout le reste (rapports
d'audit ponctuels, exports de données, scripts d'export historiques) migre
vers planning/, docs/ ou scripts/ selon sa nature.
19. Implications de nommage#
SCREAMING_SNAKE_CASE.mdvskebab-case.md: la cible retient kebab-case comme convention (déjà dominante dansplanning/— 33/37 fichiers epic-prefixés). Les fichiers SCREAMING_SNAKE_CASE existants (RIJAL_CANONICAL_REFERENCE_*,LIVE_AGENT_*,SCIENTIFIC_KNOWLEDGE_LAYER_ROADMAP.md,ISNAD_SCIENTIFIC_PRINCIPLES.md, etc.) ne sont pas renommés en E11-T2 — seule la convention future est fixée ici. Un renommage de masse est un choix distinct, à valider séparément (impact sur les liens existants).scratch/vs.scratch/: voir §17 — règle établie, pas de renommage immédiat des fichiers existants dansscratch/.
20. Principes de migration#
- Ne jamais déplacer une migration Supabase déjà appliquée.
- Ne jamais déplacer un fichier sans avoir confirmé toutes ses références (imports, scripts npm, liens de documentation).
- Toute migration se fait par lot homogène (une feature à la fois), jamais en un seul gros commit.
- Chaque lot de migration doit repasser
tsc --noEmit+npm run build+ les suites de tests concernées avant validation. - Les fichiers E4 locaux non commités restent strictement hors périmètre de toute migration tant qu'ils n'ont pas été explicitement traités par leur propriétaire.
- Aucune migration ne commence sans validation explicite du Project Lead sur CE document.
21. Séquence de migration recommandée (future, non exécutée)#
M1 Nettoyage racine générés (tsconfig.tsbuildinfo → gitignore + untrack)
M2 Racine : relocalisation des rapports/exports isolés (AUDIT-REPORT.md,
audit-candidates.json, HUMAN_REVIEW_NARRATORS.json, data-export/)
M3 docs/ + planning/ (introduction des sous-dossiers architecture/adr/
scientific/product/development et epics/reports/archive)
M4 scripts/ (introduction des sous-dossiers audit/import/validation/
maintenance/migration, déplacement par lot)
M5 src/core/ (extraction de src/config/ + i18n/theme/fonts depuis lib/) — ✅ FAIT (E11-T7 LOT A)
M6 src/shared/ (extraction des 4 composants génériques confirmés) — ✅ FAIT (E11-T7 LOT A)
M7 src/features/reading/ + src/features/library/ (les plus petites,
déjà bien isolées)
M8 src/features/openiti/ + src/features/commentary/
M9 src/features/hadith/ + src/features/narrator/ (les plus gros, les
plus risqués — dernier lot applicatif)
M10 src/lib/ résiduel (vérification qu'il ne reste que des primitives)
M11 scratch/ → planning/archive/
M12 Nettoyage final (branches mergées, worktrees clos) — décision Project
Lead distincte, hors périmètre technique de cette séquence
Chaque étape M1-M12 correspond à une micro-tâche E11 future distincte, pas à une action de cette mission T2.
Document produit par E11-T2. Ne remplace pas le jugement du Project Lead — sert de base de décision.