docs: document Lardon3D architecture foundations

This commit is contained in:
fy59 2026-08-06 21:19:06 +02:00
parent d5b6216ef8
commit 6379dce843
2 changed files with 233 additions and 0 deletions

View file

@ -0,0 +1,121 @@
# Revue technique des fondations
## Périmètre et conclusion
Cette revue couvre `task`, `task_queue`, le profil matériel, les snapshots de
ressources, le gouverneur, les réservations et leur intégration au scheduler.
Aucune fuite, course, interblocage ou violation reproductible de l'invariant
d'admission n'a été détecté par l'inspection et les tests actuels. Aucun code de
production n'a donc été modifié.
## Invariants actuellement garantis
- Une tâche possède une estimation copiée à sa création et exposée seulement
par copie.
- Le scheduler reçoit explicitement son gouverneur et refuse un gouverneur nul.
- Le worker obtient une réservation active avant d'appeler
`lardon3d_task_start`; celui-ci revalide la réservation avant le callback.
- Un callback lancé par la file dispose d'une copie cohérente de son contrat :
lot, RAM, GPU, CPU et slots IO/GPU.
- `WAIT` conserve la tâche en tête et endort le worker sur une condition
variable. Le mutex de file empêche une notification concurrente de se perdre
entre la décision et l'attente.
- `REJECT` termine la tâche sans appeler son callback. `REDUCE_BATCH` transmet
le contrat réduit.
- La réservation détenue par le worker est libérée après succès, échec ou
annulation. Une pause en cours conserve volontairement la réservation.
- La destruction de la file annule les tâches, réveille et rejoint le worker,
puis détruit les tâches dont elle est propriétaire.
- Les compteurs du gouverneur et la création des réservations sont protégés par
un mutex unique. Une double libération est refusée sans débiter les budgets.
- Les calculs de taille contrôlent multiplication et addition ; les compteurs
CPU et slots ne peuvent croître au-delà des budgets calculés.
- Le profil représente les capacités stables. Les snapshots sont des valeurs
datées et indépendantes ; le scheduler ne prend aucune décision de ressources
lui-même.
## Limites connues
- La file possède un seul worker et applique un FIFO strict. Une tâche en tête
qui reçoit `WAIT` bloque les tâches suivantes, même si certaines seraient
admissibles.
- Une libération extérieure au scheduler exige ensuite un appel à
`lardon3d_task_queue_resources_changed`. Le gouverneur ne publie pas encore
automatiquement cet événement.
- Les réservations libérées restent comme tombstones jusqu'à la destruction du
gouverneur. Cela sécurise la double libération mais fait croître la mémoire
avec le nombre historique de contrats.
- Une erreur de capture du snapshot fait échouer la tâche ; il n'existe pas
encore de distinction entre erreur transitoire de mesure et rejet durable.
- Le gouverneur et la file doivent être détruits après arrêt de leurs appelants.
Leur destruction concurrente avec une API active n'est pas prise en charge.
- Les tâches, checkpoints, files et réservations ne sont pas persistés.
- Il n'existe ni DAG, ni priorité, ni pool de workers, ni orchestration de
séquences adaptatives successives.
## Risques à surveiller
- Formaliser l'ordre de durée de vie : la file doit être détruite avant son
gouverneur ; une tâche cédée à la file ne doit plus être détruite directement.
- Ne jamais permettre à un composant extérieur de libérer la réservation privée
du worker. L'appel `get_active` et le démarrage sont sûrs dans le modèle de
propriété actuel, pas face à une libération concurrente volontaire.
- Éviter qu'un callback détruise ou joigne sa propre tâche, ce qui pourrait
attendre sa propre fin.
- Conserver les prédicats autour de chaque attente de condition et maintenir le
même mutex pour décision `WAIT` et mise en sommeil.
- Surveiller les identifiants et compteurs historiques sur les très longues
sessions, même si leur débordement est irréaliste avec les allocations
actuelles.
- Ne pas transformer `MemAvailable`, le swap ou la zram en promesse de mémoire
supplémentaire. Les snapshots peuvent déjà refléter une consommation réelle
en plus des réservations comptables ; une politique future doit rester
conservatrice.
- Garder la publication de résultats indépendante du contrat d'exécution : seul
un résultat validé atomiquement peut devenir visible.
## Cohérence documentaire
Les documents actuels correspondent au code : responsabilités séparées,
réservation préalable, pause conservant les ressources, worker unique et
notification explicite. La vue d'ensemble décrit comme futurs — et non comme
existants — les séquences complètes, la reprise persistante, les snapshots live
et le viewer Vulkan.
## Ordre recommandé des prochains tickets
1. Formaliser les contrats de propriété, les événements de libération et les
erreurs transitoires de snapshot.
2. Définir un format de résultat atomique avec identifiant, validation et point
de reprise.
3. Ajouter l'enchaînement borné de lots adaptatifs sous réservations successives.
4. Borner les files et introduire la contre-pression.
5. Persister tâches et checkpoints nécessaires à la reprise après crash.
6. Ajouter ensuite un DAG minimal, puis les priorités.
7. Généraliser vers des pools CPU, IO et GPU en conservant le gouverneur comme
unique arbitre.
8. Publier des snapshots validés avant d'introduire le viewer séparé.
## Éléments à ne pas réécrire lors du passage à OpenCode
- Les structures opaques `Task`, `TaskQueue`, `ResourceGovernor` et
`ResourceReservation`.
- La séparation profil matériel / snapshot dynamique / politique / réservation.
- Le calcul centralisé et protégé des budgets et lots.
- L'invariant « réservation active avant callback » et la copie du contrat vers
la tâche.
- L'annulation coopérative, les checkpoints de pause et la propriété ncurses du
thread principal.
- Le FIFO à condition variable comme implémentation V1 fiable ; il doit évoluer
par extension, pas être remplacé avant que les besoins DAG soient spécifiés.
- Les écritures atomiques, rollbacks ciblés et validations déjà utilisés par les
projets et imports.
- Les tests de concurrence, de double libération, d'annulation et de destruction
sûre, qui constituent la base de non-régression.
## Validation exécutée
- Suite normale : 10 tests réussis sur 10.
- ASan/UBSan : 10 tests réussis sur 10, aucun diagnostic.
- TSan : 10 tests réussis sur 10, aucune course signalée.
- `git diff --check` : réussi avant la rédaction du présent rapport.

View file

@ -0,0 +1,112 @@
# Vue d'ensemble de l'architecture Lardon3D
## Finalité et flux global
Lardon3D est une application Linux de reconstruction 3D pilotée par une TUI
ncursesw. Le terminal reste le centre de contrôle : il gère les projets, lance
les opérations, présente leur progression et permet leur annulation. Le futur
viewer Vulkan sera un processus ou composant graphique séparé, affiché sur le
workspace 8 ; il ne remplacera pas la TUI et ne devra jamais la bloquer.
```text
TUI / Projet
Task
Estimate
Governor
Reservation
Scheduler
Worker
Résultat atomique
Viewer live
```
## Composants actuels
Les projets persistants regroupent leur configuration, les images originales,
le manifeste, les résultats de reconstruction, les exports et les journaux.
Leur création est protégée contre l'écrasement et les écritures structurantes
utilisent des remplacements atomiques.
L'import d'images s'exécute de manière asynchrone et annulable, sans appel
ncurses depuis son worker. Il copie individuellement les fichiers admissibles
et maintient un manifeste cohérent. Le catalogue charge et valide ce manifeste
en mémoire. La vue d'images en dérive des indices triés et filtrés sans modifier
le catalogue, le manifeste ou les images.
Le moteur de tâches fournit les états, la progression, la pause, l'annulation
coopérative et les callbacks. La file actuelle possède un worker unique et
respecte l'ordre FIFO. Chaque tâche porte une estimation immuable de ses coûts
RAM, GPU, CPU et IO ainsi que des bornes de lot.
Le profil matériel décrit les capacités stables détectées sur la machine. Les
snapshots décrivent les ressources disponibles à un instant donné. Le Resource
Governor combine profil, snapshot, marges de sécurité et réservations actives.
Il décide si une demande doit démarrer, attendre, réduire son lot ou être
refusée, puis matérialise toute admission par une réservation opaque.
Le scheduler ne décide jamais des ressources. Il demande une réservation au
gouverneur juste avant l'exécution et transmet au callback une copie du contrat
accordé. L'invariant est strict : aucun callback de tâche n'est lancé sans
réservation active validée. Après succès, échec ou annulation, cette réservation
est libérée exactement une fois. Une tâche déjà en pause conserve son contrat
dans cette première version.
## Résultats et publication live
Les traitements futurs fonctionneront par séquences adaptatives : lire un lot
borné, calculer, écrire un résultat atomique, libérer la mémoire, puis traiter
le lot suivant. La stabilité du système hôte et la réactivité de la TUI ont
priorité sur le débit maximal.
Le viewer live ne devra observer que des snapshots de résultats complètement
validés et publiés atomiquement. Il ne lira jamais un fichier intermédiaire et
ne partagera pas directement les buffers de travail d'un worker. Une
interruption doit laisser le dernier snapshot validé exploitable et permettre
la reprise à une frontière de séquence connue.
## Principes non négociables
- Aucune tâche lourde monolithique ni chargement complet d'un projet en RAM.
- Traitement par séquences adaptatives et libération entre les lots.
- Budgets RAM, GPU, CPU et IO explicitement bornés et réservés.
- Files de travail et buffers intermédiaires bornés.
- La zram est un filet de sécurité, jamais une extension du budget normal.
- La RAM partagée des iGPU est comptabilisée dans le budget système.
- Écritures atomiques, rollback ciblé et absence de résultat partiellement
publié.
- Reprise après interruption depuis le dernier état validé.
- Viewer live séparé, non bloquant et lecteur de snapshots validés seulement.
- Le système hôte, la TUI et les données utilisateur restent prioritaires sur
le débit de reconstruction.
## Limites actuelles
La file ne possède encore ni DAG, ni priorités, ni pool de workers CPU/IO/GPU.
Les tâches et leur progression ne sont pas persistées après un arrêt. Les
séquences adaptatives sont préparées par les contrats de lot mais leur
enchaînement complet n'est pas encore orchestré. Le viewer Vulkan et la
publication live restent à implémenter.
## Ordre recommandé des prochains tickets
1. Définir les résultats atomiques, leurs métadonnées de validation et leurs
points de reprise.
2. Introduire l'exécution d'une tâche en séquences de lots adaptatifs, toujours
sous réservations successives.
3. Borner explicitement les files et définir la contre-pression entre étapes.
4. Persister les tâches, checkpoints et états nécessaires à la reprise après
crash.
5. Ajouter un DAG minimal et seulement ensuite les priorités.
6. Introduire des pools CPU, IO et GPU sans déplacer l'arbitrage hors du
gouverneur.
7. Publier des snapshots live validés et versionnés.
8. Ajouter le viewer Vulkan séparé sur le workspace 8 comme consommateur en
lecture seule de ces snapshots.