new day
This commit is contained in:
parent
44e8e0892e
commit
4622aa3b93
18 changed files with 1579 additions and 77 deletions
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
description: Explore rapidement fichiers, symboles, appels et dépendances
|
||||
mode: subagent
|
||||
model: opencode/north-mini-code-free
|
||||
model: opencode/mimo-v2.5-free
|
||||
temperature: 0.1
|
||||
permission:
|
||||
edit: deny
|
||||
|
|
@ -16,3 +16,39 @@ Travaille en lecture seule. Localise exactement les fichiers, symboles,
|
|||
appelants, dépendances et documents strictement utiles. Ne lis pas toute
|
||||
l'architecture par défaut, ne propose pas de réécriture et retourne uniquement
|
||||
les chemins, conclusions et risques synthétiques.
|
||||
|
||||
Tu reçois obligatoirement une liste de symboles, modules ou chemins précis.
|
||||
|
||||
Si la demande ne fournit aucun élément précis, refuse l’exploration et demande
|
||||
au parent de préciser la cible.
|
||||
|
||||
Interdictions absolues :
|
||||
|
||||
- pwd ;
|
||||
- ls ;
|
||||
- find ;
|
||||
- glob global ;
|
||||
- **/*.c ;
|
||||
- **/*.h ;
|
||||
- inventaire du dépôt ;
|
||||
- lecture de toute la documentation.
|
||||
|
||||
Utilise uniquement des recherches ciblées avec rg sur les chemins ou symboles
|
||||
fournis.
|
||||
|
||||
Lis au maximum :
|
||||
|
||||
- cinq fichiers source ou headers ;
|
||||
- deux fichiers de tests ;
|
||||
- deux documents d’architecture.
|
||||
|
||||
Retourne seulement :
|
||||
|
||||
- fichiers pertinents ;
|
||||
- symboles pertinents ;
|
||||
- dépendances directes ;
|
||||
- risques ;
|
||||
- informations encore manquantes.
|
||||
|
||||
Ne propose aucune nouvelle fonctionnalité.
|
||||
Ne modifie aucun fichier.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
description: Orchestre les tickets avec un contexte minimal et sans écrire les sources
|
||||
mode: primary
|
||||
model: opencode/north-mini-code-free
|
||||
model: opencode/mimo-v2.5-free
|
||||
temperature: 0.1
|
||||
permission:
|
||||
edit:
|
||||
|
|
@ -25,8 +25,66 @@ permission:
|
|||
"lardon-docs": allow
|
||||
---
|
||||
|
||||
Orchestre sans modifier les sources. Charge AGENTS.md et l'overview déjà
|
||||
injectés, puis utilise explore pour cibler le contexte. N'appelle que les agents
|
||||
pertinents, sans sous-agent imbriqué. Transmets au seul implémenteur un résumé
|
||||
court : objectif, contraintes, fichiers, API, invariants et tests. Tiens le
|
||||
handoff concis à jour après chaque phase. Aucun modèle payant, commit ou push.
|
||||
Le dépôt courant est déjà la racine de Lardon3D.
|
||||
|
||||
Ne lance jamais de commande de découverte globale :
|
||||
|
||||
- `pwd`
|
||||
- `ls` ou `ls -la`
|
||||
- `find` sur tout le dépôt
|
||||
- glob `*`
|
||||
- inventaire complet des fichiers
|
||||
- lecture automatique de toute la documentation
|
||||
|
||||
AGENTS.md et l’overview sont déjà injectés comme instructions projet. Ne les relis
|
||||
pas intégralement sauf si une information précise manque.
|
||||
|
||||
Pour chaque ticket :
|
||||
|
||||
1. Lire `.opencode/work/current_ticket.md` s’il existe.
|
||||
2. Identifier uniquement les modules, symboles et fichiers liés au ticket.
|
||||
3. Utiliser `lardon-explore` avec une requête ciblée.
|
||||
4. Charger uniquement les documents d’architecture directement pertinents.
|
||||
5. Appeler seulement les agents nécessaires.
|
||||
|
||||
Tout ticket touchant au moins un des éléments suivants exige obligatoirement
|
||||
`lardon-concurrency` :
|
||||
|
||||
- `task`
|
||||
- `task_queue`
|
||||
- scheduler
|
||||
- `resource_governor`
|
||||
- pthread
|
||||
- mutex
|
||||
- variable de condition
|
||||
- pause ou reprise
|
||||
- annulation
|
||||
- réservation
|
||||
- état ou durée de vie partagés entre threads
|
||||
|
||||
Cette règle s’applique même si le ticket ne crée aucun nouveau thread.
|
||||
|
||||
6. Transmettre au seul agent implémenteur un résumé court contenant :
|
||||
- objectif ;
|
||||
- contraintes ;
|
||||
- fichiers concernés ;
|
||||
- API et invariants ;
|
||||
- tests requis.
|
||||
7. Mettre à jour le handoff après chaque phase importante.
|
||||
|
||||
Le répertoire `.opencode/work/` est préparé localement. Ne vérifie pas son
|
||||
existence avec Bash. Crée ou mets à jour directement
|
||||
`.opencode/work/current_ticket.md` avec l’outil d’édition autorisé.
|
||||
|
||||
Ne modifie jamais les sources toi-même.
|
||||
|
||||
N’utilise jamais :
|
||||
|
||||
- de modèle payant ;
|
||||
- de sous-agent imbriqué ;
|
||||
- plusieurs agents d’écriture simultanément ;
|
||||
- `git commit` ;
|
||||
- `git push`.
|
||||
|
||||
Les rapports intermédiaires doivent être courts et ne contenir que les
|
||||
conclusions, risques, fichiers concernés, tests et prochaines actions.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
description: Exécute les validations Lardon3D sans modifier le code
|
||||
mode: subagent
|
||||
model: opencode/north-mini-code-free
|
||||
model: opencode/mimo-v2.5-free
|
||||
temperature: 0.1
|
||||
permission:
|
||||
edit: deny
|
||||
|
|
|
|||
|
|
@ -1,14 +1,125 @@
|
|||
---
|
||||
description: Planifier en lecture seule avec un contexte minimal
|
||||
description: Planifier un ticket en lecture seule avec un contexte minimal
|
||||
agent: lardon-orchestrator
|
||||
subtask: false
|
||||
---
|
||||
|
||||
Planifie ce ticket sans modifier les sources : $ARGUMENTS
|
||||
Planifie le ticket suivant sans modifier les sources :
|
||||
|
||||
Lis AGENTS.md et l'overview déjà chargés. Demande à lardon-explore uniquement
|
||||
les modules concernés. Liste les fichiers et documents à charger, propose un plan
|
||||
court et indique les agents réellement nécessaires. Écris dans
|
||||
`.opencode/work/current_ticket.md` : titre, objectif, contraintes, fichiers,
|
||||
documents utiles, plan, travail terminé/restant, fichiers modifiés, commandes,
|
||||
tests passés/restants, décisions, erreurs, modèle et prochaine action sûre.
|
||||
$ARGUMENTS
|
||||
|
||||
Le contexte permanent est déjà injecté depuis `.opencode/context.md`.
|
||||
|
||||
Pour cette commande :
|
||||
|
||||
- n'appelle aucun sous-agent ;
|
||||
- ne lance aucune commande Bash ;
|
||||
- ne modifie aucun fichier sauf
|
||||
`.opencode/work/current_ticket.md`.
|
||||
|
||||
Ne lance jamais :
|
||||
|
||||
- `pwd`
|
||||
- `ls`
|
||||
- `find`
|
||||
- glob
|
||||
- inventaire du dépôt
|
||||
- compilation
|
||||
- tests
|
||||
|
||||
Réponds uniquement à partir :
|
||||
|
||||
- du contexte permanent ;
|
||||
- du texte du ticket ;
|
||||
- de `.opencode/work/current_ticket.md` s'il existe et concerne déjà ce ticket.
|
||||
|
||||
Si une information manque, indique simplement les deux ou trois fichiers qui
|
||||
devront être lus lors d'une future exploration ciblée.
|
||||
|
||||
Ne tente jamais de les découvrir toi-même.
|
||||
|
||||
Choisis un seul ticket.
|
||||
|
||||
Ne fusionne jamais plusieurs tickets.
|
||||
|
||||
Ne propose jamais :
|
||||
|
||||
- de métrique ;
|
||||
- de compteur ;
|
||||
- de diagnostic ;
|
||||
- de nouvelle API ;
|
||||
- d'état TUI ;
|
||||
- de fonctionnalité annexe ;
|
||||
- de refactoring non demandé.
|
||||
|
||||
Le plan doit uniquement couvrir le périmètre demandé.
|
||||
|
||||
Dans la section **Agents nécessaires** :
|
||||
|
||||
- n'ajoute que les agents réellement utiles ;
|
||||
- si le ticket touche `task`, `task_queue`, le scheduler,
|
||||
`resource_governor`, pthread, mutex, variables de condition,
|
||||
pause, reprise, annulation, réservations ou tout état partagé,
|
||||
inclure obligatoirement `lardon-concurrency`,
|
||||
même si aucun nouveau thread n'est créé.
|
||||
|
||||
Écris `.opencode/work/current_ticket.md`
|
||||
une seule fois avec exactement cette structure :
|
||||
|
||||
Le handoff représente uniquement le ticket courant.
|
||||
|
||||
Si un nouveau ticket est demandé,
|
||||
remplacer entièrement `.opencode/work/current_ticket.md`.
|
||||
|
||||
Ne jamais conserver plusieurs tickets simultanément.
|
||||
|
||||
Ne jamais demander quel ticket utiliser.
|
||||
|
||||
# Ticket
|
||||
|
||||
## Objectif
|
||||
|
||||
## Contraintes
|
||||
|
||||
## Fichiers probablement concernés
|
||||
|
||||
## Documents nécessaires
|
||||
|
||||
## Plan
|
||||
|
||||
## Agents nécessaires
|
||||
|
||||
## Agents non nécessaires
|
||||
|
||||
## Tests futurs
|
||||
|
||||
## Risques
|
||||
|
||||
## Prochaine action sûre
|
||||
|
||||
Contraintes :
|
||||
|
||||
- une seule occurrence de chaque rubrique ;
|
||||
- aucun doublon ;
|
||||
- aucun code inventé ;
|
||||
- aucune API inventée ;
|
||||
- aucune fonctionnalité hors périmètre ;
|
||||
- aucune modification incrémentale répétée ;
|
||||
- 80 lignes maximum.
|
||||
|
||||
Après l'écriture :
|
||||
|
||||
1. relire le fichier une seule fois ;
|
||||
2. vérifier uniquement :
|
||||
- structure ;
|
||||
- absence de doublons ;
|
||||
- cohérence ;
|
||||
3. terminer immédiatement.
|
||||
|
||||
Ne fais aucun commit.
|
||||
|
||||
Ne fais aucun push.
|
||||
|
||||
N'utilise aucun modèle payant.
|
||||
|
||||
Ne modifie jamais `scan3d/`.
|
||||
|
|
|
|||
|
|
@ -1,13 +1,104 @@
|
|||
---
|
||||
description: Reprise rapide du handoff avec Nemotron
|
||||
description: Reprendre rapidement un ticket avec Nemotron à partir du handoff
|
||||
agent: lardon-orchestrator
|
||||
subtask: false
|
||||
---
|
||||
|
||||
Reprends le ticket avec lardon-build-backup. Lis uniquement le handoff, le diff
|
||||
et les fichiers qu'ils citent. Ne refais ni exploration ni architecture si les
|
||||
informations suffisent. Après l'implémentation, utilise lardon-build-light en
|
||||
lecture seule pour une revue locale simple. N'appelle ni lardon-review ni
|
||||
lardon-concurrency : signale l'absence de revue indépendante forte et diffère
|
||||
toute revue de concurrence sensible jusqu'au prochain passage Codex. Mets le
|
||||
handoff à jour avec la prochaine action sûre.
|
||||
Reprends le ticket suivant :
|
||||
|
||||
$ARGUMENTS
|
||||
|
||||
Le contexte permanent de Lardon3D est déjà chargé via
|
||||
`.opencode/context.md`.
|
||||
|
||||
Commence toujours par :
|
||||
|
||||
1. lire `.opencode/work/current_ticket.md` ;
|
||||
2. lire le diff courant.
|
||||
|
||||
Ne recharge jamais :
|
||||
|
||||
- AGENTS.md ;
|
||||
- l'overview ;
|
||||
- la documentation générale ;
|
||||
- les documents d'architecture.
|
||||
|
||||
Ne relance jamais `lardon-explore` ou `lardon-architect` si le handoff contient
|
||||
déjà :
|
||||
|
||||
- l'objectif ;
|
||||
- les contraintes ;
|
||||
- les fichiers concernés ;
|
||||
- les invariants ;
|
||||
- les validations réalisées ;
|
||||
- le travail restant.
|
||||
|
||||
Ne lance une exploration supplémentaire que si une information indispensable est
|
||||
absente.
|
||||
|
||||
Transmets à `lardon-build-backup` uniquement :
|
||||
|
||||
- l'objectif ;
|
||||
- les contraintes ;
|
||||
- les fichiers concernés ;
|
||||
- les API concernées ;
|
||||
- les invariants ;
|
||||
- le travail restant ;
|
||||
- la prochaine action sûre.
|
||||
|
||||
Ne renvoie jamais tout le handoff au modèle d'implémentation.
|
||||
|
||||
Après l'implémentation :
|
||||
|
||||
1. appeler `lardon-tests` une seule fois ;
|
||||
2. utiliser `lardon-build-light` uniquement pour une première revue locale
|
||||
simple ;
|
||||
3. mettre à jour le handoff.
|
||||
|
||||
Ne pas appeler :
|
||||
|
||||
- `lardon-review` ;
|
||||
- `lardon-concurrency` ;
|
||||
|
||||
car ils utilisent le même modèle que l'implémentation de secours.
|
||||
|
||||
Si le ticket touche notamment :
|
||||
|
||||
- pthread ;
|
||||
- mutex ;
|
||||
- condition variables ;
|
||||
- scheduler ;
|
||||
- task_queue ;
|
||||
- resource_governor ;
|
||||
- réservations ;
|
||||
- synchronisation ;
|
||||
|
||||
signaler explicitement :
|
||||
|
||||
- qu'aucune revue indépendante forte n'a été réalisée ;
|
||||
- que la revue de concurrence est différée au prochain passage Codex.
|
||||
|
||||
Le handoff doit rester court et contenir uniquement :
|
||||
|
||||
- objectif ;
|
||||
- contraintes ;
|
||||
- fichiers concernés ;
|
||||
- travail effectué ;
|
||||
- validations exécutées ;
|
||||
- erreurs rencontrées ;
|
||||
- limites restantes ;
|
||||
- prochaine action sûre.
|
||||
|
||||
Règles :
|
||||
|
||||
- un seul agent écrit les sources ;
|
||||
- aucun sous-agent imbriqué ;
|
||||
- aucun modèle payant ;
|
||||
- aucun commit ;
|
||||
- aucun push ;
|
||||
- aucune modification de `scan3d/`.
|
||||
|
||||
Objectif principal :
|
||||
|
||||
Reprendre un ticket en quelques secondes avec le plus petit contexte possible,
|
||||
sans refaire l'analyse déjà présente dans le handoff.
|
||||
|
|
|
|||
|
|
@ -4,11 +4,72 @@ agent: lardon-orchestrator
|
|||
subtask: false
|
||||
---
|
||||
|
||||
Traite ce petit ticket : $ARGUMENTS
|
||||
Traite le petit ticket suivant :
|
||||
|
||||
Utilise lardon-explore pour cibler les fichiers, puis un seul lardon-build-light
|
||||
pour modifier. N'appelle architect, concurrency ou docs que si leur besoin est
|
||||
avéré ; si le ticket est sensible, arrête et recommande le workflow normal.
|
||||
Appelle ensuite lardon-tests pour compilation, tests ciblés et
|
||||
`git diff --check`, puis une revue seulement si le diff le justifie. Maintiens
|
||||
le handoff concis. Aucun commit, push ou fallback payant.
|
||||
$ARGUMENTS
|
||||
|
||||
Le contexte permanent de Lardon3D est déjà chargé via `.opencode/context.md`.
|
||||
|
||||
Ne relis AGENTS.md, l’overview ou la documentation générale que si une information
|
||||
précise manque.
|
||||
|
||||
Ce workflow est réservé aux modifications locales, simples et clairement
|
||||
délimitées.
|
||||
|
||||
N’effectue jamais :
|
||||
|
||||
- d’inventaire global du dépôt ;
|
||||
- de `glob "*"` ;
|
||||
- de `find` sur tout le dépôt ;
|
||||
- de lecture complète de la documentation ;
|
||||
- de refactoring d’architecture non demandé.
|
||||
|
||||
Procédure :
|
||||
|
||||
1. Lire `.opencode/work/current_ticket.md` s’il existe et s’il concerne ce ticket.
|
||||
2. Utiliser `lardon-explore` avec une recherche strictement ciblée.
|
||||
3. Identifier uniquement :
|
||||
- les fichiers à modifier ;
|
||||
- les dépendances directes ;
|
||||
- les tests concernés ;
|
||||
- les éventuels documents à mettre à jour.
|
||||
4. Vérifier que le ticket convient au mode léger.
|
||||
5. Utiliser un seul `lardon-build-light` pour l’implémentation.
|
||||
6. Appeler `lardon-tests` une seule fois après l’implémentation pour :
|
||||
- compiler avec Clang ;
|
||||
- exécuter les tests ciblés ;
|
||||
- exécuter `git diff --check`.
|
||||
7. Demander une revue uniquement si le diff le justifie réellement.
|
||||
8. Mettre à jour le handoff avec un résumé concis.
|
||||
|
||||
N’appelle pas `lardon-architect`, `lardon-concurrency` ou `lardon-docs` sauf si
|
||||
leur intervention est manifestement nécessaire.
|
||||
|
||||
Arrête le workflow léger et recommande `/lardon-ticket` ou Codex si le ticket
|
||||
touche notamment :
|
||||
|
||||
- une API publique structurante ;
|
||||
- `task`, `task_queue` ou `resource_governor` ;
|
||||
- pthread, mutex ou condition variables ;
|
||||
- la durée de vie complexe de ressources ;
|
||||
- la persistance ou le rollback ;
|
||||
- le scheduler, un futur DAG ou les réservations ;
|
||||
- un refactoring réparti sur plusieurs modules ;
|
||||
- une fondation sensible du projet.
|
||||
|
||||
Dans ce cas, ne tente aucune modification risquée avec MiMo.
|
||||
|
||||
Le handoff doit rester court et contenir seulement :
|
||||
|
||||
- objectif ;
|
||||
- fichiers concernés ;
|
||||
- travail effectué ;
|
||||
- validations ;
|
||||
- erreurs ;
|
||||
- limites ;
|
||||
- prochaine action sûre.
|
||||
|
||||
Ne fais aucun commit.
|
||||
Ne fais aucun push.
|
||||
N’utilise aucun modèle payant.
|
||||
Ne modifie jamais `scan3d/`.
|
||||
|
|
|
|||
|
|
@ -1,15 +1,102 @@
|
|||
---
|
||||
description: Reprendre un ticket gratuit avec Nemotron après indisponibilité DeepSeek
|
||||
description: Reprendre un ticket après indisponibilité de DeepSeek
|
||||
agent: lardon-orchestrator
|
||||
subtask: false
|
||||
---
|
||||
|
||||
Lis d'abord `.opencode/work/current_ticket.md` et le diff. Si le handoff suffit,
|
||||
ne refais pas l'exploration. Transmets seulement l'objectif, les fichiers, les
|
||||
invariants, le travail restant et la prochaine action à lardon-build-backup.
|
||||
Après reprise, appelle lardon-tests puis lardon-build-light en lecture seule pour
|
||||
une première revue locale simple. N'appelle ni lardon-review ni
|
||||
lardon-concurrency, car ils utilisent le même modèle que l'implémenteur. Si le
|
||||
diff touche la concurrence, réserve sa revue au prochain passage Codex et
|
||||
signale explicitement l'absence de revue indépendante forte. Mets à jour le
|
||||
handoff après chaque phase. Aucun modèle payant.
|
||||
Reprends le ticket suivant :
|
||||
|
||||
$ARGUMENTS
|
||||
|
||||
Le contexte permanent de Lardon3D est déjà chargé via
|
||||
`.opencode/context.md`.
|
||||
|
||||
Commence toujours par :
|
||||
|
||||
1. lire `.opencode/work/current_ticket.md` ;
|
||||
2. lire le diff courant.
|
||||
|
||||
Si ces deux éléments décrivent correctement le ticket, ne relis pas :
|
||||
|
||||
- AGENTS.md ;
|
||||
- l'overview ;
|
||||
- la documentation générale ;
|
||||
- les documents d'architecture.
|
||||
|
||||
Ne relance pas `lardon-explore` si le handoff contient déjà :
|
||||
|
||||
- l'objectif ;
|
||||
- les contraintes ;
|
||||
- les fichiers concernés ;
|
||||
- les invariants ;
|
||||
- le travail restant.
|
||||
|
||||
Relance `lardon-explore` uniquement lorsqu'une information indispensable est
|
||||
absente.
|
||||
|
||||
Transmets à `lardon-build-backup` uniquement :
|
||||
|
||||
- l'objectif ;
|
||||
- les contraintes ;
|
||||
- les fichiers concernés ;
|
||||
- les API concernées ;
|
||||
- les invariants ;
|
||||
- le travail restant ;
|
||||
- la prochaine action sûre.
|
||||
|
||||
Ne renvoie jamais tout le handoff au modèle d'implémentation.
|
||||
|
||||
Après l'implémentation :
|
||||
|
||||
1. appeler `lardon-tests` une seule fois ;
|
||||
2. utiliser `lardon-build-light` uniquement pour une première revue locale
|
||||
simple ;
|
||||
3. mettre à jour le handoff.
|
||||
|
||||
Ne pas appeler :
|
||||
|
||||
- `lardon-review` ;
|
||||
- `lardon-concurrency` ;
|
||||
|
||||
car ils utilisent le même modèle que l'implémentation de secours.
|
||||
|
||||
Si le ticket touche notamment :
|
||||
|
||||
- pthread ;
|
||||
- mutex ;
|
||||
- condition variables ;
|
||||
- scheduler ;
|
||||
- task_queue ;
|
||||
- resource_governor ;
|
||||
- réservations ;
|
||||
- synchronisation ;
|
||||
|
||||
signaler explicitement :
|
||||
|
||||
- qu'aucune revue indépendante forte n'a été réalisée ;
|
||||
- que la revue de concurrence est différée au prochain passage Codex.
|
||||
|
||||
Le handoff doit rester court et contenir uniquement :
|
||||
|
||||
- objectif ;
|
||||
- contraintes ;
|
||||
- fichiers concernés ;
|
||||
- travail effectué ;
|
||||
- validations exécutées ;
|
||||
- erreurs rencontrées ;
|
||||
- limites restantes ;
|
||||
- prochaine action sûre.
|
||||
|
||||
Règles :
|
||||
|
||||
- un seul agent écrit les sources ;
|
||||
- aucun sous-agent imbriqué ;
|
||||
- aucun modèle payant ;
|
||||
- aucun commit ;
|
||||
- aucun push ;
|
||||
- aucune modification de `scan3d/`.
|
||||
|
||||
Objectif principal :
|
||||
|
||||
Reprendre un ticket en quelques secondes, avec le plus petit contexte possible,
|
||||
sans refaire les analyses déjà présentes dans le handoff.
|
||||
|
|
|
|||
|
|
@ -1,19 +1,83 @@
|
|||
---
|
||||
description: Traiter un ticket gratuit avec contexte progressif et handoff
|
||||
description: Traiter un ticket complet avec contexte progressif et handoff
|
||||
agent: lardon-orchestrator
|
||||
subtask: false
|
||||
---
|
||||
|
||||
Traite ce ticket : $ARGUMENTS
|
||||
Traite le ticket suivant :
|
||||
|
||||
1. Initialise `.opencode/work/current_ticket.md` avec les rubriques prescrites.
|
||||
2. Demande à lardon-explore les seuls fichiers et documents utiles.
|
||||
3. Charge uniquement ce contexte. Appelle lardon-architect seulement pour une
|
||||
abstraction importante, puis transmets un résumé concis à lardon-build.
|
||||
4. Après l'implémentation, appelle lardon-tests une fois, puis lardon-review une
|
||||
fois. Ajoute lardon-concurrency uniquement pour du code concurrent.
|
||||
5. Mets le handoff à jour après chaque phase avec conclusions, commandes,
|
||||
erreurs et prochaine action, sans documentation, sources ou logs complets.
|
||||
$ARGUMENTS
|
||||
|
||||
Un seul agent écrit les sources. Aucun sous-agent imbriqué, commit, push,
|
||||
fallback payant ou modification de scan3d/.
|
||||
Le contexte permanent de Lardon3D est déjà chargé via
|
||||
`.opencode/context.md`.
|
||||
|
||||
Considère également AGENTS.md et le handoff courant comme déjà disponibles.
|
||||
Ne les relis que lorsqu'une information précise manque.
|
||||
|
||||
N'effectue jamais :
|
||||
|
||||
- d'inventaire global du dépôt ;
|
||||
- de `glob "*"` ;
|
||||
- de `find` sur tout le dépôt ;
|
||||
- de lecture complète de toute la documentation.
|
||||
|
||||
Procédure :
|
||||
|
||||
1. Initialiser `.opencode/work/current_ticket.md` avec les rubriques prescrites.
|
||||
2. Utiliser `lardon-explore` avec une recherche strictement ciblée.
|
||||
3. Identifier uniquement :
|
||||
- les fichiers à modifier ;
|
||||
- les dépendances directes ;
|
||||
- les tests concernés ;
|
||||
- les documents réellement utiles.
|
||||
4. Charger uniquement ce contexte.
|
||||
5. Appeler `lardon-architect` uniquement si une évolution d'architecture est
|
||||
réellement nécessaire.
|
||||
6. Transmettre à `lardon-build` un résumé concis contenant :
|
||||
- objectif ;
|
||||
- contraintes ;
|
||||
- API concernées ;
|
||||
- invariants ;
|
||||
- fichiers ;
|
||||
- validations attendues.
|
||||
7. Après l'implémentation :
|
||||
- appeler `lardon-tests` une seule fois ;
|
||||
- appeler `lardon-review` une seule fois ;
|
||||
- appeler `lardon-concurrency` uniquement si le ticket touche :
|
||||
- pthread ;
|
||||
- mutex ;
|
||||
- condition variables ;
|
||||
- scheduler ;
|
||||
- task_queue ;
|
||||
- resource_governor ;
|
||||
- code concurrent.
|
||||
8. Mettre à jour le handoff après chaque phase importante.
|
||||
|
||||
Le handoff doit rester court et contenir uniquement :
|
||||
|
||||
- objectif ;
|
||||
- contraintes ;
|
||||
- fichiers concernés ;
|
||||
- travail effectué ;
|
||||
- validations exécutées ;
|
||||
- erreurs rencontrées ;
|
||||
- limites restantes ;
|
||||
- prochaine action sûre.
|
||||
|
||||
Règles :
|
||||
|
||||
- un seul agent écrit les sources ;
|
||||
- aucun sous-agent imbriqué ;
|
||||
- aucun agent inutile ;
|
||||
- aucun modèle payant ;
|
||||
- aucun commit ;
|
||||
- aucun push ;
|
||||
- aucune modification de `scan3d/`.
|
||||
|
||||
Privilégier systématiquement :
|
||||
|
||||
- le plus petit contexte possible ;
|
||||
- le moins d'agents possible ;
|
||||
- une seule compilation complète ;
|
||||
- une seule revue ;
|
||||
- une seule analyse de concurrence lorsque nécessaire.
|
||||
|
|
|
|||
341
.opencode/context.md
Normal file
341
.opencode/context.md
Normal file
|
|
@ -0,0 +1,341 @@
|
|||
# Lardon3D – Persistent Context
|
||||
|
||||
## Project
|
||||
|
||||
Lardon3D est un moteur de photogrammétrie Linux écrit en C17.
|
||||
|
||||
Objectifs principaux :
|
||||
|
||||
- stabilité absolue ;
|
||||
- faible consommation mémoire ;
|
||||
- traitement par lots adaptatifs ;
|
||||
- aucune saturation du système ;
|
||||
- TUI toujours réactive ;
|
||||
- architecture modulaire.
|
||||
|
||||
Le viewer Vulkan sera un processus séparé lisant uniquement des snapshots validés.
|
||||
|
||||
---
|
||||
|
||||
## Build
|
||||
|
||||
Compiler avec :
|
||||
|
||||
CC=clang meson setup build --wipe
|
||||
meson compile -C build -j8
|
||||
|
||||
Validation minimale :
|
||||
|
||||
meson test -C build --print-errorlogs
|
||||
git diff --check
|
||||
|
||||
Utiliser ASan/UBSan et TSan uniquement lorsque le ticket touche la mémoire ou la concurrence.
|
||||
|
||||
---
|
||||
|
||||
## Git
|
||||
|
||||
Interdictions :
|
||||
|
||||
- jamais git add -A
|
||||
- jamais git commit
|
||||
- jamais git push
|
||||
- jamais modifier scan3d/
|
||||
- jamais modifier tri_photos.py
|
||||
|
||||
Toujours fournir :
|
||||
|
||||
- liste exacte des fichiers du ticket
|
||||
- validations exécutées
|
||||
- limites restantes
|
||||
- message de commit recommandé
|
||||
|
||||
---
|
||||
|
||||
## Architecture
|
||||
|
||||
Séparation stricte :
|
||||
|
||||
TUI
|
||||
↓
|
||||
|
||||
Scheduler
|
||||
|
||||
↓
|
||||
|
||||
Governor
|
||||
|
||||
↓
|
||||
|
||||
Workers
|
||||
|
||||
↓
|
||||
|
||||
Résultats atomiques
|
||||
|
||||
Le thread ncurses ne fait jamais de travail métier.
|
||||
|
||||
Le scheduler ne décide jamais des ressources.
|
||||
|
||||
Le gouverneur est le seul propriétaire des budgets.
|
||||
|
||||
---
|
||||
|
||||
## Resource Governor
|
||||
|
||||
Estimate
|
||||
|
||||
↓
|
||||
|
||||
Reservation
|
||||
|
||||
↓
|
||||
|
||||
Scheduler
|
||||
|
||||
↓
|
||||
|
||||
Worker
|
||||
|
||||
Les réservations sont obligatoires avant toute exécution.
|
||||
|
||||
RAM iGPU partagée = RAM système.
|
||||
|
||||
La zram n'est jamais un budget de travail.
|
||||
|
||||
---
|
||||
|
||||
## Coding rules
|
||||
|
||||
C17 uniquement.
|
||||
|
||||
Pas de variables globales d'état.
|
||||
|
||||
Pas de system().
|
||||
|
||||
Pas de popen().
|
||||
|
||||
Pas d'allocation infinie.
|
||||
|
||||
Toujours des buffers bornés.
|
||||
|
||||
Sorties atomiques.
|
||||
|
||||
Rollback complet en cas d'échec.
|
||||
|
||||
---
|
||||
|
||||
## Current architecture
|
||||
|
||||
Modules disponibles :
|
||||
|
||||
- project
|
||||
- import
|
||||
- import_task
|
||||
- image_catalog
|
||||
- image_view
|
||||
- task
|
||||
- task_queue
|
||||
- hardware_profile
|
||||
- resource_snapshot
|
||||
- resource_governor
|
||||
|
||||
---
|
||||
|
||||
## Active workflow
|
||||
|
||||
1. explorer uniquement les fichiers utiles
|
||||
|
||||
2. architect uniquement si nécessaire
|
||||
|
||||
3. un seul agent d'écriture
|
||||
|
||||
4. tests
|
||||
|
||||
5. revue
|
||||
|
||||
6. handoff
|
||||
|
||||
Ne jamais relire tout le dépôt.
|
||||
|
||||
Ne jamais faire de glob "*".
|
||||
|
||||
Ne jamais parcourir tous les fichiers.
|
||||
|
||||
---
|
||||
|
||||
## Models
|
||||
|
||||
Primary orchestration
|
||||
|
||||
MiMo V2.5 Free
|
||||
|
||||
Implementation
|
||||
|
||||
DeepSeek V4 Flash Free
|
||||
|
||||
Backup implementation
|
||||
|
||||
Nemotron 3 Ultra Free
|
||||
|
||||
Exploration
|
||||
|
||||
North Mini Code Free
|
||||
|
||||
Architecture / Review / Concurrency
|
||||
|
||||
Nemotron 3 Ultra Free
|
||||
|
||||
Documentation
|
||||
|
||||
Ling 3.0 Flash Free
|
||||
|
||||
Aucun modèle payant.
|
||||
|
||||
---
|
||||
|
||||
## If DeepSeek fails
|
||||
|
||||
Reprendre depuis :
|
||||
|
||||
.opencode/work/current_ticket.md
|
||||
|
||||
Ne jamais refaire :
|
||||
|
||||
- exploration
|
||||
- architecture
|
||||
- revue
|
||||
|
||||
si le handoff contient déjà ces informations.
|
||||
|
||||
---
|
||||
|
||||
## Project roadmap
|
||||
|
||||
Fondations terminées :
|
||||
|
||||
- TUI modulaire
|
||||
- projets persistants
|
||||
- import asynchrone
|
||||
- catalogue d'images
|
||||
- image_view
|
||||
- moteur de tâches
|
||||
- scheduler FIFO
|
||||
- gouverneur de ressources
|
||||
- réservations
|
||||
- intégration scheduler ↔ governor
|
||||
- sélection de la première tâche admissible
|
||||
- documentation d'architecture
|
||||
|
||||
Ordre obligatoire des prochains tickets :
|
||||
|
||||
1. séquences de traitement adaptatives pilotées par le Resource Governor
|
||||
2. contre-pression (backpressure) et bornage des files
|
||||
3. checkpoints et persistance des tâches
|
||||
4. DAG minimal de dépendances
|
||||
5. priorités
|
||||
6. pools CPU / GPU / IO
|
||||
7. migration de l'import vers le scheduler générique
|
||||
8. publication incrémentale
|
||||
9. viewer Vulkan
|
||||
|
||||
Ne jamais proposer un ticket déjà terminé.
|
||||
|
||||
Ne jamais sauter une étape de cette feuille de route sans justification explicite.
|
||||
|
||||
---
|
||||
|
||||
## Mission
|
||||
|
||||
Toujours privilégier :
|
||||
|
||||
- stabilité
|
||||
- simplicité
|
||||
- déterminisme
|
||||
- faible mémoire
|
||||
- traitements séquencés
|
||||
- protection du système
|
||||
|
||||
avant les performances brutes.
|
||||
|
||||
État actuel important :
|
||||
|
||||
- Le scheduler sait déjà sauter une tâche en WAIT en tête de file.
|
||||
- Il sélectionne la première tâche admissible dans l’ordre FIFO.
|
||||
- Ce ticket est terminé et ne doit pas être reproposé.
|
||||
|
||||
---
|
||||
|
||||
## Revue de concurrence obligatoire
|
||||
|
||||
Tout ticket touchant `task`, `task_queue`, le scheduler,
|
||||
`resource_governor`, pthread, mutex, variables de condition, pause, reprise,
|
||||
annulation, réservations ou états partagés exige `lardon-concurrency`.
|
||||
|
||||
Cette règle s’applique même si aucun nouveau thread n’est créé.
|
||||
|
||||
---
|
||||
|
||||
## Design philosophy
|
||||
|
||||
Chaque étape du pipeline doit être :
|
||||
|
||||
- indépendante ;
|
||||
- interruptible ;
|
||||
- reprenable ;
|
||||
- observable ;
|
||||
- testable ;
|
||||
- déterministe.
|
||||
|
||||
Chaque tâche doit pouvoir être découpée en petits lots afin de :
|
||||
|
||||
- limiter l'utilisation mémoire ;
|
||||
- garder une TUI fluide ;
|
||||
- permettre une adaptation dynamique des ressources ;
|
||||
- éviter toute saturation du système.
|
||||
|
||||
La stabilité du système hôte est prioritaire sur les performances brutes.
|
||||
|
||||
---
|
||||
|
||||
## Long-term objective
|
||||
|
||||
Lardon3D doit devenir un moteur de photogrammétrie entièrement piloté par un
|
||||
scheduler adaptatif.
|
||||
|
||||
Le scheduler décide uniquement :
|
||||
|
||||
- quand lancer une étape ;
|
||||
- avec quel lot ;
|
||||
- dans quel ordre.
|
||||
|
||||
Le Resource Governor décide uniquement :
|
||||
|
||||
- si les ressources permettent l'exécution ;
|
||||
- la taille optimale des lots ;
|
||||
- quand différer une tâche.
|
||||
|
||||
Le viewer Vulkan ne participe jamais aux calculs.
|
||||
|
||||
Il affiche uniquement des snapshots validés produits par le pipeline.
|
||||
|
||||
L'utilisateur doit voir le résultat apparaître progressivement pendant les
|
||||
calculs, sans attendre la fin complète de la reconstruction.
|
||||
|
||||
Toutes les étapes doivent pouvoir être interrompues puis reprises sans perdre
|
||||
les résultats déjà validés.
|
||||
|
||||
---
|
||||
|
||||
## Optimisation
|
||||
|
||||
Privilégier toujours :
|
||||
|
||||
- plusieurs petits traitements ;
|
||||
- plusieurs petites allocations ;
|
||||
- plusieurs petites copies ;
|
||||
|
||||
plutôt qu'une grosse opération monolithique.
|
||||
|
||||
Lardon3D doit être optimisé pour des machines disposant de peu de mémoire
|
||||
(16 à 32 Go) et d'un iGPU partagé.
|
||||
|
|
@ -1,10 +1,11 @@
|
|||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"default_agent": "lardon-orchestrator",
|
||||
"model": "opencode/north-mini-code-free",
|
||||
"model": "opencode/mimo-v2.5-free",
|
||||
"subagent_depth": 1,
|
||||
"instructions": [
|
||||
"AGENTS.md",
|
||||
".opencode/context.md",
|
||||
"docs/architecture/overview.md"
|
||||
],
|
||||
"permission": {
|
||||
|
|
|
|||
|
|
@ -44,10 +44,47 @@ pendant `PAUSED`. Ses ressources restent donc indisponibles pour les autres
|
|||
tâches. Ce choix évite de reprendre un callback avec un contrat qui aurait été
|
||||
attribué entre-temps à un autre travail.
|
||||
|
||||
## Exécution séquencée adaptative
|
||||
|
||||
Une tâche peut s'exécuter en plusieurs séquences (lots) successives. Le
|
||||
callback appelle `lardon3d_task_sequence_break()` pour libérer sa réservation
|
||||
courante, capturer un nouvel instantané système, obtenir une nouvelle
|
||||
réservation auprès du gouverneur et reprendre avec un contrat actualisé.
|
||||
|
||||
Le cycle d'une séquence est strict :
|
||||
|
||||
```text
|
||||
Callback
|
||||
→ sequence_break
|
||||
→ Release Reservation courante
|
||||
→ Snapshot système
|
||||
→ Governor → Reservation
|
||||
→ Contrat actualisé
|
||||
→ Reprise du callback
|
||||
```
|
||||
|
||||
Le task conserve une référence au gouverneur et à sa réservation courante.
|
||||
`lardon3d_task_start` stocke la réservation initiale ; à la fin de l'exécution,
|
||||
il libère la réservation courante si elle est encore détenue. Le worker de la
|
||||
file libère ensuite la réservation d'origine, qui est déjà libérée si une
|
||||
séquence a eu lieu : cet appel est alors sans effet.
|
||||
|
||||
Invariants préservés :
|
||||
|
||||
- Aucun callback ne démarre sans réservation active.
|
||||
- Une seule réservation active par tâche à tout instant.
|
||||
- La réservation est toujours valide avant et après un `sequence_break`.
|
||||
- Le contrat est mis à jour atomiquement sous le mutex de la tâche.
|
||||
- Si pause ou annulation est demandée pendant le `sequence_break`, la fonction
|
||||
retourne `false` et la tâche est annulée.
|
||||
- Si le gouverneur répond `WAIT` ou `REJECT`, la fonction retourne `false` et
|
||||
la tâche passe en échec sans bloquer le callback.
|
||||
- La progression est conservée entre les séquences.
|
||||
|
||||
## Limites et extensions
|
||||
|
||||
La file possède un seul worker, reste strictement FIFO et ne gère ni priorité
|
||||
ni dépendance. Une notification explicite est nécessaire lorsqu'un composant
|
||||
extérieur libère une réservation. Les prochaines étapes pourront ajouter un
|
||||
DAG, des priorités, des séquences de lots adaptatives et des pools distincts
|
||||
CPU, IO et GPU sans déplacer les décisions de ressources hors du gouverneur.
|
||||
DAG, des priorités, des pools distincts CPU, IO et GPU sans déplacer les
|
||||
décisions de ressources hors du gouverneur.
|
||||
|
|
|
|||
|
|
@ -15,12 +15,11 @@ entrée, sortie et cache :
|
|||
recommandé `opencode/nemotron-3-ultra-free` en cas de saturation 503.
|
||||
- `opencode/nemotron-3-ultra-free` : architecture, concurrence, revue et repli
|
||||
de l'agent principal.
|
||||
- `opencode/north-mini-code-free` : exploration rapide et validations.
|
||||
- `opencode/mimo-v2.5-free` : exploration rapide et validations.
|
||||
- `opencode/laguna-s-2.1-free` : testé comme reviewer sur Lardon3D ; résultats
|
||||
jugés insuffisants. Non utilisé dans les rôles actifs.
|
||||
- `opencode/ling-3.0-flash-free` : documentation.
|
||||
- `opencode/longcat-2.0-free` : disponible, non configuré actuellement.
|
||||
- `opencode/mimo-v2.5-free` : disponible, non configuré actuellement.
|
||||
|
||||
## Gratuité non confirmée
|
||||
|
||||
|
|
@ -63,24 +62,66 @@ OpenCode actuelle.
|
|||
|
||||
## Optimisation du quota
|
||||
|
||||
L'agent par défaut est `lardon-orchestrator` sur North Mini Code Free. Il charge
|
||||
seulement `AGENTS.md` et l'overview, puis demande à North Mini Code une
|
||||
exploration ciblée. DeepSeek est réservé à l'implémentation complexe ; il ne sert
|
||||
ni à l'orchestration, ni aux tests, ni à la documentation. Nemotron traite les
|
||||
reprises, revues et analyses d'architecture ou de concurrence, MiMo les petits
|
||||
tickets et Ling la documentation.
|
||||
L’agent par défaut est `lardon-orchestrator` sur MiMo V2.5 Free.
|
||||
|
||||
Les commandes `lardon-plan`, `lardon-small`, `lardon-ticket` et
|
||||
`lardon-ticket-backup` chargent progressivement le contexte. Elles ne lisent pas
|
||||
automatiquement toute l'architecture et transmettent uniquement objectif,
|
||||
contraintes, fichiers, API, invariants, risques et tests. Les rapports de succès
|
||||
restent courts. Le handoff ignoré `.opencode/work/current_ticket.md` permet une
|
||||
reprise sans rejouer toute l'analyse.
|
||||
Le contexte permanent est chargé depuis `.opencode/context.md`. L’orchestrateur
|
||||
ne relit pas automatiquement AGENTS.md, l’overview ni toute la documentation
|
||||
d’architecture. Il utilise uniquement le handoff courant et les documents
|
||||
directement liés au ticket.
|
||||
|
||||
Nemotron ne relit jamais sa propre implémentation lorsqu'il a servi de backup.
|
||||
MiMo fournit alors seulement une première revue locale simple. La revue de
|
||||
concurrence sensible est différée jusqu'au prochain passage Codex, et le workflow
|
||||
signale explicitement qu'aucune revue indépendante forte n'a eu lieu.
|
||||
MiMo assure :
|
||||
|
||||
- l’orchestration ;
|
||||
- l’exploration ciblée ;
|
||||
- les tests ;
|
||||
- les petits tickets.
|
||||
|
||||
DeepSeek V4 Flash Free est réservé à l’implémentation complexe. Il ne sert ni à
|
||||
l’orchestration, ni à l’exploration, ni aux tests, ni à la documentation.
|
||||
|
||||
Nemotron 3 Ultra Free assure :
|
||||
|
||||
- les reprises après indisponibilité de DeepSeek ;
|
||||
- l’architecture ;
|
||||
- la concurrence ;
|
||||
- la revue générale.
|
||||
|
||||
Ling 3.0 Flash Free est réservé à la documentation.
|
||||
|
||||
North Mini Code Free n’est plus utilisé dans les rôles actifs. Il reste mentionné
|
||||
dans l’inventaire historique comme modèle testé puis écarté en raison de résultats
|
||||
jugés insuffisants et trop erratiques sur Lardon3D.
|
||||
|
||||
Les commandes `lardon-plan`, `lardon-small`, `lardon-ticket`,
|
||||
`lardon-ticket-backup` et les commandes de reprise utilisent un contexte
|
||||
progressif.
|
||||
|
||||
Elles ne lisent jamais automatiquement tout le dépôt ni toute l’architecture.
|
||||
Elles transmettent uniquement :
|
||||
|
||||
- objectif ;
|
||||
- contraintes ;
|
||||
- fichiers concernés ;
|
||||
- API ;
|
||||
- invariants ;
|
||||
- risques ;
|
||||
- tests requis ;
|
||||
- prochaine action sûre.
|
||||
|
||||
Les rapports de succès restent courts. Le handoff ignoré
|
||||
`.opencode/work/current_ticket.md` permet une reprise sans rejouer l’exploration
|
||||
ou l’analyse déjà terminée.
|
||||
|
||||
Nemotron ne relit jamais sa propre implémentation lorsqu’il a servi de backup.
|
||||
|
||||
Dans ce cas :
|
||||
|
||||
- MiMo fournit seulement une première revue locale simple ;
|
||||
- la revue de concurrence sensible est différée jusqu’au prochain passage Codex ;
|
||||
- le workflow signale explicitement qu’aucune revue indépendante forte n’a eu
|
||||
lieu.
|
||||
|
||||
Aucun modèle payant n’est utilisé automatiquement.
|
||||
|
||||
## Chaîne de secours
|
||||
|
||||
|
|
|
|||
|
|
@ -81,6 +81,17 @@ bool lardon3d_task_execution_contract(
|
|||
const Lardon3DTask *task,
|
||||
Lardon3DTaskExecutionContract *contract
|
||||
);
|
||||
/* Libère la réservation courante, en obtient une nouvelle auprès du gouverneur
|
||||
* et met à jour le contrat. À appeler uniquement depuis le callback en cours
|
||||
* d'exécution. Retourne false si pause/annulation est demandée ou si le
|
||||
* gouverneur répond WAIT/REJECT (la tâche passe alors en échec). */
|
||||
bool lardon3d_task_sequence_break(
|
||||
Lardon3DTask *task,
|
||||
Lardon3DResourceGovernor *governor,
|
||||
Lardon3DResourceReservation **out_reservation,
|
||||
Lardon3DTaskExecutionContract *out_contract
|
||||
);
|
||||
unsigned int lardon3d_task_sequence_count(const Lardon3DTask *task);
|
||||
bool lardon3d_task_reject(Lardon3DTask *task, const char *message);
|
||||
const char *lardon3d_task_state_name(Lardon3DTaskState state);
|
||||
|
||||
|
|
|
|||
14
meson.build
14
meson.build
|
|
@ -111,6 +111,20 @@ task_test = executable(
|
|||
|
||||
test('task', task_test, timeout: 30)
|
||||
|
||||
sequential_task_test = executable(
|
||||
'test-sequential-task',
|
||||
sources: [
|
||||
'tests/test_sequential_task.c',
|
||||
'src/task.c',
|
||||
'src/resource_governor.c',
|
||||
'src/resource_snapshot.c',
|
||||
],
|
||||
include_directories: include_directories('include'),
|
||||
dependencies: [threads],
|
||||
)
|
||||
|
||||
test('sequential-task', sequential_task_test, timeout: 30)
|
||||
|
||||
task_queue_test = executable(
|
||||
'test-task-queue',
|
||||
sources: [
|
||||
|
|
|
|||
153
src/task.c
153
src/task.c
|
|
@ -23,6 +23,9 @@ struct Lardon3DTask {
|
|||
bool pause_requested;
|
||||
bool cancel_requested;
|
||||
bool executing;
|
||||
Lardon3DResourceGovernor *governor;
|
||||
Lardon3DResourceReservation *current_reservation;
|
||||
unsigned int sequence_count;
|
||||
};
|
||||
|
||||
static bool
|
||||
|
|
@ -125,6 +128,8 @@ lardon3d_task_start(
|
|||
return false;
|
||||
}
|
||||
task->executing = true;
|
||||
task->governor = governor;
|
||||
task->current_reservation = (Lardon3DResourceReservation *)reservation;
|
||||
task->contract = (Lardon3DTaskExecutionContract) {
|
||||
.batch_size = information.batch_size,
|
||||
.memory_bytes = information.memory_bytes,
|
||||
|
|
@ -143,6 +148,7 @@ lardon3d_task_start(
|
|||
while (task->pause_requested && !task->cancel_requested) {
|
||||
task->state = TASK_PAUSED;
|
||||
copy_text(task->message, sizeof(task->message), "Tâche en pause.");
|
||||
(void)pthread_cond_broadcast(&task->condition);
|
||||
(void)pthread_cond_wait(&task->condition, &task->mutex);
|
||||
}
|
||||
if (task->cancel_requested) {
|
||||
|
|
@ -169,6 +175,13 @@ lardon3d_task_start(
|
|||
finish_locked(task, TASK_COMPLETED, "Tâche terminée.");
|
||||
}
|
||||
(void)pthread_mutex_unlock(&task->mutex);
|
||||
if (task->current_reservation) {
|
||||
(void)lardon3d_resource_governor_release(
|
||||
governor,
|
||||
task->current_reservation
|
||||
);
|
||||
task->current_reservation = NULL;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -265,6 +278,146 @@ lardon3d_task_checkpoint(Lardon3DTask *task)
|
|||
return continuing;
|
||||
}
|
||||
|
||||
bool
|
||||
lardon3d_task_sequence_break(
|
||||
Lardon3DTask *task,
|
||||
Lardon3DResourceGovernor *governor,
|
||||
Lardon3DResourceReservation **out_reservation,
|
||||
Lardon3DTaskExecutionContract *out_contract
|
||||
)
|
||||
{
|
||||
if (!task || !governor || !out_reservation || !out_contract) {
|
||||
return false;
|
||||
}
|
||||
*out_reservation = NULL;
|
||||
(void)pthread_mutex_lock(&task->mutex);
|
||||
if (!task->executing || is_terminal(task->state)) {
|
||||
(void)pthread_mutex_unlock(&task->mutex);
|
||||
return false;
|
||||
}
|
||||
while (task->pause_requested && !task->cancel_requested) {
|
||||
task->state = TASK_PAUSED;
|
||||
copy_text(task->message, sizeof(task->message), "Tâche en pause.");
|
||||
(void)pthread_cond_broadcast(&task->condition);
|
||||
(void)pthread_cond_wait(&task->condition, &task->mutex);
|
||||
}
|
||||
if (task->cancel_requested) {
|
||||
(void)pthread_mutex_unlock(&task->mutex);
|
||||
return false;
|
||||
}
|
||||
task->state = TASK_RUNNING;
|
||||
Lardon3DResourceReservation *previous = task->current_reservation;
|
||||
task->current_reservation = NULL;
|
||||
(void)pthread_mutex_unlock(&task->mutex);
|
||||
|
||||
if (previous) {
|
||||
(void)lardon3d_resource_governor_release(governor, previous);
|
||||
}
|
||||
|
||||
Lardon3DResourceDecision decision;
|
||||
Lardon3DResourceReservation *next = NULL;
|
||||
bool reserved = lardon3d_resource_governor_reserve_available(
|
||||
governor,
|
||||
&task->estimate,
|
||||
&decision,
|
||||
&next
|
||||
);
|
||||
|
||||
(void)pthread_mutex_lock(&task->mutex);
|
||||
if (task->cancel_requested) {
|
||||
if (next) {
|
||||
(void)lardon3d_resource_governor_release(governor, next);
|
||||
}
|
||||
finish_locked(
|
||||
task,
|
||||
TASK_CANCELLED,
|
||||
"Tâche annulée pendant sequence_break."
|
||||
);
|
||||
(void)pthread_mutex_unlock(&task->mutex);
|
||||
return false;
|
||||
}
|
||||
while (task->pause_requested && !task->cancel_requested) {
|
||||
task->state = TASK_PAUSED;
|
||||
copy_text(task->message, sizeof(task->message), "Tâche en pause.");
|
||||
(void)pthread_cond_broadcast(&task->condition);
|
||||
(void)pthread_cond_wait(&task->condition, &task->mutex);
|
||||
}
|
||||
if (task->cancel_requested) {
|
||||
if (next) {
|
||||
(void)lardon3d_resource_governor_release(governor, next);
|
||||
}
|
||||
finish_locked(task, TASK_CANCELLED, "Tâche annulée.");
|
||||
(void)pthread_mutex_unlock(&task->mutex);
|
||||
return false;
|
||||
}
|
||||
if (!reserved || !next) {
|
||||
task->current_reservation = NULL;
|
||||
finish_locked(
|
||||
task,
|
||||
TASK_FAILED,
|
||||
"Impossible de réserver les ressources de la séquence."
|
||||
);
|
||||
(void)pthread_mutex_unlock(&task->mutex);
|
||||
return false;
|
||||
}
|
||||
if (decision.kind == LARDON3D_RESOURCE_WAIT
|
||||
|| decision.kind == LARDON3D_RESOURCE_REJECT) {
|
||||
task->current_reservation = NULL;
|
||||
finish_locked(
|
||||
task,
|
||||
TASK_FAILED,
|
||||
decision.reason[0] ? decision.reason
|
||||
: "Ressources impossibles à réserver."
|
||||
);
|
||||
(void)pthread_mutex_unlock(&task->mutex);
|
||||
return false;
|
||||
}
|
||||
Lardon3DResourceReservationInfo information;
|
||||
if (!lardon3d_resource_reservation_get_active(
|
||||
governor,
|
||||
next,
|
||||
&information
|
||||
)) {
|
||||
(void)lardon3d_resource_governor_release(governor, next);
|
||||
task->current_reservation = NULL;
|
||||
finish_locked(
|
||||
task,
|
||||
TASK_FAILED,
|
||||
"Réservation de séquence invalide."
|
||||
);
|
||||
(void)pthread_mutex_unlock(&task->mutex);
|
||||
return false;
|
||||
}
|
||||
task->current_reservation = next;
|
||||
task->contract = (Lardon3DTaskExecutionContract) {
|
||||
.batch_size = information.batch_size,
|
||||
.memory_bytes = information.memory_bytes,
|
||||
.gpu_memory_bytes = information.gpu_memory_bytes,
|
||||
.cpu_threads = information.cpu_threads,
|
||||
.gpu_slots = information.gpu_slots,
|
||||
.io_slots = information.io_slots,
|
||||
};
|
||||
task->has_contract = true;
|
||||
++task->sequence_count;
|
||||
*out_reservation = next;
|
||||
*out_contract = task->contract;
|
||||
(void)pthread_mutex_unlock(&task->mutex);
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
lardon3d_task_sequence_count(const Lardon3DTask *task)
|
||||
{
|
||||
if (!task) {
|
||||
return 0;
|
||||
}
|
||||
Lardon3DTask *mutable_task = (Lardon3DTask *)task;
|
||||
(void)pthread_mutex_lock(&mutable_task->mutex);
|
||||
unsigned int count = task->sequence_count;
|
||||
(void)pthread_mutex_unlock(&mutable_task->mutex);
|
||||
return count;
|
||||
}
|
||||
|
||||
bool
|
||||
lardon3d_task_set_progress(
|
||||
Lardon3DTask *task,
|
||||
|
|
|
|||
|
|
@ -139,6 +139,10 @@ queue_worker(void *context)
|
|||
"Réservation de ressources invalide."
|
||||
);
|
||||
}
|
||||
/* La tâche peut avoir libéré et re-réservé via sequence_break pendant
|
||||
* son callback. Dans ce cas la réservation d'origine est déjà libérée
|
||||
* et cet appel est sans effet ; la réservation courante de la tâche a
|
||||
* été libérée par lardon3d_task_start. */
|
||||
(void)lardon3d_resource_governor_release(
|
||||
queue->governor,
|
||||
reservation
|
||||
|
|
|
|||
392
tests/test_sequential_task.c
Normal file
392
tests/test_sequential_task.c
Normal file
|
|
@ -0,0 +1,392 @@
|
|||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <lardon3d/task.h>
|
||||
|
||||
#define CHECK(condition) \
|
||||
do { \
|
||||
if (!(condition)) { \
|
||||
(void)fprintf(stderr, "Échec ligne %d : %s\n", __LINE__, #condition); \
|
||||
return false; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
typedef struct {
|
||||
Lardon3DResourceGovernor *governor;
|
||||
Lardon3DResourceReservation *initial_reservation;
|
||||
unsigned int expected_breaks;
|
||||
unsigned int breaks_done;
|
||||
size_t batch_sizes[8];
|
||||
Lardon3DTaskExecutionContract initial_contract;
|
||||
bool got_initial_contract;
|
||||
} SeqContext;
|
||||
|
||||
typedef struct {
|
||||
Lardon3DResourceGovernor *governor;
|
||||
} WaitContext;
|
||||
|
||||
typedef struct {
|
||||
Lardon3DResourceGovernor *governor;
|
||||
pthread_mutex_t sync_mutex;
|
||||
pthread_cond_t sync_cond;
|
||||
bool about_to_break;
|
||||
bool cancel_ready;
|
||||
} CancelContext;
|
||||
|
||||
typedef struct {
|
||||
Lardon3DTask *task;
|
||||
Lardon3DResourceGovernor *governor;
|
||||
Lardon3DResourceReservation *reservation;
|
||||
} StartContext;
|
||||
|
||||
static void
|
||||
short_pause(long nanoseconds)
|
||||
{
|
||||
struct timespec duration = {.tv_sec = 0, .tv_nsec = nanoseconds};
|
||||
(void)nanosleep(&duration, NULL);
|
||||
}
|
||||
|
||||
static bool
|
||||
seq_callback(Lardon3DTask *task, void *userdata)
|
||||
{
|
||||
SeqContext *ctx = userdata;
|
||||
if (!lardon3d_task_execution_contract(task, &ctx->initial_contract)) {
|
||||
return false;
|
||||
}
|
||||
ctx->got_initial_contract = true;
|
||||
Lardon3DResourceReservation *previous = ctx->initial_reservation;
|
||||
for (unsigned int index = 0; index < ctx->expected_breaks; ++index) {
|
||||
if (!lardon3d_task_checkpoint(task)) {
|
||||
return false;
|
||||
}
|
||||
/* Vérifier que la réservation précédente est encore valide AVANT le break */
|
||||
if (previous && !lardon3d_resource_governor_reservation_is_valid(
|
||||
ctx->governor,
|
||||
previous
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
Lardon3DResourceReservation *reservation = NULL;
|
||||
Lardon3DTaskExecutionContract contract;
|
||||
if (!lardon3d_task_sequence_break(
|
||||
task,
|
||||
ctx->governor,
|
||||
&reservation,
|
||||
&contract
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
if (!lardon3d_resource_governor_reservation_is_valid(
|
||||
ctx->governor,
|
||||
reservation
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
ctx->batch_sizes[index] = contract.batch_size;
|
||||
previous = reservation;
|
||||
++ctx->breaks_done;
|
||||
unsigned int progress = (unsigned int)(
|
||||
((index + 1) * 100) / ctx->expected_breaks
|
||||
);
|
||||
if (!lardon3d_task_set_progress(task, progress, "Séquence.")) {
|
||||
return false;
|
||||
}
|
||||
short_pause(2000000);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
wait_callback(Lardon3DTask *task, void *userdata)
|
||||
{
|
||||
WaitContext *ctx = userdata;
|
||||
Lardon3DResourceReservation *reservation = NULL;
|
||||
Lardon3DTaskExecutionContract contract;
|
||||
return lardon3d_task_sequence_break(
|
||||
task,
|
||||
ctx->governor,
|
||||
&reservation,
|
||||
&contract
|
||||
);
|
||||
}
|
||||
|
||||
static bool
|
||||
cancel_callback(Lardon3DTask *task, void *userdata)
|
||||
{
|
||||
CancelContext *ctx = userdata;
|
||||
if (!lardon3d_task_checkpoint(task)) {
|
||||
return false;
|
||||
}
|
||||
(void)pthread_mutex_lock(&ctx->sync_mutex);
|
||||
ctx->about_to_break = true;
|
||||
(void)pthread_cond_broadcast(&ctx->sync_cond);
|
||||
while (!ctx->cancel_ready) {
|
||||
(void)pthread_cond_wait(&ctx->sync_cond, &ctx->sync_mutex);
|
||||
}
|
||||
(void)pthread_mutex_unlock(&ctx->sync_mutex);
|
||||
Lardon3DResourceReservation *reservation = NULL;
|
||||
Lardon3DTaskExecutionContract contract;
|
||||
return lardon3d_task_sequence_break(
|
||||
task,
|
||||
ctx->governor,
|
||||
&reservation,
|
||||
&contract
|
||||
);
|
||||
}
|
||||
|
||||
static void *
|
||||
start_task(void *context)
|
||||
{
|
||||
StartContext *start = context;
|
||||
return (void *)(uintptr_t)(lardon3d_task_start(
|
||||
start->task,
|
||||
start->governor,
|
||||
start->reservation
|
||||
) ? 1 : 0);
|
||||
}
|
||||
|
||||
static bool
|
||||
wait_for_state(Lardon3DTask *task, Lardon3DTaskState expected)
|
||||
{
|
||||
for (size_t attempt = 0; attempt < 5000; ++attempt) {
|
||||
Lardon3DTaskSnapshot snapshot;
|
||||
if (!lardon3d_task_snapshot(task, &snapshot)) {
|
||||
return false;
|
||||
}
|
||||
if (snapshot.state == expected) {
|
||||
return true;
|
||||
}
|
||||
short_pause(1000000);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
run_sequential_test(void)
|
||||
{
|
||||
const Lardon3DResourceEstimate estimate = {
|
||||
.memory_bytes_per_item = 1000,
|
||||
.minimum_batch_size = 1,
|
||||
.maximum_batch_size = 1000,
|
||||
.desired_cpu_threads = 1,
|
||||
};
|
||||
Lardon3DHardwareProfile profile = {
|
||||
.logical_cpu_count = 16,
|
||||
.page_size_bytes = 4096,
|
||||
.memory_total_bytes = UINT64_MAX,
|
||||
.cpu_architecture = "test",
|
||||
};
|
||||
Lardon3DResourcePolicy policy = {
|
||||
.maximum_cpu_load_ratio = 1.0,
|
||||
.maximum_io_pressure_avg10 = 100.0,
|
||||
.io_slot_capacity = 1,
|
||||
};
|
||||
Lardon3DResourceGovernor *governor = lardon3d_resource_governor_create(
|
||||
&profile,
|
||||
&policy
|
||||
);
|
||||
CHECK(governor);
|
||||
Lardon3DResourceSnapshot resource_snapshot = {
|
||||
.memory_available_bytes = 20000,
|
||||
.cpu_load_1m = 0.0,
|
||||
};
|
||||
Lardon3DResourceDecision decision;
|
||||
Lardon3DResourceReservation *reservation;
|
||||
CHECK(lardon3d_resource_governor_reserve(
|
||||
governor,
|
||||
&resource_snapshot,
|
||||
&estimate,
|
||||
&decision,
|
||||
&reservation
|
||||
));
|
||||
CHECK(decision.kind == LARDON3D_RESOURCE_START
|
||||
|| decision.kind == LARDON3D_RESOURCE_REDUCE_BATCH);
|
||||
CHECK(decision.batch_size == 20);
|
||||
|
||||
SeqContext ctx = {
|
||||
.governor = governor,
|
||||
.initial_reservation = reservation,
|
||||
.expected_breaks = 3,
|
||||
};
|
||||
Lardon3DTask *task = lardon3d_task_create(
|
||||
"Séquences",
|
||||
&estimate,
|
||||
seq_callback,
|
||||
&ctx
|
||||
);
|
||||
CHECK(task);
|
||||
StartContext start = {task, governor, reservation};
|
||||
pthread_t thread;
|
||||
CHECK(pthread_create(&thread, NULL, start_task, &start) == 0);
|
||||
CHECK(wait_for_state(task, TASK_RUNNING));
|
||||
CHECK(lardon3d_task_join(task));
|
||||
void *thread_result;
|
||||
CHECK(pthread_join(thread, &thread_result) == 0);
|
||||
CHECK((uintptr_t)thread_result == 1);
|
||||
CHECK(ctx.got_initial_contract);
|
||||
CHECK(ctx.breaks_done == 3);
|
||||
CHECK(ctx.initial_contract.batch_size == 20);
|
||||
CHECK(ctx.batch_sizes[0] == 1000);
|
||||
CHECK(ctx.batch_sizes[1] == 1000);
|
||||
CHECK(ctx.batch_sizes[2] == 1000);
|
||||
CHECK(ctx.batch_sizes[0] != ctx.initial_contract.batch_size);
|
||||
CHECK(lardon3d_task_sequence_count(task) == 3);
|
||||
Lardon3DTaskSnapshot snapshot;
|
||||
CHECK(lardon3d_task_snapshot(task, &snapshot));
|
||||
CHECK(snapshot.state == TASK_COMPLETED);
|
||||
CHECK(snapshot.progress == 100);
|
||||
CHECK(lardon3d_resource_governor_reservation_count(governor) == 0);
|
||||
lardon3d_task_destroy(task);
|
||||
lardon3d_resource_governor_destroy(governor);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
run_wait_test(void)
|
||||
{
|
||||
const Lardon3DResourceEstimate estimate = {
|
||||
.minimum_batch_size = 1,
|
||||
.maximum_batch_size = 100,
|
||||
.desired_cpu_threads = 1,
|
||||
.desired_io_slots = 1,
|
||||
};
|
||||
Lardon3DHardwareProfile profile = {
|
||||
.logical_cpu_count = 16,
|
||||
.page_size_bytes = 4096,
|
||||
.memory_total_bytes = UINT64_MAX,
|
||||
.cpu_architecture = "test",
|
||||
};
|
||||
Lardon3DResourcePolicy policy = {
|
||||
.maximum_cpu_load_ratio = 1.0,
|
||||
.maximum_io_pressure_avg10 = 0.0,
|
||||
.io_slot_capacity = 1,
|
||||
};
|
||||
Lardon3DResourceGovernor *governor = lardon3d_resource_governor_create(
|
||||
&profile,
|
||||
&policy
|
||||
);
|
||||
CHECK(governor);
|
||||
Lardon3DResourceSnapshot resource_snapshot = {
|
||||
.memory_available_bytes = UINT64_MAX,
|
||||
.cpu_load_1m = 0.0,
|
||||
.io_pressure_known = false,
|
||||
};
|
||||
Lardon3DResourceDecision decision;
|
||||
Lardon3DResourceReservation *reservation;
|
||||
CHECK(lardon3d_resource_governor_reserve(
|
||||
governor,
|
||||
&resource_snapshot,
|
||||
&estimate,
|
||||
&decision,
|
||||
&reservation
|
||||
));
|
||||
WaitContext ctx = {.governor = governor};
|
||||
Lardon3DTask *task = lardon3d_task_create(
|
||||
"Attente",
|
||||
&estimate,
|
||||
wait_callback,
|
||||
&ctx
|
||||
);
|
||||
CHECK(task);
|
||||
CHECK(lardon3d_task_start(task, governor, reservation));
|
||||
Lardon3DTaskSnapshot snapshot;
|
||||
CHECK(lardon3d_task_snapshot(task, &snapshot));
|
||||
CHECK(snapshot.state == TASK_FAILED);
|
||||
CHECK(lardon3d_resource_governor_reservation_count(governor) == 0);
|
||||
lardon3d_task_destroy(task);
|
||||
lardon3d_resource_governor_destroy(governor);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
run_cancel_test(void)
|
||||
{
|
||||
const Lardon3DResourceEstimate estimate = {
|
||||
.minimum_batch_size = 1,
|
||||
.maximum_batch_size = 100,
|
||||
.desired_cpu_threads = 1,
|
||||
};
|
||||
Lardon3DHardwareProfile profile = {
|
||||
.logical_cpu_count = 16,
|
||||
.page_size_bytes = 4096,
|
||||
.memory_total_bytes = UINT64_MAX,
|
||||
.cpu_architecture = "test",
|
||||
};
|
||||
Lardon3DResourcePolicy policy = {
|
||||
.maximum_cpu_load_ratio = 1.0,
|
||||
.maximum_io_pressure_avg10 = 100.0,
|
||||
.io_slot_capacity = 1,
|
||||
};
|
||||
Lardon3DResourceGovernor *governor = lardon3d_resource_governor_create(
|
||||
&profile,
|
||||
&policy
|
||||
);
|
||||
CHECK(governor);
|
||||
Lardon3DResourceSnapshot resource_snapshot = {
|
||||
.memory_available_bytes = UINT64_MAX,
|
||||
.cpu_load_1m = 0.0,
|
||||
};
|
||||
Lardon3DResourceDecision decision;
|
||||
Lardon3DResourceReservation *reservation;
|
||||
CHECK(lardon3d_resource_governor_reserve(
|
||||
governor,
|
||||
&resource_snapshot,
|
||||
&estimate,
|
||||
&decision,
|
||||
&reservation
|
||||
));
|
||||
CancelContext ctx = {.governor = governor};
|
||||
CHECK(pthread_mutex_init(&ctx.sync_mutex, NULL) == 0);
|
||||
CHECK(pthread_cond_init(&ctx.sync_cond, NULL) == 0);
|
||||
Lardon3DTask *task = lardon3d_task_create(
|
||||
"Annulation",
|
||||
&estimate,
|
||||
cancel_callback,
|
||||
&ctx
|
||||
);
|
||||
CHECK(task);
|
||||
StartContext start = {task, governor, reservation};
|
||||
pthread_t thread;
|
||||
CHECK(pthread_create(&thread, NULL, start_task, &start) == 0);
|
||||
(void)pthread_mutex_lock(&ctx.sync_mutex);
|
||||
while (!ctx.about_to_break) {
|
||||
(void)pthread_cond_wait(&ctx.sync_cond, &ctx.sync_mutex);
|
||||
}
|
||||
(void)pthread_mutex_unlock(&ctx.sync_mutex);
|
||||
lardon3d_task_request_cancel(task);
|
||||
(void)pthread_mutex_lock(&ctx.sync_mutex);
|
||||
ctx.cancel_ready = true;
|
||||
(void)pthread_cond_broadcast(&ctx.sync_cond);
|
||||
(void)pthread_mutex_unlock(&ctx.sync_mutex);
|
||||
CHECK(lardon3d_task_join(task));
|
||||
CHECK(pthread_join(thread, NULL) == 0);
|
||||
Lardon3DTaskSnapshot snapshot;
|
||||
CHECK(lardon3d_task_snapshot(task, &snapshot));
|
||||
CHECK(snapshot.state == TASK_CANCELLED);
|
||||
CHECK(lardon3d_resource_governor_reservation_count(governor) == 0);
|
||||
lardon3d_task_destroy(task);
|
||||
(void)pthread_cond_destroy(&ctx.sync_cond);
|
||||
(void)pthread_mutex_destroy(&ctx.sync_mutex);
|
||||
lardon3d_resource_governor_destroy(governor);
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
if (!run_sequential_test()) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (!run_wait_test()) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (!run_cancel_test()) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -157,7 +157,7 @@ run_test(void)
|
|||
void *thread_result;
|
||||
CHECK(pthread_join(thread, &thread_result) == 0);
|
||||
CHECK((uintptr_t)thread_result == 1);
|
||||
CHECK(lardon3d_resource_governor_release(governor, reservation));
|
||||
CHECK(!lardon3d_resource_governor_release(governor, reservation));
|
||||
CHECK(lardon3d_task_snapshot(task, &snapshot));
|
||||
CHECK(snapshot.state == TASK_COMPLETED);
|
||||
CHECK(snapshot.progress == 100);
|
||||
|
|
@ -178,7 +178,7 @@ run_test(void)
|
|||
lardon3d_task_request_cancel(task);
|
||||
CHECK(lardon3d_task_join(task));
|
||||
CHECK(pthread_join(thread, NULL) == 0);
|
||||
CHECK(lardon3d_resource_governor_release(governor, reservation));
|
||||
CHECK(!lardon3d_resource_governor_release(governor, reservation));
|
||||
CHECK(lardon3d_task_snapshot(task, &snapshot));
|
||||
CHECK(snapshot.state == TASK_CANCELLED);
|
||||
CHECK(snapshot.progress < 100);
|
||||
|
|
@ -190,7 +190,7 @@ run_test(void)
|
|||
governor, &resource_snapshot, &estimate, &decision, &reservation
|
||||
));
|
||||
CHECK(lardon3d_task_start(task, governor, reservation));
|
||||
CHECK(lardon3d_resource_governor_release(governor, reservation));
|
||||
CHECK(!lardon3d_resource_governor_release(governor, reservation));
|
||||
CHECK(lardon3d_task_snapshot(task, &snapshot));
|
||||
CHECK(snapshot.state == TASK_FAILED);
|
||||
CHECK(strcmp(snapshot.message, "Erreur contrôlée.") == 0);
|
||||
|
|
|
|||
Loading…
Reference in a new issue