Politique de taille du dépôt — CoursIA
Le dépôt pèse ~1,2 GiB de pack pour un projet pédagogique. Ce document explique pourquoi ce poids est le prix d’une décision délibérée, ce qui est acquis (et ne sera pas réécrit), et ce qui est surveillé à l’avenir. Mesure, pas impression.
1. Pourquoi les sorties de notebooks restent committées (C.2 / H.1)
Les notebooks pédagogiques sont committés avec leurs sorties. C’est une règle dure du projet (notebook-conventions C.2) : les outputs sont le livrable pédagogique — ils prouvent que le code s’exécute et montrent le résultat attendu. Retirer les sorties détruirait cette preuve (H.1 : validation = exécution complète + outputs vérifiés). Le poids du dépôt est donc, pour une large part, le coût d’une exigence de qualité, pas une négligence.
2. Deux refus argumentés (acquis, non négociables)
2.1 nbstripout : NON
Stripping les sorties à l’indexation détruirait le livrable (C.2) et falsifierait la preuve d’exécution (H.1). Un notebook pédagogique sans ses outputs n’est plus qu’un script : il ne montre plus le résultat de l’algorithme, la figure générée, la métrique du backtest. Cette règle est posée noir sur blanc pour clore le sujet — la taille n’est pas un motif de retirer les sorties.
2.2 Réécriture d’historique (git filter-repo, BFG) : NON
Le dépôt compte ~95 forks étudiants. Réécrire l’historique casserait chacun d’eux (tout pull ultérieur entrerait en conflit). Le poids passé est acquis : les grands blobs déjà committés (cf. §3) restent dans l’historique. La politique est entièrement tournée vers l’avenir — on surveille ce qui entre, on ne défait pas ce qui est fait.
3. Mesure réelle
Deux angles, deux méthodes : ce qui est committé (blobs dans le dépôt) et ce qui est dans .git/ localement (artefacts d’administration, dépendants de la machine). Ne pas mélanger.
3.1 Blobs du dépôt (le poids partageable)
Mesurable firsthand via git rev-list --objects --all | git cat-file --batch-check (équivalent fonctionnel à git-sizer pour le classement par blob, sans dépendance Go). Top 5 décroissant (mesure ai-01 2026-08-07, reproduit par le PR #9912) :
| Taille | Blob | Statut | Décision |
|---|---|---|---|
| 63 MB | Sudoku/IKVM.Java.dll |
vendored (pont Java IKVM pour Sudoku/Tweety, #4667) | acquis — vendored légitime |
| 53 MB | Argument_Analysis/libs/org.tweetyproject.tweety-full-1.28-…jar |
vendored (Tweety) | acquis — vendored légitime |
| 29 MB | QuantConnect/ML-Training-Pipeline/checkpoints/lstm/…/model.pt |
supprimé (history-only, désormais gitignoré) | incident passé — §4 empêche la récurrence |
| 25 MB | ML/ML.Net/taxi-fare.csv |
dataset pédagogique | candidat LFS futur (§5) |
| 21 MB | GenAI/Audio/02-Advanced/02-4-Demucs-Source-Separation.ipynb (+ ×N révisions) |
notebook + outputs (audio base64) | acquis — poids légitime C.2 |
Le pack agrégé (~1,2 GiB bare) reflète : (a) les blobs vendored légitimes, (b) l’historique des notebooks-avec-outputs (chaque révision d’un notebook riche compte), (c) quelques incidents passés (le model.pt) désormais nettoyés de l’arbre courant.
Comment lire
git count-objects -vH.size-packest la taille cumulée des.packdansobjects/pack/— c’est la mesure distante (ce que tout clone télécharge). Lepacks: Nindique le nombre de.packnon coalescés : un chiffre élevé signifie quegit gcn’a pas encore été lancé localement depuis longtemps, pas une dette du dépôt distant. Lestmp_pack_*signalés enwarning: garbage foundsont du garbage local à la machine (ungit gcles élimine), pas un problème du dépôt distant — ne pas les confondre avec le sujet.
3.2 .git/ local (artefacts d’administration, par machine)
du -sh .git/ agrège six composantes qu’il faut distinguer — confondre .git/ avec « le poids du dépôt » est une erreur fréquente (la PR #9912 mesurait ai-01 et en oubliait deux). Mesure ai-01 2026-08-07 (méthode : du -sh .git/<composante> par sous-dossier, hors du -sh .git/* qui timeoute sur les 200+ worktrees) :
| Composante | Ordre de grandeur | Ce que c’est | Qui le produit |
|---|---|---|---|
.git/modules/ |
~4,0 GiB | submodules (§5.1) — clones des dépôts référencés par .gitmodules |
un git submodule update --init --recursive |
.git/worktrees/ |
~1,7 GiB | worktrees éphémères créés par les agents workers | git worktree add ../CoursIA-<sujet> (cf. CLAUDE.md §A et git-workflow.md) |
.git/objects/ |
~1,6 GiB | le store d’objets (≈ size-pack + delta + dangling) |
tout git fetch / git commit |
.git/wt-* (résiduels) |
~950 MiB | worktrees laissés par un crash ou un worktree mal démonté | agents sans git worktree remove propre |
.git/lfs/ |
~73 MiB | cache LFS (objets téléchargés mais pas encore promus) | un git lfs fetch |
.git/logs/ |
~7 MiB | historique des refs (reflog) | tout mouvement de HEAD |
Total .git/ |
~8,2 GiB | — | — |
Ces chiffres sont datés 2026-08-07 sur ai-01. Ils servent à illustrer l’ordre de grandeur et la proportion de chaque composante — pas un absolu à reporter. Un
git gcpeut faire varierobjects/; ungit worktree prunepeut faire chuterwt-*; un worker actif qui ouvre un worktree fait croîtreworktrees/. La méthode compte, le chiffre périme.L’angle mort du commentaire #9912 : les deux composantes produites par le harnais (
worktrees/1,7 GiB etwt-*résiduels 950 MiB) étaient absentes de la décomposition initiale — qui parlait de « 1,45 GiB size-pack ».du -sh .git/*timeout sur les machines avec beaucoup de worktrees (200+ chez ai-01) : la mesure agrégée n’est récupérable que composante par composante, ou viagit worktree listpour le décompte.
3.3 Maintenance (locale, à la demande)
Quelques gestes d’hygiène sans valeur de fond, à exécuter quand l’espace disque devient gênant sur la machine :
git worktree prune— nettoie.git/wt-*(worktrees non référencés pargit worktree list).git gc --aggressive --prune=now— recompacte.git/objects/; coûteux en CPU, à éviter pendant une session de travail.git submodule deinit -f <submodule>puisgit worktree remove— pour libérermodules/si un submodule n’est plus utilisé localement (ne touche pas le dépôt distant).
Ces gestes ne réduisent pas la taille du dépôt partageable (§3.1) : pour cela, la voie est LFS au prochain ajout (§5), pas la rétro-conversion de l’existant (§2.2).
4. Ce qui ne doit JAMAIS entrer
Ces catégories n’ont pas vocation dans le dépôt — un check advisory (§6) les signale, et le .gitignore les exclut quand elles sont prévisibles :
- Checkpoints de modèles (
.pt,.pth,.ckpt,.safetensorsde training) — cf. l’incidentmodel.pt29 MB, supprimé puis gitignoré. Un checkpoint n’est pas un livrable pédagogique : le notebook documente comment l’entraîner, pas le poids binaire du résultat. - Artefacts
_outputvolumineux (sorties Papermill_output.ipynbrégénérées) — ce sont des artefacts de processus, pas du matériel versionné. - Caches (
__pycache__/,.pytest_cache/,bin/,obj/) — déjà couverts par.gitignoreet la convention_archive/(#9535). - Données brutes volumineuses non pédagogiques (dump de production, logs complets).
5. Candidats Git LFS à l’avenir
Pour les futurs ajouts (pas de rétro-conversion de l’existant), Git LFS est la voie désignée au-dessus du seuil advisory (§6) :
- Datasets (
.csv/.parquetpédagogiques au-delà du seuil, ex:taxi-fare.csv) — le notebook les consomme mais le binaire n’a pas besoin d’être dans l’historique git. - Assets binaires GenAI (modèles de base, poids, datasets d’images).
- Renders et figures binaires hors notebooks (galerie README) quand ils dépassent le seuil.
Le seuil advisory (§6) est là pour déclencher la conversation : un blob > seuil dans une PR ouvre la question « LFS ou justification pédagogique ? », sans bloquer le merge.
5.1 Submodules : usage réel et angle mort du check §6
Le dépôt utilise 5 submodules (inscrits dans .gitmodules), et ils ont tous la même nature depuis #14518 — ce sont des forks qu’on fait vivre : MetaGeneticSharp (jsboige), Z3.Linq, Automata, semantic-fleet (MyIntelligenceAgency), Argumentum (ArgumentumGames, agent permanent dédié). Sous-projets factorisés hors du monorepo, dont le backlog est le nôtre (cf submodule-maintenance.md).
Les dépendances de build tierces ne sont plus des submodules : foundry-lib/lib/* (forge-std, openzeppelin-contracts, account-abstraction) s’installe via forge install --no-git, pinné sur foundry-lib/foundry.lock, et vit sous .gitignore. La distinction « libs vendored / dépôts propres » que cette section portait n’a plus d’objet : un upstream qu’on ne fait pas vivre n’a aucune raison d’encombrer .gitmodules.
Les submodules sont l’alternative structurelle à LFS pour externaliser le poids hors de l’arbre : un gitlink pèse quelques octets, quel que soit le poids du dépôt référencé. C’est précisément ce qui crée leur angle mort.
- Angle mort du check §6 : un submodule n’est pas un blob du dépôt parent — c’est une référence de commit (
gitlink). Le scangit diff --diff-filter=Aderepo-size-advisory.ymlne le voit donc jamais, quel que soit le poids du dépôt référencé. L’introduction d’un submodule pointant vers un dépôt de plusieurs GiB ne déclencherait aucun warning advisory. - Décision : les 8 submodules actuels sont des dépendances stables (libs vendored + sous- projets propres), légitimes au même titre que les blobs vendored de §3. L’ajout d’un nouveau submodule doit être documenté dans la PR avec le poids du dépôt référencé et la raison (vendored légitime vs sous-projet propre vs déplacement LFS-like) — le check §6 ne peut pas le mesurer, donc c’est la revue humaine qui porte la garde. Critère de refus : un submodule dont l’unique motivation est « cacher du poids » plutôt qu’une réelle factorisation ou dépendance externe stable.
6. Check advisory (jamais bloquant)
Un workflow CI (.github/workflows/repo-size-advisory.yml) signale, sur chaque PR, les blobs ajoutés au-dessus du seuil retenu. Il est advisory (exit 0, ::warning::) — conforme au pattern des gates de visibilité (variation-tag-guard) : il rend le fait visible sans bloquer le travail.
Seuil retenu : 10 MiB, justifié par la mesure §3 : il capture les datasets/checkpoints/ vendored-binaries (25–63 MB) tout en respectant la queue légitime des notebooks-avec-outputs de taille modeste. Le seuil est calibré sur les chiffres réels, pas sur une intuition.
Voir aussi
- notebook-conventions.md — C.2 (outputs committés), H.1 (validation = exécution + outputs)
- secrets-hygiene.md — règle 6 (Stop & Repair, jamais scrubber une sortie)
- Convention
_archive/— #9535